diff options
Diffstat (limited to 'pdf/splash/SplashClip.cc')
-rw-r--r-- | pdf/splash/SplashClip.cc | 270 |
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; +} |