mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 10:14:44 +00:00

* sumatrapdf - vendor import * everything compiles (libjpeg, poppler, fitz, sumatrapdf) * does NOT link (remove the comment tags in the parent directory.rbuild file (rosapps dir) to build it) svn path=/trunk/; revision=29295
270 lines
6.5 KiB
C++
270 lines
6.5 KiB
C++
//========================================================================
|
|
//
|
|
// SplashClip.cc
|
|
//
|
|
//========================================================================
|
|
|
|
#include <config.h>
|
|
|
|
#ifdef USE_GCC_PRAGMAS
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "goo/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 **)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 = 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;
|
|
}
|