<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span>>Unfortunately only implemented for shadings where the 3 vertices of the </span>triangle have the same color for now since i got lost trying to implement the coloring (and also have no pdf to check against)<br>
<span> </span><br>
</div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span>Is the PDF with this fixed issue an example?</span></div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
<a href="https://bugs.freedesktop.org/show_bug.cgi?id=90570" id="LPlnk997719">https://bugs.freedesktop.org/show_bug.cgi?id=90570</a><br>
</div>
<div>
<div id="appendonsend"></div>
<div style="font-family:Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> poppler <poppler-bounces@lists.freedesktop.org> on behalf of GitLab Mirror <gitlab-mirror@kemper.freedesktop.org><br>
<b>Sent:</b> Thursday, February 27, 2020 8:17 AM<br>
<b>To:</b> poppler@lists.freedesktop.org <poppler@lists.freedesktop.org><br>
<b>Subject:</b> [poppler] poppler/SplashOutputDev.cc poppler/SplashOutputDev.h splash/Splash.cc splash/SplashPattern.h splash/SplashTypes.h</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="PlainText">poppler/SplashOutputDev.cc | 51 ++++----<br>
poppler/SplashOutputDev.h | 11 +<br>
splash/Splash.cc | 271 ++++++++++++++++++++++++++++++++-------------<br>
splash/SplashPattern.h | 7 -<br>
splash/SplashTypes.h | 7 +<br>
5 files changed, 246 insertions(+), 101 deletions(-)<br>
<br>
New commits:<br>
commit 68af136fb2934a65f912d84a619c39c75d6d90b9<br>
Author: Albert Astals Cid <aacid@kde.org><br>
Date: Sat Feb 22 10:05:25 2020 +0100<br>
<br>
Implement Splash::gouraudTriangleShadedFill for non parametrized shadings<br>
<br>
Fixes #881<br>
<br>
Unfortunately only implemented for shadings where the 3 vertices of the<br>
triangle have the same color for now since i got lost trying to<br>
implement the coloring (and also have no pdf to check against)<br>
<br>
The reason this fixes #881 is because if Splash::gouraudTriangleShadedFill<br>
returns false because it doesn't natively support this shading, the<br>
default rendering algorithm of Gfx.cc kicks in, and that rendering what<br>
does is render different triangles without them knowing they belong to<br>
the same shading, meaning that if you have some opacity the edges of the<br>
triangles will overlap and and up having different color than the one<br>
you really wanted<br>
<br>
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc<br>
index dbbd29a9..047b2d2d 100644<br>
--- a/poppler/SplashOutputDev.cc<br>
+++ b/poppler/SplashOutputDev.cc<br>
@@ -82,9 +82,9 @@<br>
static const double s_minLineWidth = 0.0;<br>
<br>
static inline void convertGfxColor(SplashColorPtr dest,<br>
- SplashColorMode colorMode,<br>
- GfxColorSpace *colorSpace,<br>
- GfxColor *src) {<br>
+ const SplashColorMode colorMode,<br>
+ const GfxColorSpace *colorSpace,<br>
+ const GfxColor *src) {<br>
SplashColor color;<br>
GfxGray gray;<br>
GfxRGB rgb;<br>
@@ -134,9 +134,9 @@ static inline void convertGfxColor(SplashColorPtr dest,<br>
// to ensure that everything is initialized.<br>
<br>
static inline void convertGfxShortColor(SplashColorPtr dest,<br>
- SplashColorMode colorMode,<br>
- GfxColorSpace *colorSpace,<br>
- GfxColor *src) {<br>
+ const SplashColorMode colorMode,<br>
+ const GfxColorSpace *colorSpace,<br>
+ const GfxColor *src) {<br>
switch (colorMode) {<br>
case splashModeMono1:<br>
case splashModeMono8:<br>
@@ -194,21 +194,29 @@ SplashGouraudPattern::SplashGouraudPattern(bool bDirectColorTranslationA,<br>
SplashGouraudPattern::~SplashGouraudPattern() {<br>
}<br>
<br>
+void SplashGouraudPattern::getNonParametrizedTriangle(int i, SplashColorMode mode, double *x0, double *y0, SplashColorPtr color0,<br>
+ double *x1, double *y1, SplashColorPtr color1,<br>
+ double *x2, double *y2, SplashColorPtr color2) {<br>
+ GfxColor c0, c1, c2;<br>
+ shading->getTriangle(i, x0, y0, &c0, x1, y1, &c1, x2, y2, &c2);<br>
+<br>
+ const GfxColorSpace* srcColorSpace = shading->getColorSpace();<br>
+ convertGfxColor(color0, mode, srcColorSpace, &c0);<br>
+ convertGfxColor(color1, mode, srcColorSpace, &c1);<br>
+ convertGfxColor(color2, mode, srcColorSpace, &c2);<br>
+}<br>
+<br>
+<br>
void SplashGouraudPattern::getParameterizedColor(double colorinterp, SplashColorMode mode, SplashColorPtr dest) {<br>
GfxColor src;<br>
- GfxColorSpace* srcColorSpace = shading->getColorSpace();<br>
- int colorComps = 3;<br>
- if (mode == splashModeCMYK8)<br>
- colorComps=4;<br>
- else if (mode == splashModeDeviceN8)<br>
- colorComps=4 + SPOT_NCOMPS;<br>
-<br>
shading->getParameterizedColor(colorinterp, &src);<br>
<br>
if (bDirectColorTranslation) {<br>
+ const int colorComps = splashColorModeNComps[mode];<br>
for (int m = 0; m < colorComps; ++m)<br>
dest[m] = colToByte(src.c[m]);<br>
} else {<br>
+ GfxColorSpace* srcColorSpace = shading->getColorSpace();<br>
convertGfxShortColor(dest, mode, srcColorSpace, &src);<br>
}<br>
}<br>
@@ -4540,17 +4548,12 @@ bool SplashOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTrian<br>
break;<br>
}<br>
// restore vector antialias because we support it here<br>
- if (shading->isParameterized()) {<br>
- SplashGouraudColor *splashShading = new SplashGouraudPattern(bDirectColorTranslation, state, shading);<br>
- bool vaa = getVectorAntialias();<br>
- bool retVal = false;<br>
- setVectorAntialias(true);<br>
- retVal = splash->gouraudTriangleShadedFill(splashShading);<br>
- setVectorAntialias(vaa);<br>
- delete splashShading;<br>
- return retVal;<br>
- }<br>
- return false;<br>
+ SplashGouraudPattern splashShading(bDirectColorTranslation, state, shading);<br>
+ const bool vaa = getVectorAntialias();<br>
+ setVectorAntialias(true);<br>
+ const bool retVal = splash->gouraudTriangleShadedFill(&splashShading);<br>
+ setVectorAntialias(vaa);<br>
+ return retVal;<br>
}<br>
<br>
bool SplashOutputDev::univariateShadedFill(GfxState *state, SplashUnivariatePattern *pattern, double tMin, double tMax) {<br>
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h<br>
index 7a670d1b..a42e724c 100644<br>
--- a/poppler/SplashOutputDev.h<br>
+++ b/poppler/SplashOutputDev.h<br>
@@ -147,11 +147,16 @@ public:<br>
<br>
bool isParameterized() override { return shading->isParameterized(); }<br>
int getNTriangles() override { return shading->getNTriangles(); }<br>
- void getTriangle(int i, double *x0, double *y0, double *color0,<br>
- double *x1, double *y1, double *color1,<br>
- double *x2, double *y2, double *color2) override<br>
+ void getParametrizedTriangle(int i, double *x0, double *y0, double *color0,<br>
+ double *x1, double *y1, double *color1,<br>
+ double *x2, double *y2, double *color2) override<br>
{ shading->getTriangle(i, x0, y0, color0, x1, y1, color1, x2, y2, color2); }<br>
<br>
+ void getNonParametrizedTriangle(int i, SplashColorMode mode,<br>
+ double *x0, double *y0, SplashColorPtr color0,<br>
+ double *x1, double *y1, SplashColorPtr color1,<br>
+ double *x2, double *y2, SplashColorPtr color2) override;<br>
+<br>
void getParameterizedColor(double colorinterp, SplashColorMode mode, SplashColorPtr dest) override;<br>
<br>
private:<br>
diff --git a/splash/Splash.cc b/splash/Splash.cc<br>
index 3d4e6177..70584ec4 100644<br>
--- a/splash/Splash.cc<br>
+++ b/splash/Splash.cc<br>
@@ -2385,7 +2385,7 @@ SplashError Splash::fillWithPattern(SplashPath *path, bool eo,<br>
SplashPipe pipe = {};<br>
int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;<br>
SplashClipResult clipRes, clipRes2;<br>
- bool adjustLine = false; <br>
+ bool adjustLine = false;<br>
int linePosI = 0;<br>
<br>
if (path->length == 0) {<br>
@@ -5381,62 +5381,23 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
int x[3] = {0, 0, 0};<br>
int y[3] = {0, 0, 0};<br>
double xt=0., xa=0., yt=0.;<br>
- double ca=0., ct=0.;<br>
-<br>
- // triangle interpolation:<br>
- //<br>
- double scanLimitMapL[2] = {0., 0.};<br>
- double scanLimitMapR[2] = {0., 0.};<br>
- double scanColorMapL[2] = {0., 0.};<br>
- double scanColorMapR[2] = {0., 0.};<br>
- double scanColorMap[2] = {0., 0.};<br>
- int scanEdgeL[2] = { 0, 0 };<br>
- int scanEdgeR[2] = { 0, 0 };<br>
- bool hasFurtherSegment = false;<br>
-<br>
- int scanLineOff = 0;<br>
- int bitmapOff = 0;<br>
- int scanLimitR = 0, scanLimitL = 0;<br>
-<br>
- int bitmapWidth = bitmap->getWidth();<br>
+<br>
+ const int bitmapWidth = bitmap->getWidth();<br>
SplashClip* clip = getClip();<br>
SplashBitmap *blitTarget = bitmap;<br>
SplashColorPtr bitmapData = bitmap->getDataPtr();<br>
- int bitmapOffLimit = bitmap->getHeight() * bitmap->getRowSize();<br>
+ const int bitmapOffLimit = bitmap->getHeight() * bitmap->getRowSize();<br>
SplashColorPtr bitmapAlpha = bitmap->getAlphaPtr();<br>
- SplashColorPtr cur = nullptr;<br>
SplashCoord* userToCanvasMatrix = getMatrix();<br>
- SplashColorMode bitmapMode = bitmap->getMode();<br>
+ const SplashColorMode bitmapMode = bitmap->getMode();<br>
bool hasAlpha = (bitmapAlpha != nullptr);<br>
- int rowSize = bitmap->getRowSize();<br>
- int colorComps = 0;<br>
- switch (bitmapMode) {<br>
- case splashModeMono1:<br>
- break;<br>
- case splashModeMono8:<br>
- colorComps=1;<br>
- break;<br>
- case splashModeRGB8:<br>
- colorComps=3;<br>
- break;<br>
- case splashModeBGR8:<br>
- colorComps=3;<br>
- break;<br>
- case splashModeXBGR8:<br>
- colorComps=4;<br>
- break;<br>
- case splashModeCMYK8:<br>
- colorComps=4;<br>
- break;<br>
- case splashModeDeviceN8:<br>
- colorComps=SPOT_NCOMPS+4;<br>
- break;<br>
- }<br>
+ const int rowSize = bitmap->getRowSize();<br>
+ const int colorComps = splashColorModeNComps[bitmapMode];<br>
<br>
SplashPipe pipe;<br>
SplashColor cSrcVal;<br>
<br>
- pipeInit(&pipe, 0, 0, nullptr, cSrcVal, (unsigned char)splashRound(state->strokeAlpha * 255), false, false);<br>
+ pipeInit(&pipe, 0, 0, nullptr, cSrcVal, (unsigned char)splashRound(state->fillAlpha * 255), false, false);<br>
<br>
if (vectorAntialias) {<br>
if (aaBuf == nullptr)<br>
@@ -5457,7 +5418,7 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
// - the final step, is performed using a SplashPipe:<br>
// - assign the actual color into cSrcVal: pipe uses cSrcVal by reference<br>
// - invoke drawPixel(&pipe,X,Y,bNoClip);<br>
- bool bDirectBlit = vectorAntialias ? false : pipe.noTransparency && !state->blendFunc;<br>
+ const bool bDirectBlit = vectorAntialias ? false : pipe.noTransparency && !state->blendFunc && !shading->isParameterized();<br>
if (!bDirectBlit) {<br>
blitTarget = new SplashBitmap(bitmap->getWidth(),<br>
bitmap->getHeight(),<br>
@@ -5469,7 +5430,7 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
bitmapAlpha = blitTarget->getAlphaPtr();<br>
<br>
// initialisation seems to be necessary:<br>
- int S = bitmap->getWidth() * bitmap->getHeight();<br>
+ const int S = bitmap->getWidth() * bitmap->getHeight();<br>
for (int i = 0; i < S; ++i)<br>
bitmapAlpha[i] = 0;<br>
hasAlpha = true;<br>
@@ -5477,10 +5438,15 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
<br>
if (shading->isParameterized()) {<br>
double color[3];<br>
- double colorinterp;<br>
+ double scanLimitMapL[2] = {0., 0.};<br>
+ double scanLimitMapR[2] = {0., 0.};<br>
+ double scanColorMapL[2] = {0., 0.};<br>
+ double scanColorMapR[2] = {0., 0.};<br>
+ int scanEdgeL[2] = { 0, 0 };<br>
+ int scanEdgeR[2] = { 0, 0 };<br>
<br>
for (int i = 0; i < shading->getNTriangles(); ++i) {<br>
- shading->getTriangle(i,<br>
+ shading->getParametrizedTriangle(i,<br>
xdbl + 0, ydbl + 0, color + 0,<br>
xdbl + 1, ydbl + 1, color + 1,<br>
xdbl + 2, ydbl + 2, color + 2);<br>
@@ -5504,9 +5470,9 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
// first two are sorted.<br>
assert(y[0] <= y[1]);<br>
if (y[1] > y[2]) {<br>
- int tmpX = x[2];<br>
- int tmpY = y[2];<br>
- double tmpC = color[2];<br>
+ const int tmpX = x[2];<br>
+ const int tmpY = y[2];<br>
+ const double tmpC = color[2];<br>
x[2] = x[1]; y[2] = y[1]; color[2] = color[1];<br>
<br>
if (y[0] > tmpY) {<br>
@@ -5578,8 +5544,8 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
scanColorMapR[0] = (color[scanEdgeR[1]] - color[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);<br>
scanColorMapR[1] = color[scanEdgeR[0]] - y[scanEdgeR[0]] * scanColorMapR[0];<br>
<br>
- hasFurtherSegment = (y[1] < y[2]);<br>
- scanLineOff = y[0] * rowSize;<br>
+ bool hasFurtherSegment = (y[1] < y[2]);<br>
+ int scanLineOff = y[0] * rowSize;<br>
<br>
for (int Y = y[0]; Y <= y[2]; ++Y, scanLineOff += rowSize) {<br>
if (hasFurtherSegment && Y == y[1]) {<br>
@@ -5614,34 +5580,34 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
xa = yt * scanLimitMapL[0] + scanLimitMapL[1];<br>
xt = yt * scanLimitMapR[0] + scanLimitMapR[1];<br>
<br>
- ca = yt * scanColorMapL[0] + scanColorMapL[1];<br>
- ct = yt * scanColorMapR[0] + scanColorMapR[1];<br>
+ const double ca = yt * scanColorMapL[0] + scanColorMapL[1];<br>
+ const double ct = yt * scanColorMapR[0] + scanColorMapR[1];<br>
<br>
- scanLimitL = splashRound(xa);<br>
- scanLimitR = splashRound(xt);<br>
+ const int scanLimitL = splashRound(xa);<br>
+ const int scanLimitR = splashRound(xt);<br>
<br>
// Ok. Now: init the color interpolation depending on the X<br>
// coordinate inside of the current scanline:<br>
- scanColorMap[0] = (scanLimitR == scanLimitL) ? 0. : ((ct - ca) / (scanLimitR - scanLimitL));<br>
- scanColorMap[1] = ca - scanLimitL * scanColorMap[0];<br>
+ const double scanColorMap0 = (scanLimitR == scanLimitL) ? 0. : ((ct - ca) / (scanLimitR - scanLimitL));<br>
+ const double scanColorMap1 = ca - scanLimitL * scanColorMap0;<br>
<br>
// handled by clipping:<br>
// assert( scanLimitL >= 0 && scanLimitR < bitmap->getWidth() );<br>
assert(scanLimitL <= scanLimitR || abs(scanLimitL - scanLimitR) <= 2); // allow rounding inaccuracies<br>
assert(scanLineOff == Y * rowSize);<br>
<br>
- colorinterp = scanColorMap[0] * scanLimitL + scanColorMap[1];<br>
+ double colorinterp = scanColorMap0 * scanLimitL + scanColorMap1;<br>
<br>
- bitmapOff = scanLineOff + scanLimitL * colorComps;<br>
+ int bitmapOff = scanLineOff + scanLimitL * colorComps;<br>
if (likely(bitmapOff >= 0)) {<br>
- for (int X = scanLimitL; X <= scanLimitR && bitmapOff + colorComps <= bitmapOffLimit; ++X, colorinterp += scanColorMap[0], bitmapOff += colorComps) {<br>
+ for (int X = scanLimitL; X <= scanLimitR && bitmapOff + colorComps <= bitmapOffLimit; ++X, colorinterp += scanColorMap0, bitmapOff += colorComps) {<br>
// FIXME : standard rectangular clipping can be done for a<br>
// complete scanline which is faster<br>
// --> see SplashClip and its methods<br>
if (!clip->test(X, Y))<br>
continue;<br>
<br>
- assert(fabs(colorinterp - (scanColorMap[0] * X + scanColorMap[1])) < 1e-10);<br>
+ assert(fabs(colorinterp - (scanColorMap0 * X + scanColorMap1)) < 1e-10);<br>
assert(bitmapOff == Y * rowSize + colorComps * X && scanLineOff == Y * rowSize);<br>
<br>
shading->getParameterizedColor(colorinterp, bitmapMode, &bitmapData[bitmapOff]);<br>
@@ -5656,24 +5622,183 @@ bool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)<br>
}<br>
}<br>
} else {<br>
- if (!bDirectBlit) {<br>
- delete blitTarget;<br>
+ SplashColor color, auxColor1, auxColor2;<br>
+ double scanLimitMapL[2] = {0., 0.};<br>
+ double scanLimitMapR[2] = {0., 0.};<br>
+ int scanEdgeL[2] = { 0, 0 };<br>
+ int scanEdgeR[2] = { 0, 0 };<br>
+<br>
+ for (int i = 0; i < shading->getNTriangles(); ++i) {<br>
+ // Sadly this current algorithm only supports shadings where the three triangle vertices have the same color<br>
+ shading->getNonParametrizedTriangle(i, bitmapMode,<br>
+ xdbl + 0, ydbl + 0, (SplashColorPtr)&color,<br>
+ xdbl + 1, ydbl + 1, (SplashColorPtr)&auxColor1,<br>
+ xdbl + 2, ydbl + 2, (SplashColorPtr)&auxColor2);<br>
+ if (!splashColorEqual(color, auxColor1) ||<br>
+ !splashColorEqual(color, auxColor2))<br>
+ {<br>
+ delete blitTarget;<br>
+ return false;<br>
+ }<br>
+ for (int m = 0; m < 3; ++m) {<br>
+ xt = xdbl[m] * (double)userToCanvasMatrix[0] + ydbl[m] * (double)userToCanvasMatrix[2] + (double)userToCanvasMatrix[4];<br>
+ yt = xdbl[m] * (double)userToCanvasMatrix[1] + ydbl[m] * (double)userToCanvasMatrix[3] + (double)userToCanvasMatrix[5];<br>
+ xdbl[m] = xt;<br>
+ ydbl[m] = yt;<br>
+ // we operate on scanlines which are integer offsets into the<br>
+ // raster image. The double offsets are of no use here.<br>
+ x[m] = splashRound(xt);<br>
+ y[m] = splashRound(yt);<br>
+ }<br>
+ // sort according to y coordinate to simplify sweep through scanlines:<br>
+ // INSERTION SORT.<br>
+ if (y[0] > y[1]) {<br>
+ Guswap(x[0], x[1]);<br>
+ Guswap(y[0], y[1]);<br>
+ }<br>
+ // first two are sorted.<br>
+ assert(y[0] <= y[1]);<br>
+ if (y[1] > y[2]) {<br>
+ const int tmpX = x[2];<br>
+ const int tmpY = y[2];<br>
+ x[2] = x[1]; y[2] = y[1];<br>
+<br>
+ if (y[0] > tmpY) {<br>
+ x[1] = x[0]; y[1] = y[0];<br>
+ x[0] = tmpX; y[0] = tmpY;<br>
+ } else {<br>
+ x[1] = tmpX; y[1] = tmpY;<br>
+ }<br>
+ }<br>
+ // first three are sorted<br>
+ assert(y[0] <= y[1]);<br>
+ assert(y[1] <= y[2]);<br>
+ /////<br>
+<br>
+ // this here is det( T ) == 0<br>
+ // where T is the matrix to map to barycentric coordinates.<br>
+ if ((x[0] - x[2]) * (y[1] - y[2]) - (x[1] - x[2]) * (y[0] - y[2]) == 0)<br>
+ continue; // degenerate triangle.<br>
+<br>
+ // this here initialises the scanline generation.<br>
+ // We start with low Y coordinates and sweep up to the large Y<br>
+ // coordinates.<br>
+ //<br>
+ // scanEdgeL[m] in {0,1,2} m=0,1<br>
+ // scanEdgeR[m] in {0,1,2} m=0,1<br>
+ //<br>
+ // are the two edges between which scanlines are (currently)<br>
+ // sweeped. The values {0,1,2} are indices into 'x' and 'y'.<br>
+ // scanEdgeL[0] = 0 means: the left scan edge has (x[0],y[0]) as vertex.<br>
+ //<br>
+ scanEdgeL[0] = 0;<br>
+ scanEdgeR[0] = 0;<br>
+ if (y[0] == y[1]) {<br>
+ scanEdgeL[0] = 1;<br>
+ scanEdgeL[1] = scanEdgeR[1] = 2;<br>
+<br>
+ } else {<br>
+ scanEdgeL[1] = 1; scanEdgeR[1] = 2;<br>
+ }<br>
+ assert(y[scanEdgeL[0]] < y[scanEdgeL[1]]);<br>
+ assert(y[scanEdgeR[0]] < y[scanEdgeR[1]]);<br>
+<br>
+ // Ok. Now prepare the linear maps which map the y coordinate of<br>
+ // the current scanline to the corresponding LEFT and RIGHT x<br>
+ // coordinate (which define the scanline).<br>
+ scanLimitMapL[0] = double(x[scanEdgeL[1]] - x[scanEdgeL[0]]) / (y[scanEdgeL[1]] - y[scanEdgeL[0]]);<br>
+ scanLimitMapL[1] = x[scanEdgeL[0]] - y[scanEdgeL[0]] * scanLimitMapL[0];<br>
+ scanLimitMapR[0] = double(x[scanEdgeR[1]] - x[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);<br>
+ scanLimitMapR[1] = x[scanEdgeR[0]] - y[scanEdgeR[0]] * scanLimitMapR[0];<br>
+<br>
+ xa = y[1] * scanLimitMapL[0] + scanLimitMapL[1];<br>
+ xt = y[1] * scanLimitMapR[0] + scanLimitMapR[1];<br>
+ if (xa > xt) {<br>
+ // I have "left" is to the right of "right".<br>
+ // Exchange sides!<br>
+ Guswap(scanEdgeL[0], scanEdgeR[0]);<br>
+ Guswap(scanEdgeL[1], scanEdgeR[1]);<br>
+ Guswap(scanLimitMapL[0], scanLimitMapR[0]);<br>
+ Guswap(scanLimitMapL[1], scanLimitMapR[1]);<br>
+ // FIXME I'm sure there is a more efficient way to check this.<br>
+ }<br>
+<br>
+ bool hasFurtherSegment = (y[1] < y[2]);<br>
+ int scanLineOff = y[0] * rowSize;<br>
+<br>
+ for (int Y = y[0]; Y <= y[2]; ++Y, scanLineOff += rowSize) {<br>
+ if (hasFurtherSegment && Y == y[1]) {<br>
+ // SWEEP EVENT: we encountered the next segment.<br>
+ //<br>
+ // switch to next segment, either at left end or at right<br>
+ // end:<br>
+ if (scanEdgeL[1] == 1) {<br>
+ scanEdgeL[0] = 1;<br>
+ scanEdgeL[1] = 2;<br>
+ scanLimitMapL[0] = double(x[scanEdgeL[1]] - x[scanEdgeL[0]]) / (y[scanEdgeL[1]] - y[scanEdgeL[0]]);<br>
+ scanLimitMapL[1] = x[scanEdgeL[0]] - y[scanEdgeL[0]] * scanLimitMapL[0];<br>
+ } else if (scanEdgeR[1] == 1) {<br>
+ scanEdgeR[0] = 1;<br>
+ scanEdgeR[1] = 2;<br>
+ scanLimitMapR[0] = double(x[scanEdgeR[1]] - x[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);<br>
+ scanLimitMapR[1] = x[scanEdgeR[0]] - y[scanEdgeR[0]] * scanLimitMapR[0];<br>
+ }<br>
+ assert( y[scanEdgeL[0]] < y[scanEdgeL[1]] );<br>
+ assert( y[scanEdgeR[0]] < y[scanEdgeR[1]] );<br>
+ hasFurtherSegment = false;<br>
+ }<br>
+<br>
+ yt = Y;<br>
+<br>
+ xa = yt * scanLimitMapL[0] + scanLimitMapL[1];<br>
+ xt = yt * scanLimitMapR[0] + scanLimitMapR[1];<br>
+<br>
+ const int scanLimitL = splashRound(xa);<br>
+ const int scanLimitR = splashRound(xt);<br>
+<br>
+ // handled by clipping:<br>
+ // assert( scanLimitL >= 0 && scanLimitR < bitmap->getWidth() );<br>
+ assert(scanLimitL <= scanLimitR || abs(scanLimitL - scanLimitR) <= 2); // allow rounding inaccuracies<br>
+ assert(scanLineOff == Y * rowSize);<br>
+<br>
+ int bitmapOff = scanLineOff + scanLimitL * colorComps;<br>
+ if (likely(bitmapOff >= 0)) {<br>
+ for (int X = scanLimitL; X <= scanLimitR && bitmapOff + colorComps <= bitmapOffLimit; ++X, bitmapOff += colorComps) {<br>
+ // FIXME : standard rectangular clipping can be done for a<br>
+ // complete scanline which is faster<br>
+ // --> see SplashClip and its methods<br>
+ if (!clip->test(X, Y))<br>
+ continue;<br>
+<br>
+ assert(bitmapOff == Y * rowSize + colorComps * X && scanLineOff == Y * rowSize);<br>
+<br>
+ for (int k = 0; k < colorComps; ++k) {<br>
+ bitmapData[bitmapOff + k] = color[k];<br>
+ }<br>
+<br>
+ // make the shading visible.<br>
+ // Note that opacity is handled by the bDirectBlit stuff, see<br>
+ // above for comments and below for implementation.<br>
+ if (hasAlpha)<br>
+ bitmapAlpha[Y * bitmapWidth + X] = 255;<br>
+ }<br>
+ }<br>
+ }<br>
}<br>
- return false;<br>
}<br>
<br>
if (!bDirectBlit) {<br>
// ok. Finalize the stuff by blitting the shading into the final<br>
// geometry, this time respecting the rendering pipe.<br>
- int W = blitTarget->getWidth();<br>
- int H = blitTarget->getHeight();<br>
- cur = cSrcVal;<br>
+ const int W = blitTarget->getWidth();<br>
+ const int H = blitTarget->getHeight();<br>
+ SplashColorPtr cur = cSrcVal;<br>
<br>
for (int X = 0; X < W; ++X) {<br>
for (int Y = 0; Y < H; ++Y) {<br>
if (!bitmapAlpha[Y * bitmapWidth + X])<br>
continue; // draw only parts of the shading!<br>
- bitmapOff = Y * rowSize + colorComps * X;<br>
+ const int bitmapOff = Y * rowSize + colorComps * X;<br>
<br>
for (int m = 0; m < colorComps; ++m)<br>
cur[m] = bitmapData[bitmapOff + m];<br>
diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h<br>
index ce7eb446..1545c097 100644<br>
--- a/splash/SplashPattern.h<br>
+++ b/splash/SplashPattern.h<br>
@@ -94,10 +94,15 @@ public:<br>
<br>
virtual int getNTriangles() = 0;<br>
<br>
- virtual void getTriangle(int i, double *x0, double *y0, double *color0,<br>
+ virtual void getParametrizedTriangle(int i, double *x0, double *y0, double *color0,<br>
double *x1, double *y1, double *color1,<br>
double *x2, double *y2, double *color2) = 0;<br>
<br>
+ virtual void getNonParametrizedTriangle(int i, SplashColorMode mode,<br>
+ double *x0, double *y0, SplashColorPtr color0,<br>
+ double *x1, double *y1, SplashColorPtr color1,<br>
+ double *x2, double *y2, SplashColorPtr color2) = 0;<br>
+<br>
virtual void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c) = 0;<br>
};<br>
<br>
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h<br>
index 7500f588..c036a56e 100644<br>
--- a/splash/SplashTypes.h<br>
+++ b/splash/SplashTypes.h<br>
@@ -128,6 +128,13 @@ static inline void splashColorCopy(SplashColorPtr dest, SplashColorConstPtr src)<br>
dest[i] = src[i];<br>
}<br>
<br>
+static inline bool splashColorEqual(SplashColorConstPtr dest, SplashColorConstPtr src) {<br>
+ for (int i = 0; i < SPOT_NCOMPS + 4; i++)<br>
+ if (dest[i] != src[i])<br>
+ return false;<br>
+ return true;<br>
+}<br>
+<br>
static inline void splashColorXor(SplashColorPtr dest, SplashColorConstPtr src) {<br>
dest[0] ^= src[0];<br>
dest[1] ^= src[1];<br>
_______________________________________________<br>
poppler mailing list<br>
poppler@lists.freedesktop.org<br>
<a href="https://lists.freedesktop.org/mailman/listinfo/poppler">https://lists.freedesktop.org/mailman/listinfo/poppler</a><br>
</div>
</span></font></div>
</div>
</body>
</html>