Thanks for immediately starting regtesting.
Thought You're in xmas vacation or have enough to do releasing 0.16.0.
Here the correction for the artefacts by pdftoppm, I made a small
mistake when optimizing my code.
Thomas
Am 27.12.2010 02:07, schrieb Albert Astals Cid:
A Dilluns, 27 de desembre de 2010, Albert Astals Cid va escriure:
A Diumenge, 26 de desembre de 2010, Thomas Freitag va escriure:
Am 04.11.2010 22:26, schrieb Albert Astals Cid:
Hi, i just commited the patch to splash with antialias and shadings,
really good work!
Now, it seems you are both magicians so i'm asking another wish :D
Of course only do this if you feel like it's fun ;-)
Have a look at the ducks and roses at
http://www.acquerra.com.au/poppler/img_0.pdf
Do you guys feel like trying to fix it?
Albert
Hi Albert!
As I already mentioned, I had a deeper look at the ducks& roses, and
espially at the wine glass.
I encountered, that there is no way to solve that in Gfx.cc, and
therefore I implemented radial shading in SplashOutputDev now. It took
me "some" days, more effort then I thought before beginning, but the
result is really beautiful, therefore I attach not only the patch but
the rendering result too, so that You can immediately what I mean with
beautiful :-)
Take it a belated xmas gift for the poppler community :-)
Good work :-)
I've found a regression though, if you run pdftotext with and without the
pdf file i'll send you in private, you'll see that the lower left square
has some "random" white pixels that are not there without the patch.
s/pdftotext/pdftoppm :D
Albert
Albert
Best regards,
Thomas
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler
.
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 0b3722a..65e4117 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -153,6 +153,257 @@ 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;
+ if (radialMaxSize > 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;
+ bitmap = new SplashBitmap(splashRound(width), splashRound(height), 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);
+ ys = splashRound(yc);
+ 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
//------------------------------------------------------------------------
@@ -3379,3 +3630,38 @@ 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 vaa = getVectorAntialias();
+ GBool retVal = gFalse;
+ // restore vector antialias because we support it here
+ setVectorAntialias(gTrue);
+ // 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);
+ }
+ setVectorAntialias(vaa);
+ 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..98178d9 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, 2* yo - 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;
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