Am 29.12.2010 18:53, schrieb Andrea Canciani:
On Wed, Dec 29, 2010 at 4:48 PM, Thomas Freitag
<[email protected]> wrote:
...
I made a mistake when solving the problem with altona_visual_1v2a_x3.pdf. I
find now a better way to solve it, which also gives a better look of the
printer paper back again.
I'd like to point yo to another pdf whose rendering regresses with the patch:
https://bugs.freedesktop.org/attachment.cgi?id=41506
Albert, can You please just change two lines in the former patch?
1. In SplashOutputDev.cc in the constructor of SplashRadialPattern, replace
+ bitmap = new SplashBitmap(splashRound(width) + 1, splashRound(height)
+ 1, colorMode != splashModeMono1, colorMode, gTrue);
through
+ bitmap = new SplashBitmap(splashRound(width) + 2,
splashRound(height) + 2, colorMode != splashModeMono1, colorMode, gTrue);
2. In Splash.cc in the painting routine radialShadedFill, where the
smaller extend circle is painted, replace
+ drawPartEllipseLine(&pipe, 2* yo - curY, xMin, xMax);
through
+ drawPartEllipseLine(&pipe, curY, xMin, xMax);
(curY is alfready recalculated two line before!)
Or just reapply the attached patch.
This solves the rendering regressions mailed by Andrea.
Thomas
In the last row, half of the inner circle is transparent with
poppler/master+radialsh.patch.
Andrea
PS: Sorry for removing most of the thread from this message, but gmail squashed
it to just one level.
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler
.
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 0b3722a..91c5c36 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -153,6 +153,270 @@ void SplashGouraudPattern::getParameterizedColor(double
colorinterp, SplashColor
}
//------------------------------------------------------------------------
+// SplashRadialPattern
+//------------------------------------------------------------------------
+// Max number of splits along the t axis for a radial shading fill.
+#define radialMaxSplits 256
+
+// Max delta allowed in any color component for a radial shading fill.
+#define radialColorDelta (dblToCol(1.0 / 256.0))
+
+// Max size of pattern bitmap of min (width, height)
+#define radialMaxSize 256
+
+SplashRadialPattern::SplashRadialPattern(GfxState *stateA, GfxRadialShading
*shadingA,
+
double sMinA, double sMaxA, SplashColorMode colorModeA) {
+ double width, height;
+ Matrix ctm;
+
+ state = stateA;
+ shading = shadingA;
+ sMin = sMinA;
+ sMax = sMaxA;
+ colorMode = colorModeA;
+ state->getCTM(&ctm);
+ ctm.invertTo(&ictm);
+ ia = 0;
+ splash = NULL;
+ bitmap = NULL;
+ // get the shading info
+ shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+ t0 = shading->getDomain0();
+ t1 = shading->getDomain1();
+ if (shading->getHasBBox())
+ shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+ else
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ width = xMax - xMin;
+ height = yMax - yMin;
+ /*
+ xMin = splashRound(xMin);
+ xMax = splashRound(xMax);
+ yMin = splashRound(yMin);
+ yMax = splashRound(yMax);
+ */
+ if (splashRound(xMax) - splashRound(xMin) > width)
+ width = splashRound(xMax) - splashRound(xMin);
+ if (splashRound(yMax) - splashRound(yMin) > height)
+ height = splashRound(yMax) - splashRound(yMin);
+ if (radialMaxSize > 0 && width > 0 && height > 0) {
+ if ( width > height)
+ scale = radialMaxSize / height;
+ else
+ scale = radialMaxSize / width;
+ } else
+ scale = 1;
+ xMin *= scale;
+ xMax *= scale;
+ yMin *= scale;
+ yMax *= scale;
+ width *= scale;
+ height *= scale;
+ if (width > 0 && height > 0) {
+ bitmap = new SplashBitmap(splashRound(width) + 2, splashRound(height)
+ 2, colorMode != splashModeMono1, colorMode, gTrue);
+ splash = new Splash(bitmap, gFalse /* AntiAlias in shading Dict! */);
+
+ // show only what is painted, delete alpha channel
+ Guchar *bitmapAlpha = bitmap->getAlphaPtr();
+ int size = bitmap->getWidth() * bitmap->getHeight();
+ for (int i = 0; i < size; ++i)
+ bitmapAlpha[i] = 0;
+ }
+
+ // change transfer matrix to fit to scaled bitmap
+ ictm.m[0] *= scale;
+ ictm.m[1] *= scale;
+ ictm.m[2] *= scale;
+ ictm.m[3] *= scale;
+ ictm.m[4] *= scale;
+ ictm.m[5] *= scale;
+ ictm.m[4] -= xMin;
+ ictm.m[5] -= yMin;
+}
+
+SplashRadialPattern::~SplashRadialPattern() {
+ if (splash) {
+ delete splash;
+ }
+ if (bitmap) {
+ delete bitmap;
+ }
+}
+
+GBool SplashRadialPattern::getColor(int x, int y, SplashColorPtr c) {
+ double xc, yc;
+ int xs, ys;
+ Guchar *bitmapAlpha;
+
+ bitmapAlpha = bitmap->getAlphaPtr();
+ ictm.transform(x, y, &xc, &yc);
+ xs = splashRound(xc) + 1;
+ ys = splashRound(yc);
+ //if (xs == -1) xs = 0;
+ if (xs < 0 || xs >= bitmap->getWidth())
+ return gFalse;
+ if (ys < 0 || ys >= bitmap->getHeight())
+ return gFalse;
+ if (bitmapAlpha[ys * bitmap->getWidth() + xs])
+ bitmap->getPixel(xs, ys, c);
+ else
+ return gFalse;
+ return gTrue;
+}
+
+static inline void getShadingColorRadialHelper(double t0, double t1, double t,
GfxRadialShading *shading, GfxColor *color)
+{
+ if (t0 < t1) {
+ if (t < t0) {
+ shading->getColor(t0, color);
+ } else if (t > t1) {
+ shading->getColor(t1, color);
+ } else {
+ shading->getColor(t, color);
+ }
+ } else {
+ if (t > t0) {
+ shading->getColor(t0, color);
+ } else if (t < t1) {
+ shading->getColor(t1, color);
+ } else {
+ shading->getColor(t, color);
+ }
+ }
+}
+
+void SplashRadialPattern::getStartCircle(SplashCoord *xsc, SplashCoord *ysc,
+
SplashCoord *radius,
+
SplashColorPtr c) {
+ GfxColor colorA;
+ GfxColorSpace* srcColorSpace = shading->getColorSpace();
+ sa = (r0 > r1) ? sMin : sMax;
+ ta = t0 + sa * (t1 - t0);
+ xa = x0 + sa * (x1 - x0);
+ ya = y0 + sa * (y1 - y0);
+ ra = r0 + sa * (r1 - r0);
+ getShadingColorRadialHelper(t0, t1, ta, shading, &colorA);
+ *radius = splashRound(ra * scale);
+ *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale -
yMin);
+ convertGfxColor(c, colorMode, srcColorSpace, &colorA);
+}
+
+static inline GBool isSameGfxColor(const GfxColor &colorA, const GfxColor
&colorB, Guint nComps, double delta) {
+ for (Guint k = 0; k < nComps; ++k) {
+ if (abs(colorA.c[k] - colorB.c[k]) > delta) {
+ return false;
+ }
+ }
+ return true;
+}
+
+GBool SplashRadialPattern::getNextCircle(SplashCoord *xsc, SplashCoord *ysc,
+
SplashCoord *radius,
+
SplashColorPtr c) {
+ GfxColor colorA, colorB;
+ GfxColorSpace* srcColorSpace = shading->getColorSpace();
+ double sb, tb, factor;
+ int ib, nComps;
+ nComps = shading->getColorSpace()->getNComps();
+ if (ia >= radialMaxSplits)
+ return gFalse;
+ getShadingColorRadialHelper(t0, t1, ta, shading, &colorA);
+ ib = radialMaxSplits;
+ sb = (r0 > r1) ? sMax : sMin;
+ tb = t0 + sb * (t1 - t0);
+ getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+ while (ib - ia > 1) {
+ if (isSameGfxColor(colorB, colorA, nComps, radialColorDelta)) {
+ // The shading is not necessarily lineal so having two points with the
+ // same color does not mean all the areas in between have the same
color too
+ int ic = ia + 1;
+ for (; ic <= ib; ic++) {
+ GfxColor colorC;
+ factor = (r0 > r1) ? (double)ic /
(double)radialMaxSplits : 1 - (double)ic / (double)radialMaxSplits;
+ double sc = sMin + factor * (sMax - sMin);
+ double tc = t0 + sc * (t1 - t0);
+ getShadingColorRadialHelper(t0, t1, tc, shading,
&colorC);
+ if (!isSameGfxColor(colorC, colorA, nComps,
radialColorDelta)) {
+ break;
+ }
+ }
+ ib = (ic > ia + 1)? ic - 1 : ia + 1;
+ factor = (r0 > r1) ? (double)ib / (double)radialMaxSplits : 1
- (double)ib / (double)radialMaxSplits;
+ sb = sMin + factor * (sMax - sMin);
+ tb = t0 + sb * (t1 - t0);
+ getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+ break;
+ }
+ ib = (ia + ib) / 2;
+ factor = (r0 > r1) ? (double)ib / (double)radialMaxSplits : 1 -
(double)ib / (double)radialMaxSplits;
+ sb = sMin + factor * (sMax - sMin);
+ tb = t0 + sb * (t1 - t0);
+ getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+ }
+ // compute center and radius of the circle
+ xa = x0 + sb * (x1 - x0);
+ ya = y0 + sb * (y1 - y0);
+ ra = r0 + sb * (r1 - r0);
+ *radius = splashRound(ra * scale);
+ *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale -
yMin);
+ convertGfxColor(c, colorMode, srcColorSpace, &colorB);
+ ia = ib;
+ ta = tb;
+ return gTrue;
+}
+
+GBool SplashRadialPattern::getLargerExtendCircle(SplashCoord *xsc, SplashCoord
*ysc,
+
SplashCoord *radius, SplashColorPtr c) {
+ GfxColor colorA;
+ GfxColorSpace* srcColorSpace = shading->getColorSpace();
+ if ((shading->getExtend0() && r0 > r1) ||
+ (shading->getExtend1() && r1 >= r0)) {
+ if (r0 > r1) {
+ ta = t0;
+ ra = r0;
+ xa = x0;
+ ya = y0;
+ } else {
+ ta = t1;
+ ra = r1;
+ xa = x1;
+ ya = y1;
+ }
+ shading->getColor(ta, &colorA);
+ *radius = splashRound(ra * scale);
+ *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya
* scale - yMin);
+ convertGfxColor(c, colorMode, srcColorSpace, &colorA);
+ return gTrue;
+ }
+ return gFalse;
+}
+
+GBool SplashRadialPattern::getSmallerExtendCircle(SplashCoord *xsc,
SplashCoord *ysc,
+
SplashCoord *radius, SplashColorPtr c) {
+ GfxColor colorA;
+ GfxColorSpace* srcColorSpace = shading->getColorSpace();
+ if ((shading->getExtend0() && r0 <= r1) ||
+ (shading->getExtend1() && r1 < r0)) {
+ if (r0 <= r1) {
+ ta = t0;
+ ra = r0;
+ xa = x0;
+ ya = y0;
+ } else {
+ ta = t1;
+ ra = r1;
+ xa = x1;
+ ya = y1;
+ }
+ shading->getColor(ta, &colorA);
+ *radius = splashRound(ra * scale);
+ *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya
* scale - yMin);
+ convertGfxColor(c, colorMode, srcColorSpace, &colorA);
+ return gTrue;
+ }
+ return gFalse;
+}
+//------------------------------------------------------------------------
// SplashAxialPattern
//------------------------------------------------------------------------
@@ -3011,14 +3275,14 @@ void SplashOutputDev::beginTransparencyGroup(GfxState
*state, double *bbox,
tx = (int)floor(xMin);
if (tx < 0) {
tx = 0;
- } else if (tx > bitmap->getWidth()) {
- tx = bitmap->getWidth();
+ } else if (tx > bitmap->getWidth() - 1) {
+ tx = bitmap->getWidth() - 1;
}
ty = (int)floor(yMin);
if (ty < 0) {
ty = 0;
- } else if (ty > bitmap->getHeight()) {
- ty = bitmap->getHeight();
+ } else if (ty > bitmap->getHeight() - 1) {
+ ty = bitmap->getHeight() - 1;
}
w = (int)ceil(xMax) - tx + 1;
if (tx + w > bitmap->getWidth()) {
@@ -3379,3 +3643,35 @@ GBool SplashOutputDev::axialShadedFill(GfxState *state,
GfxAxialShading *shading
return retVal;
}
+
+GBool SplashOutputDev::radialShadedFill(GfxState *state, GfxRadialShading
*shading, double sMin, double sMax) {
+ double xMin, yMin, xMax, yMax;
+ SplashPath *path;
+
+ GBool retVal = gFalse;
+ // get the clip region bbox
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+
+ // fill the region
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
+ state->closePath();
+ path = convertPath(state, state->getPath());
+
+ SplashRadialColor *pattern = new SplashRadialPattern(state, shading, sMin,
sMax, colorMode);
+ if (pattern->isOk()) {
+ // first draw the radial shading in its own bitmap
+ retVal = (pattern->getSplash()->radialShadedFill(pattern) ==
splashOk);
+ // now use this bitmap as dynamic pattern:
+ if (retVal) {
+ retVal = (splash->shadedFill(path, shading->getHasBBox(),
pattern) == splashOk);
+ }
+ }
+ state->clearPath();
+ delete pattern;
+ delete path;
+
+ return retVal;
+}
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index 570d036..1e243c2 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -105,6 +105,45 @@ private:
GBool bDirectColorTranslation;
};
+// see GfxState.h, GfxRadialShading
+class SplashRadialPattern: public SplashRadialColor {
+public:
+
+ SplashRadialPattern(GfxState *state, GfxRadialShading *shading, double sMin,
double sMax, SplashColorMode colorMode);
+
+ GBool isOk() { return (bitmap != NULL); }
+
+ Splash *getSplash() { return splash; }
+
+ SplashBitmap *getBitmap() { return bitmap; }
+
+ virtual SplashPattern *copy() { return new SplashRadialPattern(state,
shading, sMin, sMax, colorMode); }
+
+ virtual ~SplashRadialPattern();
+
+ virtual GBool getColor(int x, int y, SplashColorPtr c);
+
+ virtual GBool isStatic() { return gFalse; }
+
+ virtual void getStartCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord
*radius, SplashColorPtr c);
+ virtual GBool getNextCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord
*radius, SplashColorPtr c);
+ virtual GBool getLargerExtendCircle(SplashCoord *x0, SplashCoord *y0,
SplashCoord *radius, SplashColorPtr c);
+ virtual GBool getSmallerExtendCircle(SplashCoord *x0, SplashCoord *y0,
SplashCoord *radius, SplashColorPtr c);
+private:
+ GfxRadialShading *shading;
+ GfxState *state;
+ Matrix ictm;
+ double sMin, sMax;
+ double xMin, xMax, yMin, yMax;
+ double scale;
+ double xa, ya, ra, ta, sa;
+ int ia;
+ double x0, y0, r0, x1, y1, r1, t0, t1;
+ Splash *splash;
+ SplashBitmap *bitmap;
+ SplashColorMode colorMode;
+};
+
//------------------------------------------------------------------------
// number of Type 3 fonts to cache
@@ -132,7 +171,7 @@ public:
// radialShadedFill()? If this returns false, these shaded fills
// will be reduced to a series of other drawing operations.
virtual GBool useShadedFills(int type)
- { return (type == 2 || type == 4 || type == 5 ) ? gTrue : gFalse; }
+ { return (type >= 2 && type <= 5) ? gTrue : gFalse; }
// Does this device use upside-down coordinates?
// (Upside-down means (0,0) is the top left corner of the page.)
@@ -186,6 +225,7 @@ public:
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading,
double tMin, double tMax);
+ virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading,
double sMin, double sMax);
virtual GBool gouraudTriangleShadedFill(GfxState *state,
GfxGouraudTriangleShading *shading);
//----- path clipping
diff --git a/splash/Splash.cc b/splash/Splash.cc
index bc317a6..a80139a 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -3531,6 +3531,257 @@ GBool
Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)
return gTrue;
}
+SplashPath *Splash::getBresenhamPoints(SplashCoord xc, SplashCoord yc,
SplashCoord rc) {
+ int radius = splashRound(rc);
+ int x0 = splashRound(xc);
+ int y0 = splashRound(yc);
+ int f = 1 - radius;
+ int ddF_x = 1;
+ int ddF_y = -2 * radius;
+ int x = 0, lastX = x;
+ int y = radius, lastY = y;
+ Guchar dummy;
+ SplashPath *splashPath = new SplashPath();
+
+ if (radius == 0) {
+ splashPath->moveTo(lastX, lastY);
+ return splashPath;
+ }
+
+ while(x < y)
+ {
+ // ddF_x == 2 * x + 1;
+ // ddF_y == -2 * y;
+ // f == x*x + y*y - radius*radius + 2*x - y + 1;
+ if(f >= 0)
+ {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+ if (lastY != y) {
+ if (splashPath->getLength())
+ splashPath->lineTo(lastX, lastY);
+ else
+ splashPath->moveTo(lastX, lastY);
+ lastY = y;
+ }
+ lastX = x;
+ }
+ for (int i = splashPath->getLength() -1; i >= 0; i--) {
+ SplashCoord curX, curY;
+ splashPath->getPoint(i, &curY, &curX, &dummy);
+ for (SplashCoord j = lastY; j >= curY; j--)
+ splashPath->lineTo(curX, j);
+ lastY = splashRound(curY - 1);
+ }
+ while (lastY >= 0)
+ splashPath->lineTo(rc, lastY--);
+ return splashPath;
+}
+
+static inline void getBEllipseLine(SplashPath *bresPoints, SplashCoord y,
SplashCoord y0, SplashCoord r, SplashCoord *x) {
+ GBool found = gFalse;
+ if (y == y0)
+ *x = r;
+ else if (y > y0) {
+ SplashCoord curX, curY;
+ Guchar dummy;
+ for (int i = 0; i < bresPoints->getLength(); i++) {
+ bresPoints->getPoint(i, &curX, &curY, &dummy);
+ if (curY + y0 == y) {
+ *x = curX;
+ return;
+ }
+ }
+ } else {
+ SplashCoord curX, curY;
+ Guchar dummy;
+ for (int i = bresPoints->getLength() - 1; i >= 0; i--) {
+ bresPoints->getPoint(i, &curX, &curY, &dummy);
+ if (y0 - curY == y) {
+ *x = curX;
+ return;
+ }
+ }
+ }
+}
+
+void Splash::drawPartEllipseLine(SplashPipe *pipe,
+ SplashCoord
y,
+ SplashCoord
xMin, SplashCoord xMax) {
+ int yI, xmaxI, xminI;
+ int height = bitmap->getHeight();
+ int width = bitmap->getWidth();
+ Guchar *bitmapAlpha = bitmap->getAlphaPtr();
+ yI = splashRound(y);
+ xmaxI = splashRound(xMax);
+ xminI = splashRound(xMin);
+ if (yI >= 0 && yI < height) {
+ if (xminI < 0)
+ xminI = 0;
+ if (xminI < width) {
+ if (xmaxI > width - 1)
+ xmaxI = width - 1;
+ drawSpan(pipe, xminI, xmaxI, yI, gTrue);
+ }
+ }
+}
+
+void Splash::drawBEllipseLine(SplashPipe *pipe, SplashPath *bresInnerPoints,
+ SplashCoord
y, SplashCoord yiMin, SplashCoord yiMax,
+ SplashCoord
yi, SplashCoord xi, SplashCoord iradius,
+ SplashCoord
xMin, SplashCoord xMax) {
+ if (y > yiMax || y < yiMin)
+ drawPartEllipseLine(pipe, y, xMin, xMax);
+ else {
+ SplashCoord xiMin, xiMax;
+ getBEllipseLine(bresInnerPoints, y, yi, iradius, &xiMin);
+ xiMax = xi + xiMin;
+ xiMin = xi - xiMin;
+ if (xiMin >= xMin || xiMax <= xMax) {
+ if (xiMax < xMin || xiMin > xMax)
+ drawPartEllipseLine(pipe, y, xMin - 1, xMax +
1);
+ else if (xiMin < xMin && xiMax < xMax)
+ drawPartEllipseLine(pipe, y, xiMax - 1, xMax +
1);
+ else if (xiMin > xMin && xiMax < xMax) {
+ drawPartEllipseLine(pipe, y, xMin - 1, xiMin +
1);
+ drawPartEllipseLine(pipe, y, xiMax - 1, xMax +
1);
+ } else
+ drawPartEllipseLine(pipe, y, xMin - 1, xiMin +
1);
+ }
+ }
+}
+
+SplashError Splash::radialShadedFill(SplashRadialColor *shading) {
+ SplashPipe pipe;
+ SplashColor cSrcVal, cNextVal;
+ SplashColorPtr cur = cSrcVal, curNext = cNextVal;
+
+ pipeInit(&pipe, 0, 0, NULL, cSrcVal, state->strokeAlpha, gFalse,
gFalse);
+
+ SplashCoord xo, yo, oradius;
+ SplashCoord xi, yi, iradius;
+ shading->getStartCircle(&xo, &yo, &oradius, cur);
+ SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+ if (bresOuterPoints == NULL)
+ return splashErrEmptyPath;
+ pipe.cSrc = cur;
+ while (shading->getNextCircle(&xi, &yi, &iradius, curNext)) {
+ if (xi == xo && yi == yo && iradius == oradius) {
+ splashColorCopy(cur, curNext);
+ continue;
+ }
+ SplashPath *bresInnerPoints = getBresenhamPoints(xi, yi,
iradius);
+ if (bresInnerPoints == NULL)
+ break;
+ SplashCoord yiMax = yi + iradius, yiMin = yi - iradius;
+ Guchar dummy;
+
+ for (int i = 0; i < bresOuterPoints->getLength(); i++) {
+ SplashCoord curX, curY;
+ SplashCoord xMin, xMax;
+ bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+ xMax = xo + curX;
+ xMin = xo - curX;
+ curY += yo;
+ if (curY >= 0 && curY < bitmap->getHeight())
+ drawBEllipseLine(&pipe, bresInnerPoints,
+ curY, yiMin, yiMax, yi, xi, iradius,
xMin, xMax);
+ curY = 2 * yo - curY;
+ if (curY >= 0 && curY < bitmap->getHeight())
+ drawBEllipseLine(&pipe, bresInnerPoints,
+ curY, yiMin, yiMax, yi, xi, iradius,
xMin, xMax);
+ }
+ delete bresOuterPoints;
+ bresOuterPoints = bresInnerPoints;
+ yo = yi; xo = xi; oradius = iradius;
+ splashColorCopy(cur, curNext);
+ }
+ delete bresOuterPoints;
+ if (shading->getSmallerExtendCircle(&xo, &yo, &oradius, cur)) {
+ SplashPath *bresPoints = getBresenhamPoints(xo, yo, oradius);
+ if (bresPoints == NULL)
+ goto DrawLarge;
+ SplashCoord xMin, xMax;
+ Guchar dummy;
+ for (int i = 0; i < bresPoints->getLength(); i++) {
+ SplashCoord curX, curY;
+ bresPoints->getPoint(i, &curX, &curY, &dummy);
+ curY += yo;
+ xMax = xo + curX;
+ xMin = xo - curX;
+ if (curY >= 0 && curY < bitmap->getHeight())
+ drawPartEllipseLine(&pipe, curY, xMin, xMax);
+ curY = 2 * yo - curY;
+ if (curY >= 0 && curY < bitmap->getHeight())
+ drawPartEllipseLine(&pipe, curY, xMin, xMax);
+ }
+ delete bresPoints;
+ }
+DrawLarge:
+ if (shading->getLargerExtendCircle(&xo, &yo, &oradius, cur)) {
+ SplashPath *bresPoints = getBresenhamPoints(xo, yo, oradius);
+ if (bresPoints == NULL)
+ goto RadialEnd;
+ SplashCoord xMin, xMax, y;
+ SplashCoord yMin, yMax;
+ yMax = yo + oradius;
+ yMin = yo - oradius;
+ Guchar dummy;
+ int i = 0;
+ if (yMax >= bitmap->getHeight()) {
+ i = splashRound(yMax - bitmap->getHeight() + 1);
+ }
+ if (yo >= bitmap->getHeight()) {
+ i = bresPoints->getLength() - 1 - splashRound(yo -
bitmap->getHeight() + 1);
+ }
+ for (y = bitmap->getHeight() - 1; y >= 0; y--) {
+ if (y > yMax || y < yMin)
+ drawPartEllipseLine(&pipe, y, 0,
bitmap->getWidth() - 1);
+ else if (y > yo) {
+ SplashCoord curX, curY;
+ bresPoints->getPoint(i++, &curX, &curY, &dummy);
+ xMin = xo - curX;
+ xMax = xo + curX;
+ if (xMin - 1 > 0)
+ drawPartEllipseLine(&pipe, y, 0, xMin +
1);
+ if (xMax + 1 < 0)
+ drawPartEllipseLine(&pipe, y, 0,
bitmap->getWidth() - 1);
+ else if (xMax + 1 < bitmap->getWidth())
+ drawPartEllipseLine(&pipe, y, xMax - 1,
bitmap->getWidth() - 1);
+ } else if (y == yo) {
+ i = bresPoints->getLength() - 1;
+ xMin = xo - oradius;
+ xMax = xo + oradius;
+ if (xMin - 1 > 0)
+ drawPartEllipseLine(&pipe, y, 0, xMin +
1);
+ if (xMax + 1 < 0)
+ drawPartEllipseLine(&pipe, y, 0,
bitmap->getWidth() - 1);
+ else if (xMax + 1 < bitmap->getWidth())
+ drawPartEllipseLine(&pipe, y, xMax - 1,
bitmap->getWidth() - 1);
+ } else {
+ SplashCoord curX, curY;
+ bresPoints->getPoint(--i, &curX, &curY, &dummy);
+ xMin = xo - curX;
+ xMax = xo + curX;
+ if (xMin - 1 > 0)
+ drawPartEllipseLine(&pipe, y, 0, xMin +
1);
+ if (xMax + 1 < 0)
+ drawPartEllipseLine(&pipe, y, 0,
bitmap->getWidth() - 1);
+ else if (xMax + 1 < bitmap->getWidth())
+ drawPartEllipseLine(&pipe, y, xMax - 1,
bitmap->getWidth() - 1);
+ }
+ }
+ delete bresPoints;
+ }
+RadialEnd:
+ return splashOk;
+}
+
SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
int xDest, int yDest, int w, int h) {
SplashColor pixel;
@@ -3950,19 +4201,25 @@ SplashError Splash::shadedFill(SplashPath *path, GBool
hasBBox,
int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
SplashClipResult clipRes;
- if (aaBuf == NULL) { // should not happen, but to be secure
+ if (vectorAntialias && aaBuf == NULL) { // should not happen, but to be
secure
return splashErrGeneric;
}
if (path->length == 0) {
return splashErrEmptyPath;
}
xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
- xPath->aaScale();
+ if (vectorAntialias) {
+ xPath->aaScale();
+ }
xPath->sort();
scanner = new SplashXPathScanner(xPath, gFalse);
- // get the min and max x and y values
- scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
+ // get the min and max x and y values
+ if (vectorAntialias) {
+ scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
+ } else {
+ scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
+ }
// check clipping
if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) !=
splashClipAllOutside) {
@@ -3977,13 +4234,34 @@ SplashError Splash::shadedFill(SplashPath *path, GBool
hasBBox,
pipeInit(&pipe, 0, yMinI, pattern, NULL, state->fillAlpha, vectorAntialias
&& !hasBBox, gFalse);
// draw the spans
- for (y = yMinI; y <= yMaxI; ++y) {
- scanner->renderAALine(aaBuf, &x0, &x1, y);
- if (clipRes != splashClipAllInside) {
- state->clip->clipAALine(aaBuf, &x0, &x1, y);
- }
- drawAALine(&pipe, x0, x1, y);
- }
+ if (vectorAntialias) {
+ for (y = yMinI; y <= yMaxI; ++y) {
+ scanner->renderAALine(aaBuf, &x0, &x1, y);
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipAALine(aaBuf, &x0, &x1, y);
+ }
+ drawAALine(&pipe, x0, x1, y);
+ }
+ } else {
+ SplashClipResult clipRes2;
+ for (y = yMinI; y <= yMaxI; ++y) {
+ while (scanner->getNextSpan(y, &x0, &x1)) {
+ if (clipRes == splashClipAllInside) {
+ drawSpan(&pipe, x0, x1, y, gTrue);
+ } else {
+ // limit the x range
+ if (x0 < state->clip->getXMinI()) {
+ x0 = state->clip->getXMinI();
+ }
+ if (x1 > state->clip->getXMaxI()) {
+ x1 = state->clip->getXMaxI();
+ }
+ clipRes2 = state->clip->testSpan(x0,
x1, y);
+ drawSpan(&pipe, x0, x1, y, clipRes2 ==
splashClipAllInside);
+ }
+ }
+ }
+ }
}
opClipRes = clipRes;
diff --git a/splash/Splash.h b/splash/Splash.h
index a52dc13..37e63f9 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -255,6 +255,14 @@ public:
SplashPattern *pattern);
// Draw a gouraud triangle shading.
GBool gouraudTriangleShadedFill(SplashGouraudColor *shading);
+ // Draw a radial shading.
+ void drawPartEllipseLine(SplashPipe *pipe, SplashCoord y, SplashCoord xMin,
SplashCoord xMax);
+ void drawBEllipseLine(SplashPipe *pipe, SplashPath *bresInnerPoints,
+ SplashCoord
y, SplashCoord yiMin, SplashCoord yiMax,
+ SplashCoord
yi, SplashCoord xi, SplashCoord iradius,
+ SplashCoord
xMin, SplashCoord xMax);
+ SplashPath *getBresenhamPoints(SplashCoord x0, SplashCoord y0, SplashCoord
radius);
+ SplashError radialShadedFill(SplashRadialColor *shading);
private:
diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h
index 09e9b1a..fb82df2 100644
--- a/splash/SplashPattern.h
+++ b/splash/SplashPattern.h
@@ -28,6 +28,8 @@
#include "SplashTypes.h"
class SplashScreen;
+class Splash;
+class SplashBitmap;
//------------------------------------------------------------------------
// SplashPattern
@@ -92,4 +94,19 @@ public:
virtual void getParameterizedColor(double t, SplashColorMode mode,
SplashColorPtr c) = 0;
};
+//------------------------------------------------------------------------
+// SplashRadialColor (needed for radialShadedFill)
+//------------------------------------------------------------------------
+
+class SplashRadialColor: public SplashPattern {
+public:
+ virtual void getStartCircle(SplashCoord *x0, SplashCoord *y0,
SplashCoord *radius, SplashColorPtr c) = 0;
+ virtual GBool getNextCircle(SplashCoord *x0, SplashCoord *y0,
SplashCoord *radius, SplashColorPtr c) = 0;
+ virtual GBool getSmallerExtendCircle(SplashCoord *x0, SplashCoord *y0,
SplashCoord *radius, SplashColorPtr c) = 0;
+ virtual GBool getLargerExtendCircle(SplashCoord *x0, SplashCoord *y0,
SplashCoord *radius, SplashColorPtr c) = 0;
+ virtual GBool isOk() = 0;
+ virtual Splash *getSplash() = 0;
+ virtual SplashBitmap *getBitmap() = 0;
+};
+
#endif
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler