summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
committerKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
commitad547a6b5986815fda458221149728d9d9ab1d87 (patch)
tree16296910eb3eca724371474ea9aea3994dc69614 /Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
parent947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff)
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc521
1 files changed, 521 insertions, 0 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
new file mode 100644
index 00000000000..bf7b802cf0d
--- /dev/null
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
@@ -0,0 +1,521 @@
+//========================================================================
+//
+// SplashClip.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "gmempp.h"
+#include "SplashErrorCodes.h"
+#include "SplashPath.h"
+#include "SplashXPath.h"
+#include "SplashXPathScanner.h"
+#include "SplashClip.h"
+
+//------------------------------------------------------------------------
+
+// Compute x * y / 255, where x and y are in [0, 255].
+static inline Guchar mul255(Guchar x, Guchar y) {
+ int z;
+
+ z = (int)x * (int)y;
+ return (Guchar)((z + (z >> 8) + 0x80) >> 8);
+}
+
+//------------------------------------------------------------------------
+// SplashClip
+//------------------------------------------------------------------------
+
+SplashClip::SplashClip(int hardXMinA, int hardYMinA,
+ int hardXMaxA, int hardYMaxA) {
+ int w;
+
+ hardXMin = hardXMinA;
+ hardYMin = hardYMinA;
+ hardXMax = hardXMaxA;
+ hardYMax = hardYMaxA;
+ xMin = hardXMin;
+ yMin = hardYMin;
+ xMax = hardXMax;
+ yMax = hardYMax;
+ intBoundsValid = gFalse;
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = gTrue;
+ prev = NULL;
+ if ((w = hardXMax + 1) <= 0) {
+ w = 1;
+ }
+ buf = (Guchar *)gmalloc(w);
+}
+
+SplashClip::SplashClip(SplashClip *clip) {
+ int w;
+
+ hardXMin = clip->hardXMin;
+ hardYMin = clip->hardYMin;
+ hardXMax = clip->hardXMax;
+ hardYMax = clip->hardYMax;
+ xMin = clip->xMin;
+ yMin = clip->yMin;
+ xMax = clip->xMax;
+ yMax = clip->yMax;
+ xMinI = clip->xMinI;
+ yMinI = clip->yMinI;
+ xMaxI = clip->xMaxI;
+ yMaxI = clip->yMaxI;
+ intBoundsValid = clip->intBoundsValid;
+ intBoundsStrokeAdjust = clip->intBoundsStrokeAdjust;
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = clip->isSimple;
+ prev = clip;
+ if ((w = splashCeil(xMax)) <= 0) {
+ w = 1;
+ }
+ buf = (Guchar *)gmalloc(w);
+}
+
+SplashClip::~SplashClip() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ delete scanners[i];
+ delete paths[i];
+ }
+ gfree(paths);
+ gfree(eo);
+ gfree(scanners);
+ gfree(buf);
+}
+
+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 *));
+ eo = (Guchar *)greallocn(eo, size, sizeof(Guchar));
+ scanners = (SplashXPathScanner **)
+ greallocn(scanners, size, sizeof(SplashXPathScanner *));
+ }
+}
+
+void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ int w, i;
+
+ for (i = 0; i < length; ++i) {
+ delete paths[i];
+ delete scanners[i];
+ }
+ gfree(paths);
+ gfree(eo);
+ gfree(scanners);
+ gfree(buf);
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = gTrue;
+ prev = NULL;
+
+ if (x0 < x1) {
+ xMin = x0;
+ xMax = x1;
+ } else {
+ xMin = x1;
+ xMax = x0;
+ }
+ if (y0 < y1) {
+ yMin = y0;
+ yMax = y1;
+ } else {
+ yMin = y1;
+ yMax = y0;
+ }
+ intBoundsValid = gFalse;
+ if ((w = splashCeil(xMax)) <= 0) {
+ w = 1;
+ }
+ buf = (Guchar *)gmalloc(w);
+}
+
+SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1) {
+ if (x0 < x1) {
+ if (x0 > xMin) {
+ xMin = x0;
+ intBoundsValid = gFalse;
+ }
+ if (x1 < xMax) {
+ xMax = x1;
+ intBoundsValid = gFalse;
+ }
+ } else {
+ if (x1 > xMin) {
+ xMin = x1;
+ intBoundsValid = gFalse;
+ }
+ if (x0 < xMax) {
+ xMax = x0;
+ intBoundsValid = gFalse;
+ }
+ }
+ if (y0 < y1) {
+ if (y0 > yMin) {
+ yMin = y0;
+ intBoundsValid = gFalse;
+ }
+ if (y1 < yMax) {
+ yMax = y1;
+ intBoundsValid = gFalse;
+ }
+ } else {
+ if (y1 > yMin) {
+ yMin = y1;
+ intBoundsValid = gFalse;
+ }
+ if (y0 < yMax) {
+ yMax = y0;
+ intBoundsValid = gFalse;
+ }
+ }
+ return splashOk;
+}
+
+SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
+ SplashCoord flatness, GBool eoA,
+ GBool enablePathSimplification,
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashXPath *xPath;
+ SplashCoord t;
+
+ xPath = new SplashXPath(path, matrix, flatness, gTrue,
+ enablePathSimplification,
+ strokeAdjust);
+
+ // check for an empty path
+ if (xPath->length == 0) {
+ xMin = yMin = 1;
+ xMax = yMax = 0;
+ intBoundsValid = gFalse;
+ delete xPath;
+ return splashOk;
+ }
+
+ // check for a rectangle
+ if (xPath->isRect) {
+ clipToRect(xPath->rectX0, xPath->rectY0, xPath->rectX1, xPath->rectY1);
+ delete xPath;
+ return splashOk;
+ }
+
+ grow(1);
+ paths[length] = xPath;
+ eo[length] = (Guchar)eoA;
+ if ((t = xPath->getXMin()) > xMin) {
+ xMin = t;
+ }
+ if ((t = xPath->getYMin()) > yMin) {
+ yMin = t;
+ }
+ if ((t = xPath->getXMax() + 1) < xMax) {
+ xMax = t;
+ }
+ if ((t = xPath->getYMax() + 1) < yMax) {
+ yMax = t;
+ }
+ intBoundsValid = gFalse;
+ scanners[length] = new SplashXPathScanner(xPath, eoA, splashFloor(yMin),
+ splashCeil(yMax) - 1);
+ ++length;
+ isSimple = gFalse;
+
+ return splashOk;
+}
+
+SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
+ int rectXMax, int rectYMax,
+ SplashStrokeAdjustMode strokeAdjust) {
+ // In general, this function tests the rectangle:
+ // x = [rectXMin, rectXMax + 1) (note: coords are ints)
+ // y = [rectYMin, rectYMax + 1)
+ // against the clipping region:
+ // x = [xMin, xMax) (note: coords are fp)
+ // y = [yMin, yMax)
+
+ if (strokeAdjust != splashStrokeAdjustOff && isSimple) {
+ // special case for stroke adjustment with a simple clipping
+ // rectangle -- the clipping region is:
+ // x = [xMinI, xMaxI + 1)
+ // y = [yMinI, yMaxI + 1)
+ updateIntBounds(strokeAdjust);
+ if (xMinI > xMaxI || yMinI > yMaxI) {
+ return splashClipAllOutside;
+ }
+ if (rectXMax + 1 <= xMinI ||
+ rectXMin >= xMaxI + 1 ||
+ rectYMax + 1 <= yMinI ||
+ rectYMin >= yMaxI + 1) {
+ return splashClipAllOutside;
+ }
+ if (rectXMin >= xMinI &&
+ rectXMax <= xMaxI &&
+ rectYMin >= yMinI &&
+ rectYMax <= yMaxI) {
+ return splashClipAllInside;
+ }
+ } else {
+ if (xMin >= xMax || yMin >= yMax) {
+ return splashClipAllOutside;
+ }
+ if ((SplashCoord)(rectXMax + 1) <= xMin ||
+ (SplashCoord)rectXMin >= xMax ||
+ (SplashCoord)(rectYMax + 1) <= yMin ||
+ (SplashCoord)rectYMin >= yMax) {
+ return splashClipAllOutside;
+ }
+ if (isSimple &&
+ (SplashCoord)rectXMin >= xMin &&
+ (SplashCoord)(rectXMax + 1) <= xMax &&
+ (SplashCoord)rectYMin >= yMin &&
+ (SplashCoord)(rectYMax + 1) <= yMax) {
+ return splashClipAllInside;
+ }
+ }
+ return splashClipPartial;
+}
+
+void SplashClip::clipSpan(Guchar *line, int y, int x0, int x1,
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashClip *clip;
+ SplashCoord d;
+ int x0a, x1a, x0b, x1b, x, i;
+
+ updateIntBounds(strokeAdjust);
+
+ //--- clip to the integer rectangle
+
+ if (y < yMinI || y > yMaxI ||
+ x1 < xMinI || x0 > xMaxI) {
+ memset(line + x0, 0, x1 - x0 + 1);
+ return;
+ }
+
+ if (x0 > xMinI) {
+ x0a = x0;
+ } else {
+ x0a = xMinI;
+ memset(line + x0, 0, x0a - x0);
+ }
+
+ if (x1 < xMaxI) {
+ x1a = x1;
+ } else {
+ x1a = xMaxI;
+ memset(line + x1a + 1, 0, x1 - x1a);
+ }
+
+ if (x0a > x1a) {
+ return;
+ }
+
+ //--- clip to the floating point rectangle
+ // (if stroke adjustment is disabled)
+
+ if (strokeAdjust == splashStrokeAdjustOff) {
+
+ // clip left edge (xMin)
+ if (x0a == xMinI) {
+ d = (SplashCoord)(xMinI + 1) - xMin;
+ line[x0a] = (Guchar)(int)((SplashCoord)line[x0a] * d);
+ }
+
+ // clip right edge (xMax)
+ if (x1a == xMaxI) {
+ d = xMax - (SplashCoord)xMaxI;
+ line[x1a] = (Guchar)(int)((SplashCoord)line[x1a] * d);
+ }
+
+ // clip top edge (yMin)
+ if (y == yMinI) {
+ d = (SplashCoord)(yMinI + 1) - yMin;
+ for (x = x0a; x <= x1a; ++x) {
+ line[x] = (Guchar)(int)((SplashCoord)line[x] * d);
+ }
+ }
+
+ // clip bottom edge (yMax)
+ if (y == yMaxI) {
+ d = yMax - (SplashCoord)yMaxI;
+ for (x = x0a; x <= x1a; ++x) {
+ line[x] = (Guchar)(int)((SplashCoord)line[x] * d);
+ }
+ }
+ }
+
+ if (isSimple) {
+ return;
+ }
+
+ //--- clip to the paths
+
+ for (clip = this; clip; clip = clip->prev) {
+ for (i = 0; i < clip->length; ++i) {
+ clip->scanners[i]->getSpan(buf, y, x0a, x1a, &x0b, &x1b);
+ if (x0a < x0b) {
+ memset(line + x0a, 0, x0b - x0a);
+ }
+ for (x = x0b; x <= x1b; ++x) {
+ line[x] = mul255(line[x], buf[x]);
+ }
+ if (x1b < x1a) {
+ memset(line + x1b + 1, 0, x1a - x1b);
+ }
+ }
+ }
+}
+
+GBool SplashClip::clipSpanBinary(Guchar *line, int y, int x0, int x1,
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashClip *clip;
+ int x0a, x1a, x0b, x1b, x, i;
+ Guchar any;
+
+ updateIntBounds(strokeAdjust);
+
+ if (y < yMinI || y > yMaxI ||
+ x1 < xMinI || x0 > xMaxI) {
+ if (x0 <= x1) {
+ memset(line + x0, 0, x1 - x0 + 1);
+ }
+ return gFalse;
+ }
+
+ if (x0 > xMinI) {
+ x0a = x0;
+ } else {
+ x0a = xMinI;
+ memset(line + x0, 0, x0a - x0);
+ }
+
+ if (x1 < xMaxI) {
+ x1a = x1;
+ } else {
+ x1a = xMaxI;
+ memset(line + x1a + 1, 0, x1 - x1a);
+ }
+
+ if (x0a > x1a) {
+ return gFalse;
+ }
+
+ if (isSimple) {
+ for (x = x0a; x <= x1a; ++x) {
+ if (line[x]) {
+ return gTrue;
+ }
+ }
+ return gFalse;
+ }
+
+ any = 0;
+ for (clip = this; clip; clip = clip->prev) {
+ for (i = 0; i < clip->length; ++i) {
+ clip->scanners[i]->getSpanBinary(buf, y, x0a, x1a, &x0b, &x1b);
+ if (x0a < x0b) {
+ memset(line + x0a, 0, x0b - x0a);
+ }
+ for (x = x0b; x <= x1b; ++x) {
+ line[x] &= buf[x];
+ any |= line[x];
+ }
+ if (x1b < x1a) {
+ memset(line + x1b + 1, 0, x1a - x1b);
+ }
+ }
+ }
+
+ return any != 0;
+}
+
+int SplashClip::getXMinI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return xMinI;
+}
+
+int SplashClip::getXMaxI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return xMaxI;
+}
+
+int SplashClip::getYMinI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return yMinI;
+}
+
+int SplashClip::getYMaxI(SplashStrokeAdjustMode strokeAdjust) {
+ updateIntBounds(strokeAdjust);
+ return yMaxI;
+}
+
+int SplashClip::getNumPaths() {
+ SplashClip *clip;
+ int n;
+
+ n = 0;
+ for (clip = this; clip; clip = clip->prev) {
+ n += clip->length;
+ }
+ return n;
+}
+
+void SplashClip::updateIntBounds(SplashStrokeAdjustMode strokeAdjust) {
+ if (intBoundsValid && strokeAdjust == intBoundsStrokeAdjust) {
+ return;
+ }
+ if (strokeAdjust != splashStrokeAdjustOff && isSimple) {
+ splashStrokeAdjust(xMin, xMax, &xMinI, &xMaxI, strokeAdjust);
+ splashStrokeAdjust(yMin, yMax, &yMinI, &yMaxI, strokeAdjust);
+ } else {
+ xMinI = splashFloor(xMin);
+ yMinI = splashFloor(yMin);
+ xMaxI = splashCeil(xMax);
+ yMaxI = splashCeil(yMax);
+ }
+ if (xMinI < hardXMin) {
+ xMinI = hardXMin;
+ }
+ if (yMinI < hardYMin) {
+ yMinI = hardYMin;
+ }
+ if (xMaxI > hardXMax) {
+ xMaxI = hardXMax;
+ }
+ if (yMaxI > hardYMax) {
+ yMaxI = hardYMax;
+ }
+ // the clipping code uses [xMinI, xMaxI] instead of [xMinI, xMaxI)
+ --xMaxI;
+ --yMaxI;
+ intBoundsValid = gTrue;
+ intBoundsStrokeAdjust = strokeAdjust;
+}