diff options
Diffstat (limited to 'kpdf/xpdf/splash/SplashClip.cpp')
-rw-r--r-- | kpdf/xpdf/splash/SplashClip.cpp | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/kpdf/xpdf/splash/SplashClip.cpp b/kpdf/xpdf/splash/SplashClip.cpp new file mode 100644 index 00000000..ba03b7a4 --- /dev/null +++ b/kpdf/xpdf/splash/SplashClip.cpp @@ -0,0 +1,382 @@ +//======================================================================== +// +// SplashClip.cpp +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <string.h> +#include "gmem.h" +#include "SplashErrorCodes.h" +#include "SplashPath.h" +#include "SplashXPath.h" +#include "SplashXPathScanner.h" +#include "SplashBitmap.h" +#include "SplashClip.h" + +//------------------------------------------------------------------------ +// SplashClip.flags +//------------------------------------------------------------------------ + +#define splashClipEO 0x01 // use even-odd rule + +//------------------------------------------------------------------------ +// SplashClip +//------------------------------------------------------------------------ + +SplashClip::SplashClip(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + GBool antialiasA) { + antialias = antialiasA; + if (x0 < x1) { + xMin = x0; + xMax = x1; + } else { + xMin = x1; + xMax = x0; + } + if (y0 < y1) { + yMin = y0; + yMax = y1; + } else { + yMin = y1; + yMax = y0; + } + xMinI = splashFloor(xMin); + yMinI = splashFloor(yMin); + xMaxI = splashFloor(xMax); + yMaxI = splashFloor(yMax); + paths = NULL; + flags = NULL; + scanners = NULL; + length = size = 0; +} + +SplashClip::SplashClip(SplashClip *clip) { + int i; + + antialias = clip->antialias; + xMin = clip->xMin; + yMin = clip->yMin; + xMax = clip->xMax; + yMax = clip->yMax; + xMinI = clip->xMinI; + yMinI = clip->yMinI; + xMaxI = clip->xMaxI; + yMaxI = clip->yMaxI; + length = clip->length; + size = clip->size; + paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *)); + flags = (Guchar *)gmallocn(size, sizeof(Guchar)); + scanners = (SplashXPathScanner **) + gmallocn(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 **)greallocn(paths, size, sizeof(SplashXPath *)); + flags = (Guchar *)greallocn(flags, size, sizeof(Guchar)); + scanners = (SplashXPathScanner **) + greallocn(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 = x0; + xMax = x1; + } else { + xMin = x1; + xMax = x0; + } + if (y0 < y1) { + yMin = y0; + yMax = y1; + } else { + yMin = y1; + yMax = y0; + } + xMinI = splashFloor(xMin); + yMinI = splashFloor(yMin); + xMaxI = splashFloor(xMax); + yMaxI = splashFloor(yMax); +} + +SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + if (x0 < x1) { + if (x0 > xMin) { + xMin = x0; + xMinI = splashFloor(xMin); + } + if (x1 < xMax) { + xMax = x1; + xMaxI = splashFloor(xMax); + } + } else { + if (x1 > xMin) { + xMin = x1; + xMinI = splashFloor(xMin); + } + if (x0 < xMax) { + xMax = x0; + xMaxI = splashFloor(xMax); + } + } + if (y0 < y1) { + if (y0 > yMin) { + yMin = y0; + yMinI = splashFloor(yMin); + } + if (y1 < yMax) { + yMax = y1; + yMaxI = splashFloor(yMax); + } + } else { + if (y1 > yMin) { + yMin = y1; + yMinI = splashFloor(yMin); + } + if (y0 < yMax) { + yMax = y0; + yMaxI = splashFloor(yMax); + } + } + return splashOk; +} + +SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness, GBool eo) { + SplashXPath *xPath; + + xPath = new SplashXPath(path, matrix, flatness, gTrue); + + // check for an empty path + if (xPath->length == 0) { + xMax = xMin - 1; + yMax = yMin - 1; + xMaxI = splashFloor(xMax); + yMaxI = splashFloor(yMax); + 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); + if (antialias) { + xPath->aaScale(); + } + 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 < xMinI || x > xMaxI || y < yMinI || y > yMaxI) { + return gFalse; + } + + // check the paths + if (antialias) { + for (i = 0; i < length; ++i) { + if (!scanners[i]->test(x * splashAASize, y * splashAASize)) { + return gFalse; + } + } + } else { + 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) { + // This tests the rectangle: + // x = [rectXMin, rectXMax + 1) (note: rect coords are ints) + // y = [rectYMin, rectYMax + 1) + // against the clipping region: + // x = [xMin, xMax] (note: clipping coords are fp) + // y = [yMin, yMax] + if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax || + (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) { + return splashClipAllOutside; + } + if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax && + (SplashCoord)rectYMin >= yMin && (SplashCoord)(rectYMax + 1) <= yMax && + length == 0) { + return splashClipAllInside; + } + return splashClipPartial; +} + +SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) { + int i; + + // This tests the rectangle: + // x = [spanXMin, spanXMax + 1) (note: span coords are ints) + // y = [spanY, spanY + 1) + // against the clipping region: + // x = [xMin, xMax] (note: clipping coords are fp) + // y = [yMin, yMax] + if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax || + (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) { + return splashClipAllOutside; + } + if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax && + (SplashCoord)spanY >= yMin && (SplashCoord)(spanY + 1) <= yMax)) { + return splashClipPartial; + } + if (antialias) { + for (i = 0; i < length; ++i) { + if (!scanners[i]->testSpan(spanXMin * splashAASize, + spanXMax * splashAASize + (splashAASize - 1), + spanY * splashAASize)) { + return splashClipPartial; + } + } + } else { + for (i = 0; i < length; ++i) { + if (!scanners[i]->testSpan(spanXMin, spanXMax, spanY)) { + return splashClipPartial; + } + } + } + return splashClipAllInside; +} + +void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) { + int xx0, xx1, xx, yy, i; + SplashColorPtr p; + + // zero out pixels with x < xMin + xx0 = *x0 * splashAASize; + xx1 = splashFloor(xMin * splashAASize); + if (xx1 > aaBuf->getWidth()) { + xx1 = aaBuf->getWidth(); + } + if (xx0 < xx1) { + xx0 &= ~7; + for (yy = 0; yy < splashAASize; ++yy) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3); + for (xx = xx0; xx + 7 < xx1; xx += 8) { + *p++ = 0; + } + if (xx < xx1) { + *p &= 0xff >> (xx1 & 7); + } + } + *x0 = splashFloor(xMin); + } + + // zero out pixels with x > xMax + xx0 = splashFloor(xMax * splashAASize) + 1; + if (xx0 < 0) { + xx0 = 0; + } + xx1 = (*x1 + 1) * splashAASize; + if (xx0 < xx1) { + for (yy = 0; yy < splashAASize; ++yy) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3); + xx = xx0; + if (xx & 7) { + *p &= 0xff00 >> (xx & 7); + xx = (xx & ~7) + 8; + ++p; + } + for (; xx < xx1; xx += 8) { + *p++ = 0; + } + } + *x1 = splashFloor(xMax); + } + + // check the paths + for (i = 0; i < length; ++i) { + scanners[i]->clipAALine(aaBuf, x0, x1, y); + } +} |