ASF Bugzilla – Attachment 16837 Details for
Bug 37236
[PATCH] Fix gradients and patterns
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Adds support for gradient repeat and transparency through rasterization
gradientRepeat.patch (text/plain), 11.87 KB, created by
Thomas Deweese
on 2005-10-30 21:54:58 UTC
(
hide
)
Description:
Adds support for gradient repeat and transparency through rasterization
Filename:
MIME Type:
Creator:
Thomas Deweese
Created:
2005-10-30 21:54:58 UTC
Size:
11.87 KB
patch
obsolete
>Index: src/java/org/apache/fop/svg/PDFGraphics2D.java >=================================================================== >--- src/java/org/apache/fop/svg/PDFGraphics2D.java (revision 329175) >+++ src/java/org/apache/fop/svg/PDFGraphics2D.java (working copy) >@@ -45,6 +45,7 @@ > import org.apache.batik.ext.awt.g2d.GraphicContext; > import org.apache.batik.ext.awt.RadialGradientPaint; > import org.apache.batik.ext.awt.LinearGradientPaint; >+import org.apache.batik.ext.awt.MultipleGradientPaint; > import org.apache.batik.ext.awt.RenderingHintsKeyExt; > import org.apache.batik.gvt.PatternPaint; > import org.apache.batik.gvt.GraphicsNode; >@@ -61,17 +62,23 @@ > import java.awt.Shape; > import java.awt.Stroke; > import java.awt.Paint; >+import java.awt.PaintContext; > import java.awt.Rectangle; >+import java.awt.Transparency; > import java.awt.Dimension; > import java.awt.BasicStroke; > import java.awt.AlphaComposite; > import java.awt.geom.AffineTransform; >+import java.awt.color.ColorSpace; > import java.awt.image.BufferedImage; >+import java.awt.image.ColorModel; >+import java.awt.image.DirectColorModel; > import java.awt.image.DataBuffer; > import java.awt.image.DataBufferInt; > import java.awt.image.ImageObserver; > import java.awt.image.RenderedImage; > import java.awt.image.Raster; >+import java.awt.image.WritableRaster; > import java.awt.image.renderable.RenderableImage; > import java.awt.geom.PathIterator; > import java.awt.geom.Point2D; >@@ -709,7 +716,18 @@ > > Paint paint = getPaint(); > if (graphicsState.setPaint(paint)) { >- applyPaint(paint, false); >+ if (!applyPaint(paint, false)) { >+ // Stroke the shape and use it to 'clip' >+ // the paint contents. >+ Shape ss = getStroke().createStrokedShape(s); >+ applyUnknownPaint(paint, ss); >+ >+ if (newClip || newTransform) { >+ currentStream.write("Q\n"); >+ graphicsState.pop(); >+ } >+ return; >+ } > } > applyStroke(getStroke()); > >@@ -831,19 +849,28 @@ > * @param paint the paint to convert to PDF > * @param fill true if the paint should be set for filling > */ >- protected void applyPaint(Paint paint, boolean fill) { >+ protected boolean applyPaint(Paint paint, boolean fill) { > preparePainting(); > >+ if (paint instanceof Color) { >+ return true; >+ } > if (paint instanceof LinearGradientPaint) { > LinearGradientPaint gp = (LinearGradientPaint)paint; >+ >+ // This code currently doesn't support 'repeat'. >+ // For linear gradients it is possible to construct >+ // a 'tile' that is repeated with a PDF pattern, but >+ // it would be very tricky as you would have to rotate >+ // the coordinate system so the repeate was axially >+ // aligned. At this point I'm just going to rasterize it. >+ MultipleGradientPaint.CycleMethodEnum cycle = gp.getCycleMethod(); >+ if (cycle != MultipleGradientPaint.NO_CYCLE) >+ return false; >+ > Color[] cols = gp.getColors(); > float[] fractions = gp.getFractions(); > >- //MultipleGradientPaint.CycleMethodEnum cycenum = gp.getCycleMethod(); >- //boolean cyclic = (cycenum == MultipleGradientPaint.REPEAT); >- // This code currently doesn't support 'repeat' as PDF has >- // no way to support this (we need to rasterize). >- > // Build proper transform from gradient space to page space > // ('Patterns' don't get userspace transform). > AffineTransform transform; >@@ -885,6 +912,8 @@ > > for (int count = 0; count < cols.length; count++) { > Color c1 = cols[count]; >+ if (c1.getAlpha() != 255) return false; // PDF can't do alpha >+ > PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(), > c1.getBlue()); > someColors.add(color1); >@@ -900,9 +929,22 @@ > someColors, theBounds, theCoords, theMatrix); > currentStream.write(myPat.getColorSpaceOut(fill)); > >- } else if (paint instanceof RadialGradientPaint) { >+ return true; >+ } >+ if (paint instanceof RadialGradientPaint) { > RadialGradientPaint rgp = (RadialGradientPaint)paint; > >+ // There is essentially no way to support repeate >+ // in PDF for radial gradients (the one option would >+ // be to 'grow' the outer circle until it fully covered >+ // the bounds and then grow the stops accordingly, the >+ // problem is that this may require an extremely large >+ // number of stops for cases where the focus is near >+ // the edge of the outer circle). so we rasterize. >+ MultipleGradientPaint.CycleMethodEnum cycle = rgp.getCycleMethod(); >+ if (cycle != MultipleGradientPaint.NO_CYCLE) >+ return false; >+ > AffineTransform transform; > transform = new AffineTransform(graphicsState.getTransform()); > transform.concatenate(getTransform()); >@@ -941,6 +983,8 @@ > List someColors = new java.util.ArrayList(); > for (int count = 0; count < cols.length; count++) { > Color cc = cols[count]; >+ if (cc.getAlpha() != 255) return false; // PDF can't do alpha >+ > someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), > cc.getBlue())); > } >@@ -960,13 +1004,16 @@ > > currentStream.write(myPat.getColorSpaceOut(fill)); > >- } else if (paint instanceof PatternPaint) { >+ return true; >+ } >+ if (paint instanceof PatternPaint) { > PatternPaint pp = (PatternPaint)paint; >- createPattern(pp, fill); >+ return createPattern(pp, fill); > } >+ return false; // unknown paint > } > >- private void createPattern(PatternPaint pp, boolean fill) { >+ private boolean createPattern(PatternPaint pp, boolean fill) { > preparePainting(); > > FontInfo fontInfo = new FontInfo(); >@@ -1061,8 +1108,124 @@ > // ignore exception, will be thrown again later > } > } >+ return true; > } > >+ protected boolean applyUnknownPaint(Paint paint, Shape shape) { >+ preparePainting(); >+ >+ Shape clip = getClip(); >+ Rectangle2D usrClipBounds, usrBounds; >+ usrBounds = shape.getBounds2D(); >+ usrClipBounds = clip.getBounds2D(); >+ if (!usrClipBounds.intersects(usrBounds)) >+ return true; >+ Rectangle2D.intersect(usrBounds, usrClipBounds, usrBounds); >+ double usrX = usrBounds.getX(); >+ double usrY = usrBounds.getY(); >+ double usrW = usrBounds.getWidth(); >+ double usrH = usrBounds.getHeight(); >+ >+ Rectangle devShapeBounds, devClipBounds, devBounds; >+ AffineTransform at = getTransform(); >+ devShapeBounds = at.createTransformedShape(shape).getBounds(); >+ devClipBounds = at.createTransformedShape(clip).getBounds(); >+ if (!devClipBounds.intersects(devShapeBounds)) >+ return true; >+ devBounds = devShapeBounds.intersection(devClipBounds); >+ int devX = devBounds.x; >+ int devY = devBounds.y; >+ int devW = devBounds.width; >+ int devH = devBounds.height; >+ >+ ColorSpace rgbCS = ColorSpace.getInstance(ColorSpace.CS_sRGB); >+ ColorModel rgbCM = new DirectColorModel >+ (rgbCS, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, >+ false, DataBuffer.TYPE_BYTE); >+ >+ PaintContext pctx = paint.createContext(rgbCM, devBounds, usrBounds, >+ at, getRenderingHints()); >+ PDFXObject imageInfo = pdfDoc.getImage >+ ("TempImage:" + pctx.toString()); >+ if (imageInfo != null) { >+ resourceContext.getPDFResources().addXObject(imageInfo); >+ } else { >+ Raster r = pctx.getRaster(devX, devY, devW, devH); >+ WritableRaster wr = (WritableRaster)r; >+ wr = wr.createWritableTranslatedChild(0, 0); >+ >+ ColorModel pcm = pctx.getColorModel(); >+ BufferedImage bi = new BufferedImage >+ (pcm, wr, pcm.isAlphaPremultiplied(), null); >+ final byte [] rgb = new byte[devW*devH*3]; >+ final int [] line = new int[devW]; >+ final byte [] mask; >+ int x, y, val, rgbIdx=0; >+ >+ if (pcm.hasAlpha()) { >+ mask = new byte[devW*devH]; >+ int maskIdx=0; >+ for (y=0; y<devH; y++) { >+ bi.getRGB(0, y, devW, 1, line, 0, devW); >+ for (x=0; x< devW; x++) { >+ val = line[x]; >+ mask[maskIdx++] = (byte)(val>>>24); >+ rgb [rgbIdx++] = (byte)((val>>16)&0x0FF); >+ rgb [rgbIdx++] = (byte)((val>> 8)&0x0FF); >+ rgb [rgbIdx++] = (byte)((val )&0x0FF); >+ } >+ } >+ } else { >+ mask = null; >+ for (y=0; y<devH; y++) { >+ bi.getRGB(0, y, devW, 1, line, 0, devW); >+ for (x=0; x< devW; x++) { >+ val = line[x]; >+ rgb [rgbIdx++] = (byte)((val>>16)&0x0FF); >+ rgb [rgbIdx++] = (byte)((val>> 8)&0x0FF); >+ rgb [rgbIdx++] = (byte)((val )&0x0FF); >+ } >+ } >+ } >+ >+ String maskRef = null; >+ if (mask != null) { >+ BitmapImage fopimg = new BitmapImage >+ ("TempImageMask:"+pctx.toString(), devW, devH, mask, null); >+ fopimg.setColorSpace(new PDFColorSpace(PDFColorSpace.DEVICE_GRAY)); >+ PDFXObject xobj = pdfDoc.addImage(resourceContext, fopimg); >+ maskRef = xobj.referencePDF(); >+ >+ if (outputStream != null) { >+ try { >+ this.pdfDoc.output(outputStream); >+ } catch (IOException ioe) { >+ // ignore exception, will be thrown again later >+ } >+ } >+ } >+ BitmapImage fopimg; >+ fopimg = new BitmapImage("TempImage:" + pctx.toString(), >+ devW, devH, rgb, maskRef); >+ fopimg.setTransparent(new PDFColor(255, 255, 255)); >+ imageInfo = pdfDoc.addImage(resourceContext, fopimg); >+ if (outputStream != null) { >+ try { >+ this.pdfDoc.output(outputStream); >+ } catch (IOException ioe) { >+ // ignore exception, will be thrown again later >+ } >+ } >+ } >+ >+ currentStream.write("q\n"); >+ writeClip(shape); >+ currentStream.write("" + usrW + " 0 0 " + (-usrH) + " " + usrX >+ + " " + (usrY + usrH) + " cm\n" + "/Im" >+ + imageInfo.getXNumber() + " Do\nQ\n"); >+ return true; >+ } >+ > /** > * Apply the stroke to the PDF. > * This takes the java stroke and outputs the appropriate settings >@@ -1512,7 +1675,16 @@ > > Paint paint = getPaint(); > if (graphicsState.setPaint(paint)) { >- applyPaint(paint, true); >+ if (!applyPaint(paint, true)) { >+ // Use the shape to 'clip' the paint contents. >+ applyUnknownPaint(paint, s); >+ >+ if (newClip || newTransform) { >+ currentStream.write("Q\n"); >+ graphicsState.pop(); >+ } >+ return; >+ } > } > > //PathIterator iter = s.getPathIterator(getTransform());
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 37236
:
16799
|
16800
|
16810
|
16837
|
16853