Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pdf/splash/SplashClip.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/splash/SplashClip.cc')
-rw-r--r--pdf/splash/SplashClip.cc270
1 files changed, 270 insertions, 0 deletions
diff --git a/pdf/splash/SplashClip.cc b/pdf/splash/SplashClip.cc
new file mode 100644
index 0000000..4c70c03
--- /dev/null
+++ b/pdf/splash/SplashClip.cc
@@ -0,0 +1,270 @@
+//========================================================================
+//
+// SplashClip.cc
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "SplashErrorCodes.h"
+#include "SplashMath.h"
+#include "SplashPath.h"
+#include "SplashXPath.h"
+#include "SplashXPathScanner.h"
+#include "SplashClip.h"
+
+//------------------------------------------------------------------------
+// SplashClip.flags
+//------------------------------------------------------------------------
+
+#define splashClipEO 0x01 // use even-odd rule
+
+//------------------------------------------------------------------------
+// SplashClip
+//------------------------------------------------------------------------
+
+SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ if (x0 < x1) {
+ xMin = splashFloor(x0);
+ xMax = splashFloor(x1);
+ } else {
+ xMin = splashFloor(x1);
+ xMax = splashFloor(x0);
+ }
+ if (y0 < y1) {
+ yMin = splashFloor(y0);
+ yMax = splashFloor(y1);
+ } else {
+ yMin = splashFloor(y1);
+ yMax = splashFloor(y0);
+ }
+ paths = NULL;
+ flags = NULL;
+ scanners = NULL;
+ length = size = 0;
+}
+
+SplashClip::SplashClip(SplashClip *clip) {
+ int i;
+
+ xMin = clip->xMin;
+ yMin = clip->yMin;
+ xMax = clip->xMax;
+ yMax = clip->yMax;
+ length = clip->length;
+ size = clip->size;
+ paths = (SplashXPath **)gmalloc(size * sizeof(SplashXPath *));
+ flags = (Guchar *)gmalloc(size * sizeof(Guchar));
+ scanners = (SplashXPathScanner **)
+ gmalloc(size * sizeof(SplashXPathScanner *));
+ for (i = 0; i < length; ++i) {
+ paths[i] = clip->paths[i]->copy();
+ flags[i] = clip->flags[i];
+ scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
+ }
+}
+
+SplashClip::~SplashClip() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ delete paths[i];
+ delete scanners[i];
+ }
+ gfree(paths);
+ gfree(flags);
+ gfree(scanners);
+}
+
+void SplashClip::grow(int nPaths) {
+ if (length + nPaths > size) {
+ if (size == 0) {
+ size = 32;
+ }
+ while (size < length + nPaths) {
+ size *= 2;
+ }
+ paths = (SplashXPath **)grealloc(paths, size * sizeof(SplashXPath *));
+ flags = (Guchar *)grealloc(flags, size * sizeof(Guchar));
+ scanners = (SplashXPathScanner **)
+ grealloc(scanners, size * sizeof(SplashXPathScanner *));
+ }
+}
+
+void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ delete paths[i];
+ delete scanners[i];
+ }
+ gfree(paths);
+ gfree(flags);
+ gfree(scanners);
+ paths = NULL;
+ flags = NULL;
+ scanners = NULL;
+ length = size = 0;
+
+ if (x0 < x1) {
+ xMin = splashFloor(x0);
+ xMax = splashFloor(x1);
+ } else {
+ xMin = splashFloor(x1);
+ xMax = splashFloor(x0);
+ }
+ if (y0 < y1) {
+ yMin = splashFloor(y0);
+ yMax = splashFloor(y1);
+ } else {
+ yMin = splashFloor(y1);
+ yMax = splashFloor(y0);
+ }
+}
+
+SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ int x0I, y0I, x1I, y1I;
+
+ if (x0 < x1) {
+ x0I = splashFloor(x0);
+ x1I = splashFloor(x1);
+ } else {
+ x0I = splashFloor(x1);
+ x1I = splashFloor(x0);
+ }
+ if (x0I > xMin) {
+ xMin = x0I;
+ }
+ if (x1I < xMax) {
+ xMax = x1I;
+ }
+ if (y0 < y1) {
+ y0I = splashFloor(y0);
+ y1I = splashFloor(y1);
+ } else {
+ y0I = splashFloor(y1);
+ y1I = splashFloor(y0);
+ }
+ if (y0I > yMin) {
+ yMin = y0I;
+ }
+ if (y1I < yMax) {
+ yMax = y1I;
+ }
+ return splashOk;
+}
+
+SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord flatness,
+ GBool eo) {
+ SplashXPath *xPath;
+
+ xPath = new SplashXPath(path, flatness, gTrue);
+
+ // check for an empty path
+ if (xPath->length == 0) {
+ xMax = xMin - 1;
+ yMax = yMin - 1;
+ delete xPath;
+
+ // check for a rectangle
+ } else if (xPath->length == 4 &&
+ ((xPath->segs[0].x0 == xPath->segs[0].x1 &&
+ xPath->segs[0].x0 == xPath->segs[1].x0 &&
+ xPath->segs[0].x0 == xPath->segs[3].x1 &&
+ xPath->segs[2].x0 == xPath->segs[2].x1 &&
+ xPath->segs[2].x0 == xPath->segs[1].x1 &&
+ xPath->segs[2].x0 == xPath->segs[3].x0 &&
+ xPath->segs[1].y0 == xPath->segs[1].y1 &&
+ xPath->segs[1].y0 == xPath->segs[0].y1 &&
+ xPath->segs[1].y0 == xPath->segs[2].y0 &&
+ xPath->segs[3].y0 == xPath->segs[3].y1 &&
+ xPath->segs[3].y0 == xPath->segs[0].y0 &&
+ xPath->segs[3].y0 == xPath->segs[2].y1) ||
+ (xPath->segs[0].y0 == xPath->segs[0].y1 &&
+ xPath->segs[0].y0 == xPath->segs[1].y0 &&
+ xPath->segs[0].y0 == xPath->segs[3].y1 &&
+ xPath->segs[2].y0 == xPath->segs[2].y1 &&
+ xPath->segs[2].y0 == xPath->segs[1].y1 &&
+ xPath->segs[2].y0 == xPath->segs[3].y0 &&
+ xPath->segs[1].x0 == xPath->segs[1].x1 &&
+ xPath->segs[1].x0 == xPath->segs[0].x1 &&
+ xPath->segs[1].x0 == xPath->segs[2].x0 &&
+ xPath->segs[3].x0 == xPath->segs[3].x1 &&
+ xPath->segs[3].x0 == xPath->segs[0].x0 &&
+ xPath->segs[3].x0 == xPath->segs[2].x1))) {
+ clipToRect(xPath->segs[0].x0, xPath->segs[0].y0,
+ xPath->segs[2].x0, xPath->segs[2].y0);
+ delete xPath;
+
+ } else {
+ grow(1);
+ xPath->sort();
+ paths[length] = xPath;
+ flags[length] = eo ? splashClipEO : 0;
+ scanners[length] = new SplashXPathScanner(xPath, eo);
+ ++length;
+ }
+
+ return splashOk;
+}
+
+GBool SplashClip::test(int x, int y) {
+ int i;
+
+ // check the rectangle
+ if (x < xMin || x > xMax || y < yMin || y > yMax) {
+ return gFalse;
+ }
+
+ // check the paths
+ for (i = 0; i < length; ++i) {
+ if (!scanners[i]->test(x, y)) {
+ return gFalse;
+ }
+ }
+
+ return gTrue;
+}
+
+SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
+ int rectXMax, int rectYMax) {
+ if (rectXMax < xMin || rectXMin > xMax ||
+ rectYMax < yMin || rectYMin > yMax) {
+ return splashClipAllOutside;
+ }
+ if (rectXMin >= xMin && rectXMax <= xMax &&
+ rectYMin >= yMin && rectYMax <= yMax &&
+ length == 0) {
+ return splashClipAllInside;
+ }
+ return splashClipPartial;
+}
+
+SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
+ int i;
+
+ if (spanXMax < xMin || spanXMin > xMax ||
+ spanY < yMin || spanY > yMax) {
+ return splashClipAllOutside;
+ }
+ if (!(spanXMin >= xMin && spanXMax <= xMax &&
+ spanY >= yMin && spanY <= yMax)) {
+ return splashClipPartial;
+ }
+ for (i = 0; i < length; ++i) {
+ if (!scanners[i]->testSpan(xMin, xMax, spanY)) {
+ return splashClipPartial;
+ }
+ }
+ return splashClipAllInside;
+}