java2d backports
Dr Andrew John Hughes
ahughes at redhat.com
Wed Feb 23 05:53:39 PST 2011
On 19:08 Tue 22 Feb , Denis Lila wrote:
> Hi.
>
> I would like to backport these changesets to head:
> http://hg.openjdk.java.net/jdk7/2d-gate/jdk/rev/4d6f9aaa2600
> http://hg.openjdk.java.net/jdk7/2d-gate/jdk/rev/4d6f9aaa2600
>
I think you need another URL there ;-)
> They will give us huge performance improvements to the drawing
> of simple shapes (and I'll finally be able to decisively close
> RH540575 ;-)
>
> I've had to make some manual modifications to the output of
> hg export (like removing CRLF line endings and removing hunks
> that change generated files) but they apply mostly cleanly
> and everything builds and works properly.
>
> Ok to push?
>
> Thank you,
> Denis.
Fine by me. We spoke about these a while back IIRC.
> diff -r e1a5ab4cf428 ChangeLog
> --- a/ChangeLog Tue Feb 22 23:07:58 2011 +0000
> +++ b/ChangeLog Tue Feb 22 19:04:38 2011 -0500
> @@ -1,3 +1,10 @@
> +2011-02-22 Denis Lila <dlila at redhat.com>
> +
> + * Makefile.am: Added 2 patches.
> + * NEWS: Updated.
> + * patches/openjdk/6775317-non-AA-simple-shape-performance.patch
> + * patches/openjdk/6766342-AA-simple-shape-performance.patch
> +
> 2011-02-22 Andrew John Hughes <ahughes at redhat.com>
>
> * patches/sunsrc.patch: Removed.
> diff -r e1a5ab4cf428 Makefile.am
> --- a/Makefile.am Tue Feb 22 23:07:58 2011 +0000
> +++ b/Makefile.am Tue Feb 22 19:04:38 2011 -0500
> @@ -325,7 +325,9 @@
> patches/openjdk/6749060-bad-lcd-aa-non-opaque-dest.patch \
> patches/openjdk/6896068-sg2d.patch \
> patches/pr633-no_javaws_man_page.patch \
> - patches/pr586-include_all_srcs.patch
> + patches/pr586-include_all_srcs.patch \
> + patches/openjdk/6775317-non-AA-simple-shape-performance.patch \
> + patches/openjdk/6766342-AA-simple-shape-performance.patch
>
> if !WITH_ALT_HSBUILD
> ICEDTEA_PATCHES += \
> diff -r e1a5ab4cf428 NEWS
> --- a/NEWS Tue Feb 22 23:07:58 2011 +0000
> +++ b/NEWS Tue Feb 22 19:04:38 2011 -0500
> @@ -425,6 +425,8 @@
> - S6779717: A Window does not show applet security warning icon on X platforms
> - S6785058: Parent don't get the focus after dialog is closed if security warning is applied
> - S6444769: java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html fails
> + - S6775317: Improve performance of non-AA transformed rectangles and single wide lines in software pipelines
> + - S6766342: Improve performance of Ductus rasterizer
> * Bug fixes
> - RH661505: JPEGs with sRGB IEC61966-2.1 color profiles have wrong colors
> - PR600: HS19 upgrade broke CACAO build on ARM
> diff -r e1a5ab4cf428 patches/openjdk/6766342-AA-simple-shape-performance.patch
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/patches/openjdk/6766342-AA-simple-shape-performance.patch Tue Feb 22 19:04:38 2011 -0500
> @@ -0,0 +1,3819 @@
> +# HG changeset patch
> +# User flar
> +# Date 1292361929 28800
> +# Node ID 4d6f9aaa2600eec36725ab7cd47cb4b652755723
> +# Parent 0eeac8ca33e329aab7a9ad0fcfb3a321cd1abd06
> +6766342: Improve performance of Ductus rasterizer
> +Reviewed-by: jgodinez, prr
> +
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 make/sun/awt/mapfile-vers
> +--- openjdk.orig/jdk/make/sun/awt/mapfile-vers Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/mapfile-vers Tue Dec 14 13:25:29 2010 -0800
> +@@ -118,6 +118,8 @@
> + Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops;
> + Java_sun_java2d_loops_MaskBlit_MaskBlit;
> + Java_sun_java2d_loops_MaskFill_MaskFill;
> ++ Java_sun_java2d_loops_MaskFill_FillAAPgram;
> ++ Java_sun_java2d_loops_MaskFill_DrawAAPgram;
> + Java_sun_java2d_loops_TransformHelper_Transform;
> + Java_sun_java2d_pipe_Region_initIDs;
> + Java_sun_java2d_pipe_SpanClipRenderer_initIDs;
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 make/sun/awt/mapfile-vers-linux
> +--- openjdk.orig/jdk/make/sun/awt/mapfile-vers-linux Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/mapfile-vers-linux Tue Dec 14 13:25:29 2010 -0800
> +@@ -115,6 +115,8 @@
> + Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops;
> + Java_sun_java2d_loops_MaskBlit_MaskBlit;
> + Java_sun_java2d_loops_MaskFill_MaskFill;
> ++ Java_sun_java2d_loops_MaskFill_FillAAPgram;
> ++ Java_sun_java2d_loops_MaskFill_DrawAAPgram;
> + Java_sun_java2d_pipe_BufferedRenderPipe_fillSpans;
> + Java_sun_java2d_pipe_SpanClipRenderer_initIDs;
> + sun_awt_image_GifImageDecoder_initIDs;
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/dc/DuctusRenderingEngine.java
> +--- openjdk.orig/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -635,6 +635,88 @@
> + return r;
> + }
> +
> ++ /**
> ++ * {@inheritDoc}
> ++ */
> ++ @Override
> ++ public AATileGenerator getAATileGenerator(double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2,
> ++ Region clip,
> ++ int bbox[])
> ++ {
> ++ // REMIND: Deal with large coordinates!
> ++ double ldx1, ldy1, ldx2, ldy2;
> ++ boolean innerpgram = (lw1 > 0 && lw2 > 0);
> ++
> ++ if (innerpgram) {
> ++ ldx1 = dx1 * lw1;
> ++ ldy1 = dy1 * lw1;
> ++ ldx2 = dx2 * lw2;
> ++ ldy2 = dy2 * lw2;
> ++ x -= (ldx1 + ldx2) / 2.0;
> ++ y -= (ldy1 + ldy2) / 2.0;
> ++ dx1 += ldx1;
> ++ dy1 += ldy1;
> ++ dx2 += ldx2;
> ++ dy2 += ldy2;
> ++ if (lw1 > 1 && lw2 > 1) {
> ++ // Inner parallelogram was entirely consumed by stroke...
> ++ innerpgram = false;
> ++ }
> ++ } else {
> ++ ldx1 = ldy1 = ldx2 = ldy2 = 0;
> ++ }
> ++
> ++ Rasterizer r = getRasterizer();
> ++
> ++ r.setUsage(Rasterizer.EOFILL);
> ++
> ++ r.beginPath();
> ++ r.beginSubpath((float) x, (float) y);
> ++ r.appendLine((float) (x+dx1), (float) (y+dy1));
> ++ r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2));
> ++ r.appendLine((float) (x+dx2), (float) (y+dy2));
> ++ r.closedSubpath();
> ++ if (innerpgram) {
> ++ x += ldx1 + ldx2;
> ++ y += ldy1 + ldy2;
> ++ dx1 -= 2.0 * ldx1;
> ++ dy1 -= 2.0 * ldy1;
> ++ dx2 -= 2.0 * ldx2;
> ++ dy2 -= 2.0 * ldy2;
> ++ r.beginSubpath((float) x, (float) y);
> ++ r.appendLine((float) (x+dx1), (float) (y+dy1));
> ++ r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2));
> ++ r.appendLine((float) (x+dx2), (float) (y+dy2));
> ++ r.closedSubpath();
> ++ }
> ++
> ++ try {
> ++ r.endPath();
> ++ r.getAlphaBox(bbox);
> ++ clip.clipBoxToBounds(bbox);
> ++ if (bbox[0] >= bbox[2] || bbox[1] >= bbox[3]) {
> ++ dropRasterizer(r);
> ++ return null;
> ++ }
> ++ r.setOutputArea(bbox[0], bbox[1],
> ++ bbox[2] - bbox[0],
> ++ bbox[3] - bbox[1]);
> ++ } catch (PRException e) {
> ++ /*
> ++ * This exeption is thrown from the native part of the Ductus
> ++ * (only in case of a debug build) to indicate that some
> ++ * segments of the path have very large coordinates.
> ++ * See 4485298 for more info.
> ++ */
> ++ System.err.println("DuctusRenderingEngine.getAATileGenerator: "+e);
> ++ }
> ++
> ++ return r;
> ++ }
> ++
> + private void feedConsumer(PathConsumer consumer, PathIterator pi) {
> + try {
> + consumer.beginPath();
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/SurfaceData.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/SurfaceData.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/SurfaceData.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -367,16 +367,17 @@
> + public static final TextPipe aaTextRenderer;
> + public static final TextPipe lcdTextRenderer;
> +
> +- protected static final CompositePipe colorPipe;
> ++ protected static final AlphaColorPipe colorPipe;
> + protected static final PixelToShapeConverter colorViaShape;
> + protected static final PixelToParallelogramConverter colorViaPgram;
> + protected static final TextPipe colorText;
> + protected static final CompositePipe clipColorPipe;
> + protected static final TextPipe clipColorText;
> + protected static final AAShapePipe AAColorShape;
> +- protected static final PixelToShapeConverter AAColorViaShape;
> ++ protected static final PixelToParallelogramConverter AAColorViaShape;
> ++ protected static final PixelToParallelogramConverter AAColorViaPgram;
> + protected static final AAShapePipe AAClipColorShape;
> +- protected static final PixelToShapeConverter AAClipColorViaShape;
> ++ protected static final PixelToParallelogramConverter AAClipColorViaShape;
> +
> + protected static final CompositePipe paintPipe;
> + protected static final SpanShapeRenderer paintShape;
> +@@ -385,9 +386,9 @@
> + protected static final CompositePipe clipPaintPipe;
> + protected static final TextPipe clipPaintText;
> + protected static final AAShapePipe AAPaintShape;
> +- protected static final PixelToShapeConverter AAPaintViaShape;
> ++ protected static final PixelToParallelogramConverter AAPaintViaShape;
> + protected static final AAShapePipe AAClipPaintShape;
> +- protected static final PixelToShapeConverter AAClipPaintViaShape;
> ++ protected static final PixelToParallelogramConverter AAClipPaintViaShape;
> +
> + protected static final CompositePipe compPipe;
> + protected static final SpanShapeRenderer compShape;
> +@@ -396,9 +397,9 @@
> + protected static final CompositePipe clipCompPipe;
> + protected static final TextPipe clipCompText;
> + protected static final AAShapePipe AACompShape;
> +- protected static final PixelToShapeConverter AACompViaShape;
> ++ protected static final PixelToParallelogramConverter AACompViaShape;
> + protected static final AAShapePipe AAClipCompShape;
> +- protected static final PixelToShapeConverter AAClipCompViaShape;
> ++ protected static final PixelToParallelogramConverter AAClipCompViaShape;
> +
> + protected static final DrawImagePipe imagepipe;
> +
> +@@ -427,6 +428,22 @@
> + }
> + }
> +
> ++ private static PixelToParallelogramConverter
> ++ makeConverter(AAShapePipe renderer,
> ++ ParallelogramPipe pgrampipe)
> ++ {
> ++ return new PixelToParallelogramConverter(renderer,
> ++ pgrampipe,
> ++ 1.0/8.0, 0.499,
> ++ false);
> ++ }
> ++
> ++ private static PixelToParallelogramConverter
> ++ makeConverter(AAShapePipe renderer)
> ++ {
> ++ return makeConverter(renderer, renderer);
> ++ }
> ++
> + static {
> + colorPrimitives = new LoopPipe();
> +
> +@@ -445,9 +462,10 @@
> + clipColorPipe = new SpanClipRenderer(colorPipe);
> + clipColorText = new TextRenderer(clipColorPipe);
> + AAColorShape = new AAShapePipe(colorPipe);
> +- AAColorViaShape = new PixelToShapeConverter(AAColorShape);
> ++ AAColorViaShape = makeConverter(AAColorShape);
> ++ AAColorViaPgram = makeConverter(AAColorShape, colorPipe);
> + AAClipColorShape = new AAShapePipe(clipColorPipe);
> +- AAClipColorViaShape = new PixelToShapeConverter(AAClipColorShape);
> ++ AAClipColorViaShape = makeConverter(AAClipColorShape);
> +
> + paintPipe = new AlphaPaintPipe();
> + paintShape = new SpanShapeRenderer.Composite(paintPipe);
> +@@ -456,9 +474,9 @@
> + clipPaintPipe = new SpanClipRenderer(paintPipe);
> + clipPaintText = new TextRenderer(clipPaintPipe);
> + AAPaintShape = new AAShapePipe(paintPipe);
> +- AAPaintViaShape = new PixelToShapeConverter(AAPaintShape);
> ++ AAPaintViaShape = makeConverter(AAPaintShape);
> + AAClipPaintShape = new AAShapePipe(clipPaintPipe);
> +- AAClipPaintViaShape = new PixelToShapeConverter(AAClipPaintShape);
> ++ AAClipPaintViaShape = makeConverter(AAClipPaintShape);
> +
> + compPipe = new GeneralCompositePipe();
> + compShape = new SpanShapeRenderer.Composite(compPipe);
> +@@ -467,9 +485,9 @@
> + clipCompPipe = new SpanClipRenderer(compPipe);
> + clipCompText = new TextRenderer(clipCompPipe);
> + AACompShape = new AAShapePipe(compPipe);
> +- AACompViaShape = new PixelToShapeConverter(AACompShape);
> ++ AACompViaShape = makeConverter(AACompShape);
> + AAClipCompShape = new AAShapePipe(clipCompPipe);
> +- AAClipCompViaShape = new PixelToShapeConverter(AAClipCompShape);
> ++ AAClipCompViaShape = makeConverter(AAClipCompShape);
> +
> + imagepipe = new DrawImage();
> + }
> +@@ -591,12 +609,12 @@
> + if (sg2d.clipState == sg2d.CLIP_SHAPE) {
> + sg2d.drawpipe = AAClipCompViaShape;
> + sg2d.fillpipe = AAClipCompViaShape;
> +- sg2d.shapepipe = AAClipCompShape;
> ++ sg2d.shapepipe = AAClipCompViaShape;
> + sg2d.textpipe = clipCompText;
> + } else {
> + sg2d.drawpipe = AACompViaShape;
> + sg2d.fillpipe = AACompViaShape;
> +- sg2d.shapepipe = AACompShape;
> ++ sg2d.shapepipe = AACompViaShape;
> + sg2d.textpipe = compText;
> + }
> + } else {
> +@@ -616,12 +634,16 @@
> + if (sg2d.clipState == sg2d.CLIP_SHAPE) {
> + sg2d.drawpipe = AAClipColorViaShape;
> + sg2d.fillpipe = AAClipColorViaShape;
> +- sg2d.shapepipe = AAClipColorShape;
> ++ sg2d.shapepipe = AAClipColorViaShape;
> + sg2d.textpipe = clipColorText;
> + } else {
> +- sg2d.drawpipe = AAColorViaShape;
> +- sg2d.fillpipe = AAColorViaShape;
> +- sg2d.shapepipe = AAColorShape;
> ++ PixelToParallelogramConverter converter =
> ++ (sg2d.alphafill.canDoParallelograms()
> ++ ? AAColorViaPgram
> ++ : AAColorViaShape);
> ++ sg2d.drawpipe = converter;
> ++ sg2d.fillpipe = converter;
> ++ sg2d.shapepipe = converter;
> + if (sg2d.paintState > sg2d.PAINT_OPAQUECOLOR ||
> + sg2d.compositeState > sg2d.COMP_ISCOPY)
> + {
> +@@ -634,12 +656,12 @@
> + if (sg2d.clipState == sg2d.CLIP_SHAPE) {
> + sg2d.drawpipe = AAClipPaintViaShape;
> + sg2d.fillpipe = AAClipPaintViaShape;
> +- sg2d.shapepipe = AAClipPaintShape;
> ++ sg2d.shapepipe = AAClipPaintViaShape;
> + sg2d.textpipe = clipPaintText;
> + } else {
> + sg2d.drawpipe = AAPaintViaShape;
> + sg2d.fillpipe = AAPaintViaShape;
> +- sg2d.shapepipe = AAPaintShape;
> ++ sg2d.shapepipe = AAPaintViaShape;
> + sg2d.textpipe = paintText;
> + }
> + }
> +@@ -793,6 +815,18 @@
> + }
> + }
> +
> ++ private static CompositeType getFillCompositeType(SunGraphics2D sg2d) {
> ++ CompositeType compType = sg2d.imageComp;
> ++ if (sg2d.compositeState == sg2d.COMP_ISCOPY) {
> ++ if (compType == CompositeType.SrcOverNoEa) {
> ++ compType = CompositeType.OpaqueSrcOverNoEa;
> ++ } else {
> ++ compType = CompositeType.SrcNoEa;
> ++ }
> ++ }
> ++ return compType;
> ++ }
> ++
> + /**
> + * Returns a MaskFill object that can be used on this destination
> + * with the source (paint) and composite types determined by the given
> +@@ -802,9 +836,10 @@
> + * surface) before returning a specific MaskFill object.
> + */
> + protected MaskFill getMaskFill(SunGraphics2D sg2d) {
> +- return MaskFill.getFromCache(getPaintSurfaceType(sg2d),
> +- sg2d.imageComp,
> +- getSurfaceType());
> ++ SurfaceType src = getPaintSurfaceType(sg2d);
> ++ CompositeType comp = getFillCompositeType(sg2d);
> ++ SurfaceType dst = getSurfaceType();
> ++ return MaskFill.getFromCache(src, comp, dst);
> + }
> +
> + private static RenderCache loopcache = new RenderCache(30);
> +@@ -816,9 +851,7 @@
> + */
> + public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
> + SurfaceType src = getPaintSurfaceType(sg2d);
> +- CompositeType comp = (sg2d.compositeState == sg2d.COMP_ISCOPY
> +- ? CompositeType.SrcNoEa
> +- : sg2d.imageComp);
> ++ CompositeType comp = getFillCompositeType(sg2d);
> + SurfaceType dst = sg2d.getSurfaceData().getSurfaceType();
> +
> + Object o = loopcache.get(src, comp, dst);
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/loops/CompositeType.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/loops/CompositeType.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/loops/CompositeType.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -27,6 +27,7 @@
> +
> + import java.awt.image.BufferedImage;
> + import java.awt.AlphaComposite;
> ++import java.util.HashMap;
> +
> + /**
> + * A CompositeType object provides a chained description of a type of
> +@@ -51,6 +52,11 @@
> + * the indicated algorithm if all of the more specific searches fail.
> + */
> + public final class CompositeType {
> ++
> ++ private static int unusedUID = 1;
> ++ private static final HashMap<String,Integer> compositeUIDMap =
> ++ new HashMap<String,Integer>(100);
> ++
> + /*
> + * CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE COMPOSITING
> + * ALGORITHMS THEY CAN PERFORM
> +@@ -153,6 +159,22 @@
> + SrcOverNoEa = SrcOver.deriveSubType(DESC_SRC_OVER_NO_EA);
> +
> + /*
> ++ * A special CompositeType for the case where we are filling in
> ++ * SrcOverNoEa mode with an opaque color. In that case then the
> ++ * best loop for us to use would be a SrcNoEa loop, but what if
> ++ * there is no such loop? In that case then we would end up
> ++ * backing off to a Src loop (which should still be fine) or an
> ++ * AnyAlpha loop which would be slower than a SrcOver loop in
> ++ * most cases.
> ++ * The fix is to use the following chain which looks for loops
> ++ * in the following order:
> ++ * SrcNoEa, Src, SrcOverNoEa, SrcOver, AnyAlpha
> ++ */
> ++ public static final CompositeType
> ++ OpaqueSrcOverNoEa = SrcOverNoEa.deriveSubType(DESC_SRC)
> ++ .deriveSubType(DESC_SRC_NO_EA);
> ++
> ++ /*
> + * END OF CompositeType OBJECTS FOR THE VARIOUS CONSTANTS
> + */
> +
> +@@ -210,7 +232,6 @@
> + }
> + }
> +
> +- private static int unusedUID = 1;
> + private int uniqueID;
> + private String desc;
> + private CompositeType next;
> +@@ -218,14 +239,20 @@
> + private CompositeType(CompositeType parent, String desc) {
> + next = parent;
> + this.desc = desc;
> +- this.uniqueID = makeUniqueID();
> ++ this.uniqueID = makeUniqueID(desc);
> + }
> +
> +- private synchronized static final int makeUniqueID() {
> +- if (unusedUID > 255) {
> +- throw new InternalError("composite type id overflow");
> ++ public synchronized static final int makeUniqueID(String desc) {
> ++ Integer i = compositeUIDMap.get(desc);
> ++
> ++ if (i == null) {
> ++ if (unusedUID > 255) {
> ++ throw new InternalError("composite type id overflow");
> ++ }
> ++ i = unusedUID++;
> ++ compositeUIDMap.put(desc, i);
> + }
> +- return unusedUID++;
> ++ return i;
> + }
> +
> + public int getUniqueID() {
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/loops/MaskFill.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/loops/MaskFill.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/loops/MaskFill.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -50,6 +50,10 @@
> + public class MaskFill extends GraphicsPrimitive
> + {
> + public static final String methodSignature = "MaskFill(...)".toString();
> ++ public static final String fillPgramSignature =
> ++ "FillAAPgram(...)".toString();
> ++ public static final String drawPgramSignature =
> ++ "DrawAAPgram(...)".toString();
> +
> + public static final int primTypeID = makePrimTypeID();
> +
> +@@ -92,6 +96,14 @@
> + return fill;
> + }
> +
> ++ protected MaskFill(String alternateSignature,
> ++ SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ super(alternateSignature, primTypeID, srctype, comptype, dsttype);
> ++ }
> ++
> + protected MaskFill(SurfaceType srctype,
> + CompositeType comptype,
> + SurfaceType dsttype)
> +@@ -115,6 +127,23 @@
> + int x, int y, int w, int h,
> + byte[] mask, int maskoff, int maskscan);
> +
> ++ public native void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
> ++ Composite comp,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2);
> ++
> ++ public native void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
> ++ Composite comp,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2);
> ++
> ++ public boolean canDoParallelograms() {
> ++ return (getNativePrim() != 0);
> ++ }
> ++
> + static {
> + GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null));
> + }
> +@@ -182,12 +211,22 @@
> +
> + private static class TraceMaskFill extends MaskFill {
> + MaskFill target;
> ++ MaskFill fillPgramTarget;
> ++ MaskFill drawPgramTarget;
> +
> + public TraceMaskFill(MaskFill target) {
> + super(target.getSourceType(),
> + target.getCompositeType(),
> + target.getDestType());
> + this.target = target;
> ++ this.fillPgramTarget = new MaskFill(fillPgramSignature,
> ++ target.getSourceType(),
> ++ target.getCompositeType(),
> ++ target.getDestType());
> ++ this.drawPgramTarget = new MaskFill(drawPgramSignature,
> ++ target.getSourceType(),
> ++ target.getCompositeType(),
> ++ target.getDestType());
> + }
> +
> + public GraphicsPrimitive traceWrap() {
> +@@ -203,5 +242,32 @@
> + target.MaskFill(sg2d, sData, comp, x, y, w, h,
> + mask, maskoff, maskscan);
> + }
> ++
> ++ public void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
> ++ Composite comp,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2)
> ++ {
> ++ tracePrimitive(fillPgramTarget);
> ++ target.FillAAPgram(sg2d, sData, comp,
> ++ x, y, dx1, dy1, dx2, dy2);
> ++ }
> ++
> ++ public void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
> ++ Composite comp,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2)
> ++ {
> ++ tracePrimitive(drawPgramTarget);
> ++ target.DrawAAPgram(sg2d, sData, comp,
> ++ x, y, dx1, dy1, dx2, dy2, lw1, lw2);
> ++ }
> ++
> ++ public boolean canDoParallelograms() {
> ++ return target.canDoParallelograms();
> ++ }
> + }
> + }
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/pipe/AAShapePipe.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -28,6 +28,7 @@
> + import java.awt.BasicStroke;
> + import java.awt.Rectangle;
> + import java.awt.Shape;
> ++import java.awt.geom.Rectangle2D;
> + import java.awt.geom.PathIterator;
> + import sun.awt.SunHints;
> + import sun.java2d.SunGraphics2D;
> +@@ -39,7 +40,9 @@
> + * This class sets up the Generator and computes the alpha tiles
> + * and then passes them on to a CompositePipe object for painting.
> + */
> +-public class AAShapePipe implements ShapeDrawPipe {
> ++public class AAShapePipe
> ++ implements ShapeDrawPipe, ParallelogramPipe
> ++{
> + static RenderingEngine renderengine = RenderingEngine.getInstance();
> +
> + CompositePipe outpipe;
> +@@ -65,6 +68,59 @@
> + renderPath(sg, s, null);
> + }
> +
> ++ private static Rectangle2D computeBBox(double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2)
> ++ {
> ++ double lox, loy, hix, hiy;
> ++ lox = hix = x;
> ++ loy = hiy = y;
> ++ if (dx1 < 0) { lox += dx1; } else { hix += dx1; }
> ++ if (dy1 < 0) { loy += dy1; } else { hiy += dy1; }
> ++ if (dx2 < 0) { lox += dx2; } else { hix += dx2; }
> ++ if (dy2 < 0) { loy += dy2; } else { hiy += dy2; }
> ++ return new Rectangle2D.Double(lox, loy, hix-lox, hiy-loy);
> ++ }
> ++
> ++ public void fillParallelogram(SunGraphics2D sg,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2)
> ++ {
> ++ Region clip = sg.getCompClip();
> ++ int abox[] = new int[4];
> ++ AATileGenerator aatg =
> ++ renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
> ++ clip, abox);
> ++ if (aatg == null) {
> ++ // Nothing to render
> ++ return;
> ++ }
> ++
> ++ renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox);
> ++ }
> ++
> ++ public void drawParallelogram(SunGraphics2D sg,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2)
> ++ {
> ++ Region clip = sg.getCompClip();
> ++ int abox[] = new int[4];
> ++ AATileGenerator aatg =
> ++ renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
> ++ clip, abox);
> ++ if (aatg == null) {
> ++ // Nothing to render
> ++ return;
> ++ }
> ++
> ++ // Note that bbox is of the original shape, not the wide path.
> ++ // This is appropriate for handing to Paint methods...
> ++ renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox);
> ++ }
> ++
> + private static byte[] theTile;
> +
> + public synchronized static byte[] getAlphaTile(int len) {
> +@@ -85,8 +141,6 @@
> + boolean adjust = (bs != null &&
> + sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
> + boolean thin = (sg.strokeState <= sg.STROKE_THINDASHED);
> +- Object context = null;
> +- byte alpha[] = null;
> +
> + Region clip = sg.getCompClip();
> + int abox[] = new int[4];
> +@@ -98,6 +152,14 @@
> + return;
> + }
> +
> ++ renderTiles(sg, s, aatg, abox);
> ++ }
> ++
> ++ public void renderTiles(SunGraphics2D sg, Shape s,
> ++ AATileGenerator aatg, int abox[])
> ++ {
> ++ Object context = null;
> ++ byte alpha[] = null;
> + try {
> + context = outpipe.startSequence(sg, s,
> + new Rectangle(abox[0], abox[1],
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/pipe/AlphaColorPipe.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -34,7 +34,7 @@
> + * into a destination that supports direct alpha compositing of a solid
> + * color, according to one of the rules in the AlphaComposite class.
> + */
> +-public class AlphaColorPipe implements CompositePipe {
> ++public class AlphaColorPipe implements CompositePipe, ParallelogramPipe {
> + public AlphaColorPipe() {
> + }
> +
> +@@ -64,4 +64,23 @@
> + public void endSequence(Object context) {
> + return;
> + }
> ++
> ++ public void fillParallelogram(SunGraphics2D sg,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2)
> ++ {
> ++ sg.alphafill.FillAAPgram(sg, sg.getSurfaceData(), sg.composite,
> ++ x, y, dx1, dy1, dx2, dy2);
> ++ }
> ++
> ++ public void drawParallelogram(SunGraphics2D sg,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2)
> ++ {
> ++ sg.alphafill.DrawAAPgram(sg, sg.getSurfaceData(), sg.composite,
> ++ x, y, dx1, dy1, dx2, dy2, lw1, lw2);
> ++ }
> + }
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/pipe/RenderingEngine.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -281,6 +281,72 @@
> + int bbox[]);
> +
> + /**
> ++ * Construct an antialiased tile generator for the given parallelogram
> ++ * store the bounds of the tile iteration in the bbox parameter.
> ++ * The parallelogram is specified as a starting point and 2 delta
> ++ * vectors that indicate the slopes of the 2 pairs of sides of the
> ++ * parallelogram.
> ++ * The 4 corners of the parallelogram are defined by the 4 points:
> ++ * <ul>
> ++ * <li> {@code x}, {@code y}
> ++ * <li> {@code x+dx1}, {@code y+dy1}
> ++ * <li> {@code x+dx1+dx2}, {@code y+dy1+dy2}
> ++ * <li> {@code x+dx2}, {@code y+dy2}
> ++ * </ul>
> ++ * The {@code lw1} and {@code lw2} parameters provide a specification
> ++ * for an optionally stroked parallelogram if they are positive numbers.
> ++ * The {@code lw1} parameter is the ratio of the length of the {@code dx1},
> ++ * {@code dx2} delta vector to half of the line width in that same
> ++ * direction.
> ++ * The {@code lw2} parameter provides the same ratio for the other delta
> ++ * vector.
> ++ * If {@code lw1} and {@code lw2} are both greater than zero, then
> ++ * the parallelogram figure is doubled by both expanding and contracting
> ++ * each delta vector by its corresponding {@code lw} value.
> ++ * If either (@code lw1) or {@code lw2} are also greater than 1, then
> ++ * the inner (contracted) parallelogram disappears and the figure is
> ++ * simply a single expanded parallelogram.
> ++ * The {@code clip} parameter specifies the current clip in effect
> ++ * in device coordinates and can be used to prune the data for the
> ++ * operation, but the renderer is not required to perform any
> ++ * clipping.
> ++ * <p>
> ++ * Upon returning, this method will fill the {@code bbox} parameter
> ++ * with 4 values indicating the bounds of the iteration of the
> ++ * tile generator.
> ++ * The iteration order of the tiles will be as specified by the
> ++ * pseudo-code:
> ++ * <pre>
> ++ * for (y = bbox[1]; y < bbox[3]; y += tileheight) {
> ++ * for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
> ++ * }
> ++ * }
> ++ * </pre>
> ++ * If there is no output to be rendered, this method may return
> ++ * null.
> ++ *
> ++ * @param x the X coordinate of the first corner of the parallelogram
> ++ * @param y the Y coordinate of the first corner of the parallelogram
> ++ * @param dx1 the X coordinate delta of the first leg of the parallelogram
> ++ * @param dy1 the Y coordinate delta of the first leg of the parallelogram
> ++ * @param dx2 the X coordinate delta of the second leg of the parallelogram
> ++ * @param dy2 the Y coordinate delta of the second leg of the parallelogram
> ++ * @param lw1 the line width ratio for the first leg of the parallelogram
> ++ * @param lw2 the line width ratio for the second leg of the parallelogram
> ++ * @param clip the current clip in effect in device coordinates
> ++ * @param bbox returns the bounds of the iteration
> ++ * @return the {@code AATileGenerator} instance to be consulted
> ++ * for tile coverages, or null if there is no output to render
> ++ * @since 1.7
> ++ */
> ++ public abstract AATileGenerator getAATileGenerator(double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2,
> ++ Region clip,
> ++ int bbox[]);
> ++
> ++ /**
> + * Returns the minimum pen width that the antialiasing rasterizer
> + * can represent without dropouts occuring.
> + * @since 1.7
> +@@ -393,5 +459,24 @@
> + bs, thin, normalize,
> + bbox);
> + }
> ++ public AATileGenerator getAATileGenerator(double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2,
> ++ Region clip,
> ++ int bbox[])
> ++ {
> ++ System.out.println(name+".getAATileGenerator("+
> ++ x+", "+y+", "+
> ++ dx1+", "+dy1+", "+
> ++ dx2+", "+dy2+", "+
> ++ lw1+", "+lw2+", "+
> ++ clip+")");
> ++ return target.getAATileGenerator(x, y,
> ++ dx1, dy1,
> ++ dx2, dy2,
> ++ lw1, lw2,
> ++ clip, bbox);
> ++ }
> + }
> + }
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -557,6 +557,69 @@
> + return ptg;
> + }
> +
> ++ public AATileGenerator getAATileGenerator(double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2,
> ++ Region clip,
> ++ int bbox[])
> ++ {
> ++ // REMIND: Deal with large coordinates!
> ++ double ldx1, ldy1, ldx2, ldy2;
> ++ boolean innerpgram = (lw1 > 0 && lw2 > 0);
> ++
> ++ if (innerpgram) {
> ++ ldx1 = dx1 * lw1;
> ++ ldy1 = dy1 * lw1;
> ++ ldx2 = dx2 * lw2;
> ++ ldy2 = dy2 * lw2;
> ++ x -= (ldx1 + ldx2) / 2.0;
> ++ y -= (ldy1 + ldy2) / 2.0;
> ++ dx1 += ldx1;
> ++ dy1 += ldy1;
> ++ dx2 += ldx2;
> ++ dy2 += ldy2;
> ++ if (lw1 > 1 && lw2 > 1) {
> ++ // Inner parallelogram was entirely consumed by stroke...
> ++ innerpgram = false;
> ++ }
> ++ } else {
> ++ ldx1 = ldy1 = ldx2 = ldy2 = 0;
> ++ }
> ++
> ++ Renderer r = new Renderer(3, 3,
> ++ clip.getLoX(), clip.getLoY(),
> ++ clip.getWidth(), clip.getHeight(),
> ++ PathIterator.WIND_EVEN_ODD);
> ++
> ++ r.moveTo((float) x, (float) y);
> ++ r.lineTo((float) (x+dx1), (float) (y+dy1));
> ++ r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2));
> ++ r.lineTo((float) (x+dx2), (float) (y+dy2));
> ++ r.closePath();
> ++
> ++ if (innerpgram) {
> ++ x += ldx1 + ldx2;
> ++ y += ldy1 + ldy2;
> ++ dx1 -= 2.0 * ldx1;
> ++ dy1 -= 2.0 * ldy1;
> ++ dx2 -= 2.0 * ldx2;
> ++ dy2 -= 2.0 * ldy2;
> ++ r.moveTo((float) x, (float) y);
> ++ r.lineTo((float) (x+dx1), (float) (y+dy1));
> ++ r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2));
> ++ r.lineTo((float) (x+dx2), (float) (y+dy2));
> ++ r.closePath();
> ++ }
> ++
> ++ r.pathDone();
> ++
> ++ r.endRendering();
> ++ PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA);
> ++ ptg.getBbox(bbox);
> ++ return ptg;
> ++ }
> ++
> + /**
> + * Returns the minimum pen width that the antialiasing rasterizer
> + * can represent without dropouts occuring.
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/native/sun/java2d/loops/DrawParallelogram.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c Tue Dec 14 13:25:29 2010 -0800
> +@@ -26,14 +26,11 @@
> + #include "math.h"
> + #include "GraphicsPrimitiveMgr.h"
> + #include "LineUtils.h"
> +-#include "LoopMacros.h"
> + #include "Trace.h"
> ++#include "ParallelogramUtils.h"
> +
> +-#include "sun_java2d_loops_FillParallelogram.h"
> + #include "sun_java2d_loops_DrawParallelogram.h"
> +
> +-DECLARE_SOLID_DRAWLINE(AnyInt);
> +-
> + #define HANDLE_PGRAM_EDGE(X1, Y1, X2, Y2, \
> + pRasInfo, pixel, pPrim, pFunc, pCompInfo) \
> + do { \
> +@@ -46,28 +43,6 @@
> + ix1, iy1, ix2, iy2, JNI_TRUE); \
> + } while (0)
> +
> +-#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \
> +- do { \
> +- double vmin, vmax; \
> +- if (dv1 < 0) { \
> +- vmin = v0+dv1; \
> +- vmax = v0; \
> +- } else { \
> +- vmin = v0; \
> +- vmax = v0+dv1; \
> +- } \
> +- if (dv2 < 0) { \
> +- vmin -= dv2; \
> +- } else { \
> +- vmax += dv2; \
> +- } \
> +- bmin = (jint) floor(vmin + 0.5); \
> +- bmax = (jint) floor(vmax + 0.5); \
> +- } while(0)
> +-
> +-#define PGRAM_INIT_X(starty, x, y, slope) \
> +- (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
> +-
> + typedef struct {
> + jdouble x0;
> + jdouble y0;
> +@@ -136,20 +111,8 @@
> + * Sort parallelogram by y values, ensure that each delta vector
> + * has a non-negative y delta.
> + */
> +- if (dy1 < 0) {
> +- x0 += dx1; y0 += dy1;
> +- dx1 = -dx1; dy1 = -dy1;
> +- }
> +- if (dy2 < 0) {
> +- x0 += dx2; y0 += dy2;
> +- dx2 = -dx2; dy2 = -dy2;
> +- }
> +- /* Sort delta vectors so dxy1 is left of dxy2. */
> +- if (dx1 * dy2 > dx2 * dy1) {
> +- double v = dx1; dx1 = dx2; dx2 = v;
> +- v = dy1; dy1 = dy2; dy2 = v;
> +- v = lw1; lw1 = lw2; lw2 = v;
> +- }
> ++ SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2,
> ++ v = lw1; lw1 = lw2; lw2 = v;);
> +
> + // dx,dy for line width in the "1" and "2" directions.
> + ldx1 = dx1 * lw1;
> +@@ -161,7 +124,7 @@
> + ox0 = x0 - (ldx1 + ldx2) / 2.0;
> + oy0 = y0 - (ldy1 + ldy2) / 2.0;
> +
> +- PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2);
> ++ PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_FALSE);
> + iy1 = (jint) floor(oy0 + 0.5);
> + iy2 = (jint) floor(oy0 + dy1 + ldy1 + dy2 + ldy2 + 0.5);
> +
> +@@ -212,7 +175,7 @@
> + // Only need to generate 4 quads if the interior still
> + // has a hole in it (i.e. if the line width ratios were
> + // both less than 1.0)
> +- if (lw1 < 1.0f && lw2 < 1.0f) {
> ++ if (lw1 < 1.0 && lw2 < 1.0) {
> + // If the line widths are both less than a pixel wide
> + // then we can use a drawline function instead for even
> + // more performance.
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/native/sun/java2d/loops/FillParallelogram.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c Tue Dec 14 13:25:29 2010 -0800
> +@@ -25,31 +25,10 @@
> +
> + #include "math.h"
> + #include "GraphicsPrimitiveMgr.h"
> ++#include "ParallelogramUtils.h"
> +
> + #include "sun_java2d_loops_FillParallelogram.h"
> +
> +-#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \
> +- do { \
> +- double vmin, vmax; \
> +- if (dv1 < 0) { \
> +- vmin = v0+dv1; \
> +- vmax = v0; \
> +- } else { \
> +- vmin = v0; \
> +- vmax = v0+dv1; \
> +- } \
> +- if (dv2 < 0) { \
> +- vmin -= dv2; \
> +- } else { \
> +- vmax += dv2; \
> +- } \
> +- bmin = (jint) floor(vmin + 0.5); \
> +- bmax = (jint) floor(vmax + 0.5); \
> +- } while(0)
> +-
> +-#define PGRAM_INIT_X(starty, x, y, slope) \
> +- (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
> +-
> + /*
> + * Class: sun_java2d_loops_FillParallelogram
> + * Method: FillParallelogram
> +@@ -76,22 +55,11 @@
> +
> + /*
> + * Sort parallelogram by y values, ensure that each delta vector
> +- * has a non-negative y delta, and eliminate degenerate parallelograms.
> ++ * has a non-negative y delta.
> + */
> +- if (dy1 < 0) {
> +- x0 += dx1; y0 += dy1;
> +- dx1 = -dx1; dy1 = -dy1;
> +- }
> +- if (dy2 < 0) {
> +- x0 += dx2; y0 += dy2;
> +- dx2 = -dx2; dy2 = -dy2;
> +- }
> +- /* Sort delta vectors so dxy1 is left of dxy2. */
> +- if (dx1 * dy2 > dx2 * dy1) {
> +- double v = dx1; dx1 = dx2; dx2 = v;
> +- v = dy1; dy1 = dy2; dy2 = v;
> +- }
> +- PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2);
> ++ SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, );
> ++
> ++ PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2, JNI_FALSE);
> + iy1 = (jint) floor(y0 + 0.5);
> + iy2 = (jint) floor(y0 + dy1 + dy2 + 0.5);
> +
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/native/sun/java2d/loops/MaskFill.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/MaskFill.c Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/MaskFill.c Tue Dec 14 13:25:29 2010 -0800
> +@@ -23,7 +23,11 @@
> + * questions.
> + */
> +
> ++#include <math.h>
> ++#include <stdlib.h>
> ++#include <string.h>
> + #include "GraphicsPrimitiveMgr.h"
> ++#include "ParallelogramUtils.h"
> +
> + #include "sun_java2d_loops_MaskFill.h"
> +
> +@@ -93,6 +97,967 @@
> + }
> + }
> + SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
> ++ }
> ++ SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
> ++}
> ++
> ++#define MASK_BUF_LEN 1024
> ++
> ++#define DblToMask(v) ((unsigned char) ((v)*255.9999))
> ++
> ++/* Fills an aligned rectangle with potentially translucent edges. */
> ++static void
> ++fillAARect(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo,
> ++ CompositeInfo *pCompInfo, jint color, unsigned char *pMask,
> ++ void *pDst,
> ++ jdouble x1, jdouble y1, jdouble x2, jdouble y2)
> ++{
> ++ jint cx1 = pRasInfo->bounds.x1;
> ++ jint cy1 = pRasInfo->bounds.y1;
> ++ jint cx2 = pRasInfo->bounds.x2;
> ++ jint cy2 = pRasInfo->bounds.y2;
> ++ jint rx1 = (jint) ceil(x1);
> ++ jint ry1 = (jint) ceil(y1);
> ++ jint rx2 = (jint) floor(x2);
> ++ jint ry2 = (jint) floor(y2);
> ++ jint width = cx2 - cx1;
> ++ jint scan = pRasInfo->scanStride;
> ++ /* Convert xy12 into the edge coverage fractions for those edges. */
> ++ x1 = rx1-x1;
> ++ y1 = ry1-y1;
> ++ x2 = x2-rx2;
> ++ y2 = y2-ry2;
> ++ if (ry2 < ry1) {
> ++ /* Accumulate bottom coverage into top coverage. */
> ++ y1 = y1 + y2 - 1.0;
> ++ /* prevent processing of "bottom fractional row" */
> ++ ry2 = cy2;
> ++ }
> ++ if (rx2 < rx1) {
> ++ /* Accumulate right coverage into left coverage. */
> ++ x1 = x1 + x2 - 1.0;
> ++ /* prevent processing of "right fractional column" */
> ++ rx2 = cx2;
> ++ }
> ++ /* Check for a visible "top fractional row" and process it */
> ++ if (cy1 < ry1) {
> ++ unsigned char midcov = DblToMask(y1);
> ++ jint x;
> ++ for (x = 0; x < width; x++) {
> ++ pMask[x] = midcov;
> ++ }
> ++ if (cx1 < rx1) {
> ++ pMask[0] = DblToMask(y1 * x1);
> ++ }
> ++ if (cx2 > rx2) {
> ++ pMask[width-1] = DblToMask(y1 * x2);
> ++ }
> ++ (*pPrim->funcs.maskfill)(pDst,
> ++ pMask, 0, 0,
> ++ width, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ pDst = PtrAddBytes(pDst, scan);
> ++ cy1++;
> ++ }
> ++ /* Check for a visible "left fract, solid middle, right fract" section. */
> ++ if (cy1 < ry2 && cy1 < cy2) {
> ++ jint midh = ((ry2 < cy2) ? ry2 : cy2) - cy1;
> ++ jint midx = cx1;
> ++ void *pMid = pDst;
> ++ /* First process the left "fractional column" if it is visible. */
> ++ if (midx < rx1) {
> ++ pMask[0] = DblToMask(x1);
> ++ /* Note: maskscan == 0 means we reuse this value for every row. */
> ++ (*pPrim->funcs.maskfill)(pMid,
> ++ pMask, 0, 0,
> ++ 1, midh,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ pMid = PtrAddBytes(pMid, pRasInfo->pixelStride);
> ++ midx++;
> ++ }
> ++ /* Process the central solid section if it is visible. */
> ++ if (midx < rx2 && midx < cx2) {
> ++ jint midw = ((rx2 < cx2) ? rx2 : cx2) - midx;
> ++ /* A NULL mask buffer means "all coverages are 0xff" */
> ++ (*pPrim->funcs.maskfill)(pMid,
> ++ NULL, 0, 0,
> ++ midw, midh,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ pMid = PtrCoord(pMid, midw, pRasInfo->pixelStride, 0, 0);
> ++ midx += midw;
> ++ }
> ++ /* Finally process the right "fractional column" if it is visible. */
> ++ if (midx < cx2) {
> ++ pMask[0] = DblToMask(x2);
> ++ /* Note: maskscan == 0 means we reuse this value for every row. */
> ++ (*pPrim->funcs.maskfill)(pMid,
> ++ pMask, 0, 0,
> ++ 1, midh,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ }
> ++ cy1 += midh;
> ++ pDst = PtrCoord(pDst, 0, 0, midh, scan);
> ++ }
> ++ /* Check for a visible "bottom fractional row" and process it */
> ++ if (cy1 < cy2) {
> ++ unsigned char midcov = DblToMask(y2);
> ++ jint x;
> ++ for (x = 0; x < width; x++) {
> ++ pMask[x] = midcov;
> ++ }
> ++ if (cx1 < rx1) {
> ++ pMask[0] = DblToMask(y2 * x1);
> ++ }
> ++ if (cx2 > rx2) {
> ++ pMask[width-1] = DblToMask(y2 * x2);
> ++ }
> ++ (*pPrim->funcs.maskfill)(pDst,
> ++ pMask, 0, 0,
> ++ width, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ }
> ++}
> ++
> ++/*
> ++ * Support code for arbitrary tracing and MaskFill filling of
> ++ * non-rectilinear (diagonal) parallelograms.
> ++ *
> ++ * This code is based upon the following model of AA coverage.
> ++ *
> ++ * Each edge of a parallelogram (for fillPgram) or a double
> ++ * parallelogram (inner and outer parallelograms for drawPgram)
> ++ * can be rasterized independently because the geometry is well
> ++ * defined in such a way that none of the sides will ever cross
> ++ * each other and they have a fixed ordering that is fairly
> ++ * well predetermined.
> ++ *
> ++ * So, for each edge we will look at the diagonal line that
> ++ * the edge makes as it passes through a row of pixels. Some
> ++ * such diagonal lines may pass entirely through the row of
> ++ * pixels in a single pixel column. Some may cut across the
> ++ * row and pass through several pixel columns before they pass
> ++ * on to the next row.
> ++ *
> ++ * As the edge passes through the row of pixels it will affect
> ++ * the coverage of the pixels it passes through as well as all
> ++ * of the pixels to the right of the edge. The coverage will
> ++ * either be increased (by a left edge of a parallelogram) or
> ++ * decreased (by a right edge) for all pixels to the right, until
> ++ * another edge passing the opposite direction is encountered.
> ++ *
> ++ * The coverage added or subtracted by an edge as it crosses a
> ++ * given pixel is calculated using a trapezoid formula in the
> ++ * following manner:
> ++ *
> ++ * /
> ++ * +-----+---/-+-----+
> ++ * | | / | |
> ++ * | | / | |
> ++ * +-----+/----+-----+
> ++ * /
> ++ *
> ++ * The area to the right of that edge for the pixel where it
> ++ * crosses is given as:
> ++ *
> ++ * trapheight * (topedge + bottomedge)/2
> ++ *
> ++ * Another thing to note is that the above formula gives the
> ++ * contribution of that edge to the given pixel where it crossed,
> ++ * but in so crossing the pixel row, it also created 100% coverage
> ++ * for all of the pixels to the right.
> ++ *
> ++ * This example was simplified in that the edge depicted crossed
> ++ * the complete pixel row and it did so entirely within the bounds
> ++ * of a single pixel column. In practice, many edges may start or
> ++ * end in a given row and thus provide only partial row coverage
> ++ * (i.e. the total "trapheight" in the formula never reaches 1.0).
> ++ * And in other cases, edges may travel sideways through several
> ++ * pixel columns on a given pixel row from where they enter it to
> ++ * where the leave it (which also mans that the trapheight for a
> ++ * given pixel will be less than 1.0, but by the time the edge
> ++ * completes its journey through the pixel row the "coverage shadow"
> ++ * that it casts on all pixels to the right eventually reaches 100%).
> ++ *
> ++ * In order to simplify the calculations so that we don't have to
> ++ * keep propagating coverages we calculate for one edge "until we
> ++ * reach another edge" we will process one edge at a time and
> ++ * simply record in a buffer the amount that an edge added to
> ++ * or subtracted from the coverage for a given pixel and its
> ++ * following right-side neighbors. Thus, the true total coverage
> ++ * of a given pixel is only determined by summing the deltas for
> ++ * that pixel and all of the pixels to its left. Since we already
> ++ * have to scan the buffer to change floating point coverages into
> ++ * mask values for a MaskFill loop, it is simple enough to sum the
> ++ * values as we perform that scan from left to right.
> ++ *
> ++ * In the above example, note that 2 deltas need to be recorded even
> ++ * though the edge only intersected a single pixel. The delta recorded
> ++ * for the pixel where the edge crossed will be approximately 55%
> ++ * (guesstimating by examining the poor ascii art) which is fine for
> ++ * determining how to render that pixel, but the rest of the pixels
> ++ * to its right should have their coverage modified by a full 100%
> ++ * and the 55% delta value we recorded for the pixel that the edge
> ++ * crossed will not get them there. We adjust for this by adding
> ++ * the "remainder" of the coverage implied by the shadow to the
> ++ * pixel immediately to the right of where we record a trapezoidal
> ++ * contribution. In this case a delta of 45% will be recorded in
> ++ * the pixel immediately to the right to raise the total to 100%.
> ++ *
> ++ * As we sum these delta values as we process the line from left
> ++ * to right, these delta values will typically drive the sum from
> ++ * 0% up to 100% and back down to 0% over the course of a single
> ++ * pixel row. In the case of a drawn (double) parallelogram the
> ++ * sum will go to 100% and back to 0% twice on most scanlines.
> ++ *
> ++ * The fillAAPgram and drawAAPgram functions drive the main flow
> ++ * of the algorithm with help from the following structures,
> ++ * macros, and functions. It is probably best to start with
> ++ * those 2 functions to gain an understanding of the algorithm.
> ++ */
> ++typedef struct {
> ++ jdouble x;
> ++ jdouble y;
> ++ jdouble xbot;
> ++ jdouble ybot;
> ++ jdouble xnexty;
> ++ jdouble ynextx;
> ++ jdouble xnextx;
> ++ jdouble linedx;
> ++ jdouble celldx;
> ++ jdouble celldy;
> ++ jboolean isTrailing;
> ++} EdgeInfo;
> ++
> ++#define MIN_DELTA (1.0/256.0)
> ++
> ++/*
> ++ * Calculates slopes and deltas for an edge and stores results in an EdgeInfo.
> ++ * Returns true if the edge was valid (i.e. not ignored for some reason).
> ++ */
> ++static jboolean
> ++storeEdge(EdgeInfo *pEdge,
> ++ jdouble x, jdouble y, jdouble dx, jdouble dy,
> ++ jint cx1, jint cy1, jint cx2, jint cy2,
> ++ jboolean isTrailing)
> ++{
> ++ jdouble xbot = x + dx;
> ++ jdouble ybot = y + dy;
> ++ jboolean ret;
> ++
> ++ pEdge->x = x;
> ++ pEdge->y = y;
> ++ pEdge->xbot = xbot;
> ++ pEdge->ybot = ybot;
> ++
> ++ /* Note that parallelograms are sorted so dy is always non-negative */
> ++ if (dy > MIN_DELTA && /* NaN and horizontal protection */
> ++ ybot > cy1 && /* NaN and "OUT_ABOVE" protection */
> ++ y < cy2 && /* NaN and "OUT_BELOW" protection */
> ++ xbot == xbot && /* NaN protection */
> ++ (x < cx2 || xbot < cx2)) /* "OUT_RIGHT" protection */
> ++ /* Note: "OUT_LEFT" segments may still contribute coverage... */
> ++ {
> ++ /* no NaNs, dy is not horizontal, and segment contributes to clip */
> ++ if (dx < -MIN_DELTA || dx > MIN_DELTA) {
> ++ /* dx is not vertical */
> ++ jdouble linedx;
> ++ jdouble celldy;
> ++ jdouble nextx;
> ++
> ++ linedx = dx / dy;
> ++ celldy = dy / dx;
> ++ if (y < cy1) {
> ++ pEdge->x = x = x + (cy1 - y) * linedx;
> ++ pEdge->y = y = cy1;
> ++ }
> ++ pEdge->linedx = linedx;
> ++ if (dx < 0) {
> ++ pEdge->celldx = -1.0;
> ++ pEdge->celldy = -celldy;
> ++ pEdge->xnextx = nextx = ceil(x) - 1.0;
> ++ } else {
> ++ pEdge->celldx = +1.0;
> ++ pEdge->celldy = celldy;
> ++ pEdge->xnextx = nextx = floor(x) + 1.0;
> ++ }
> ++ pEdge->ynextx = y + (nextx - x) * celldy;
> ++ pEdge->xnexty = x + ((floor(y) + 1) - y) * linedx;
> ++ } else {
> ++ /* dx is essentially vertical */
> ++ if (y < cy1) {
> ++ pEdge->y = y = cy1;
> ++ }
> ++ pEdge->xbot = x;
> ++ pEdge->linedx = 0.0;
> ++ pEdge->celldx = 0.0;
> ++ pEdge->celldy = 1.0;
> ++ pEdge->xnextx = x;
> ++ pEdge->xnexty = x;
> ++ pEdge->ynextx = ybot;
> ++ }
> ++ ret = JNI_TRUE;
> ++ } else {
> ++ /* There is some reason to ignore this segment, "celldy=0" omits it */
> ++ pEdge->ybot = y;
> ++ pEdge->linedx = dx;
> ++ pEdge->celldx = dx;
> ++ pEdge->celldy = 0.0;
> ++ pEdge->xnextx = xbot;
> ++ pEdge->xnexty = xbot;
> ++ pEdge->ynextx = y;
> ++ ret = JNI_FALSE;
> ++ }
> ++ pEdge->isTrailing = isTrailing;
> ++ return ret;
> ++}
> ++
> ++/*
> ++ * Calculates and stores slopes and deltas for all edges of a parallelogram.
> ++ * Returns true if at least 1 edge was valid (i.e. not ignored for some reason).
> ++ *
> ++ * The inverted flag is true for an outer parallelogram (left and right
> ++ * edges are leading and trailing) and false for an inner parallelogram
> ++ * (where the left edge is trailing and the right edge is leading).
> ++ */
> ++static jboolean
> ++storePgram(EdgeInfo *pLeftEdge, EdgeInfo *pRightEdge,
> ++ jdouble x, jdouble y,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2,
> ++ jint cx1, jint cy1, jint cx2, jint cy2,
> ++ jboolean inverted)
> ++{
> ++ jboolean ret = JNI_FALSE;
> ++ ret = (storeEdge(pLeftEdge + 0,
> ++ x , y , dx1, dy1,
> ++ cx1, cy1, cx2, cy2, inverted) || ret);
> ++ ret = (storeEdge(pLeftEdge + 1,
> ++ x+dx1, y+dy1, dx2, dy2,
> ++ cx1, cy1, cx2, cy2, inverted) || ret);
> ++ ret = (storeEdge(pRightEdge + 0,
> ++ x , y , dx2, dy2,
> ++ cx1, cy1, cx2, cy2, !inverted) || ret);
> ++ ret = (storeEdge(pRightEdge + 1,
> ++ x+dx2, y+dy2, dx1, dy1,
> ++ cx1, cy1, cx2, cy2, !inverted) || ret);
> ++ return ret;
> ++}
> ++
> ++/*
> ++ * The X0,Y0,X1,Y1 values represent a trapezoidal fragment whose
> ++ * coverage must be accounted for in the accum buffer.
> ++ *
> ++ * All four values are assumed to fall within (or on the edge of)
> ++ * a single pixel.
> ++ *
> ++ * The trapezoid area is accumulated into the proper element of
> ++ * the accum buffer and the remainder of the "slice height" is
> ++ * accumulated into the element to its right.
> ++ */
> ++#define INSERT_ACCUM(pACCUM, IMIN, IMAX, X0, Y0, X1, Y1, CX1, CX2, MULT) \
> ++ do { \
> ++ jdouble xmid = ((X0) + (X1)) * 0.5; \
> ++ if (xmid <= (CX2)) { \
> ++ jdouble sliceh = ((Y1) - (Y0)); \
> ++ jdouble slicearea; \
> ++ jint i; \
> ++ if (xmid < (CX1)) { \
> ++ /* Accumulate the entire slice height into accum[0]. */ \
> ++ i = 0; \
> ++ slicearea = sliceh; \
> ++ } else { \
> ++ jdouble xpos = floor(xmid); \
> ++ i = ((jint) xpos) - (CX1); \
> ++ slicearea = (xpos+1-xmid) * sliceh; \
> ++ } \
> ++ if (IMIN > i) { \
> ++ IMIN = i; \
> ++ } \
> ++ (pACCUM)[i++] += (jfloat) ((MULT) * slicearea); \
> ++ (pACCUM)[i++] += (jfloat) ((MULT) * (sliceh - slicearea)); \
> ++ if (IMAX < i) { \
> ++ IMAX = i; \
> ++ } \
> ++ } \
> ++ } while (0)
> ++
> ++/*
> ++ * Accumulate the contributions for a given edge crossing a given
> ++ * scan line into the corresponding entries of the accum buffer.
> ++ * CY1 is the Y coordinate of the top edge of the scanline and CY2
> ++ * is equal to (CY1 + 1) and is the Y coordinate of the bottom edge
> ++ * of the scanline. CX1 and CX2 are the left and right edges of the
> ++ * clip (or area of interest) being rendered.
> ++ *
> ++ * The edge is processed from the top edge to the bottom edge and
> ++ * a single pixel column at a time.
> ++ */
> ++#define ACCUM_EDGE(pEDGE, pACCUM, IMIN, IMAX, CX1, CY1, CX2, CY2) \
> ++ do { \
> ++ jdouble x, y, xnext, ynext, xlast, ylast, dx, dy, mult; \
> ++ y = (pEDGE)->y; \
> ++ dy = (pEDGE)->celldy; \
> ++ ylast = (pEDGE)->ybot; \
> ++ if (ylast <= (CY1) || y >= (CY2) || dy == 0.0) { \
> ++ break; \
> ++ } \
> ++ x = (pEDGE)->x; \
> ++ dx = (pEDGE)->celldx; \
> ++ if (ylast > (CY2)) { \
> ++ ylast = (CY2); \
> ++ xlast = (pEDGE)->xnexty; \
> ++ } else { \
> ++ xlast = (pEDGE)->xbot; \
> ++ } \
> ++ xnext = (pEDGE)->xnextx; \
> ++ ynext = (pEDGE)->ynextx; \
> ++ mult = ((pEDGE)->isTrailing) ? -1.0 : 1.0; \
> ++ while (ynext <= ylast) { \
> ++ INSERT_ACCUM(pACCUM, IMIN, IMAX, \
> ++ x, y, xnext, ynext, \
> ++ CX1, CX2, mult); \
> ++ x = xnext; \
> ++ y = ynext; \
> ++ xnext += dx; \
> ++ ynext += dy; \
> ++ } \
> ++ (pEDGE)->ynextx = ynext; \
> ++ (pEDGE)->xnextx = xnext; \
> ++ INSERT_ACCUM(pACCUM, IMIN, IMAX, \
> ++ x, y, xlast, ylast, \
> ++ CX1, CX2, mult); \
> ++ (pEDGE)->x = xlast; \
> ++ (pEDGE)->y = ylast; \
> ++ (pEDGE)->xnexty = xlast + (pEDGE)->linedx; \
> ++ } while(0)
> ++
> ++/* Main function to fill a single Parallelogram */
> ++static void
> ++fillAAPgram(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo,
> ++ CompositeInfo *pCompInfo, jint color, unsigned char *pMask,
> ++ void *pDst,
> ++ jdouble x1, jdouble y1,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2)
> ++{
> ++ jint cx1 = pRasInfo->bounds.x1;
> ++ jint cy1 = pRasInfo->bounds.y1;
> ++ jint cx2 = pRasInfo->bounds.x2;
> ++ jint cy2 = pRasInfo->bounds.y2;
> ++ jint width = cx2 - cx1;
> ++ EdgeInfo edges[4];
> ++ jfloat localaccum[MASK_BUF_LEN + 1];
> ++ jfloat *pAccum;
> ++
> ++ if (!storePgram(edges + 0, edges + 2,
> ++ x1, y1, dx1, dy1, dx2, dy2,
> ++ cx1, cy1, cx2, cy2,
> ++ JNI_FALSE))
> ++ {
> ++ return;
> ++ }
> ++
> ++ pAccum = ((width > MASK_BUF_LEN)
> ++ ? malloc((width + 1) * sizeof(jfloat))
> ++ : localaccum);
> ++ if (pAccum == NULL) {
> ++ return;
> ++ }
> ++ memset(pAccum, 0, (width+1) * sizeof(jfloat));
> ++
> ++ while (cy1 < cy2) {
> ++ jint lmin, lmax, rmin, rmax;
> ++ jint moff, x;
> ++ jdouble accum;
> ++ unsigned char lastcov;
> ++
> ++ lmin = rmin = width + 2;
> ++ lmax = rmax = 0;
> ++ ACCUM_EDGE(&edges[0], pAccum, lmin, lmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[1], pAccum, lmin, lmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[2], pAccum, rmin, rmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[3], pAccum, rmin, rmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ if (lmax > width) {
> ++ lmax = width; /* Extra col has data we do not need. */
> ++ }
> ++ if (rmax > width) {
> ++ rmax = width; /* Extra col has data we do not need. */
> ++ }
> ++ /* If ranges overlap, handle both in the first pass. */
> ++ if (rmin <= lmax) {
> ++ lmax = rmax;
> ++ }
> ++
> ++ x = lmin;
> ++ accum = 0.0;
> ++ moff = 0;
> ++ lastcov = 0;
> ++ while (x < lmax) {
> ++ accum += pAccum[x];
> ++ pAccum[x] = 0.0f;
> ++ pMask[moff++] = lastcov = DblToMask(accum);
> ++ x++;
> ++ }
> ++ /* Check for a solid center section. */
> ++ if (lastcov == 0xFF) {
> ++ jint endx;
> ++ void *pRow;
> ++
> ++ /* First process the existing partial coverage data. */
> ++ if (moff > 0) {
> ++ pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ pMask, 0, 0,
> ++ moff, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ moff = 0;
> ++ }
> ++
> ++ /* Where does the center section end? */
> ++ /* If there is no right AA edge in the accum buffer, then */
> ++ /* the right edge was beyond the clip, so fill out to width */
> ++ endx = (rmin < rmax) ? rmin : width;
> ++ if (x < endx) {
> ++ pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ NULL, 0, 0,
> ++ endx - x, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ x = endx;
> ++ }
> ++ } else if (lastcov > 0 && rmin >= rmax) {
> ++ /* We are not at 0 coverage, but there is no right edge, */
> ++ /* force a right edge so we process pixels out to width. */
> ++ rmax = width;
> ++ }
> ++ /* The following loop will process the right AA edge and/or any */
> ++ /* partial coverage center section not processed above. */
> ++ while (x < rmax) {
> ++ accum += pAccum[x];
> ++ pAccum[x] = 0.0f;
> ++ pMask[moff++] = DblToMask(accum);
> ++ x++;
> ++ }
> ++ if (moff > 0) {
> ++ void *pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ pMask, 0, 0,
> ++ moff, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ }
> ++ pDst = PtrAddBytes(pDst, pRasInfo->scanStride);
> ++ cy1++;
> ++ }
> ++ if (pAccum != localaccum) {
> ++ free(pAccum);
> ++ }
> ++}
> ++
> ++/*
> ++ * Class: sun_java2d_loops_MaskFill
> ++ * Method: FillAAPgram
> ++ * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDD)V
> ++ */
> ++JNIEXPORT void JNICALL
> ++Java_sun_java2d_loops_MaskFill_FillAAPgram
> ++ (JNIEnv *env, jobject self,
> ++ jobject sg2d, jobject sData, jobject comp,
> ++ jdouble x0, jdouble y0,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2)
> ++{
> ++ SurfaceDataOps *sdOps;
> ++ SurfaceDataRasInfo rasInfo;
> ++ NativePrimitive *pPrim;
> ++ CompositeInfo compInfo;
> ++ jint ix1, iy1, ix2, iy2;
> ++
> ++ if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) {
> ++ return;
> ++ }
> ++
> ++ /*
> ++ * Sort parallelogram by y values, ensure that each delta vector
> ++ * has a non-negative y delta.
> ++ */
> ++ SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, );
> ++
> ++ PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2, JNI_TRUE);
> ++ iy1 = (jint) floor(y0);
> ++ iy2 = (jint) ceil(y0 + dy1 + dy2);
> ++
> ++ pPrim = GetNativePrim(env, self);
> ++ if (pPrim == NULL) {
> ++ return;
> ++ }
> ++ if (pPrim->pCompType->getCompInfo != NULL) {
> ++ (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
> ++ }
> ++
> ++ sdOps = SurfaceData_GetOps(env, sData);
> ++ if (sdOps == 0) {
> ++ return;
> ++ }
> ++
> ++ GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
> ++ SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
> ++ if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
> ++ rasInfo.bounds.x2 <= rasInfo.bounds.x1)
> ++ {
> ++ return;
> ++ }
> ++
> ++ if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
> ++ return;
> ++ }
> ++
> ++ ix1 = rasInfo.bounds.x1;
> ++ iy1 = rasInfo.bounds.y1;
> ++ ix2 = rasInfo.bounds.x2;
> ++ iy2 = rasInfo.bounds.y2;
> ++ if (ix2 > ix1 && iy2 > iy1) {
> ++ jint width = ix2 - ix1;
> ++ jint color = GrPrim_Sg2dGetEaRGB(env, sg2d);
> ++ unsigned char localmask[MASK_BUF_LEN];
> ++ unsigned char *pMask = ((width > MASK_BUF_LEN)
> ++ ? malloc(width)
> ++ : localmask);
> ++
> ++ sdOps->GetRasInfo(env, sdOps, &rasInfo);
> ++ if (rasInfo.rasBase != NULL && pMask != NULL) {
> ++ void *pDst = PtrCoord(rasInfo.rasBase,
> ++ ix1, rasInfo.pixelStride,
> ++ iy1, rasInfo.scanStride);
> ++ if (dy1 == 0 && dx2 == 0) {
> ++ if (dx1 < 0) {
> ++ // We sorted by Y above, but not by X
> ++ x0 += dx1;
> ++ dx1 = -dx1;
> ++ }
> ++ fillAARect(pPrim, &rasInfo, &compInfo,
> ++ color, pMask, pDst,
> ++ x0, y0, x0+dx1, y0+dy2);
> ++ } else if (dx1 == 0 && dy2 == 0) {
> ++ if (dx2 < 0) {
> ++ // We sorted by Y above, but not by X
> ++ x0 += dx2;
> ++ dx2 = -dx2;
> ++ }
> ++ fillAARect(pPrim, &rasInfo, &compInfo,
> ++ color, pMask, pDst,
> ++ x0, y0, x0+dx2, y0+dy1);
> ++ } else {
> ++ fillAAPgram(pPrim, &rasInfo, &compInfo,
> ++ color, pMask, pDst,
> ++ x0, y0, dx1, dy1, dx2, dy2);
> ++ }
> ++ }
> ++ SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
> ++ if (pMask != NULL && pMask != localmask) {
> ++ free(pMask);
> ++ }
> + }
> + SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
> + }
> ++
> ++/* Main function to fill a double pair of (inner and outer) parallelograms */
> ++static void
> ++drawAAPgram(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo,
> ++ CompositeInfo *pCompInfo, jint color, unsigned char *pMask,
> ++ void *pDst,
> ++ jdouble ox0, jdouble oy0,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2,
> ++ jdouble ldx1, jdouble ldy1,
> ++ jdouble ldx2, jdouble ldy2)
> ++{
> ++ jint cx1 = pRasInfo->bounds.x1;
> ++ jint cy1 = pRasInfo->bounds.y1;
> ++ jint cx2 = pRasInfo->bounds.x2;
> ++ jint cy2 = pRasInfo->bounds.y2;
> ++ jint width = cx2 - cx1;
> ++ EdgeInfo edges[8];
> ++ jfloat localaccum[MASK_BUF_LEN + 1];
> ++ jfloat *pAccum;
> ++
> ++ if (!storePgram(edges + 0, edges + 6,
> ++ ox0, oy0,
> ++ dx1 + ldx1, dy1 + ldy1,
> ++ dx2 + ldx2, dy2 + ldy2,
> ++ cx1, cy1, cx2, cy2,
> ++ JNI_FALSE))
> ++ {
> ++ /* If outer pgram does not contribute, then inner cannot either. */
> ++ return;
> ++ }
> ++ storePgram(edges + 2, edges + 4,
> ++ ox0 + ldx1 + ldx2, oy0 + ldy1 + ldy2,
> ++ dx1 - ldx1, dy1 - ldy1,
> ++ dx2 - ldx2, dy2 - ldy2,
> ++ cx1, cy1, cx2, cy2,
> ++ JNI_TRUE);
> ++
> ++ pAccum = ((width > MASK_BUF_LEN)
> ++ ? malloc((width + 1) * sizeof(jfloat))
> ++ : localaccum);
> ++ if (pAccum == NULL) {
> ++ return;
> ++ }
> ++ memset(pAccum, 0, (width+1) * sizeof(jfloat));
> ++
> ++ while (cy1 < cy2) {
> ++ jint lmin, lmax, rmin, rmax;
> ++ jint moff, x;
> ++ jdouble accum;
> ++ unsigned char lastcov;
> ++
> ++ lmin = rmin = width + 2;
> ++ lmax = rmax = 0;
> ++ ACCUM_EDGE(&edges[0], pAccum, lmin, lmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[1], pAccum, lmin, lmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[2], pAccum, lmin, lmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[3], pAccum, lmin, lmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[4], pAccum, rmin, rmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[5], pAccum, rmin, rmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[6], pAccum, rmin, rmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ ACCUM_EDGE(&edges[7], pAccum, rmin, rmax,
> ++ cx1, cy1, cx2, cy1+1);
> ++ if (lmax > width) {
> ++ lmax = width; /* Extra col has data we do not need. */
> ++ }
> ++ if (rmax > width) {
> ++ rmax = width; /* Extra col has data we do not need. */
> ++ }
> ++ /* If ranges overlap, handle both in the first pass. */
> ++ if (rmin <= lmax) {
> ++ lmax = rmax;
> ++ }
> ++
> ++ x = lmin;
> ++ accum = 0.0;
> ++ moff = 0;
> ++ lastcov = 0;
> ++ while (x < lmax) {
> ++ accum += pAccum[x];
> ++ pAccum[x] = 0.0f;
> ++ pMask[moff++] = lastcov = DblToMask(accum);
> ++ x++;
> ++ }
> ++ /* Check for an empty or solidcenter section. */
> ++ if (lastcov == 0 || lastcov == 0xFF) {
> ++ jint endx;
> ++ void *pRow;
> ++
> ++ /* First process the existing partial coverage data. */
> ++ if (moff > 0) {
> ++ pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ pMask, 0, 0,
> ++ moff, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ moff = 0;
> ++ }
> ++
> ++ /* Where does the center section end? */
> ++ /* If there is no right AA edge in the accum buffer, then */
> ++ /* the right edge was beyond the clip, so fill out to width */
> ++ endx = (rmin < rmax) ? rmin : width;
> ++ if (x < endx) {
> ++ if (lastcov == 0xFF) {
> ++ pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ NULL, 0, 0,
> ++ endx - x, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ }
> ++ x = endx;
> ++ }
> ++ } else if (rmin >= rmax) {
> ++ /* We are not at 0 coverage, but there is no right edge, */
> ++ /* force a right edge so we process pixels out to width. */
> ++ rmax = width;
> ++ }
> ++ /* The following loop will process the right AA edge and/or any */
> ++ /* partial coverage center section not processed above. */
> ++ while (x < rmax) {
> ++ accum += pAccum[x];
> ++ pAccum[x] = 0.0f;
> ++ pMask[moff++] = lastcov = DblToMask(accum);
> ++ x++;
> ++ }
> ++ if (moff > 0) {
> ++ void *pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ pMask, 0, 0,
> ++ moff, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ }
> ++ if (lastcov == 0xFF && x < width) {
> ++ void *pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0);
> ++ (*pPrim->funcs.maskfill)(pRow,
> ++ NULL, 0, 0,
> ++ width - x, 1,
> ++ color, pRasInfo,
> ++ pPrim, pCompInfo);
> ++ }
> ++ pDst = PtrAddBytes(pDst, pRasInfo->scanStride);
> ++ cy1++;
> ++ }
> ++ if (pAccum != localaccum) {
> ++ free(pAccum);
> ++ }
> ++}
> ++
> ++/*
> ++ * Class: sun_java2d_loops_MaskFill
> ++ * Method: DrawAAPgram
> ++ * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDDDD)V
> ++ */
> ++JNIEXPORT void JNICALL
> ++Java_sun_java2d_loops_MaskFill_DrawAAPgram
> ++ (JNIEnv *env, jobject self,
> ++ jobject sg2d, jobject sData, jobject comp,
> ++ jdouble x0, jdouble y0,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2,
> ++ jdouble lw1, jdouble lw2)
> ++{
> ++ SurfaceDataOps *sdOps;
> ++ SurfaceDataRasInfo rasInfo;
> ++ NativePrimitive *pPrim;
> ++ CompositeInfo compInfo;
> ++ jint ix1, iy1, ix2, iy2;
> ++ jdouble ldx1, ldy1, ldx2, ldy2;
> ++ jdouble ox0, oy0;
> ++
> ++ if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) {
> ++ return;
> ++ }
> ++
> ++ /*
> ++ * Sort parallelogram by y values, ensure that each delta vector
> ++ * has a non-negative y delta.
> ++ */
> ++ SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2,
> ++ v = lw1; lw1 = lw2; lw2 = v;);
> ++
> ++ // dx,dy for line width in the "1" and "2" directions.
> ++ ldx1 = dx1 * lw1;
> ++ ldy1 = dy1 * lw1;
> ++ ldx2 = dx2 * lw2;
> ++ ldy2 = dy2 * lw2;
> ++
> ++ // calculate origin of the outer parallelogram
> ++ ox0 = x0 - (ldx1 + ldx2) / 2.0;
> ++ oy0 = y0 - (ldy1 + ldy2) / 2.0;
> ++
> ++ if (lw1 >= 1.0 || lw2 >= 1.0) {
> ++ /* Only need to fill an outer pgram if the interior no longer
> ++ * has a hole in it (i.e. if either of the line width ratios
> ++ * were greater than or equal to 1.0).
> ++ */
> ++ Java_sun_java2d_loops_MaskFill_FillAAPgram(env, self,
> ++ sg2d, sData, comp,
> ++ ox0, oy0,
> ++ dx1 + ldx1, dy1 + ldy1,
> ++ dx2 + ldx2, dy2 + ldy2);
> ++ return;
> ++ }
> ++
> ++ PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_TRUE);
> ++ iy1 = (jint) floor(oy0);
> ++ iy2 = (jint) ceil(oy0 + dy1 + ldy1 + dy2 + ldy2);
> ++
> ++ pPrim = GetNativePrim(env, self);
> ++ if (pPrim == NULL) {
> ++ return;
> ++ }
> ++ if (pPrim->pCompType->getCompInfo != NULL) {
> ++ (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
> ++ }
> ++
> ++ sdOps = SurfaceData_GetOps(env, sData);
> ++ if (sdOps == 0) {
> ++ return;
> ++ }
> ++
> ++ GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
> ++ SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
> ++ if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
> ++ rasInfo.bounds.x2 <= rasInfo.bounds.x1)
> ++ {
> ++ return;
> ++ }
> ++
> ++ if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
> ++ return;
> ++ }
> ++
> ++ ix1 = rasInfo.bounds.x1;
> ++ iy1 = rasInfo.bounds.y1;
> ++ ix2 = rasInfo.bounds.x2;
> ++ iy2 = rasInfo.bounds.y2;
> ++ if (ix2 > ix1 && iy2 > iy1) {
> ++ jint width = ix2 - ix1;
> ++ jint color = GrPrim_Sg2dGetEaRGB(env, sg2d);
> ++ unsigned char localmask[MASK_BUF_LEN];
> ++ unsigned char *pMask = ((width > MASK_BUF_LEN)
> ++ ? malloc(width)
> ++ : localmask);
> ++
> ++ sdOps->GetRasInfo(env, sdOps, &rasInfo);
> ++ if (rasInfo.rasBase != NULL && pMask != NULL) {
> ++ void *pDst = PtrCoord(rasInfo.rasBase,
> ++ ix1, rasInfo.pixelStride,
> ++ iy1, rasInfo.scanStride);
> ++ /*
> ++ * NOTE: aligned rects could probably be drawn
> ++ * even faster with a little work here.
> ++ * if (dy1 == 0 && dx2 == 0) {
> ++ * drawAARect(pPrim, &rasInfo, &compInfo,
> ++ * color, pMask, pDst,
> ++ * ox0, oy0, ox0+dx1+ldx1, oy0+dy2+ldy2, ldx1, ldy2);
> ++ * } else if (dx1 == 0 && dy2 == 0) {
> ++ * drawAARect(pPrim, &rasInfo, &compInfo,
> ++ * color, pMask, pDst,
> ++ * ox0, oy0, ox0+dx2+ldx2, oy0+dy1+ldy1, ldx2, ldy1);
> ++ * } else {
> ++ */
> ++ drawAAPgram(pPrim, &rasInfo, &compInfo,
> ++ color, pMask, pDst,
> ++ ox0, oy0,
> ++ dx1, dy1, dx2, dy2,
> ++ ldx1, ldy1, ldx2, ldy2);
> ++ /*
> ++ * }
> ++ */
> ++ }
> ++ SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
> ++ if (pMask != NULL && pMask != localmask) {
> ++ free(pMask);
> ++ }
> ++ }
> ++ SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
> ++}
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/share/native/sun/java2d/loops/ParallelogramUtils.h
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/ParallelogramUtils.h Tue Dec 14 13:25:29 2010 -0800
> +@@ -0,0 +1,83 @@
> ++/*
> ++ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
> ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> ++ *
> ++ * This code is free software; you can redistribute it and/or modify it
> ++ * under the terms of the GNU General Public License version 2 only, as
> ++ * published by the Free Software Foundation. Oracle designates this
> ++ * particular file as subject to the "Classpath" exception as provided
> ++ * by Oracle in the LICENSE file that accompanied this code.
> ++ *
> ++ * This code is distributed in the hope that it will be useful, but WITHOUT
> ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> ++ * version 2 for more details (a copy is included in the LICENSE file that
> ++ * accompanied this code).
> ++ *
> ++ * You should have received a copy of the GNU General Public License version
> ++ * 2 along with this work; if not, write to the Free Software Foundation,
> ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> ++ *
> ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> ++ * or visit www.oracle.com if you need additional information or have any
> ++ * questions.
> ++ */
> ++
> ++#ifndef ParallelogramUtils_h_Included
> ++#define ParallelogramUtils_h_Included
> ++
> ++#ifdef __cplusplus
> ++extern "C" {
> ++#endif
> ++
> ++#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2, AA) \
> ++ do { \
> ++ double vmin, vmax; \
> ++ if (dv1 < 0) { \
> ++ vmin = v0+dv1; \
> ++ vmax = v0; \
> ++ } else { \
> ++ vmin = v0; \
> ++ vmax = v0+dv1; \
> ++ } \
> ++ if (dv2 < 0) { \
> ++ vmin += dv2; \
> ++ } else { \
> ++ vmax += dv2; \
> ++ } \
> ++ if (AA) { \
> ++ bmin = (jint) floor(vmin); \
> ++ bmax = (jint) ceil(vmax); \
> ++ } else { \
> ++ bmin = (jint) floor(vmin + 0.5); \
> ++ bmax = (jint) floor(vmax + 0.5); \
> ++ } \
> ++ } while(0)
> ++
> ++#define PGRAM_INIT_X(starty, x, y, slope) \
> ++ (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
> ++
> ++/*
> ++ * Sort parallelogram by y values, ensure that each delta vector
> ++ * has a non-negative y delta.
> ++ */
> ++#define SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, OTHER_SWAP_CODE) \
> ++ do { \
> ++ if (dy1 < 0) { \
> ++ x0 += dx1; y0 += dy1; \
> ++ dx1 = -dx1; dy1 = -dy1; \
> ++ } \
> ++ if (dy2 < 0) { \
> ++ x0 += dx2; y0 += dy2; \
> ++ dx2 = -dx2; dy2 = -dy2; \
> ++ } \
> ++ /* Sort delta vectors so dxy1 is left of dxy2. */ \
> ++ if (dx1 * dy2 > dx2 * dy1) { \
> ++ double v; \
> ++ v = dx1; dx1 = dx2; dx2 = v; \
> ++ v = dy1; dy1 = dy2; dy2 = v; \
> ++ OTHER_SWAP_CODE \
> ++ } \
> ++ } while(0)
> ++
> ++#endif /* ParallelogramUtils_h_Included */
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c
> +--- openjdk.orig/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c Tue Dec 14 13:25:29 2010 -0800
> +@@ -517,13 +517,15 @@
> + ADD_SUFF(AnyIntSetRect)(pRasInfo, 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> + #else
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + if (cnstA != 0xff) {
> + fgColor = (cnstA << 24) | (cnstR << 16) | (cnstG << 8) | cnstB;
> + }
> + ADD_SUFF(AnyIntSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + #endif
> + return;
> + }
> +@@ -582,11 +584,13 @@
> + }
> +
> + if (pMask == NULL) {
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + fgColor = (cnstR << 24) | (cnstG << 16) | (cnstB << 8) | cnstA;
> + ADD_SUFF(Any4ByteSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + return;
> + }
> +
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c
> +--- openjdk.orig/jdk/src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c Fri Dec 10 16:14:04 2010 -0800
> ++++ openjdk/jdk/src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c Tue Dec 14 13:25:29 2010 -0800
> +@@ -150,10 +150,12 @@
> + }
> +
> + if (pMask == NULL) {
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + ADD_SUFF(AnyIntSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + return;
> + }
> +
> +@@ -214,15 +216,17 @@
> + cnstB = (fgColor ) & 0xff;
> +
> + if (pMask == NULL) {
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + if (cnstA == 0) {
> + fgColor = 0;
> + } else {
> + fgColor = (fgColor << 8) | cnstA;
> + }
> + ADD_SUFF(Any4ByteSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + return;
> + }
> +
> +@@ -390,10 +394,12 @@
> + if (cnstA == 0) fgColor = 0;
> +
> + if (pMask == NULL) {
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + ADD_SUFF(AnyIntSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + return;
> + }
> +
> +@@ -458,10 +464,12 @@
> + }
> +
> + if (pMask == NULL) {
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + ADD_SUFF(AnyIntSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + return;
> + }
> +
> +@@ -526,10 +534,12 @@
> + }
> +
> + if (pMask == NULL) {
> ++ void *pBase = pRasInfo->rasBase;
> ++ pRasInfo->rasBase = rasBase;
> + ADD_SUFF(Any3ByteSetRect)(pRasInfo,
> +- pRasInfo->bounds.x1, pRasInfo->bounds.y1,
> +- pRasInfo->bounds.x2, pRasInfo->bounds.y2,
> ++ 0, 0, width, height,
> + fgColor, pPrim, pCompInfo);
> ++ pRasInfo->rasBase = pBase;
> + return;
> + }
> +
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 test/java/awt/Graphics2D/RenderClipTest/6766342.tests
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/test/java/awt/Graphics2D/RenderClipTest/6766342.tests Tue Dec 14 13:25:29 2010 -0800
> +@@ -0,0 +1,3 @@
> ++Filled AA Pure Rect(5, 29.4, 10, 10)
> ++Stroked AA Pure Rect(5, 4.4, 10, 10)
> ++Stroked AA Line(20, 20, -10, 20)
> +diff -r 0eeac8ca33e3 -r 4d6f9aaa2600 test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java Tue Dec 14 13:25:29 2010 -0800
> +@@ -0,0 +1,1634 @@
> ++/*
> ++ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
> ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> ++ *
> ++ * This code is free software; you can redistribute it and/or modify it
> ++ * under the terms of the GNU General Public License version 2 only, as
> ++ * published by the Free Software Foundation.
> ++ *
> ++ * This code is distributed in the hope that it will be useful, but WITHOUT
> ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> ++ * version 2 for more details (a copy is included in the LICENSE file that
> ++ * accompanied this code).
> ++ *
> ++ * You should have received a copy of the GNU General Public License version
> ++ * 2 along with this work; if not, write to the Free Software Foundation,
> ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> ++ *
> ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> ++ * or visit www.oracle.com if you need additional information or have any
> ++ * questions.
> ++ */
> ++
> ++/*
> ++ * @test
> ++ * @bug 6766342
> ++ * @summary Tests clipping invariance for AA rectangle and line primitives
> ++ * @run main RenderClipTest -strict -readfile 6766342.tests
> ++ * @run main RenderClipTest -rectsuite -count 10
> ++ */
> ++
> ++import java.awt.*;
> ++import java.awt.geom.*;
> ++import java.awt.image.*;
> ++import java.awt.event.*;
> ++import java.util.Vector;
> ++import java.io.*;
> ++
> ++public class RenderClipTest {
> ++ public static double randDblCoord() {
> ++ return Math.random()*60 - 10;
> ++ }
> ++
> ++ public static float randFltCoord() {
> ++ return (float) randDblCoord();
> ++ }
> ++
> ++ public static int randIntCoord() {
> ++ return (int) Math.round(randDblCoord());
> ++ }
> ++
> ++ public static int randInt(int n) {
> ++ return ((int) (Math.random() * (n*4))) >> 2;
> ++ }
> ++
> ++ static int numtests;
> ++ static int numerrors;
> ++ static int numfillfailures;
> ++ static int numstrokefailures;
> ++ static int maxerr;
> ++
> ++ static boolean useAA;
> ++ static boolean strokePure;
> ++ static boolean testFill;
> ++ static boolean testDraw;
> ++ static boolean silent;
> ++ static boolean verbose;
> ++ static boolean strict;
> ++ static boolean showErrors;
> ++ static float lw;
> ++ static double rot;
> ++
> ++ static BufferedImage imgref;
> ++ static BufferedImage imgtst;
> ++
> ++ static Graphics2D grefclear;
> ++ static Graphics2D gtstclear;
> ++ static Graphics2D grefrender;
> ++ static Graphics2D gtstrender;
> ++
> ++ public static abstract class AnnotatedRenderOp {
> ++ public static AnnotatedRenderOp parse(String str) {
> ++ AnnotatedRenderOp ar;
> ++ if (((ar = Cubic.tryparse(str)) != null) ||
> ++ ((ar = Quad.tryparse(str)) != null) ||
> ++ ((ar = Poly.tryparse(str)) != null) ||
> ++ ((ar = Path.tryparse(str)) != null) ||
> ++ ((ar = Rect.tryparse(str)) != null) ||
> ++ ((ar = Line.tryparse(str)) != null) ||
> ++ ((ar = RectMethod.tryparse(str)) != null) ||
> ++ ((ar = LineMethod.tryparse(str)) != null))
> ++ {
> ++ return ar;
> ++ }
> ++ System.err.println("Unable to parse shape: "+str);
> ++ return null;
> ++ }
> ++
> ++ public abstract void randomize();
> ++
> ++ public abstract void fill(Graphics2D g2d);
> ++
> ++ public abstract void draw(Graphics2D g2d);
> ++ }
> ++
> ++ public static abstract class AnnotatedShapeOp extends AnnotatedRenderOp {
> ++ public abstract Shape getShape();
> ++
> ++ public void fill(Graphics2D g2d) {
> ++ g2d.fill(getShape());
> ++ }
> ++
> ++ public void draw(Graphics2D g2d) {
> ++ g2d.draw(getShape());
> ++ }
> ++ }
> ++
> ++ public static void usage(String err) {
> ++ if (err != null) {
> ++ System.err.println(err);
> ++ }
> ++ System.err.println("usage: java RenderClipTest "+
> ++ "[-read[file F]] [-rectsuite] [-fill] [-draw]");
> ++ System.err.println(" "+
> ++ "[-aa] [-pure] [-lw N] [-rot N]");
> ++ System.err.println(" "+
> ++ "[-rectmethod] [-linemethod] [-rect] [-line]");
> ++ System.err.println(" "+
> ++ "[-cubic] [-quad] [-poly] [-path]");
> ++ System.err.println(" "+
> ++ "[-silent] [-verbose] [-showerr] [-count N]");
> ++ System.err.println(" "+
> ++ "[-strict] [-usage]");
> ++ System.err.println(" -read Read test data from stdin");
> ++ System.err.println(" -readfile F Read test data from file F");
> ++ System.err.println(" -rectsuite Run a suite of rect/line tests");
> ++ System.err.println(" -fill Test g.fill*(...)");
> ++ System.err.println(" -draw Test g.draw*(...)");
> ++ System.err.println(" -aa Use antialiased rendering");
> ++ System.err.println(" -pure Use STROKE_PURE hint");
> ++ System.err.println(" -lw N Test line widths of N "+
> ++ "(default 1.0)");
> ++ System.err.println(" -rot N Test rotation by N degrees "+
> ++ "(default 0.0)");
> ++ System.err.println(" -rectmethod Test fillRect/drawRect methods");
> ++ System.err.println(" -linemethod Test drawLine method");
> ++ System.err.println(" -rect Test Rectangle2D shapes");
> ++ System.err.println(" -line Test Line2D shapes");
> ++ System.err.println(" -cubic Test CubicCurve2D shapes");
> ++ System.err.println(" -quad Test QuadCurve2D shapes");
> ++ System.err.println(" -poly Test Polygon shapes");
> ++ System.err.println(" -path Test GeneralPath shapes");
> ++ System.err.println(" -silent Do not print out error curves");
> ++ System.err.println(" -verbose Print out progress info");
> ++ System.err.println(" -showerr Display errors on screen");
> ++ System.err.println(" -count N N tests per shape, then exit "+
> ++ "(default 1000)");
> ++ System.err.println(" -strict All failures are important");
> ++ System.err.println(" -usage Print this help, then exit");
> ++ System.exit((err != null) ? -1 : 0);
> ++ }
> ++
> ++ public static void main(String argv[]) {
> ++ boolean readTests = false;
> ++ String readFile = null;
> ++ boolean rectsuite = false;
> ++ int count = 1000;
> ++ lw = 1.0f;
> ++ rot = 0.0;
> ++ Vector<AnnotatedRenderOp> testOps = new Vector<AnnotatedRenderOp>();
> ++ for (int i = 0; i < argv.length; i++) {
> ++ String arg = argv[i].toLowerCase();
> ++ if (arg.equals("-aa")) {
> ++ useAA = true;
> ++ } else if (arg.equals("-pure")) {
> ++ strokePure = true;
> ++ } else if (arg.equals("-fill")) {
> ++ testFill = true;
> ++ } else if (arg.equals("-draw")) {
> ++ testDraw = true;
> ++ } else if (arg.equals("-lw")) {
> ++ if (i+1 >= argv.length) {
> ++ usage("Missing argument: "+argv[i]);
> ++ }
> ++ lw = Float.parseFloat(argv[++i]);
> ++ } else if (arg.equals("-rot")) {
> ++ if (i+1 >= argv.length) {
> ++ usage("Missing argument: "+argv[i]);
> ++ }
> ++ rot = Double.parseDouble(argv[++i]);
> ++ } else if (arg.equals("-cubic")) {
> ++ testOps.add(new Cubic());
> ++ } else if (arg.equals("-quad")) {
> ++ testOps.add(new Quad());
> ++ } else if (arg.equals("-poly")) {
> ++ testOps.add(new Poly());
> ++ } else if (arg.equals("-path")) {
> ++ testOps.add(new Path());
> ++ } else if (arg.equals("-rect")) {
> ++ testOps.add(new Rect());
> ++ } else if (arg.equals("-line")) {
> ++ testOps.add(new Line());
> ++ } else if (arg.equals("-rectmethod")) {
> ++ testOps.add(new RectMethod());
> ++ } else if (arg.equals("-linemethod")) {
> ++ testOps.add(new LineMethod());
> ++ } else if (arg.equals("-verbose")) {
> ++ verbose = true;
> ++ } else if (arg.equals("-strict")) {
> ++ strict = true;
> ++ } else if (arg.equals("-silent")) {
> ++ silent = true;
> ++ } else if (arg.equals("-showerr")) {
> ++ showErrors = true;
> ++ } else if (arg.equals("-readfile")) {
> ++ if (i+1 >= argv.length) {
> ++ usage("Missing argument: "+argv[i]);
> ++ }
> ++ readTests = true;
> ++ readFile = argv[++i];
> ++ } else if (arg.equals("-read")) {
> ++ readTests = true;
> ++ readFile = null;
> ++ } else if (arg.equals("-rectsuite")) {
> ++ rectsuite = true;
> ++ } else if (arg.equals("-count")) {
> ++ if (i+1 >= argv.length) {
> ++ usage("Missing argument: "+argv[i]);
> ++ }
> ++ count = Integer.parseInt(argv[++i]);
> ++ } else if (arg.equals("-usage")) {
> ++ usage(null);
> ++ } else {
> ++ usage("Unknown argument: "+argv[i]);
> ++ }
> ++ }
> ++ if (readTests) {
> ++ if (rectsuite || testDraw || testFill ||
> ++ useAA || strokePure ||
> ++ lw != 1.0f || rot != 0.0 ||
> ++ testOps.size() > 0)
> ++ {
> ++ usage("Should not specify test types with -read options");
> ++ }
> ++ } else if (rectsuite) {
> ++ if (testDraw || testFill ||
> ++ useAA || strokePure ||
> ++ lw != 1.0f || rot != 0.0 ||
> ++ testOps.size() > 0)
> ++ {
> ++ usage("Should not specify test types with -rectsuite option");
> ++ }
> ++ } else {
> ++ if (!testDraw && !testFill) {
> ++ usage("No work: Must specify one or both of "+
> ++ "-fill or -draw");
> ++ }
> ++ if (testOps.size() == 0) {
> ++ usage("No work: Must specify one or more of "+
> ++ "-rect[method], -line[method], "+
> ++ "-cubic, -quad, -poly, or -path");
> ++ }
> ++ }
> ++ initImages();
> ++ if (readTests) {
> ++ try {
> ++ InputStream is;
> ++ if (readFile == null) {
> ++ is = System.in;
> ++ } else {
> ++ File f =
> ++ new File(System.getProperty("test.src", "."),
> ++ readFile);
> ++ is = new FileInputStream(f);
> ++ }
> ++ parseAndRun(is);
> ++ } catch (IOException e) {
> ++ throw new RuntimeException(e);
> ++ }
> ++ } else if (rectsuite) {
> ++ runRectSuite(count);
> ++ } else {
> ++ initGCs();
> ++ for (int k = 0; k < testOps.size(); k++) {
> ++ AnnotatedRenderOp ar = testOps.get(k);
> ++ runRandomTests(ar, count);
> ++ }
> ++ disposeGCs();
> ++ }
> ++ grefclear.dispose();
> ++ gtstclear.dispose();
> ++ grefclear = gtstclear = null;
> ++ reportStatistics();
> ++ }
> ++
> ++ public static int reportStatistics() {
> ++ String connector = "";
> ++ if (numfillfailures > 0) {
> ++ System.out.print(numfillfailures+" fills ");
> ++ connector = "and ";
> ++ }
> ++ if (numstrokefailures > 0) {
> ++ System.out.print(connector+numstrokefailures+" strokes ");
> ++ }
> ++ int totalfailures = numfillfailures + numstrokefailures;
> ++ if (totalfailures == 0) {
> ++ System.out.print("0 ");
> ++ }
> ++ System.out.println("out of "+numtests+" tests failed...");
> ++ int critical = numerrors;
> ++ if (strict) {
> ++ critical += totalfailures;
> ++ }
> ++ if (critical > 0) {
> ++ throw new RuntimeException(critical+" tests had critical errors");
> ++ }
> ++ System.out.println("No tests had critical errors");
> ++ return (numerrors+totalfailures);
> ++ }
> ++
> ++ public static void runRectSuite(int count) {
> ++ AnnotatedRenderOp ops[] = {
> ++ new Rect(),
> ++ new RectMethod(),
> ++ new Line(),
> ++ new LineMethod(),
> ++ };
> ++ // Sometimes different fill algorithms are chosen for
> ++ // thin and wide line modes, make sure we test both...
> ++ float filllinewidths[] = { 0.0f, 2.0f };
> ++ float drawlinewidths[] = { 0.0f, 0.5f, 1.0f,
> ++ 2.0f, 2.5f,
> ++ 5.0f, 5.3f };
> ++ double rotations[] = { 0.0, 15.0, 90.0,
> ++ 135.0, 180.0,
> ++ 200.0, 270.0,
> ++ 300.0};
> ++ for (AnnotatedRenderOp ar: ops) {
> ++ for (double r: rotations) {
> ++ rot = r;
> ++ for (int i = 0; i < 8; i++) {
> ++ float linewidths[];
> ++ if ((i & 1) == 0) {
> ++ if ((ar instanceof Line) ||
> ++ (ar instanceof LineMethod))
> ++ {
> ++ continue;
> ++ }
> ++ testFill = true;
> ++ testDraw = false;
> ++ linewidths = filllinewidths;
> ++ } else {
> ++ testFill = false;
> ++ testDraw = true;
> ++ linewidths = drawlinewidths;
> ++ }
> ++ useAA = ((i & 2) != 0);
> ++ strokePure = ((i & 4) != 0);
> ++ for (float w : linewidths) {
> ++ lw = w;
> ++ runSuiteTests(ar, count);
> ++ }
> ++ }
> ++ }
> ++ }
> ++ }
> ++
> ++ public static void runSuiteTests(AnnotatedRenderOp ar, int count) {
> ++ if (verbose) {
> ++ System.out.print("Running ");
> ++ System.out.print(testFill ? "Fill " : "Draw ");
> ++ System.out.print(BaseName(ar));
> ++ if (useAA) {
> ++ System.out.print(" AA");
> ++ }
> ++ if (strokePure) {
> ++ System.out.print(" Pure");
> ++ }
> ++ if (lw != 1.0f) {
> ++ System.out.print(" lw="+lw);
> ++ }
> ++ if (rot != 0.0f) {
> ++ System.out.print(" rot="+rot);
> ++ }
> ++ System.out.println();
> ++ }
> ++ initGCs();
> ++ runRandomTests(ar, count);
> ++ disposeGCs();
> ++ }
> ++
> ++ public static String BaseName(AnnotatedRenderOp ar) {
> ++ String s = ar.toString();
> ++ int leftparen = s.indexOf('(');
> ++ if (leftparen >= 0) {
> ++ s = s.substring(0, leftparen);
> ++ }
> ++ return s;
> ++ }
> ++
> ++ public static void runRandomTests(AnnotatedRenderOp ar, int count) {
> ++ for (int i = 0; i < count; i++) {
> ++ ar.randomize();
> ++ if (testDraw) {
> ++ test(ar, false);
> ++ }
> ++ if (testFill) {
> ++ test(ar, true);
> ++ }
> ++ }
> ++ }
> ++
> ++ public static void initImages() {
> ++ imgref = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
> ++ imgtst = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
> ++ grefclear = imgref.createGraphics();
> ++ gtstclear = imgtst.createGraphics();
> ++ grefclear.setColor(Color.white);
> ++ gtstclear.setColor(Color.white);
> ++ }
> ++
> ++ public static void initGCs() {
> ++ grefrender = imgref.createGraphics();
> ++ gtstrender = imgtst.createGraphics();
> ++ gtstrender.clipRect(10, 10, 20, 20);
> ++ grefrender.setColor(Color.blue);
> ++ gtstrender.setColor(Color.blue);
> ++ if (lw != 1.0f) {
> ++ BasicStroke bs = new BasicStroke(lw);
> ++ grefrender.setStroke(bs);
> ++ gtstrender.setStroke(bs);
> ++ }
> ++ if (rot != 0.0) {
> ++ double rotrad = Math.toRadians(rot);
> ++ grefrender.rotate(rotrad, 20, 20);
> ++ gtstrender.rotate(rotrad, 20, 20);
> ++ }
> ++ if (strokePure) {
> ++ grefrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
> ++ RenderingHints.VALUE_STROKE_PURE);
> ++ gtstrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
> ++ RenderingHints.VALUE_STROKE_PURE);
> ++ }
> ++ if (useAA) {
> ++ grefrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
> ++ RenderingHints.VALUE_ANTIALIAS_ON);
> ++ gtstrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
> ++ RenderingHints.VALUE_ANTIALIAS_ON);
> ++ maxerr = 1;
> ++ }
> ++ }
> ++
> ++ public static void disposeGCs() {
> ++ grefrender.dispose();
> ++ gtstrender.dispose();
> ++ grefrender = gtstrender = null;
> ++ }
> ++
> ++ public static void parseAndRun(InputStream in) throws IOException {
> ++ BufferedReader br = new BufferedReader(new InputStreamReader(in));
> ++ String str;
> ++ while ((str = br.readLine()) != null) {
> ++ if (str.startsWith("Stroked ") || str.startsWith("Filled ")) {
> ++ parseTest(str);
> ++ continue;
> ++ }
> ++ if (str.startsWith("Running ")) {
> ++ continue;
> ++ }
> ++ if (str.startsWith("Failed: ")) {
> ++ continue;
> ++ }
> ++ if (str.indexOf(" out of ") > 0 &&
> ++ str.indexOf(" tests failed...") > 0)
> ++ {
> ++ continue;
> ++ }
> ++ if (str.indexOf(" tests had critical errors") > 0) {
> ++ continue;
> ++ }
> ++ System.err.println("Unparseable line: "+str);
> ++ }
> ++ }
> ++
> ++ public static void parseTest(String origstr) {
> ++ String str = origstr;
> ++ boolean isfill = false;
> ++ useAA = strokePure = false;
> ++ lw = 1.0f;
> ++ rot = 0.0;
> ++ if (str.startsWith("Stroked ")) {
> ++ str = str.substring(8);
> ++ isfill = false;
> ++ } else if (str.startsWith("Filled ")) {
> ++ str = str.substring(7);
> ++ isfill = true;
> ++ } else {
> ++ System.err.println("Unparseable test line: "+origstr);
> ++ }
> ++ if (str.startsWith("AA ")) {
> ++ str = str.substring(3);
> ++ useAA = true;
> ++ }
> ++ if (str.startsWith("Pure ")) {
> ++ str = str.substring(5);
> ++ strokePure = true;
> ++ }
> ++ if (str.startsWith("Lw=")) {
> ++ int index = str.indexOf(' ', 3);
> ++ if (index > 0) {
> ++ lw = Float.parseFloat(str.substring(3, index));
> ++ str = str.substring(index+1);
> ++ }
> ++ }
> ++ if (str.startsWith("Rot=")) {
> ++ int index = str.indexOf(' ', 4);
> ++ if (index > 0) {
> ++ rot = Double.parseDouble(str.substring(4, index));
> ++ str = str.substring(index+1);
> ++ }
> ++ }
> ++ AnnotatedRenderOp ar = AnnotatedRenderOp.parse(str);
> ++ if (ar != null) {
> ++ initGCs();
> ++ test(ar, isfill);
> ++ disposeGCs();
> ++ } else {
> ++ System.err.println("Unparseable test line: "+origstr);
> ++ }
> ++ }
> ++
> ++ public static void test(AnnotatedRenderOp ar, boolean isfill) {
> ++ grefclear.fillRect(0, 0, 40, 40);
> ++ gtstclear.fillRect(0, 0, 40, 40);
> ++ if (isfill) {
> ++ ar.fill(grefrender);
> ++ ar.fill(gtstrender);
> ++ } else {
> ++ ar.draw(grefrender);
> ++ ar.draw(gtstrender);
> ++ }
> ++ check(imgref, imgtst, ar, isfill);
> ++ }
> ++
> ++ public static int[] getData(BufferedImage img) {
> ++ Raster r = img.getRaster();
> ++ DataBufferInt dbi = (DataBufferInt) r.getDataBuffer();
> ++ return dbi.getData();
> ++ }
> ++
> ++ public static int getScan(BufferedImage img) {
> ++ Raster r = img.getRaster();
> ++ SinglePixelPackedSampleModel sppsm =
> ++ (SinglePixelPackedSampleModel) r.getSampleModel();
> ++ return sppsm.getScanlineStride();
> ++ }
> ++
> ++ public static int getOffset(BufferedImage img) {
> ++ Raster r = img.getRaster();
> ++ SinglePixelPackedSampleModel sppsm =
> ++ (SinglePixelPackedSampleModel) r.getSampleModel();
> ++ return sppsm.getOffset(-r.getSampleModelTranslateX(),
> ++ -r.getSampleModelTranslateY());
> ++ }
> ++
> ++ final static int opaque = 0xff000000;
> ++ final static int whitergb = Color.white.getRGB();
> ++
> ++ public static final int maxdiff(int rgb1, int rgb2) {
> ++ int maxd = 0;
> ++ for (int i = 0; i < 32; i += 8) {
> ++ int c1 = (rgb1 >> i) & 0xff;
> ++ int c2 = (rgb2 >> i) & 0xff;
> ++ int d = Math.abs(c1-c2);
> ++ if (maxd < d) {
> ++ maxd = d;
> ++ }
> ++ }
> ++ return maxd;
> ++ }
> ++
> ++ public static void check(BufferedImage imgref, BufferedImage imgtst,
> ++ AnnotatedRenderOp ar, boolean wasfill)
> ++ {
> ++ numtests++;
> ++ int dataref[] = getData(imgref);
> ++ int datatst[] = getData(imgtst);
> ++ int scanref = getScan(imgref);
> ++ int scantst = getScan(imgtst);
> ++ int offref = getOffset(imgref);
> ++ int offtst = getOffset(imgtst);
> ++
> ++ // We want to check for errors outside the clip at a higher
> ++ // priority than errors involving different pixels touched
> ++ // inside the clip.
> ++
> ++ // Check above clip
> ++ if (check(ar, wasfill,
> ++ null, 0, 0,
> ++ datatst, scantst, offtst,
> ++ 0, 0, 40, 10))
> ++ {
> ++ return;
> ++ }
> ++ // Check below clip
> ++ if (check(ar, wasfill,
> ++ null, 0, 0,
> ++ datatst, scantst, offtst,
> ++ 0, 30, 40, 40))
> ++ {
> ++ return;
> ++ }
> ++ // Check left of clip
> ++ if (check(ar, wasfill,
> ++ null, 0, 0,
> ++ datatst, scantst, offtst,
> ++ 0, 10, 10, 30))
> ++ {
> ++ return;
> ++ }
> ++ // Check right of clip
> ++ if (check(ar, wasfill,
> ++ null, 0, 0,
> ++ datatst, scantst, offtst,
> ++ 30, 10, 40, 30))
> ++ {
> ++ return;
> ++ }
> ++ // Check inside clip
> ++ check(ar, wasfill,
> ++ dataref, scanref, offref,
> ++ datatst, scantst, offtst,
> ++ 10, 10, 30, 30);
> ++ }
> ++
> ++ public static boolean check(AnnotatedRenderOp ar, boolean wasfill,
> ++ int dataref[], int scanref, int offref,
> ++ int datatst[], int scantst, int offtst,
> ++ int x0, int y0, int x1, int y1)
> ++ {
> ++ offref += scanref * y0;
> ++ offtst += scantst * y0;
> ++ for (int y = y0; y < y1; y++) {
> ++ for (int x = x0; x < x1; x++) {
> ++ boolean failed;
> ++ String reason;
> ++ int rgbref;
> ++ int rgbtst;
> ++
> ++ rgbtst = datatst[offtst+x] | opaque;
> ++ if (dataref == null) {
> ++ /* Outside of clip, must be white, no error tolerance */
> ++ rgbref = whitergb;
> ++ failed = (rgbtst != rgbref);
> ++ reason = "stray pixel rendered outside of clip";
> ++ } else {
> ++ /* Inside of clip, check for maxerr delta in components */
> ++ rgbref = dataref[offref+x] | opaque;
> ++ failed = (rgbref != rgbtst &&
> ++ maxdiff(rgbref, rgbtst) > maxerr);
> ++ reason = "different pixel rendered inside clip";
> ++ }
> ++ if (failed) {
> ++ if (dataref == null) {
> ++ numerrors++;
> ++ }
> ++ if (wasfill) {
> ++ numfillfailures++;
> ++ } else {
> ++ numstrokefailures++;
> ++ }
> ++ if (!silent) {
> ++ System.out.println("Failed: "+reason+" at "+x+", "+y+
> ++ " ["+Integer.toHexString(rgbref)+
> ++ " != "+Integer.toHexString(rgbtst)+
> ++ "]");
> ++ System.out.print(wasfill ? "Filled " : "Stroked ");
> ++ if (useAA) System.out.print("AA ");
> ++ if (strokePure) System.out.print("Pure ");
> ++ if (lw != 1) System.out.print("Lw="+lw+" ");
> ++ if (rot != 0) System.out.print("Rot="+rot+" ");
> ++ System.out.println(ar);
> ++ }
> ++ if (showErrors) {
> ++ show(imgref, imgtst);
> ++ }
> ++ return true;
> ++ }
> ++ }
> ++ offref += scanref;
> ++ offtst += scantst;
> ++ }
> ++ return false;
> ++ }
> ++
> ++ static ErrorWindow errw;
> ++
> ++ public static void show(BufferedImage imgref, BufferedImage imgtst) {
> ++ ErrorWindow errw = new ErrorWindow();
> ++ errw.setImages(imgref, imgtst);
> ++ errw.setVisible(true);
> ++ errw.waitForHide();
> ++ errw.dispose();
> ++ }
> ++
> ++ public static class Cubic extends AnnotatedShapeOp {
> ++ public static Cubic tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("Cubic(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(6);
> ++ double coords[] = new double[8];
> ++ boolean foundparen = false;
> ++ for (int i = 0; i < coords.length; i++) {
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ if (i < coords.length-1) {
> ++ return null;
> ++ }
> ++ index = str.indexOf(")");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ foundparen = true;
> ++ }
> ++ String num = str.substring(0, index);
> ++ try {
> ++ coords[i] = Double.parseDouble(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ }
> ++ if (!foundparen || str.length() > 0) {
> ++ return null;
> ++ }
> ++ Cubic c = new Cubic();
> ++ c.cubic.setCurve(coords[0], coords[1],
> ++ coords[2], coords[3],
> ++ coords[4], coords[5],
> ++ coords[6], coords[7]);
> ++ return c;
> ++ }
> ++
> ++ private CubicCurve2D cubic = new CubicCurve2D.Double();
> ++
> ++ public void randomize() {
> ++ cubic.setCurve(randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord());
> ++ }
> ++
> ++ public Shape getShape() {
> ++ return cubic;
> ++ }
> ++
> ++ public String toString() {
> ++ return ("Cubic("+
> ++ cubic.getX1()+", "+
> ++ cubic.getY1()+", "+
> ++ cubic.getCtrlX1()+", "+
> ++ cubic.getCtrlY1()+", "+
> ++ cubic.getCtrlX2()+", "+
> ++ cubic.getCtrlY2()+", "+
> ++ cubic.getX2()+", "+
> ++ cubic.getY2()
> ++ +")");
> ++ }
> ++ }
> ++
> ++ public static class Quad extends AnnotatedShapeOp {
> ++ public static Quad tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("Quad(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(5);
> ++ double coords[] = new double[6];
> ++ boolean foundparen = false;
> ++ for (int i = 0; i < coords.length; i++) {
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ if (i < coords.length-1) {
> ++ return null;
> ++ }
> ++ index = str.indexOf(")");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ foundparen = true;
> ++ }
> ++ String num = str.substring(0, index);
> ++ try {
> ++ coords[i] = Double.parseDouble(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ }
> ++ if (!foundparen || str.length() > 0) {
> ++ return null;
> ++ }
> ++ Quad c = new Quad();
> ++ c.quad.setCurve(coords[0], coords[1],
> ++ coords[2], coords[3],
> ++ coords[4], coords[5]);
> ++ return c;
> ++ }
> ++
> ++ private QuadCurve2D quad = new QuadCurve2D.Double();
> ++
> ++ public void randomize() {
> ++ quad.setCurve(randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord());
> ++ }
> ++
> ++ public Shape getShape() {
> ++ return quad;
> ++ }
> ++
> ++ public String toString() {
> ++ return ("Quad("+
> ++ quad.getX1()+", "+
> ++ quad.getY1()+", "+
> ++ quad.getCtrlX()+", "+
> ++ quad.getCtrlY()+", "+
> ++ quad.getX2()+", "+
> ++ quad.getY2()
> ++ +")");
> ++ }
> ++ }
> ++
> ++ public static class Poly extends AnnotatedShapeOp {
> ++ public static Poly tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("Poly(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(5);
> ++ Polygon p = new Polygon();
> ++ while (true) {
> ++ int x, y;
> ++ str = str.trim();
> ++ if (str.startsWith(")")) {
> ++ str = str.substring(1);
> ++ break;
> ++ }
> ++ if (p.npoints > 0) {
> ++ if (str.startsWith(",")) {
> ++ str = str.substring(2).trim();
> ++ } else {
> ++ return null;
> ++ }
> ++ }
> ++ if (str.startsWith("[")) {
> ++ str = str.substring(1);
> ++ } else {
> ++ return null;
> ++ }
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ String num = str.substring(0, index);
> ++ try {
> ++ x = Integer.parseInt(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ index = str.indexOf("]");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ num = str.substring(0, index).trim();
> ++ try {
> ++ y = Integer.parseInt(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ p.addPoint(x, y);
> ++ }
> ++ if (str.length() > 0) {
> ++ return null;
> ++ }
> ++ if (p.npoints < 3) {
> ++ return null;
> ++ }
> ++ return new Poly(p);
> ++ }
> ++
> ++ private Polygon poly;
> ++
> ++ public Poly() {
> ++ this.poly = new Polygon();
> ++ }
> ++
> ++ private Poly(Polygon p) {
> ++ this.poly = p;
> ++ }
> ++
> ++ public void randomize() {
> ++ poly.reset();
> ++ poly.addPoint(randIntCoord(), randIntCoord());
> ++ poly.addPoint(randIntCoord(), randIntCoord());
> ++ poly.addPoint(randIntCoord(), randIntCoord());
> ++ poly.addPoint(randIntCoord(), randIntCoord());
> ++ poly.addPoint(randIntCoord(), randIntCoord());
> ++ }
> ++
> ++ public Shape getShape() {
> ++ return poly;
> ++ }
> ++
> ++ public String toString() {
> ++ StringBuffer sb = new StringBuffer(100);
> ++ sb.append("Poly(");
> ++ for (int i = 0; i < poly.npoints; i++) {
> ++ if (i != 0) {
> ++ sb.append(", ");
> ++ }
> ++ sb.append("[");
> ++ sb.append(poly.xpoints[i]);
> ++ sb.append(", ");
> ++ sb.append(poly.ypoints[i]);
> ++ sb.append("]");
> ++ }
> ++ sb.append(")");
> ++ return sb.toString();
> ++ }
> ++ }
> ++
> ++ public static class Path extends AnnotatedShapeOp {
> ++ public static Path tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("Path(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(5);
> ++ GeneralPath gp = new GeneralPath();
> ++ float coords[] = new float[6];
> ++ int numsegs = 0;
> ++ while (true) {
> ++ int type;
> ++ int n;
> ++ str = str.trim();
> ++ if (str.startsWith(")")) {
> ++ str = str.substring(1);
> ++ break;
> ++ }
> ++ if (str.startsWith("M[")) {
> ++ type = PathIterator.SEG_MOVETO;
> ++ n = 2;
> ++ } else if (str.startsWith("L[")) {
> ++ type = PathIterator.SEG_LINETO;
> ++ n = 2;
> ++ } else if (str.startsWith("Q[")) {
> ++ type = PathIterator.SEG_QUADTO;
> ++ n = 4;
> ++ } else if (str.startsWith("C[")) {
> ++ type = PathIterator.SEG_CUBICTO;
> ++ n = 6;
> ++ } else if (str.startsWith("E[")) {
> ++ type = PathIterator.SEG_CLOSE;
> ++ n = 0;
> ++ } else {
> ++ return null;
> ++ }
> ++ str = str.substring(2);
> ++ if (n == 0) {
> ++ if (str.startsWith("]")) {
> ++ str = str.substring(1);
> ++ } else {
> ++ return null;
> ++ }
> ++ }
> ++ for (int i = 0; i < n; i++) {
> ++ int index;
> ++ if (i < n-1) {
> ++ index = str.indexOf(",");
> ++ } else {
> ++ index = str.indexOf("]");
> ++ }
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ String num = str.substring(0, index);
> ++ try {
> ++ coords[i] = Float.parseFloat(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1).trim();
> ++ }
> ++ switch (type) {
> ++ case PathIterator.SEG_MOVETO:
> ++ gp.moveTo(coords[0], coords[1]);
> ++ break;
> ++ case PathIterator.SEG_LINETO:
> ++ gp.lineTo(coords[0], coords[1]);
> ++ break;
> ++ case PathIterator.SEG_QUADTO:
> ++ gp.quadTo(coords[0], coords[1],
> ++ coords[2], coords[3]);
> ++ break;
> ++ case PathIterator.SEG_CUBICTO:
> ++ gp.curveTo(coords[0], coords[1],
> ++ coords[2], coords[3],
> ++ coords[4], coords[5]);
> ++ break;
> ++ case PathIterator.SEG_CLOSE:
> ++ gp.closePath();
> ++ break;
> ++ }
> ++ numsegs++;
> ++ }
> ++ if (str.length() > 0) {
> ++ return null;
> ++ }
> ++ if (numsegs < 2) {
> ++ return null;
> ++ }
> ++ return new Path(gp);
> ++ }
> ++
> ++ private GeneralPath path;
> ++
> ++ public Path() {
> ++ this.path = new GeneralPath();
> ++ }
> ++
> ++ private Path(GeneralPath gp) {
> ++ this.path = gp;
> ++ }
> ++
> ++ public void randomize() {
> ++ path.reset();
> ++ path.moveTo(randFltCoord(), randFltCoord());
> ++ for (int i = randInt(5)+3; i > 0; --i) {
> ++ switch(randInt(5)) {
> ++ case 0:
> ++ path.moveTo(randFltCoord(), randFltCoord());
> ++ break;
> ++ case 1:
> ++ path.lineTo(randFltCoord(), randFltCoord());
> ++ break;
> ++ case 2:
> ++ path.quadTo(randFltCoord(), randFltCoord(),
> ++ randFltCoord(), randFltCoord());
> ++ break;
> ++ case 3:
> ++ path.curveTo(randFltCoord(), randFltCoord(),
> ++ randFltCoord(), randFltCoord(),
> ++ randFltCoord(), randFltCoord());
> ++ break;
> ++ case 4:
> ++ path.closePath();
> ++ break;
> ++ }
> ++ }
> ++ }
> ++
> ++ public Shape getShape() {
> ++ return path;
> ++ }
> ++
> ++ public String toString() {
> ++ StringBuffer sb = new StringBuffer(100);
> ++ sb.append("Path(");
> ++ PathIterator pi = path.getPathIterator(null);
> ++ float coords[] = new float[6];
> ++ boolean first = true;
> ++ while (!pi.isDone()) {
> ++ int n;
> ++ char c;
> ++ switch(pi.currentSegment(coords)) {
> ++ case PathIterator.SEG_MOVETO:
> ++ c = 'M';
> ++ n = 2;
> ++ break;
> ++ case PathIterator.SEG_LINETO:
> ++ c = 'L';
> ++ n = 2;
> ++ break;
> ++ case PathIterator.SEG_QUADTO:
> ++ c = 'Q';
> ++ n = 4;
> ++ break;
> ++ case PathIterator.SEG_CUBICTO:
> ++ c = 'C';
> ++ n = 6;
> ++ break;
> ++ case PathIterator.SEG_CLOSE:
> ++ c = 'E';
> ++ n = 0;
> ++ break;
> ++ default:
> ++ throw new InternalError("Unknown segment!");
> ++ }
> ++ sb.append(c);
> ++ sb.append("[");
> ++ for (int i = 0; i < n; i++) {
> ++ if (i != 0) {
> ++ sb.append(",");
> ++ }
> ++ sb.append(coords[i]);
> ++ }
> ++ sb.append("]");
> ++ pi.next();
> ++ }
> ++ sb.append(")");
> ++ return sb.toString();
> ++ }
> ++ }
> ++
> ++ public static class Rect extends AnnotatedShapeOp {
> ++ public static Rect tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("Rect(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(5);
> ++ double coords[] = new double[4];
> ++ boolean foundparen = false;
> ++ for (int i = 0; i < coords.length; i++) {
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ if (i < coords.length-1) {
> ++ return null;
> ++ }
> ++ index = str.indexOf(")");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ foundparen = true;
> ++ }
> ++ String num = str.substring(0, index);
> ++ try {
> ++ coords[i] = Double.parseDouble(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ }
> ++ if (!foundparen || str.length() > 0) {
> ++ return null;
> ++ }
> ++ Rect r = new Rect();
> ++ r.rect.setRect(coords[0], coords[1],
> ++ coords[2], coords[3]);
> ++ return r;
> ++ }
> ++
> ++ private Rectangle2D rect = new Rectangle2D.Double();
> ++
> ++ public void randomize() {
> ++ rect.setRect(randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord());
> ++ }
> ++
> ++ public Shape getShape() {
> ++ return rect;
> ++ }
> ++
> ++ public String toString() {
> ++ return ("Rect("+
> ++ rect.getX()+", "+
> ++ rect.getY()+", "+
> ++ rect.getWidth()+", "+
> ++ rect.getHeight()
> ++ +")");
> ++ }
> ++ }
> ++
> ++ public static class Line extends AnnotatedShapeOp {
> ++ public static Line tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("Line(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(5);
> ++ double coords[] = new double[4];
> ++ boolean foundparen = false;
> ++ for (int i = 0; i < coords.length; i++) {
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ if (i < coords.length-1) {
> ++ return null;
> ++ }
> ++ index = str.indexOf(")");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ foundparen = true;
> ++ }
> ++ String num = str.substring(0, index);
> ++ try {
> ++ coords[i] = Double.parseDouble(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ }
> ++ if (!foundparen || str.length() > 0) {
> ++ return null;
> ++ }
> ++ Line l = new Line();
> ++ l.line.setLine(coords[0], coords[1],
> ++ coords[2], coords[3]);
> ++ return l;
> ++ }
> ++
> ++ private Line2D line = new Line2D.Double();
> ++
> ++ public void randomize() {
> ++ line.setLine(randDblCoord(), randDblCoord(),
> ++ randDblCoord(), randDblCoord());
> ++ }
> ++
> ++ public Shape getShape() {
> ++ return line;
> ++ }
> ++
> ++ public String toString() {
> ++ return ("Line("+
> ++ line.getX1()+", "+
> ++ line.getY1()+", "+
> ++ line.getX2()+", "+
> ++ line.getY2()
> ++ +")");
> ++ }
> ++ }
> ++
> ++ public static class RectMethod extends AnnotatedRenderOp {
> ++ public static RectMethod tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("RectMethod(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(11);
> ++ int coords[] = new int[4];
> ++ boolean foundparen = false;
> ++ for (int i = 0; i < coords.length; i++) {
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ if (i < coords.length-1) {
> ++ return null;
> ++ }
> ++ index = str.indexOf(")");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ foundparen = true;
> ++ }
> ++ String num = str.substring(0, index).trim();
> ++ try {
> ++ coords[i] = Integer.parseInt(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ }
> ++ if (!foundparen || str.length() > 0) {
> ++ return null;
> ++ }
> ++ RectMethod rm = new RectMethod();
> ++ rm.rect.setBounds(coords[0], coords[1],
> ++ coords[2], coords[3]);
> ++ return rm;
> ++ }
> ++
> ++ private Rectangle rect = new Rectangle();
> ++
> ++ public void randomize() {
> ++ rect.setBounds(randIntCoord(), randIntCoord(),
> ++ randIntCoord(), randIntCoord());
> ++ }
> ++
> ++ public void fill(Graphics2D g2d) {
> ++ g2d.fillRect(rect.x, rect.y, rect.width, rect.height);
> ++ }
> ++
> ++ public void draw(Graphics2D g2d) {
> ++ g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
> ++ }
> ++
> ++ public String toString() {
> ++ return ("RectMethod("+
> ++ rect.x+", "+
> ++ rect.y+", "+
> ++ rect.width+", "+
> ++ rect.height
> ++ +")");
> ++ }
> ++ }
> ++
> ++ public static class LineMethod extends AnnotatedRenderOp {
> ++ public static LineMethod tryparse(String str) {
> ++ str = str.trim();
> ++ if (!str.startsWith("LineMethod(")) {
> ++ return null;
> ++ }
> ++ str = str.substring(11);
> ++ int coords[] = new int[4];
> ++ boolean foundparen = false;
> ++ for (int i = 0; i < coords.length; i++) {
> ++ int index = str.indexOf(",");
> ++ if (index < 0) {
> ++ if (i < coords.length-1) {
> ++ return null;
> ++ }
> ++ index = str.indexOf(")");
> ++ if (index < 0) {
> ++ return null;
> ++ }
> ++ foundparen = true;
> ++ }
> ++ String num = str.substring(0, index).trim();
> ++ try {
> ++ coords[i] = Integer.parseInt(num);
> ++ } catch (NumberFormatException nfe) {
> ++ return null;
> ++ }
> ++ str = str.substring(index+1);
> ++ }
> ++ if (!foundparen || str.length() > 0) {
> ++ return null;
> ++ }
> ++ LineMethod lm = new LineMethod();
> ++ lm.line = coords;
> ++ return lm;
> ++ }
> ++
> ++ private int line[] = new int[4];
> ++
> ++ public void randomize() {
> ++ line[0] = randIntCoord();
> ++ line[1] = randIntCoord();
> ++ line[2] = randIntCoord();
> ++ line[3] = randIntCoord();
> ++ }
> ++
> ++ public void fill(Graphics2D g2d) {
> ++ }
> ++
> ++ public void draw(Graphics2D g2d) {
> ++ g2d.drawLine(line[0], line[1], line[2], line[3]);
> ++ }
> ++
> ++ public String toString() {
> ++ return ("LineMethod("+
> ++ line[0]+", "+
> ++ line[1]+", "+
> ++ line[2]+", "+
> ++ line[3]
> ++ +")");
> ++ }
> ++ }
> ++
> ++ public static class ErrorWindow extends Frame {
> ++ ImageCanvas unclipped;
> ++ ImageCanvas reference;
> ++ ImageCanvas actual;
> ++ ImageCanvas diff;
> ++
> ++ public ErrorWindow() {
> ++ super("Error Comparison Window");
> ++
> ++ unclipped = new ImageCanvas();
> ++ reference = new ImageCanvas();
> ++ actual = new ImageCanvas();
> ++ diff = new ImageCanvas();
> ++
> ++ setLayout(new SmartGridLayout(0, 2, 5, 5));
> ++ addImagePanel(unclipped, "Unclipped rendering");
> ++ addImagePanel(reference, "Clipped reference");
> ++ addImagePanel(actual, "Actual clipped");
> ++ addImagePanel(diff, "Difference");
> ++
> ++ addWindowListener(new WindowAdapter() {
> ++ public void windowClosing(WindowEvent e) {
> ++ setVisible(false);
> ++ }
> ++ });
> ++ }
> ++
> ++ public void addImagePanel(ImageCanvas ic, String label) {
> ++ add(ic);
> ++ add(new Label(label));
> ++ }
> ++
> ++ public void setImages(BufferedImage imgref, BufferedImage imgtst) {
> ++ unclipped.setImage(imgref);
> ++ reference.setReference(imgref);
> ++ actual.setImage(imgtst);
> ++ diff.setDiff(reference.getImage(), imgtst);
> ++ invalidate();
> ++ pack();
> ++ repaint();
> ++ }
> ++
> ++ public void setVisible(boolean vis) {
> ++ super.setVisible(vis);
> ++ synchronized (this) {
> ++ notifyAll();
> ++ }
> ++ }
> ++
> ++ public synchronized void waitForHide() {
> ++ while (isShowing()) {
> ++ try {
> ++ wait();
> ++ } catch (InterruptedException e) {
> ++ System.exit(2);
> ++ }
> ++ }
> ++ }
> ++ }
> ++
> ++ public static class SmartGridLayout implements LayoutManager {
> ++ int rows;
> ++ int cols;
> ++ int hgap;
> ++ int vgap;
> ++
> ++ public SmartGridLayout(int r, int c, int h, int v) {
> ++ this.rows = r;
> ++ this.cols = c;
> ++ this.hgap = h;
> ++ this.vgap = v;
> ++ }
> ++
> ++ public void addLayoutComponent(String name, Component comp) {
> ++ }
> ++
> ++ public void removeLayoutComponent(Component comp) {
> ++ }
> ++
> ++ public int[][] getGridSizes(Container parent, boolean min) {
> ++ int ncomponents = parent.getComponentCount();
> ++ int nrows = rows;
> ++ int ncols = cols;
> ++
> ++ if (nrows > 0) {
> ++ ncols = (ncomponents + nrows - 1) / nrows;
> ++ } else {
> ++ nrows = (ncomponents + ncols - 1) / ncols;
> ++ }
> ++ int widths[] = new int[ncols+1];
> ++ int heights[] = new int[nrows+1];
> ++ int x = 0;
> ++ int y = 0;
> ++ for (int i = 0 ; i < ncomponents ; i++) {
> ++ Component comp = parent.getComponent(i);
> ++ Dimension d = (min
> ++ ? comp.getMinimumSize()
> ++ : comp.getPreferredSize());
> ++ if (widths[x] < d.width) {
> ++ widths[x] = d.width;
> ++ }
> ++ if (heights[y] < d.height) {
> ++ heights[y] = d.height;
> ++ }
> ++ x++;
> ++ if (x >= ncols) {
> ++ x = 0;
> ++ y++;
> ++ }
> ++ }
> ++ for (int i = 0; i < ncols; i++) {
> ++ widths[ncols] += widths[i];
> ++ }
> ++ for (int i = 0; i < nrows; i++) {
> ++ heights[nrows] += heights[i];
> ++ }
> ++ return new int[][] { widths, heights };
> ++ }
> ++
> ++ public Dimension getSize(Container parent, boolean min) {
> ++ int sizes[][] = getGridSizes(parent, min);
> ++ int widths[] = sizes[0];
> ++ int heights[] = sizes[1];
> ++ int nrows = heights.length-1;
> ++ int ncols = widths.length-1;
> ++ int w = widths[ncols];
> ++ int h = heights[nrows];
> ++ Insets insets = parent.getInsets();
> ++ return new Dimension(insets.left+insets.right + w+(ncols+1)*hgap,
> ++ insets.top+insets.bottom + h+(nrows+1)*vgap);
> ++ }
> ++
> ++ public Dimension preferredLayoutSize(Container parent) {
> ++ return getSize(parent, false);
> ++ }
> ++
> ++ public Dimension minimumLayoutSize(Container parent) {
> ++ return getSize(parent, true);
> ++ }
> ++
> ++ public void layoutContainer(Container parent) {
> ++ int pref[][] = getGridSizes(parent, false);
> ++ int min[][] = getGridSizes(parent, true);
> ++ int minwidths[] = min[0];
> ++ int minheights[] = min[1];
> ++ int prefwidths[] = pref[0];
> ++ int prefheights[] = pref[1];
> ++ int nrows = minheights.length - 1;
> ++ int ncols = minwidths.length - 1;
> ++ Insets insets = parent.getInsets();
> ++ int w = parent.getWidth() - insets.left - insets.right;
> ++ int h = parent.getHeight() - insets.top - insets.bottom;
> ++ w = w - (ncols+1)*hgap;
> ++ h = h - (nrows+1)*vgap;
> ++ int widths[] = calculateSizes(w, ncols, minwidths, prefwidths);
> ++ int heights[] = calculateSizes(h, nrows, minheights, prefheights);
> ++ int ncomponents = parent.getComponentCount();
> ++ int x = insets.left + hgap;
> ++ int y = insets.top + vgap;
> ++ int r = 0;
> ++ int c = 0;
> ++ for (int i = 0; i < ncomponents; i++) {
> ++ parent.getComponent(i).setBounds(x, y, widths[c], heights[r]);
> ++ x += widths[c++] + hgap;
> ++ if (c >= ncols) {
> ++ c = 0;
> ++ x = insets.left + hgap;
> ++ y += heights[r++] + vgap;
> ++ if (r >= nrows) {
> ++ // just in case
> ++ break;
> ++ }
> ++ }
> ++ }
> ++ }
> ++
> ++ public static int[] calculateSizes(int total, int num,
> ++ int minsizes[], int prefsizes[])
> ++ {
> ++ if (total <= minsizes[num]) {
> ++ return minsizes;
> ++ }
> ++ if (total >= prefsizes[num]) {
> ++ return prefsizes;
> ++ }
> ++ int sizes[] = new int[total];
> ++ int prevhappy = 0;
> ++ int nhappy = 0;
> ++ int happysize = 0;
> ++ do {
> ++ int addsize = (total - happysize) / (num - nhappy);
> ++ happysize = 0;
> ++ for (int i = 0; i < num; i++) {
> ++ if (sizes[i] >= prefsizes[i] ||
> ++ minsizes[i] + addsize > prefsizes[i])
> ++ {
> ++ happysize += (sizes[i] = prefsizes[i]);
> ++ nhappy++;
> ++ } else {
> ++ sizes[i] = minsizes[i] + addsize;
> ++ }
> ++ }
> ++ } while (nhappy < num && nhappy > prevhappy);
> ++ return sizes;
> ++ }
> ++ }
> ++
> ++ public static class ImageCanvas extends Canvas {
> ++ BufferedImage image;
> ++
> ++ public void setImage(BufferedImage img) {
> ++ this.image = img;
> ++ }
> ++
> ++ public BufferedImage getImage() {
> ++ return image;
> ++ }
> ++
> ++ public void checkImage(int w, int h) {
> ++ if (image == null ||
> ++ image.getWidth() < w ||
> ++ image.getHeight() < h)
> ++ {
> ++ image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
> ++ }
> ++ }
> ++
> ++ public void setReference(BufferedImage img) {
> ++ checkImage(img.getWidth(), img.getHeight());
> ++ Graphics g = image.createGraphics();
> ++ g.drawImage(img, 0, 0, null);
> ++ g.setColor(Color.white);
> ++ g.fillRect(0, 0, 30, 10);
> ++ g.fillRect(30, 0, 10, 30);
> ++ g.fillRect(10, 30, 30, 10);
> ++ g.fillRect(0, 10, 10, 30);
> ++ g.dispose();
> ++ }
> ++
> ++ public void setDiff(BufferedImage imgref, BufferedImage imgtst) {
> ++ int w = Math.max(imgref.getWidth(), imgtst.getWidth());
> ++ int h = Math.max(imgref.getHeight(), imgtst.getHeight());
> ++ checkImage(w, h);
> ++ Graphics g = image.createGraphics();
> ++ g.drawImage(imgref, 0, 0, null);
> ++ g.setXORMode(Color.white);
> ++ g.drawImage(imgtst, 0, 0, null);
> ++ g.setPaintMode();
> ++ g.setColor(new Color(1f, 1f, 0f, 0.25f));
> ++ g.fillRect(10, 10, 20, 20);
> ++ g.setColor(new Color(1f, 0f, 0f, 0.25f));
> ++ g.fillRect(0, 0, 30, 10);
> ++ g.fillRect(30, 0, 10, 30);
> ++ g.fillRect(10, 30, 30, 10);
> ++ g.fillRect(0, 10, 10, 30);
> ++ g.dispose();
> ++ }
> ++
> ++ public Dimension getPreferredSize() {
> ++ if (image == null) {
> ++ return new Dimension();
> ++ } else {
> ++ return new Dimension(image.getWidth(), image.getHeight());
> ++ }
> ++ }
> ++
> ++ public void paint(Graphics g) {
> ++ g.drawImage(image, 0, 0, null);
> ++ }
> ++ }
> ++}
> diff -r e1a5ab4cf428 patches/openjdk/6775317-non-AA-simple-shape-performance.patch
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/patches/openjdk/6775317-non-AA-simple-shape-performance.patch Tue Feb 22 19:04:38 2011 -0500
> @@ -0,0 +1,1697 @@
> +# HG changeset patch
> +# User flar
> +# Date 1291700748 28800
> +# Node ID 47cd69eff64122a14e1e1557bc0f6e00f66e9980
> +# Parent 1d4340015b85857a7f001fff4776307f576dc274
> +6775317: Improve performance of non-AA transformed rectangles and single wide lines in software pipelines
> +Reviewed-by: jgodinez, prr
> +
> +diff -r 1d4340015b85 -r 47cd69eff641 make/sun/awt/Depend.mak
> +--- openjdk.orig/jdk/make/sun/awt/Depend.mak Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/Depend.mak Mon Dec 06 21:45:48 2010 -0800
> +@@ -18,11 +18,15 @@
> + J2D_SRC = $(SUN_SRC)/java2d
> + J2D_FONT_SRC = $(SUN_SRC)/font
> + J2D_WINDOWS_SRC = $(WINDOWS_SRC)/native/sun/java2d
> ++AWT_WINDOWS_SRC = $(WINDOWS_SRC)/native/sun/awt
> + LOOP_SRC = $(SUN_SRC)/java2d/loops
> + PIPE_SRC = $(SUN_SRC)/java2d/pipe
> + WINDOWS_SRC = $(TOPDIR)/src/windows
> + SRC = $(WINDOWS_SRC)/native/sun/windows
> +
> ++# ensure consistent sort order
> ++LC_ALL:= C
> ++
> + SRCDIRS = \
> + $(COMP_SRC) \
> + $(DEBUG_SRC) \
> +@@ -61,6 +65,7 @@
> + -I$(J2D_WINDOWS_SRC)/windows \
> + -I$(J2D_WINDOWS_SRC)/d3d \
> + -I$(J2D_WINDOWS_SRC)/opengl \
> ++ -I$(AWT_WINDOWS_SRC) \
> + -I$(LOOP_SRC) \
> + -I$(PIPE_SRC) \
> + -I$(SRC)
> +@@ -68,22 +73,29 @@
> + STUBFILES = \
> + $(STUBDIR)/ddraw.h \
> + $(STUBDIR)/d3d.h \
> ++ $(STUBDIR)/d3d9.h \
> + $(STUBDIR)/Ole2.h \
> + $(STUBDIR)/Zmouse.h \
> + $(STUBDIR)/cderr.h \
> ++ $(STUBDIR)/comdef.h \
> + $(STUBDIR)/commctrl.h \
> + $(STUBDIR)/commdlg.h \
> ++ $(STUBDIR)/comutil.h \
> + $(STUBDIR)/direct.h \
> + $(STUBDIR)/d3dcom.h \
> + $(STUBDIR)/imm.h \
> + $(STUBDIR)/ime.h \
> + $(STUBDIR)/io.h \
> ++ $(STUBDIR)/map \
> + $(STUBDIR)/mmsystem.h \
> + $(STUBDIR)/new.h \
> ++ $(STUBDIR)/new \
> + $(STUBDIR)/ole2.h \
> ++ $(STUBDIR)/process.h \
> + $(STUBDIR)/richole.h \
> + $(STUBDIR)/richedit.h \
> + $(STUBDIR)/shellapi.h \
> ++ $(STUBDIR)/shlwapi.h \
> + $(STUBDIR)/shlobj.h \
> + $(STUBDIR)/tchar.h \
> + $(STUBDIR)/winbase.h \
> +@@ -135,6 +147,9 @@
> + include FILES_export_windows.gmk
> +
> + EXTRAFILES_java = \
> ++ sun/java2d/opengl/OGLContext/OGLContextCaps.java \
> ++ sun/java2d/d3d/D3DPaints/MultiGradient.java \
> ++ sun/java2d/d3d/D3DContext/D3DContextCaps.java \
> + java/lang/Integer.java
> +
> + FILES_java = $(FILES_export) $(FILES_export2) $(FILES_export3) \
> +diff -r 1d4340015b85 -r 47cd69eff641 make/sun/awt/FILES_c_unix.gmk
> +--- openjdk.orig/jdk/make/sun/awt/FILES_c_unix.gmk Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/FILES_c_unix.gmk Mon Dec 06 21:45:48 2010 -0800
> +@@ -85,6 +85,8 @@
> + ScaledBlit.c \
> + FillRect.c \
> + FillSpans.c \
> ++ FillParallelogram.c \
> ++ DrawParallelogram.c \
> + DrawLine.c \
> + DrawRect.c \
> + DrawPolygons.c \
> +diff -r 1d4340015b85 -r 47cd69eff641 make/sun/awt/FILES_c_windows.gmk
> +--- openjdk.orig/jdk/make/sun/awt/FILES_c_windows.gmk Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/FILES_c_windows.gmk Mon Dec 06 21:45:48 2010 -0800
> +@@ -30,6 +30,8 @@
> + ScaledBlit.c \
> + FillRect.c \
> + FillSpans.c \
> ++ FillParallelogram.c \
> ++ DrawParallelogram.c \
> + DrawLine.c \
> + DrawRect.c \
> + DrawPolygons.c \
> +diff -r 1d4340015b85 -r 47cd69eff641 make/sun/awt/FILES_export_unix.gmk
> +--- openjdk.orig/jdk/make/sun/awt/FILES_export_unix.gmk Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/FILES_export_unix.gmk Mon Dec 06 21:45:48 2010 -0800
> +@@ -36,6 +36,8 @@
> + sun/java2d/loops/TransformBlit.java \
> + sun/java2d/loops/FillRect.java \
> + sun/java2d/loops/FillSpans.java \
> ++ sun/java2d/loops/FillParallelogram.java \
> ++ sun/java2d/loops/DrawParallelogram.java \
> + sun/java2d/loops/DrawGlyphList.java \
> + sun/java2d/loops/DrawGlyphListAA.java \
> + sun/java2d/loops/DrawGlyphListLCD.java \
> +diff -r 1d4340015b85 -r 47cd69eff641 make/sun/awt/FILES_export_windows.gmk
> +--- openjdk.orig/jdk/make/sun/awt/FILES_export_windows.gmk Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/FILES_export_windows.gmk Mon Dec 06 21:45:48 2010 -0800
> +@@ -135,6 +135,8 @@
> + sun/java2d/loops/ScaledBlit.java \
> + sun/java2d/loops/FillRect.java \
> + sun/java2d/loops/FillSpans.java \
> ++ sun/java2d/loops/FillParallelogram.java \
> ++ sun/java2d/loops/DrawParallelogram.java \
> + sun/java2d/loops/DrawGlyphList.java \
> + sun/java2d/loops/DrawGlyphListAA.java \
> + sun/java2d/loops/DrawGlyphListLCD.java \
> +diff -r 1d4340015b85 -r 47cd69eff641 make/sun/awt/mapfile-vers
> +--- openjdk.orig/jdk/make/sun/awt/mapfile-vers Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/make/sun/awt/mapfile-vers Mon Dec 06 21:45:48 2010 -0800
> +@@ -112,6 +112,8 @@
> + Java_sun_java2d_loops_DrawRect_DrawRect;
> + Java_sun_java2d_loops_FillRect_FillRect;
> + Java_sun_java2d_loops_FillSpans_FillSpans;
> ++ Java_sun_java2d_loops_FillParallelogram_FillParallelogram;
> ++ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram;
> + Java_sun_java2d_loops_GraphicsPrimitiveMgr_initIDs;
> + Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops;
> + Java_sun_java2d_loops_MaskBlit_MaskBlit;
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/classes/sun/java2d/SurfaceData.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/SurfaceData.java Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/SurfaceData.java Mon Dec 06 21:45:48 2010 -0800
> +@@ -46,11 +46,15 @@
> + import sun.java2d.loops.DrawPath;
> + import sun.java2d.loops.FillPath;
> + import sun.java2d.loops.FillSpans;
> ++import sun.java2d.loops.FillParallelogram;
> ++import sun.java2d.loops.DrawParallelogram;
> + import sun.java2d.loops.FontInfo;
> + import sun.java2d.loops.DrawGlyphList;
> + import sun.java2d.loops.DrawGlyphListAA;
> + import sun.java2d.loops.DrawGlyphListLCD;
> + import sun.java2d.pipe.LoopPipe;
> ++import sun.java2d.pipe.ShapeDrawPipe;
> ++import sun.java2d.pipe.ParallelogramPipe;
> + import sun.java2d.pipe.CompositePipe;
> + import sun.java2d.pipe.GeneralCompositePipe;
> + import sun.java2d.pipe.SpanClipRenderer;
> +@@ -59,6 +63,7 @@
> + import sun.java2d.pipe.AlphaPaintPipe;
> + import sun.java2d.pipe.AlphaColorPipe;
> + import sun.java2d.pipe.PixelToShapeConverter;
> ++import sun.java2d.pipe.PixelToParallelogramConverter;
> + import sun.java2d.pipe.TextPipe;
> + import sun.java2d.pipe.TextRenderer;
> + import sun.java2d.pipe.AATextRenderer;
> +@@ -364,6 +369,7 @@
> +
> + protected static final CompositePipe colorPipe;
> + protected static final PixelToShapeConverter colorViaShape;
> ++ protected static final PixelToParallelogramConverter colorViaPgram;
> + protected static final TextPipe colorText;
> + protected static final CompositePipe clipColorPipe;
> + protected static final TextPipe clipColorText;
> +@@ -396,6 +402,31 @@
> +
> + protected static final DrawImagePipe imagepipe;
> +
> ++ // Utility subclass to add the LoopBasedPipe tagging interface
> ++ static class PixelToShapeLoopConverter
> ++ extends PixelToShapeConverter
> ++ implements LoopBasedPipe
> ++ {
> ++ public PixelToShapeLoopConverter(ShapeDrawPipe pipe) {
> ++ super(pipe);
> ++ }
> ++ }
> ++
> ++ // Utility subclass to add the LoopBasedPipe tagging interface
> ++ static class PixelToPgramLoopConverter
> ++ extends PixelToParallelogramConverter
> ++ implements LoopBasedPipe
> ++ {
> ++ public PixelToPgramLoopConverter(ShapeDrawPipe shapepipe,
> ++ ParallelogramPipe pgrampipe,
> ++ double minPenSize,
> ++ double normPosition,
> ++ boolean adjustfill)
> ++ {
> ++ super(shapepipe, pgrampipe, minPenSize, normPosition, adjustfill);
> ++ }
> ++ }
> ++
> + static {
> + colorPrimitives = new LoopPipe();
> +
> +@@ -406,7 +437,10 @@
> +
> + colorPipe = new AlphaColorPipe();
> + // colorShape = colorPrimitives;
> +- colorViaShape = new PixelToShapeConverter(colorPrimitives);
> ++ colorViaShape = new PixelToShapeLoopConverter(colorPrimitives);
> ++ colorViaPgram = new PixelToPgramLoopConverter(colorPrimitives,
> ++ colorPrimitives,
> ++ 1.0, 0.25, true);
> + colorText = new TextRenderer(colorPipe);
> + clipColorPipe = new SpanClipRenderer(colorPipe);
> + clipColorText = new TextRenderer(clipColorPipe);
> +@@ -441,10 +475,12 @@
> + }
> +
> + /* Not all surfaces and rendering mode combinations support LCD text. */
> +- static final int LCDLOOP_UNKNOWN = 0;
> +- static final int LCDLOOP_FOUND = 1;
> +- static final int LCDLOOP_NOTFOUND = 2;
> ++ static final int LOOP_UNKNOWN = 0;
> ++ static final int LOOP_FOUND = 1;
> ++ static final int LOOP_NOTFOUND = 2;
> + int haveLCDLoop;
> ++ int havePgramXORLoop;
> ++ int havePgramSolidLoop;
> +
> + public boolean canRenderLCDText(SunGraphics2D sg2d) {
> + // For now the answer can only be true in the following cases:
> +@@ -453,18 +489,48 @@
> + sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&
> + sg2d.surfaceData.getTransparency() == Transparency.OPAQUE)
> + {
> +- if (haveLCDLoop == LCDLOOP_UNKNOWN) {
> ++ if (haveLCDLoop == LOOP_UNKNOWN) {
> + DrawGlyphListLCD loop =
> + DrawGlyphListLCD.locate(SurfaceType.AnyColor,
> + CompositeType.SrcNoEa,
> + getSurfaceType());
> +- haveLCDLoop = (loop!= null) ? LCDLOOP_FOUND : LCDLOOP_NOTFOUND;
> ++ haveLCDLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;
> + }
> +- return haveLCDLoop == LCDLOOP_FOUND;
> ++ return haveLCDLoop == LOOP_FOUND;
> + }
> + return false; /* for now - in the future we may want to search */
> + }
> +
> ++ public boolean canRenderParallelograms(SunGraphics2D sg2d) {
> ++ if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {
> ++ if (sg2d.compositeState == sg2d.COMP_XOR) {
> ++ if (havePgramXORLoop == LOOP_UNKNOWN) {
> ++ FillParallelogram loop =
> ++ FillParallelogram.locate(SurfaceType.AnyColor,
> ++ CompositeType.Xor,
> ++ getSurfaceType());
> ++ havePgramXORLoop =
> ++ (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;
> ++ }
> ++ return havePgramXORLoop == LOOP_FOUND;
> ++ } else if (sg2d.compositeState <= sg2d.COMP_ISCOPY &&
> ++ sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
> ++ sg2d.clipState != sg2d.CLIP_SHAPE)
> ++ {
> ++ if (havePgramSolidLoop == LOOP_UNKNOWN) {
> ++ FillParallelogram loop =
> ++ FillParallelogram.locate(SurfaceType.AnyColor,
> ++ CompositeType.SrcNoEa,
> ++ getSurfaceType());
> ++ havePgramSolidLoop =
> ++ (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;
> ++ }
> ++ return havePgramSolidLoop == LOOP_FOUND;
> ++ }
> ++ }
> ++ return false;
> ++ }
> ++
> + public void validatePipe(SunGraphics2D sg2d) {
> + sg2d.imagepipe = imagepipe;
> + if (sg2d.compositeState == sg2d.COMP_XOR) {
> +@@ -480,9 +546,21 @@
> + // text drawn in XOR mode with a Paint object.
> + sg2d.textpipe = outlineTextRenderer;
> + } else {
> ++ PixelToShapeConverter converter;
> ++ if (canRenderParallelograms(sg2d)) {
> ++ converter = colorViaPgram;
> ++ // Note that we use the transforming pipe here because it
> ++ // will examine the shape and possibly perform an optimized
> ++ // operation if it can be simplified. The simplifications
> ++ // will be valid for all STROKE and TRANSFORM types.
> ++ sg2d.shapepipe = colorViaPgram;
> ++ } else {
> ++ converter = colorViaShape;
> ++ sg2d.shapepipe = colorPrimitives;
> ++ }
> + if (sg2d.clipState == sg2d.CLIP_SHAPE) {
> +- sg2d.drawpipe = colorViaShape;
> +- sg2d.fillpipe = colorViaShape;
> ++ sg2d.drawpipe = converter;
> ++ sg2d.fillpipe = converter;
> + // REMIND: We should not be changing text strategies
> + // between outline and glyph rendering based upon the
> + // presence of a complex clip as that could cause a
> +@@ -494,11 +572,11 @@
> + sg2d.textpipe = outlineTextRenderer;
> + } else {
> + if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
> +- sg2d.drawpipe = colorViaShape;
> +- sg2d.fillpipe = colorViaShape;
> ++ sg2d.drawpipe = converter;
> ++ sg2d.fillpipe = converter;
> + } else {
> + if (sg2d.strokeState != sg2d.STROKE_THIN) {
> +- sg2d.drawpipe = colorViaShape;
> ++ sg2d.drawpipe = converter;
> + } else {
> + sg2d.drawpipe = colorPrimitives;
> + }
> +@@ -506,7 +584,6 @@
> + }
> + sg2d.textpipe = solidTextRenderer;
> + }
> +- sg2d.shapepipe = colorPrimitives;
> + // assert(sg2d.surfaceData == this);
> + }
> + } else if (sg2d.compositeState == sg2d.COMP_CUSTOM) {
> +@@ -589,12 +666,24 @@
> + }
> + }
> + } else {
> ++ PixelToShapeConverter converter;
> ++ if (canRenderParallelograms(sg2d)) {
> ++ converter = colorViaPgram;
> ++ // Note that we use the transforming pipe here because it
> ++ // will examine the shape and possibly perform an optimized
> ++ // operation if it can be simplified. The simplifications
> ++ // will be valid for all STROKE and TRANSFORM types.
> ++ sg2d.shapepipe = colorViaPgram;
> ++ } else {
> ++ converter = colorViaShape;
> ++ sg2d.shapepipe = colorPrimitives;
> ++ }
> + if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
> +- sg2d.drawpipe = colorViaShape;
> +- sg2d.fillpipe = colorViaShape;
> ++ sg2d.drawpipe = converter;
> ++ sg2d.fillpipe = converter;
> + } else {
> + if (sg2d.strokeState != sg2d.STROKE_THIN) {
> +- sg2d.drawpipe = colorViaShape;
> ++ sg2d.drawpipe = converter;
> + } else {
> + sg2d.drawpipe = colorPrimitives;
> + }
> +@@ -602,7 +691,6 @@
> + }
> +
> + sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */);
> +- sg2d.shapepipe = colorPrimitives;
> + // assert(sg2d.surfaceData == this);
> + }
> +
> +@@ -761,6 +849,8 @@
> + loops.drawPathLoop = DrawPath.locate(src, comp, dst);
> + loops.fillPathLoop = FillPath.locate(src, comp, dst);
> + loops.fillSpansLoop = FillSpans.locate(src, comp, dst);
> ++ loops.fillParallelogramLoop = FillParallelogram.locate(src, comp, dst);
> ++ loops.drawParallelogramLoop = DrawParallelogram.locate(src, comp, dst);
> + loops.drawGlyphListLoop = DrawGlyphList.locate(src, comp, dst);
> + loops.drawGlyphListAALoop = DrawGlyphListAA.locate(src, comp, dst);
> + loops.drawGlyphListLCDLoop = DrawGlyphListLCD.locate(src, comp, dst);
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/classes/sun/java2d/loops/DrawParallelogram.java
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/src/share/classes/sun/java2d/loops/DrawParallelogram.java Mon Dec 06 21:45:48 2010 -0800
> +@@ -0,0 +1,123 @@
> ++/*
> ++ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
> ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> ++ *
> ++ * This code is free software; you can redistribute it and/or modify it
> ++ * under the terms of the GNU General Public License version 2 only, as
> ++ * published by the Free Software Foundation. Oracle designates this
> ++ * particular file as subject to the "Classpath" exception as provided
> ++ * by Oracle in the LICENSE file that accompanied this code.
> ++ *
> ++ * This code is distributed in the hope that it will be useful, but WITHOUT
> ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> ++ * version 2 for more details (a copy is included in the LICENSE file that
> ++ * accompanied this code).
> ++ *
> ++ * You should have received a copy of the GNU General Public License version
> ++ * 2 along with this work; if not, write to the Free Software Foundation,
> ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> ++ *
> ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> ++ * or visit www.oracle.com if you need additional information or have any
> ++ * questions.
> ++ */
> ++
> ++/*
> ++ * @author Jim Graham
> ++ */
> ++
> ++package sun.java2d.loops;
> ++
> ++import sun.java2d.loops.GraphicsPrimitive;
> ++import sun.java2d.SunGraphics2D;
> ++import sun.java2d.SurfaceData;
> ++
> ++/**
> ++ * DrawParallelogram
> ++ * 1) fill the area between the 4 edges of an outer parallelogram
> ++ * (as specified by an origin and 2 delta vectors)
> ++ * but also outside the 4 edges of an inner parallelogram
> ++ * (as specified by proportional amounts of the outer delta vectors)
> ++ */
> ++public class DrawParallelogram extends GraphicsPrimitive
> ++{
> ++ public final static String methodSignature =
> ++ "DrawParallelogram(...)".toString();
> ++
> ++ public final static int primTypeID = makePrimTypeID();
> ++
> ++ public static DrawParallelogram locate(SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ return (DrawParallelogram)
> ++ GraphicsPrimitiveMgr.locate(primTypeID,
> ++ srctype, comptype, dsttype);
> ++ }
> ++
> ++ protected DrawParallelogram(SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ super(methodSignature, primTypeID,
> ++ srctype, comptype, dsttype);
> ++ }
> ++
> ++ public DrawParallelogram(long pNativePrim,
> ++ SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ super(pNativePrim, methodSignature, primTypeID,
> ++ srctype, comptype, dsttype);
> ++ }
> ++
> ++ /**
> ++ * All DrawParallelogram implementors must have this invoker method
> ++ */
> ++ public native void DrawParallelogram(SunGraphics2D sg, SurfaceData dest,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2);
> ++
> ++ public GraphicsPrimitive makePrimitive(SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ // REMIND: iterate with a FillRect primitive?
> ++ throw new InternalError("DrawParallelogram not implemented for "+
> ++ srctype+" with "+comptype);
> ++ }
> ++
> ++ public GraphicsPrimitive traceWrap() {
> ++ return new TraceDrawParallelogram(this);
> ++ }
> ++
> ++ private static class TraceDrawParallelogram extends DrawParallelogram {
> ++ DrawParallelogram target;
> ++
> ++ public TraceDrawParallelogram(DrawParallelogram target) {
> ++ super(target.getSourceType(),
> ++ target.getCompositeType(),
> ++ target.getDestType());
> ++ this.target = target;
> ++ }
> ++
> ++ public GraphicsPrimitive traceWrap() {
> ++ return this;
> ++ }
> ++
> ++ public void DrawParallelogram(SunGraphics2D sg2d, SurfaceData dest,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2)
> ++ {
> ++ tracePrimitive(target);
> ++ target.DrawParallelogram(sg2d, dest,
> ++ x, y, dx1, dy1, dx2, dy2, lw1, lw2);
> ++ }
> ++ }
> ++}
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/classes/sun/java2d/loops/FillParallelogram.java
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/src/share/classes/sun/java2d/loops/FillParallelogram.java Mon Dec 06 21:45:48 2010 -0800
> +@@ -0,0 +1,118 @@
> ++/*
> ++ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
> ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> ++ *
> ++ * This code is free software; you can redistribute it and/or modify it
> ++ * under the terms of the GNU General Public License version 2 only, as
> ++ * published by the Free Software Foundation. Oracle designates this
> ++ * particular file as subject to the "Classpath" exception as provided
> ++ * by Oracle in the LICENSE file that accompanied this code.
> ++ *
> ++ * This code is distributed in the hope that it will be useful, but WITHOUT
> ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> ++ * version 2 for more details (a copy is included in the LICENSE file that
> ++ * accompanied this code).
> ++ *
> ++ * You should have received a copy of the GNU General Public License version
> ++ * 2 along with this work; if not, write to the Free Software Foundation,
> ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> ++ *
> ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> ++ * or visit www.oracle.com if you need additional information or have any
> ++ * questions.
> ++ */
> ++
> ++/*
> ++ * @author Jim Graham
> ++ */
> ++
> ++package sun.java2d.loops;
> ++
> ++import sun.java2d.loops.GraphicsPrimitive;
> ++import sun.java2d.SunGraphics2D;
> ++import sun.java2d.SurfaceData;
> ++
> ++/**
> ++ * FillParallelogram
> ++ * 1) fill the area between the 4 edges of a parallelogram
> ++ * (as specified by an origin and 2 delta vectors)
> ++ */
> ++public class FillParallelogram extends GraphicsPrimitive
> ++{
> ++ public final static String methodSignature =
> ++ "FillParallelogram(...)".toString();
> ++
> ++ public final static int primTypeID = makePrimTypeID();
> ++
> ++ public static FillParallelogram locate(SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ return (FillParallelogram)
> ++ GraphicsPrimitiveMgr.locate(primTypeID,
> ++ srctype, comptype, dsttype);
> ++ }
> ++
> ++ protected FillParallelogram(SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ super(methodSignature, primTypeID,
> ++ srctype, comptype, dsttype);
> ++ }
> ++
> ++ public FillParallelogram(long pNativePrim,
> ++ SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ super(pNativePrim, methodSignature, primTypeID,
> ++ srctype, comptype, dsttype);
> ++ }
> ++
> ++ /**
> ++ * All FillParallelogram implementors must have this invoker method
> ++ */
> ++ public native void FillParallelogram(SunGraphics2D sg2d, SurfaceData dest,
> ++ double x0, double y0,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2);
> ++
> ++ public GraphicsPrimitive makePrimitive(SurfaceType srctype,
> ++ CompositeType comptype,
> ++ SurfaceType dsttype)
> ++ {
> ++ // REMIND: iterate with a FillRect primitive?
> ++ throw new InternalError("FillParallelogram not implemented for "+
> ++ srctype+" with "+comptype);
> ++ }
> ++
> ++ public GraphicsPrimitive traceWrap() {
> ++ return new TraceFillParallelogram(this);
> ++ }
> ++
> ++ private static class TraceFillParallelogram extends FillParallelogram {
> ++ FillParallelogram target;
> ++
> ++ public TraceFillParallelogram(FillParallelogram target) {
> ++ super(target.getSourceType(),
> ++ target.getCompositeType(),
> ++ target.getDestType());
> ++ this.target = target;
> ++ }
> ++
> ++ public GraphicsPrimitive traceWrap() {
> ++ return this;
> ++ }
> ++
> ++ public void FillParallelogram(SunGraphics2D sg2d, SurfaceData dest,
> ++ double x0, double y0,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2)
> ++ {
> ++ tracePrimitive(target);
> ++ target.FillParallelogram(sg2d, dest, x0, y0, dx1, dy1, dx2, dy2);
> ++ }
> ++ }
> ++}
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/classes/sun/java2d/loops/RenderLoops.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/loops/RenderLoops.java Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/loops/RenderLoops.java Mon Dec 06 21:45:48 2010 -0800
> +@@ -47,6 +47,8 @@
> + public DrawPath drawPathLoop;
> + public FillPath fillPathLoop;
> + public FillSpans fillSpansLoop;
> ++ public FillParallelogram fillParallelogramLoop;
> ++ public DrawParallelogram drawParallelogramLoop;
> + public DrawGlyphList drawGlyphListLoop;
> + public DrawGlyphListAA drawGlyphListAALoop;
> + public DrawGlyphListLCD drawGlyphListLCDLoop;
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/classes/sun/java2d/pipe/LoopPipe.java
> +--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java Mon Dec 06 21:45:48 2010 -0800
> +@@ -41,11 +41,14 @@
> + import sun.java2d.SurfaceData;
> + import sun.java2d.loops.FontInfo;
> + import sun.java2d.loops.DrawPolygons;
> ++import sun.java2d.loops.FillParallelogram;
> ++import sun.java2d.loops.DrawParallelogram;
> + import sun.awt.SunHints;
> +
> + public class LoopPipe
> + implements PixelDrawPipe,
> + PixelFillPipe,
> ++ ParallelogramPipe,
> + ShapeDrawPipe,
> + LoopBasedPipe
> + {
> +@@ -347,4 +350,25 @@
> + sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
> + }
> + }
> ++
> ++ public void fillParallelogram(SunGraphics2D sg2d,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2)
> ++ {
> ++ FillParallelogram fp = sg2d.loops.fillParallelogramLoop;
> ++ fp.FillParallelogram(sg2d, sg2d.getSurfaceData(),
> ++ x, y, dx1, dy1, dx2, dy2);
> ++ }
> ++
> ++ public void drawParallelogram(SunGraphics2D sg2d,
> ++ double x, double y,
> ++ double dx1, double dy1,
> ++ double dx2, double dy2,
> ++ double lw1, double lw2)
> ++ {
> ++ DrawParallelogram dp = sg2d.loops.drawParallelogramLoop;
> ++ dp.DrawParallelogram(sg2d, sg2d.getSurfaceData(),
> ++ x, y, dx1, dy1, dx2, dy2, lw1, lw2);
> ++ }
> + }
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/Any3Byte.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/Any3Byte.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/Any3Byte.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -38,6 +38,7 @@
> +
> + DECLARE_SOLID_FILLRECT(Any3Byte);
> + DECLARE_SOLID_FILLSPANS(Any3Byte);
> ++DECLARE_SOLID_PARALLELOGRAM(Any3Byte);
> + DECLARE_SOLID_DRAWLINE(Any3Byte);
> + DECLARE_XOR_FILLRECT(Any3Byte);
> + DECLARE_XOR_FILLSPANS(Any3Byte);
> +@@ -48,6 +49,7 @@
> + NativePrimitive Any3BytePrimitives[] = {
> + REGISTER_SOLID_FILLRECT(Any3Byte),
> + REGISTER_SOLID_FILLSPANS(Any3Byte),
> ++ REGISTER_SOLID_PARALLELOGRAM(Any3Byte),
> + REGISTER_SOLID_LINE_PRIMITIVES(Any3Byte),
> + REGISTER_XOR_FILLRECT(Any3Byte),
> + REGISTER_XOR_FILLSPANS(Any3Byte),
> +@@ -72,6 +74,8 @@
> +
> + DEFINE_SOLID_FILLSPANS(Any3Byte)
> +
> ++DEFINE_SOLID_PARALLELOGRAM(Any3Byte)
> ++
> + DEFINE_SOLID_DRAWLINE(Any3Byte)
> +
> + DEFINE_XOR_FILLRECT(Any3Byte)
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/Any4Byte.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/Any4Byte.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/Any4Byte.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -41,6 +41,7 @@
> +
> + DECLARE_SOLID_FILLRECT(Any4Byte);
> + DECLARE_SOLID_FILLSPANS(Any4Byte);
> ++DECLARE_SOLID_PARALLELOGRAM(Any4Byte);
> + DECLARE_SOLID_DRAWLINE(Any4Byte);
> + DECLARE_XOR_FILLRECT(Any4Byte);
> + DECLARE_XOR_FILLSPANS(Any4Byte);
> +@@ -51,6 +52,7 @@
> + NativePrimitive Any4BytePrimitives[] = {
> + REGISTER_SOLID_FILLRECT(Any4Byte),
> + REGISTER_SOLID_FILLSPANS(Any4Byte),
> ++ REGISTER_SOLID_PARALLELOGRAM(Any4Byte),
> + REGISTER_SOLID_LINE_PRIMITIVES(Any4Byte),
> + REGISTER_XOR_FILLRECT(Any4Byte),
> + REGISTER_XOR_FILLSPANS(Any4Byte),
> +@@ -75,6 +77,8 @@
> +
> + DEFINE_SOLID_FILLSPANS(Any4Byte)
> +
> ++DEFINE_SOLID_PARALLELOGRAM(Any4Byte)
> ++
> + DEFINE_SOLID_DRAWLINE(Any4Byte)
> +
> + DEFINE_XOR_FILLRECT(Any4Byte)
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/AnyByte.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/AnyByte.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/AnyByte.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -38,6 +38,7 @@
> +
> + DECLARE_SOLID_FILLRECT(AnyByte);
> + DECLARE_SOLID_FILLSPANS(AnyByte);
> ++DECLARE_SOLID_PARALLELOGRAM(AnyByte);
> + DECLARE_SOLID_DRAWLINE(AnyByte);
> + DECLARE_XOR_FILLRECT(AnyByte);
> + DECLARE_XOR_FILLSPANS(AnyByte);
> +@@ -48,6 +49,7 @@
> + NativePrimitive AnyBytePrimitives[] = {
> + REGISTER_SOLID_FILLRECT(AnyByte),
> + REGISTER_SOLID_FILLSPANS(AnyByte),
> ++ REGISTER_SOLID_PARALLELOGRAM(AnyByte),
> + REGISTER_SOLID_LINE_PRIMITIVES(AnyByte),
> + REGISTER_XOR_FILLRECT(AnyByte),
> + REGISTER_XOR_FILLSPANS(AnyByte),
> +@@ -72,6 +74,8 @@
> +
> + DEFINE_SOLID_FILLSPANS(AnyByte)
> +
> ++DEFINE_SOLID_PARALLELOGRAM(AnyByte)
> ++
> + DEFINE_SOLID_DRAWLINE(AnyByte)
> +
> + DEFINE_XOR_FILLRECT(AnyByte)
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/AnyInt.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/AnyInt.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/AnyInt.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -38,6 +38,7 @@
> +
> + DECLARE_SOLID_FILLRECT(AnyInt);
> + DECLARE_SOLID_FILLSPANS(AnyInt);
> ++DECLARE_SOLID_PARALLELOGRAM(AnyInt);
> + DECLARE_SOLID_DRAWLINE(AnyInt);
> + DECLARE_XOR_FILLRECT(AnyInt);
> + DECLARE_XOR_FILLSPANS(AnyInt);
> +@@ -48,6 +49,7 @@
> + NativePrimitive AnyIntPrimitives[] = {
> + REGISTER_SOLID_FILLRECT(AnyInt),
> + REGISTER_SOLID_FILLSPANS(AnyInt),
> ++ REGISTER_SOLID_PARALLELOGRAM(AnyInt),
> + REGISTER_SOLID_LINE_PRIMITIVES(AnyInt),
> + REGISTER_XOR_FILLRECT(AnyInt),
> + REGISTER_XOR_FILLSPANS(AnyInt),
> +@@ -72,6 +74,8 @@
> +
> + DEFINE_SOLID_FILLSPANS(AnyInt)
> +
> ++DEFINE_SOLID_PARALLELOGRAM(AnyInt)
> ++
> + DEFINE_SOLID_DRAWLINE(AnyInt)
> +
> + DEFINE_XOR_FILLRECT(AnyInt)
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/AnyShort.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/AnyShort.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/AnyShort.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -38,6 +38,7 @@
> +
> + DECLARE_SOLID_FILLRECT(AnyShort);
> + DECLARE_SOLID_FILLSPANS(AnyShort);
> ++DECLARE_SOLID_PARALLELOGRAM(AnyShort);
> + DECLARE_SOLID_DRAWLINE(AnyShort);
> + DECLARE_XOR_FILLRECT(AnyShort);
> + DECLARE_XOR_FILLSPANS(AnyShort);
> +@@ -48,6 +49,7 @@
> + NativePrimitive AnyShortPrimitives[] = {
> + REGISTER_SOLID_FILLRECT(AnyShort),
> + REGISTER_SOLID_FILLSPANS(AnyShort),
> ++ REGISTER_SOLID_PARALLELOGRAM(AnyShort),
> + REGISTER_SOLID_LINE_PRIMITIVES(AnyShort),
> + REGISTER_XOR_FILLRECT(AnyShort),
> + REGISTER_XOR_FILLSPANS(AnyShort),
> +@@ -72,6 +74,8 @@
> +
> + DEFINE_SOLID_FILLSPANS(AnyShort)
> +
> ++DEFINE_SOLID_PARALLELOGRAM(AnyShort)
> ++
> + DEFINE_SOLID_DRAWLINE(AnyShort)
> +
> + DEFINE_XOR_FILLRECT(AnyShort)
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/DrawParallelogram.c
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -0,0 +1,341 @@
> ++/*
> ++ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
> ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> ++ *
> ++ * This code is free software; you can redistribute it and/or modify it
> ++ * under the terms of the GNU General Public License version 2 only, as
> ++ * published by the Free Software Foundation. Oracle designates this
> ++ * particular file as subject to the "Classpath" exception as provided
> ++ * by Oracle in the LICENSE file that accompanied this code.
> ++ *
> ++ * This code is distributed in the hope that it will be useful, but WITHOUT
> ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> ++ * version 2 for more details (a copy is included in the LICENSE file that
> ++ * accompanied this code).
> ++ *
> ++ * You should have received a copy of the GNU General Public License version
> ++ * 2 along with this work; if not, write to the Free Software Foundation,
> ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> ++ *
> ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> ++ * or visit www.oracle.com if you need additional information or have any
> ++ * questions.
> ++ */
> ++
> ++#include "math.h"
> ++#include "GraphicsPrimitiveMgr.h"
> ++#include "LineUtils.h"
> ++#include "LoopMacros.h"
> ++#include "Trace.h"
> ++
> ++#include "sun_java2d_loops_FillParallelogram.h"
> ++#include "sun_java2d_loops_DrawParallelogram.h"
> ++
> ++DECLARE_SOLID_DRAWLINE(AnyInt);
> ++
> ++#define HANDLE_PGRAM_EDGE(X1, Y1, X2, Y2, \
> ++ pRasInfo, pixel, pPrim, pFunc, pCompInfo) \
> ++ do { \
> ++ jint ix1 = (jint) floor(X1); \
> ++ jint ix2 = (jint) floor(X2); \
> ++ jint iy1 = (jint) floor(Y1); \
> ++ jint iy2 = (jint) floor(Y2); \
> ++ LineUtils_ProcessLine(pRasInfo, pixel, \
> ++ pFunc, pPrim, pCompInfo, \
> ++ ix1, iy1, ix2, iy2, JNI_TRUE); \
> ++ } while (0)
> ++
> ++#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \
> ++ do { \
> ++ double vmin, vmax; \
> ++ if (dv1 < 0) { \
> ++ vmin = v0+dv1; \
> ++ vmax = v0; \
> ++ } else { \
> ++ vmin = v0; \
> ++ vmax = v0+dv1; \
> ++ } \
> ++ if (dv2 < 0) { \
> ++ vmin -= dv2; \
> ++ } else { \
> ++ vmax += dv2; \
> ++ } \
> ++ bmin = (jint) floor(vmin + 0.5); \
> ++ bmax = (jint) floor(vmax + 0.5); \
> ++ } while(0)
> ++
> ++#define PGRAM_INIT_X(starty, x, y, slope) \
> ++ (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
> ++
> ++typedef struct {
> ++ jdouble x0;
> ++ jdouble y0;
> ++ jdouble y1;
> ++ jdouble slope;
> ++ jlong dx;
> ++ jint ystart;
> ++ jint yend;
> ++} EdgeInfo;
> ++
> ++#define STORE_EDGE(pEDGE, X0, Y0, Y1, SLOPE, DELTAX) \
> ++ do { \
> ++ (pEDGE)->x0 = (X0); \
> ++ (pEDGE)->y0 = (Y0); \
> ++ (pEDGE)->y1 = (Y1); \
> ++ (pEDGE)->slope = (SLOPE); \
> ++ (pEDGE)->dx = (DELTAX); \
> ++ (pEDGE)->ystart = (jint) floor((Y0) + 0.5); \
> ++ (pEDGE)->yend = (jint) floor((Y1) + 0.5); \
> ++ } while (0)
> ++
> ++#define STORE_PGRAM(pLTEDGE, pRTEDGE, \
> ++ X0, Y0, dX1, dY1, dX2, dY2, \
> ++ SLOPE1, SLOPE2, DELTAX1, DELTAX2) \
> ++ do { \
> ++ STORE_EDGE((pLTEDGE)+0, \
> ++ (X0), (Y0), (Y0) + (dY1), \
> ++ (SLOPE1), (DELTAX1)); \
> ++ STORE_EDGE((pRTEDGE)+0, \
> ++ (X0), (Y0), (Y0) + (dY2), \
> ++ (SLOPE2), (DELTAX2)); \
> ++ STORE_EDGE((pLTEDGE)+1, \
> ++ (X0) + (dX1), (Y0) + (dY1), (Y0) + (dY1) + (dY2), \
> ++ (SLOPE2), (DELTAX2)); \
> ++ STORE_EDGE((pRTEDGE)+1, \
> ++ (X0) + (dX2), (Y0) + (dY2), (Y0) + (dY1) + (dY2), \
> ++ (SLOPE1), (DELTAX1)); \
> ++ } while (0)
> ++
> ++/*
> ++ * Class: sun_java2d_loops_DrawParallelogram
> ++ * Method: DrawParallelogram
> ++ * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;DDDDDDDD)V
> ++ */
> ++JNIEXPORT void JNICALL
> ++Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram
> ++ (JNIEnv *env, jobject self,
> ++ jobject sg2d, jobject sData,
> ++ jdouble x0, jdouble y0,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2,
> ++ jdouble lw1, jdouble lw2)
> ++{
> ++ SurfaceDataOps *sdOps;
> ++ SurfaceDataRasInfo rasInfo;
> ++ NativePrimitive *pPrim;
> ++ CompositeInfo compInfo;
> ++ jint pixel;
> ++ EdgeInfo edges[8];
> ++ EdgeInfo *active[4];
> ++ jint ix1, iy1, ix2, iy2;
> ++ jdouble ldx1, ldy1, ldx2, ldy2;
> ++ jdouble ox0, oy0;
> ++
> ++ /*
> ++ * Sort parallelogram by y values, ensure that each delta vector
> ++ * has a non-negative y delta.
> ++ */
> ++ if (dy1 < 0) {
> ++ x0 += dx1; y0 += dy1;
> ++ dx1 = -dx1; dy1 = -dy1;
> ++ }
> ++ if (dy2 < 0) {
> ++ x0 += dx2; y0 += dy2;
> ++ dx2 = -dx2; dy2 = -dy2;
> ++ }
> ++ /* Sort delta vectors so dxy1 is left of dxy2. */
> ++ if (dx1 * dy2 > dx2 * dy1) {
> ++ double v = dx1; dx1 = dx2; dx2 = v;
> ++ v = dy1; dy1 = dy2; dy2 = v;
> ++ v = lw1; lw1 = lw2; lw2 = v;
> ++ }
> ++
> ++ // dx,dy for line width in the "1" and "2" directions.
> ++ ldx1 = dx1 * lw1;
> ++ ldy1 = dy1 * lw1;
> ++ ldx2 = dx2 * lw2;
> ++ ldy2 = dy2 * lw2;
> ++
> ++ // calculate origin of the outer parallelogram
> ++ ox0 = x0 - (ldx1 + ldx2) / 2.0;
> ++ oy0 = y0 - (ldy1 + ldy2) / 2.0;
> ++
> ++ PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2);
> ++ iy1 = (jint) floor(oy0 + 0.5);
> ++ iy2 = (jint) floor(oy0 + dy1 + ldy1 + dy2 + ldy2 + 0.5);
> ++
> ++ pPrim = GetNativePrim(env, self);
> ++ if (pPrim == NULL) {
> ++ return;
> ++ }
> ++ pixel = GrPrim_Sg2dGetPixel(env, sg2d);
> ++ if (pPrim->pCompType->getCompInfo != NULL) {
> ++ GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
> ++ }
> ++
> ++ sdOps = SurfaceData_GetOps(env, sData);
> ++ if (sdOps == NULL) {
> ++ return;
> ++ }
> ++
> ++ GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
> ++ SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
> ++ if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
> ++ rasInfo.bounds.x2 <= rasInfo.bounds.x1)
> ++ {
> ++ return;
> ++ }
> ++
> ++ if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
> ++ return;
> ++ }
> ++
> ++ ix1 = rasInfo.bounds.x1;
> ++ iy1 = rasInfo.bounds.y1;
> ++ ix2 = rasInfo.bounds.x2;
> ++ iy2 = rasInfo.bounds.y2;
> ++ if (ix2 > ix1 && iy2 > iy1) {
> ++ sdOps->GetRasInfo(env, sdOps, &rasInfo);
> ++ if (rasInfo.rasBase) {
> ++ jdouble lslope, rslope;
> ++ jlong ldx, rdx;
> ++ jint loy, hiy, numedges;
> ++ FillParallelogramFunc *pFill =
> ++ pPrim->funcs.drawparallelogram->fillpgram;
> ++
> ++ lslope = (dy1 == 0) ? 0 : dx1 / dy1;
> ++ rslope = (dy2 == 0) ? 0 : dx2 / dy2;
> ++ ldx = DblToLong(lslope);
> ++ rdx = DblToLong(rslope);
> ++
> ++ // Only need to generate 4 quads if the interior still
> ++ // has a hole in it (i.e. if the line width ratios were
> ++ // both less than 1.0)
> ++ if (lw1 < 1.0f && lw2 < 1.0f) {
> ++ // If the line widths are both less than a pixel wide
> ++ // then we can use a drawline function instead for even
> ++ // more performance.
> ++ lw1 = sqrt(ldx1*ldx1 + ldy1*ldy1);
> ++ lw2 = sqrt(ldx2*ldx2 + ldy2*ldy2);
> ++ if (lw1 <= 1.0001 && lw2 <= 1.0001) {
> ++ jdouble x3, y3;
> ++ DrawLineFunc *pLine =
> ++ pPrim->funcs.drawparallelogram->drawline;
> ++
> ++ x3 = (dx1 += x0);
> ++ y3 = (dy1 += y0);
> ++ x3 += dx2;
> ++ y3 += dy2;
> ++ dx2 += x0;
> ++ dy2 += y0;
> ++
> ++ HANDLE_PGRAM_EDGE( x0, y0, dx1, dy1,
> ++ &rasInfo, pixel, pPrim, pLine, &compInfo);
> ++ HANDLE_PGRAM_EDGE(dx1, dy1, x3, y3,
> ++ &rasInfo, pixel, pPrim, pLine, &compInfo);
> ++ HANDLE_PGRAM_EDGE( x3, y3, dx2, dy2,
> ++ &rasInfo, pixel, pPrim, pLine, &compInfo);
> ++ HANDLE_PGRAM_EDGE(dx2, dy2, x0, y0,
> ++ &rasInfo, pixel, pPrim, pLine, &compInfo);
> ++ SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
> ++ SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
> ++ return;
> ++ }
> ++
> ++ // To simplify the edge management below we presort the
> ++ // inner and outer edges so that they are globally sorted
> ++ // from left to right. If you scan across the array of
> ++ // edges for a given Y range then the edges you encounter
> ++ // will be sorted in X as well.
> ++ // If AB are left top and bottom edges of outer parallelogram,
> ++ // and CD are the right pair of edges, and abcd are the
> ++ // corresponding inner parallelogram edges then we want them
> ++ // sorted as ABabcdCD to ensure this horizontal ordering.
> ++ // Conceptually it is like 2 pairs of nested parentheses.
> ++ STORE_PGRAM(edges + 2, edges + 4,
> ++ ox0 + ldx1 + ldx2, oy0 + ldy1 + ldy2,
> ++ dx1 - ldx1, dy1 - ldy1,
> ++ dx2 - ldx2, dy2 - ldy2,
> ++ lslope, rslope, ldx, rdx);
> ++ numedges = 8;
> ++ } else {
> ++ // The line width ratios were large enough to consume
> ++ // the entire hole in the middle of the parallelogram
> ++ // so we can just issue one large quad for the outer
> ++ // parallelogram.
> ++ numedges = 4;
> ++ }
> ++
> ++ // The outer parallelogram always goes in the first two
> ++ // and last two entries in the array so we either have
> ++ // ABabcdCD ordering for 8 edges or ABCD ordering for 4
> ++ // edges. See comment above where we store the inner
> ++ // parallelogram for a more complete description.
> ++ STORE_PGRAM(edges + 0, edges + numedges-2,
> ++ ox0, oy0,
> ++ dx1 + ldx1, dy1 + ldy1,
> ++ dx2 + ldx2, dy2 + ldy2,
> ++ lslope, rslope, ldx, rdx);
> ++
> ++ loy = edges[0].ystart;
> ++ if (loy < iy1) loy = iy1;
> ++ while (loy < iy2) {
> ++ jint numactive = 0;
> ++ jint cur;
> ++
> ++ hiy = iy2;
> ++ // Maintaining a sorted edge list is probably overkill for
> ++ // 4 or 8 edges. The indices chosen above for storing the
> ++ // inner and outer left and right edges already guarantee
> ++ // left to right ordering so we just need to scan for edges
> ++ // that overlap the current Y range (and also determine the
> ++ // maximum Y value for which the range is valid).
> ++ for (cur = 0; cur < numedges; cur++) {
> ++ EdgeInfo *pEdge = &edges[cur];
> ++ jint yend = pEdge->yend;
> ++ if (loy < yend) {
> ++ // This edge is still in play, have we reached it yet?
> ++ jint ystart = pEdge->ystart;
> ++ if (loy < ystart) {
> ++ // This edge is not active (yet)
> ++ // Stop before we get to the top of it
> ++ if (hiy > ystart) hiy = ystart;
> ++ } else {
> ++ // This edge is active, store it
> ++ active[numactive++] = pEdge;
> ++ // And stop when we get to the bottom of it
> ++ if (hiy > yend) hiy = yend;
> ++ }
> ++ }
> ++ }
> ++#ifdef DEBUG
> ++ if ((numactive & 1) != 0) {
> ++ J2dTraceLn1(J2D_TRACE_ERROR,
> ++ "DrawParallelogram: "
> ++ "ODD NUMBER OF PGRAM EDGES (%d)!!",
> ++ numactive);
> ++ }
> ++#endif
> ++ for (cur = 0; cur < numactive; cur += 2) {
> ++ EdgeInfo *pLeft = active[cur+0];
> ++ EdgeInfo *pRight = active[cur+1];
> ++ jlong lx = PGRAM_INIT_X(loy,
> ++ pLeft->x0, pLeft->y0,
> ++ pLeft->slope);
> ++ jlong rx = PGRAM_INIT_X(loy,
> ++ pRight->x0, pRight->y0,
> ++ pRight->slope);
> ++ (*pFill)(&rasInfo,
> ++ ix1, loy, ix2, hiy,
> ++ lx, pLeft->dx,
> ++ rx, pRight->dx,
> ++ pixel, pPrim, &compInfo);
> ++ }
> ++ loy = hiy;
> ++ }
> ++ }
> ++ SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
> ++ }
> ++ SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
> ++}
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/FillParallelogram.c
> +--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -0,0 +1,209 @@
> ++/*
> ++ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
> ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> ++ *
> ++ * This code is free software; you can redistribute it and/or modify it
> ++ * under the terms of the GNU General Public License version 2 only, as
> ++ * published by the Free Software Foundation. Oracle designates this
> ++ * particular file as subject to the "Classpath" exception as provided
> ++ * by Oracle in the LICENSE file that accompanied this code.
> ++ *
> ++ * This code is distributed in the hope that it will be useful, but WITHOUT
> ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> ++ * version 2 for more details (a copy is included in the LICENSE file that
> ++ * accompanied this code).
> ++ *
> ++ * You should have received a copy of the GNU General Public License version
> ++ * 2 along with this work; if not, write to the Free Software Foundation,
> ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> ++ *
> ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> ++ * or visit www.oracle.com if you need additional information or have any
> ++ * questions.
> ++ */
> ++
> ++#include "math.h"
> ++#include "GraphicsPrimitiveMgr.h"
> ++
> ++#include "sun_java2d_loops_FillParallelogram.h"
> ++
> ++#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \
> ++ do { \
> ++ double vmin, vmax; \
> ++ if (dv1 < 0) { \
> ++ vmin = v0+dv1; \
> ++ vmax = v0; \
> ++ } else { \
> ++ vmin = v0; \
> ++ vmax = v0+dv1; \
> ++ } \
> ++ if (dv2 < 0) { \
> ++ vmin -= dv2; \
> ++ } else { \
> ++ vmax += dv2; \
> ++ } \
> ++ bmin = (jint) floor(vmin + 0.5); \
> ++ bmax = (jint) floor(vmax + 0.5); \
> ++ } while(0)
> ++
> ++#define PGRAM_INIT_X(starty, x, y, slope) \
> ++ (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
> ++
> ++/*
> ++ * Class: sun_java2d_loops_FillParallelogram
> ++ * Method: FillParallelogram
> ++ * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;DDDDDD)V
> ++ */
> ++JNIEXPORT void JNICALL
> ++Java_sun_java2d_loops_FillParallelogram_FillParallelogram
> ++ (JNIEnv *env, jobject self,
> ++ jobject sg2d, jobject sData,
> ++ jdouble x0, jdouble y0,
> ++ jdouble dx1, jdouble dy1,
> ++ jdouble dx2, jdouble dy2)
> ++{
> ++ SurfaceDataOps *sdOps;
> ++ SurfaceDataRasInfo rasInfo;
> ++ NativePrimitive *pPrim;
> ++ CompositeInfo compInfo;
> ++ jint pixel;
> ++ jint ix1, iy1, ix2, iy2;
> ++
> ++ if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) {
> ++ return;
> ++ }
> ++
> ++ /*
> ++ * Sort parallelogram by y values, ensure that each delta vector
> ++ * has a non-negative y delta, and eliminate degenerate parallelograms.
> ++ */
> ++ if (dy1 < 0) {
> ++ x0 += dx1; y0 += dy1;
> ++ dx1 = -dx1; dy1 = -dy1;
> ++ }
> ++ if (dy2 < 0) {
> ++ x0 += dx2; y0 += dy2;
> ++ dx2 = -dx2; dy2 = -dy2;
> ++ }
> ++ /* Sort delta vectors so dxy1 is left of dxy2. */
> ++ if (dx1 * dy2 > dx2 * dy1) {
> ++ double v = dx1; dx1 = dx2; dx2 = v;
> ++ v = dy1; dy1 = dy2; dy2 = v;
> ++ }
> ++ PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2);
> ++ iy1 = (jint) floor(y0 + 0.5);
> ++ iy2 = (jint) floor(y0 + dy1 + dy2 + 0.5);
> ++
> ++ pPrim = GetNativePrim(env, self);
> ++ if (pPrim == NULL) {
> ++ return;
> ++ }
> ++ pixel = GrPrim_Sg2dGetPixel(env, sg2d);
> ++ if (pPrim->pCompType->getCompInfo != NULL) {
> ++ GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
> ++ }
> ++
> ++ sdOps = SurfaceData_GetOps(env, sData);
> ++ if (sdOps == NULL) {
> ++ return;
> ++ }
> ++
> ++ GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
> ++ SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
> ++ if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
> ++ rasInfo.bounds.x2 <= rasInfo.bounds.x1)
> ++ {
> ++ return;
> ++ }
> ++
> ++ if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
> ++ return;
> ++ }
> ++
> ++ ix1 = rasInfo.bounds.x1;
> ++ iy1 = rasInfo.bounds.y1;
> ++ ix2 = rasInfo.bounds.x2;
> ++ iy2 = rasInfo.bounds.y2;
> ++ if (ix2 > ix1 && iy2 > iy1) {
> ++ sdOps->GetRasInfo(env, sdOps, &rasInfo);
> ++ if (rasInfo.rasBase) {
> ++ jdouble lslope = (dy1 == 0) ? 0 : dx1 / dy1;
> ++ jdouble rslope = (dy2 == 0) ? 0 : dx2 / dy2;
> ++ jlong ldx = DblToLong(lslope);
> ++ jlong rdx = DblToLong(rslope);
> ++ jint cy1, cy2, loy, hiy;
> ++ dx1 += x0;
> ++ dy1 += y0;
> ++ dx2 += x0;
> ++ dy2 += y0;
> ++ cy1 = (jint) floor(dy1 + 0.5);
> ++ cy2 = (jint) floor(dy2 + 0.5);
> ++
> ++ /* Top triangular portion. */
> ++ loy = iy1;
> ++ hiy = (cy1 < cy2) ? cy1 : cy2;
> ++ if (hiy > iy2) hiy = iy2;
> ++ if (loy < hiy) {
> ++ jlong lx = PGRAM_INIT_X(loy, x0, y0, lslope);
> ++ jlong rx = PGRAM_INIT_X(loy, x0, y0, rslope);
> ++ (*pPrim->funcs.fillparallelogram)(&rasInfo,
> ++ ix1, loy, ix2, hiy,
> ++ lx, ldx, rx, rdx,
> ++ pixel, pPrim, &compInfo);
> ++ }
> ++
> ++ /* Middle parallelogram portion, which way does it slant? */
> ++ if (cy1 < cy2) {
> ++ /* Middle parallelogram portion, slanted to right. */
> ++ /* left leg turned a corner at y0+dy1 */
> ++ /* right leg continuing on its initial trajectory from y0 */
> ++ loy = cy1;
> ++ hiy = cy2;
> ++ if (loy < iy1) loy = iy1;
> ++ if (hiy > iy2) hiy = iy2;
> ++ if (loy < hiy) {
> ++ jlong lx = PGRAM_INIT_X(loy, dx1, dy1, rslope);
> ++ jlong rx = PGRAM_INIT_X(loy, x0, y0, rslope);
> ++ (*pPrim->funcs.fillparallelogram)(&rasInfo,
> ++ ix1, loy, ix2, hiy,
> ++ lx, rdx, rx, rdx,
> ++ pixel, pPrim, &compInfo);
> ++ }
> ++ } else if (cy2 < cy1) {
> ++ /* Middle parallelogram portion, slanted to left. */
> ++ /* left leg continuing on its initial trajectory from y0 */
> ++ /* right leg turned a corner at y0+dy2 */
> ++ loy = cy2;
> ++ hiy = cy1;
> ++ if (loy < iy1) loy = iy1;
> ++ if (hiy > iy2) hiy = iy2;
> ++ if (loy < hiy) {
> ++ jlong lx = PGRAM_INIT_X(loy, x0, y0, lslope);
> ++ jlong rx = PGRAM_INIT_X(loy, dx2, dy2, lslope);
> ++ (*pPrim->funcs.fillparallelogram)(&rasInfo,
> ++ ix1, loy, ix2, hiy,
> ++ lx, ldx, rx, ldx,
> ++ pixel, pPrim, &compInfo);
> ++ }
> ++ }
> ++
> ++ /* Bottom triangular portion. */
> ++ loy = (cy1 > cy2) ? cy1 : cy2;
> ++ if (loy < iy1) loy = iy1;
> ++ hiy = iy2;
> ++ if (loy < hiy) {
> ++ /* left leg turned its corner at y0+dy1, now moving right */
> ++ /* right leg turned its corner at y0+dy2, now moving left */
> ++ jlong lx = PGRAM_INIT_X(loy, dx1, dy1, rslope);
> ++ jlong rx = PGRAM_INIT_X(loy, dx2, dy2, lslope);
> ++ (*pPrim->funcs.fillparallelogram)(&rasInfo,
> ++ ix1, loy, ix2, hiy,
> ++ lx, rdx, rx, ldx,
> ++ pixel, pPrim, &compInfo);
> ++ }
> ++ }
> ++ SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
> ++ }
> ++ SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
> ++}
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -574,6 +574,8 @@
> + { "sun/java2d/loops/ScaledBlit", SD_LOCK_READ, SD_LOCK_WRITE, NULL, NULL},
> + { "sun/java2d/loops/FillRect", 0, SD_LOCK_WRITE, NULL, NULL},
> + { "sun/java2d/loops/FillSpans", 0, SD_LOCK_PARTIAL_WRITE, NULL, NULL},
> ++ { "sun/java2d/loops/FillParallelogram", 0, SD_LOCK_PARTIAL_WRITE, NULL, NULL},
> ++ { "sun/java2d/loops/DrawParallelogram", 0, SD_LOCK_PARTIAL_WRITE, NULL, NULL},
> + { "sun/java2d/loops/DrawLine", 0, SD_LOCK_PARTIAL_WRITE, NULL, NULL},
> + { "sun/java2d/loops/DrawRect", 0, SD_LOCK_PARTIAL_WRITE, NULL, NULL},
> + { "sun/java2d/loops/DrawPolygons", 0, SD_LOCK_PARTIAL_WRITE, NULL, NULL},
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h Mon Dec 06 21:45:48 2010 -0800
> +@@ -334,6 +334,26 @@
> + jint yfract, jint dyfract);
> +
> + /*
> ++ * The signature of the inner loop function for a "FillParallelogram"
> ++ * Note that this same inner loop is used for native DrawParallelogram
> ++ * primitives.
> ++ * Note that these functions are paired with equivalent DrawLine
> ++ * inner loop functions to facilitate nicer looking and faster thin
> ++ * transformed drawrect calls.
> ++ */
> ++typedef void (FillParallelogramFunc)(SurfaceDataRasInfo *pRasInfo,
> ++ jint lox, jint loy, jint hix, jint hiy,
> ++ jlong leftx, jlong dleftx,
> ++ jlong rightx, jlong drightx,
> ++ jint pixel, struct _NativePrimitive *pPrim,
> ++ CompositeInfo *pCompInfo);
> ++
> ++typedef struct {
> ++ FillParallelogramFunc *fillpgram;
> ++ DrawLineFunc *drawline;
> ++} DrawParallelogramFuncs;
> ++
> ++/*
> + * This structure contains all information for defining a single
> + * native GraphicsPrimitive, including:
> + * - The information about the type of the GraphicsPrimitive subclass.
> +@@ -363,6 +383,8 @@
> + ScaleBlitFunc *scaledblit;
> + FillRectFunc *fillrect;
> + FillSpansFunc *fillspans;
> ++ FillParallelogramFunc *fillparallelogram;
> ++ DrawParallelogramFuncs *drawparallelogram;
> + DrawLineFunc *drawline;
> + MaskFillFunc *maskfill;
> + MaskBlitFunc *maskblit;
> +@@ -393,6 +415,8 @@
> + PrimitiveType ScaledBlit;
> + PrimitiveType FillRect;
> + PrimitiveType FillSpans;
> ++ PrimitiveType FillParallelogram;
> ++ PrimitiveType DrawParallelogram;
> + PrimitiveType DrawLine;
> + PrimitiveType DrawRect;
> + PrimitiveType DrawPolygons;
> +@@ -536,6 +560,7 @@
> + #define LongOneHalf (((jlong) 1) << 31)
> + #define IntToLong(i) (((jlong) (i)) << 32)
> + #define DblToLong(d) ((jlong) ((d) * IntToLong(1)))
> ++#define LongToDbl(l) (((jdouble) l) / IntToLong(1))
> + #define WholeOfLong(l) ((jint) ((l) >> 32))
> + #define FractOfLong(l) ((jint) (l))
> + #define URShift(i, n) (((juint) (i)) >> (n))
> +@@ -595,6 +620,10 @@
> + #define REGISTER_FILLSPANS(SRC, COMP, DST, FUNC) \
> + REGISTER_PRIMITIVE(FillSpans, SRC, COMP, DST, FUNC)
> +
> ++#define REGISTER_FILLPGRAM(SRC, COMP, DST, FUNC) \
> ++ REGISTER_PRIMITIVE(FillParallelogram, SRC, COMP, DST, FUNC), \
> ++ REGISTER_PRIMITIVE(DrawParallelogram, SRC, COMP, DST, FUNC)
> ++
> + #define REGISTER_LINE_PRIMITIVES(SRC, COMP, DST, FUNC) \
> + REGISTER_PRIMITIVE(DrawLine, SRC, COMP, DST, FUNC), \
> + REGISTER_PRIMITIVE(DrawRect, SRC, COMP, DST, FUNC), \
> +diff -r 1d4340015b85 -r 47cd69eff641 src/share/native/sun/java2d/loops/LoopMacros.h
> +--- openjdk.orig/jdk/src/share/native/sun/java2d/loops/LoopMacros.h Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/share/native/sun/java2d/loops/LoopMacros.h Mon Dec 06 21:45:48 2010 -0800
> +@@ -607,6 +607,12 @@
> +
> + #define NAME_TRANSFORMHELPER_FUNCS(TYPE) TYPE ## TransformHelperFuncs
> +
> ++#define NAME_SOLID_FILLPGRAM(TYPE) TYPE ## SetParallelogram
> ++#define NAME_SOLID_PGRAM_FUNCS(TYPE) TYPE ## SetParallelogramFuncs
> ++
> ++#define NAME_XOR_FILLPGRAM(TYPE) TYPE ## XorParallelogram
> ++#define NAME_XOR_PGRAM_FUNCS(TYPE) TYPE ## XorParallelogramFuncs
> ++
> + /*
> + * These macros conveniently name and declare the indicated native
> + * primitive loop function for forward referencing.
> +@@ -689,6 +695,16 @@
> + TransformHelperFunc NAME_TRANSFORMHELPER_BC(TYPE); \
> + TransformHelperFuncs NAME_TRANSFORMHELPER_FUNCS(TYPE)
> +
> ++#define DECLARE_SOLID_PARALLELOGRAM(TYPE) \
> ++ FillParallelogramFunc NAME_SOLID_FILLPGRAM(TYPE); \
> ++ DECLARE_SOLID_DRAWLINE(TYPE); \
> ++ DrawParallelogramFuncs NAME_SOLID_PGRAM_FUNCS(TYPE)
> ++
> ++#define DECLARE_XOR_PARALLELOGRAM(TYPE) \
> ++ FillParallelogramFunc NAME_XOR_FILLPGRAM(TYPE); \
> ++ DECLARE_XOR_DRAWLINE(TYPE); \
> ++ DrawParallelogramFuncs NAME_XOR_PGRAM_FUNCS(TYPE)
> ++
> + /*
> + * These macros construct the necessary NativePrimitive structure
> + * for the indicated native primitive loop function which will be
> +@@ -800,6 +816,18 @@
> + REGISTER_PRIMITIVE(TransformHelper, TYPE, SrcNoEa, IntArgbPre, \
> + (AnyFunc *) &NAME_TRANSFORMHELPER_FUNCS(TYPE))
> +
> ++#define REGISTER_SOLID_PARALLELOGRAM(TYPE) \
> ++ REGISTER_PRIMITIVE(FillParallelogram, AnyColor, SrcNoEa, TYPE, \
> ++ NAME_SOLID_FILLPGRAM(TYPE)), \
> ++ REGISTER_PRIMITIVE(DrawParallelogram, AnyColor, SrcNoEa, TYPE, \
> ++ (AnyFunc *) &NAME_SOLID_PGRAM_FUNCS(TYPE))
> ++
> ++#define REGISTER_XOR_PARALLELOGRAM(TYPE) \
> ++ REGISTER_PRIMITIVE(FillParallelogram, AnyColor, Xor, TYPE, \
> ++ NAME_XOR_FILLPGRAM(TYPE)), \
> ++ REGISTER_PRIMITIVE(DrawParallelogram, AnyColor, Xor, TYPE, \
> ++ (AnyFunc *) &NAME_XOR_PGRAM_FUNCS(TYPE))
> ++
> + /*
> + * This macro defines an entire function to implement a Blit inner loop
> + * for copying pixels of a common type from one buffer to another.
> +@@ -1265,6 +1293,51 @@
> + }
> +
> + /*
> ++ * This macro defines an entire function to implement a FillParallelogram
> ++ * inner loop for tracing 2 diagonal edges (left and right) and setting
> ++ * those regions of pixels between them to a specific pixel value.
> ++ * No blending of the fill color is done with the pixels.
> ++ */
> ++#define DEFINE_SOLID_FILLPGRAM(DST) \
> ++void NAME_SOLID_FILLPGRAM(DST)(SurfaceDataRasInfo *pRasInfo, \
> ++ jint lox, jint loy, jint hix, jint hiy, \
> ++ jlong leftx, jlong dleftx, \
> ++ jlong rightx, jlong drightx, \
> ++ jint pixel, struct _NativePrimitive *pPrim, \
> ++ CompositeInfo *pCompInfo) \
> ++{ \
> ++ Declare ## DST ## PixelData(pix) \
> ++ jint scan = pRasInfo->scanStride; \
> ++ DST ## DataType *pPix = PtrCoord(pRasInfo->rasBase, 0, 0, loy, scan); \
> ++ \
> ++ Extract ## DST ## PixelData(pixel, pix); \
> ++ while (loy < hiy) { \
> ++ jint lx = WholeOfLong(leftx); \
> ++ jint rx = WholeOfLong(rightx); \
> ++ if (lx < lox) lx = lox; \
> ++ if (rx > hix) rx = hix; \
> ++ while (lx < rx) { \
> ++ Store ## DST ## PixelData(pPix, lx, pixel, pix); \
> ++ lx++; \
> ++ } \
> ++ pPix = PtrAddBytes(pPix, scan); \
> ++ leftx += dleftx; \
> ++ rightx += drightx; \
> ++ loy++; \
> ++ } \
> ++}
> ++
> ++#define DEFINE_SOLID_DRAWPARALLELOGRAM_FUNCS(DST) \
> ++ DrawParallelogramFuncs NAME_SOLID_PGRAM_FUNCS(DST) = { \
> ++ NAME_SOLID_FILLPGRAM(DST), \
> ++ NAME_SOLID_DRAWLINE(DST), \
> ++ };
> ++
> ++#define DEFINE_SOLID_PARALLELOGRAM(DST) \
> ++ DEFINE_SOLID_FILLPGRAM(DST) \
> ++ DEFINE_SOLID_DRAWPARALLELOGRAM_FUNCS(DST)
> ++
> ++/*
> + * This macro declares the bumpmajor and bumpminor variables used for the
> + * DrawLine functions.
> + */
> +diff -r 1d4340015b85 -r 47cd69eff641 src/solaris/native/sun/java2d/loops/java2d_Mlib.c
> +--- openjdk.orig/jdk/src/solaris/native/sun/java2d/loops/java2d_Mlib.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/solaris/native/sun/java2d/loops/java2d_Mlib.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -282,6 +282,50 @@
> +
> + /***************************************************************/
> +
> ++#define DEFINE_SET_PGRAM(FUNC, ANYTYPE, NCHAN) \
> ++void ADD_SUFF(ANYTYPE##FUNC)(SurfaceDataRasInfo *pRasInfo, \
> ++ jint lox, jint loy, \
> ++ jint hix, jint hiy, \
> ++ jlong leftx, jlong dleftx, \
> ++ jlong rightx, jlong drightx, \
> ++ jint pixel, NativePrimitive * pPrim, \
> ++ CompositeInfo * pCompInfo) \
> ++{ \
> ++ mlib_image dst[1]; \
> ++ mlib_s32 dstScan = pRasInfo->scanStride; \
> ++ mlib_u8 *dstBase = (mlib_u8*)(pRasInfo->rasBase), *pdst; \
> ++ mlib_s32 c_arr[4]; \
> ++ \
> ++ STORE_CONST_##NCHAN(c_arr, pixel); \
> ++ pdst = dstBase + loy*dstScan; \
> ++ \
> ++ while (loy < hiy) { \
> ++ jint lx = WholeOfLong(leftx); \
> ++ jint rx = WholeOfLong(rightx); \
> ++ if (lx < lox) lx = lox; \
> ++ if (rx > hix) rx = hix; \
> ++ \
> ++ MLIB_IMAGE_SET(dst, MLIB_##ANYTYPE, NCHAN_##ANYTYPE, \
> ++ rx-lx, 1, dstScan, \
> ++ pdst + lx*ANYTYPE##PixelStride); \
> ++ \
> ++ mlib_ImageClear(dst, c_arr); \
> ++ \
> ++ pdst = PtrAddBytes(pdst, dstScan); \
> ++ leftx += dleftx; \
> ++ rightx += drightx; \
> ++ loy++; \
> ++ } \
> ++}
> ++
> ++DEFINE_SET_PGRAM(SetParallelogram, Any3Byte, 3)
> ++DEFINE_SET_PGRAM(SetParallelogram, Any4Byte, 4)
> ++DEFINE_SET_PGRAM(SetParallelogram, AnyByte, 1)
> ++DEFINE_SET_PGRAM(SetParallelogram, AnyInt, 1)
> ++DEFINE_SET_PGRAM(SetParallelogram, AnyShort, 1)
> ++
> ++/***************************************************************/
> ++
> + #define SCALE_COPY(index, chan) \
> + pDst[chan] = pSrc[index]
> +
> +diff -r 1d4340015b85 -r 47cd69eff641 src/solaris/native/sun/java2d/loops/vis_FuncArray.c
> +--- openjdk.orig/jdk/src/solaris/native/sun/java2d/loops/vis_FuncArray.c Mon Dec 06 16:10:01 2010 -0800
> ++++ openjdk/jdk/src/solaris/native/sun/java2d/loops/vis_FuncArray.c Mon Dec 06 21:45:48 2010 -0800
> +@@ -51,6 +51,7 @@
> + DEF_FUNC(AnyByteSetLine)
> + DEF_FUNC(AnyByteSetRect)
> + DEF_FUNC(AnyByteSetSpans)
> ++DEF_FUNC(AnyByteSetParallelogram)
> + DEF_FUNC(AnyByteXorLine)
> + DEF_FUNC(AnyByteXorRect)
> + DEF_FUNC(AnyByteXorSpans)
> +@@ -62,6 +63,7 @@
> + DEF_FUNC(AnyShortSetLine)
> + DEF_FUNC(AnyShortSetRect)
> + DEF_FUNC(AnyShortSetSpans)
> ++DEF_FUNC(AnyShortSetParallelogram)
> + DEF_FUNC(AnyShortXorLine)
> + DEF_FUNC(AnyShortXorRect)
> + DEF_FUNC(AnyShortXorSpans)
> +@@ -73,6 +75,7 @@
> + DEF_FUNC(Any3ByteSetLine)
> + DEF_FUNC(Any3ByteSetRect)
> + DEF_FUNC(Any3ByteSetSpans)
> ++DEF_FUNC(Any3ByteSetParallelogram)
> + DEF_FUNC(Any3ByteXorLine)
> + DEF_FUNC(Any3ByteXorRect)
> + DEF_FUNC(Any3ByteXorSpans)
> +@@ -84,6 +87,7 @@
> + DEF_FUNC(Any4ByteSetLine)
> + DEF_FUNC(Any4ByteSetRect)
> + DEF_FUNC(Any4ByteSetSpans)
> ++DEF_FUNC(Any4ByteSetParallelogram)
> + DEF_FUNC(Any4ByteXorLine)
> + DEF_FUNC(Any4ByteXorRect)
> + DEF_FUNC(Any4ByteXorSpans)
> +@@ -95,6 +99,7 @@
> + DEF_FUNC(AnyIntSetLine)
> + DEF_FUNC(AnyIntSetRect)
> + DEF_FUNC(AnyIntSetSpans)
> ++DEF_FUNC(AnyIntSetParallelogram)
> + DEF_FUNC(AnyIntXorLine)
> + DEF_FUNC(AnyIntXorRect)
> + DEF_FUNC(AnyIntXorSpans)
> +@@ -513,6 +518,7 @@
> + ADD_FUNC(AnyByteSetLine),
> + ADD_FUNC(AnyByteSetRect),
> + ADD_FUNC(AnyByteSetSpans),
> ++ ADD_FUNC(AnyByteSetParallelogram),
> + ADD_FUNC(AnyByteXorLine),
> + ADD_FUNC(AnyByteXorRect),
> + ADD_FUNC(AnyByteXorSpans),
> +@@ -524,6 +530,7 @@
> + ADD_FUNC(AnyShortSetLine),
> + ADD_FUNC(AnyShortSetRect),
> + ADD_FUNC(AnyShortSetSpans),
> ++ ADD_FUNC(AnyShortSetParallelogram),
> + ADD_FUNC(AnyShortXorLine),
> + ADD_FUNC(AnyShortXorRect),
> + ADD_FUNC(AnyShortXorSpans),
> +@@ -533,6 +540,7 @@
> + ADD_FUNC(Any3ByteSetLine),
> + ADD_FUNC(Any3ByteSetRect),
> + ADD_FUNC(Any3ByteSetSpans),
> ++ ADD_FUNC(Any3ByteSetParallelogram),
> + ADD_FUNC(Any3ByteXorLine),
> + ADD_FUNC(Any3ByteXorRect),
> + ADD_FUNC(Any3ByteXorSpans),
> +@@ -544,6 +552,7 @@
> + ADD_FUNC(Any4ByteSetLine),
> + ADD_FUNC(Any4ByteSetRect),
> + ADD_FUNC(Any4ByteSetSpans),
> ++ ADD_FUNC(Any4ByteSetParallelogram),
> + ADD_FUNC(Any4ByteXorLine),
> + ADD_FUNC(Any4ByteXorRect),
> + ADD_FUNC(Any4ByteXorSpans),
> +@@ -555,6 +564,7 @@
> + ADD_FUNC(AnyIntSetLine),
> + ADD_FUNC(AnyIntSetRect),
> + ADD_FUNC(AnyIntSetSpans),
> ++ ADD_FUNC(AnyIntSetParallelogram),
> + ADD_FUNC(AnyIntXorLine),
> + ADD_FUNC(AnyIntXorRect),
> + ADD_FUNC(AnyIntXorSpans),
--
Andrew :)
Free Java Software Engineer
Red Hat, Inc. (http://www.redhat.com)
Support Free Java!
Contribute to GNU Classpath and IcedTea
http://www.gnu.org/software/classpath
http://icedtea.classpath.org
PGP Key: F5862A37 (https://keys.indymedia.org/)
Fingerprint = EA30 D855 D50F 90CD F54D 0698 0713 C3ED F586 2A37
More information about the distro-pkg-dev
mailing list