//======================================================================== // // SplashClip.cc // //======================================================================== #include #ifdef USE_GCC_PRAGMAS #pragma implementation #endif #include #include #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; }