You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
6.5 KiB
270 lines
6.5 KiB
//======================================================================== |
|
// |
|
// 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; |
|
}
|
|
|