[SCM] SVGSalamander: SVG Library for Java branch, upstream, updated. 4e55347e5e2a1a9144a6d4a4ce9083314e9c3cfb
Nicolas Dandrimont
dandrimont-guest at alioth.debian.org
Fri Apr 15 14:31:32 UTC 2011
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "SVGSalamander: SVG Library for Java".
The branch, upstream has been updated
via 4e55347e5e2a1a9144a6d4a4ce9083314e9c3cfb (commit)
from 2e80aa58d8c5ebded4db1f0fa6cb7a799bbc9c06 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
.../java/com/kitfox/svg/batik/GraphicsUtil.java | 382 ------
.../com/kitfox/svg/batik/LinearGradientPaint.java | 354 -----
.../svg/batik/LinearGradientPaintContext.java | 529 --------
.../kitfox/svg/batik/MultipleGradientPaint.java | 236 ----
.../svg/batik/MultipleGradientPaintContext.java | 1421 --------------------
.../com/kitfox/svg/batik/RadialGradientPaint.java | 491 -------
.../svg/batik/RadialGradientPaintContext.java | 775 -----------
7 files changed, 0 insertions(+), 4188 deletions(-)
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/GraphicsUtil.java b/svg-core/src/main/java/com/kitfox/svg/batik/GraphicsUtil.java
deleted file mode 100644
index b52148b..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/GraphicsUtil.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
-import java.awt.GraphicsDevice;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.color.ColorSpace;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentSampleModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferInt;
-import java.awt.image.DataBufferShort;
-import java.awt.image.DataBufferUShort;
-import java.awt.image.DirectColorModel;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.awt.image.SampleModel;
-import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.WritableRaster;
-import java.awt.image.renderable.RenderContext;
-import java.awt.image.renderable.RenderableImage;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-
-/**
- *
- * @author kitfox
- */
-public class GraphicsUtil
-{
-
- /** Creates a new instance of GraphicsUtil */
- public GraphicsUtil()
- {
- }
-
- /**
- * Create a new ColorModel with it's alpha premultiplied state matching
- * newAlphaPreMult.
- * @param cm The ColorModel to change the alpha premult state of.
- * @param newAlphaPreMult The new state of alpha premult.
- * @return A new colorModel that has isAlphaPremultiplied()
- * equal to newAlphaPreMult.
- */
- public static ColorModel coerceColorModel(ColorModel cm, boolean newAlphaPreMult)
- {
- if (cm.isAlphaPremultiplied() == newAlphaPreMult)
- return cm;
-
- // Easiest way to build proper colormodel for new Alpha state...
- // Eventually this should switch on known ColorModel types and
- // only fall back on this hack when the CM type is unknown.
- WritableRaster wr = cm.createCompatibleWritableRaster(1,1);
- return cm.coerceData(wr, newAlphaPreMult);
- }
-
- /**
- * Coerces data within a bufferedImage to match newAlphaPreMult,
- * Note that this can not change the colormodel of bi so you
- *
- * @param wr The raster to change the state of.
- * @param cm The colormodel currently associated with data in wr.
- * @param newAlphaPreMult The desired state of alpha Premult for raster.
- * @return A new colormodel that matches newAlphaPreMult.
- */
- public static ColorModel coerceData(WritableRaster wr, ColorModel cm, boolean newAlphaPreMult)
- {
-
- // System.out.println("CoerceData: " + cm.isAlphaPremultiplied() +
- // " Out: " + newAlphaPreMult);
- if (cm.hasAlpha()== false)
- // Nothing to do no alpha channel
- return cm;
-
- if (cm.isAlphaPremultiplied() == newAlphaPreMult)
- // nothing to do alpha state matches...
- return cm;
-
- // System.out.println("CoerceData: " + wr.getSampleModel());
-
- int [] pixel = null;
- int bands = wr.getNumBands();
- float norm;
- if (newAlphaPreMult)
- {
- if (is_BYTE_COMP_Data(wr.getSampleModel()))
- mult_BYTE_COMP_Data(wr);
- else if (is_INT_PACK_Data(wr.getSampleModel(), true))
- mult_INT_PACK_Data(wr);
- else
- {
- norm = 1f/255f;
- int x0, x1, y0, y1, a, b;
- float alpha;
- x0 = wr.getMinX();
- x1 = x0+wr.getWidth();
- y0 = wr.getMinY();
- y1 = y0+wr.getHeight();
- for (int y=y0; y<y1; y++)
- for (int x=x0; x<x1; x++)
- {
- pixel = wr.getPixel(x,y,pixel);
- a = pixel[bands-1];
- if ((a >= 0) && (a < 255))
- {
- alpha = a*norm;
- for (b=0; b<bands-1; b++)
- pixel[b] = (int)(pixel[b]*alpha+0.5f);
- wr.setPixel(x,y,pixel);
- }
- }
- }
- } else
- {
- if (is_BYTE_COMP_Data(wr.getSampleModel()))
- divide_BYTE_COMP_Data(wr);
- else if (is_INT_PACK_Data(wr.getSampleModel(), true))
- divide_INT_PACK_Data(wr);
- else
- {
- int x0, x1, y0, y1, a, b;
- float ialpha;
- x0 = wr.getMinX();
- x1 = x0+wr.getWidth();
- y0 = wr.getMinY();
- y1 = y0+wr.getHeight();
- for (int y=y0; y<y1; y++)
- for (int x=x0; x<x1; x++)
- {
- pixel = wr.getPixel(x,y,pixel);
- a = pixel[bands-1];
- if ((a > 0) && (a < 255))
- {
- ialpha = 255/(float)a;
- for (b=0; b<bands-1; b++)
- pixel[b] = (int)(pixel[b]*ialpha+0.5f);
- wr.setPixel(x,y,pixel);
- }
- }
- }
- }
-
- return coerceColorModel(cm, newAlphaPreMult);
- }
-
-
- public static boolean is_INT_PACK_Data(SampleModel sm,
- boolean requireAlpha)
- {
- // Check ColorModel is of type DirectColorModel
- if(!(sm instanceof SinglePixelPackedSampleModel)) return false;
-
- // Check transfer type
- if(sm.getDataType() != DataBuffer.TYPE_INT) return false;
-
- SinglePixelPackedSampleModel sppsm;
- sppsm = (SinglePixelPackedSampleModel)sm;
-
- int [] masks = sppsm.getBitMasks();
- if (masks.length == 3)
- {
- if (requireAlpha) return false;
- } else if (masks.length != 4)
- return false;
-
- if(masks[0] != 0x00ff0000) return false;
- if(masks[1] != 0x0000ff00) return false;
- if(masks[2] != 0x000000ff) return false;
- if ((masks.length == 4) &&
- (masks[3] != 0xff000000)) return false;
-
- return true;
- }
-
- protected static void mult_INT_PACK_Data(WritableRaster wr)
- {
- // System.out.println("Multiply Int: " + wr);
-
- SinglePixelPackedSampleModel sppsm;
- sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
-
- final int width = wr.getWidth();
-
- final int scanStride = sppsm.getScanlineStride();
- DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
- final int base
- = (db.getOffset() +
- sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
- wr.getMinY()-wr.getSampleModelTranslateY()));
- int n=0;
- // Access the pixel data array
- final int pixels[] = db.getBankData()[0];
- for (int y=0; y<wr.getHeight(); y++)
- {
- int sp = base + y*scanStride;
- final int end = sp + width;
- while (sp < end)
- {
- int pixel = pixels[sp];
- int a = pixel>>>24;
- if ((a>=0) && (a<255))
- {
- pixels[sp] = ((a << 24) |
- ((((pixel&0xFF0000)*a)>>8)&0xFF0000) |
- ((((pixel&0x00FF00)*a)>>8)&0x00FF00) |
- ((((pixel&0x0000FF)*a)>>8)&0x0000FF));
- }
- sp++;
- }
- }
- }
-
- protected static void divide_INT_PACK_Data(WritableRaster wr)
- {
- // System.out.println("Divide Int");
-
- SinglePixelPackedSampleModel sppsm;
- sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
-
- final int width = wr.getWidth();
-
- final int scanStride = sppsm.getScanlineStride();
- DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
- final int base
- = (db.getOffset() +
- sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
- wr.getMinY()-wr.getSampleModelTranslateY()));
- int pixel, a, aFP, n=0;
- // Access the pixel data array
- final int pixels[] = db.getBankData()[0];
- for (int y=0; y<wr.getHeight(); y++)
- {
- int sp = base + y*scanStride;
- final int end = sp + width;
- while (sp < end)
- {
- pixel = pixels[sp];
- a = pixel>>>24;
- if (a<=0)
- {
- pixels[sp] = 0x00FFFFFF;
- }
- else if (a<255)
- {
- aFP = (0x00FF0000/a);
- pixels[sp] =
- ((a << 24) |
- (((((pixel&0xFF0000)>>16)*aFP)&0xFF0000) ) |
- (((((pixel&0x00FF00)>>8) *aFP)&0xFF0000)>>8 ) |
- (((((pixel&0x0000FF)) *aFP)&0xFF0000)>>16));
- }
- sp++;
- }
- }
- }
-
- public static boolean is_BYTE_COMP_Data(SampleModel sm)
- {
- // Check ColorModel is of type DirectColorModel
- if(!(sm instanceof ComponentSampleModel)) return false;
-
- // Check transfer type
- if(sm.getDataType() != DataBuffer.TYPE_BYTE) return false;
-
- return true;
- }
-
- protected static void mult_BYTE_COMP_Data(WritableRaster wr)
- {
- // System.out.println("Multiply Int: " + wr);
-
- ComponentSampleModel csm;
- csm = (ComponentSampleModel)wr.getSampleModel();
-
- final int width = wr.getWidth();
-
- final int scanStride = csm.getScanlineStride();
- final int pixStride = csm.getPixelStride();
- final int [] bandOff = csm.getBandOffsets();
-
- DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
- final int base
- = (db.getOffset() +
- csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
- wr.getMinY()-wr.getSampleModelTranslateY()));
-
-
- int a=0;
- int aOff = bandOff[bandOff.length-1];
- int bands = bandOff.length-1;
- int b, i;
-
- // Access the pixel data array
- final byte pixels[] = db.getBankData()[0];
- for (int y=0; y<wr.getHeight(); y++)
- {
- int sp = base + y*scanStride;
- final int end = sp + width*pixStride;
- while (sp < end)
- {
- a = pixels[sp+aOff]&0xFF;
- if (a!=0xFF)
- for (b=0; b<bands; b++)
- {
- i = sp+bandOff[b];
- pixels[i] = (byte)(((pixels[i]&0xFF)*a)>>8);
- }
- sp+=pixStride;
- }
- }
- }
-
- protected static void divide_BYTE_COMP_Data(WritableRaster wr)
- {
- // System.out.println("Multiply Int: " + wr);
-
- ComponentSampleModel csm;
- csm = (ComponentSampleModel)wr.getSampleModel();
-
- final int width = wr.getWidth();
-
- final int scanStride = csm.getScanlineStride();
- final int pixStride = csm.getPixelStride();
- final int [] bandOff = csm.getBandOffsets();
-
- DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
- final int base
- = (db.getOffset() +
- csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
- wr.getMinY()-wr.getSampleModelTranslateY()));
-
-
- int a=0;
- int aOff = bandOff[bandOff.length-1];
- int bands = bandOff.length-1;
- int b, i;
- // Access the pixel data array
- final byte pixels[] = db.getBankData()[0];
- for (int y=0; y<wr.getHeight(); y++)
- {
- int sp = base + y*scanStride;
- final int end = sp + width*pixStride;
- while (sp < end)
- {
- a = pixels[sp+aOff]&0xFF;
- if (a==0)
- {
- for (b=0; b<bands; b++)
- pixels[sp+bandOff[b]] = (byte)0xFF;
- } else if (a<255)
- {
- int aFP = (0x00FF0000/a);
- for (b=0; b<bands; b++)
- {
- i = sp+bandOff[b];
- pixels[i] = (byte)(((pixels[i]&0xFF)*aFP)>>>16);
- }
- }
- sp+=pixStride;
- }
- }
- }
-
-
-}
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/LinearGradientPaint.java b/svg-core/src/main/java/com/kitfox/svg/batik/LinearGradientPaint.java
deleted file mode 100644
index 50ff7cc..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/LinearGradientPaint.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.PaintContext;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ColorModel;
-
-/**
- * The <code>LinearGradientPaint</code> class provides a way to fill
- * a {@link java.awt.Shape} with a linear color gradient pattern. The user may
- * specify 2 or more gradient colors, and this paint will provide an
- * interpolation between each color. The user also specifies start and end
- * points which define where in user space the color gradient should begin
- * and end.
- * <p>
- * The user must provide an array of floats specifying how to distribute the
- * colors along the gradient. These values should range from 0.0 to 1.0 and
- * act like keyframes along the gradient (they mark where the gradient should
- * be exactly a particular color).
- * <p>
- * For example:
- * <br>
- * <code>
- * <p>
- * Point2D start = new Point2D.Float(0, 0);<br>
- * Point2D end = new Point2D.Float(100,100);<br>
- * float[] dist = {0.0, 0.2, 1.0};<br>
- * Color[] colors = {Color.red, Color.white, Color.blue};<br>
- * LinearGradientPaint p = new LinearGradientPaint(start, end, dist, colors);
- * </code>
- *<p>
- * This code will create a LinearGradientPaint which interpolates between
- * red and white for the first 20% of the gradient and between white and blue
- * for the remaining 80%.
- *
- * <p> In the event that the user does not set the first keyframe value equal
- * to 0 and the last keyframe value equal to 1, keyframes will be created at
- * these positions and the first and last colors will be replicated there.
- * So, if a user specifies the following arrays to construct a gradient:<br>
- * {Color.blue, Color.red}, {.3, .7}<br>
- * this will be converted to a gradient with the following keyframes:
- * {Color.blue, Color.blue, Color.red, Color.red}, {0, .3, .7, 1}
- *
- * <p>
- * The user may also select what action the LinearGradientPaint should take
- * when filling color outside the start and end points. If no cycle method is
- * specified, NO_CYCLE will be chosen by default, so the endpoint colors
- * will be used to fill the remaining area.
- *
- * <p> The following image demonstrates the options NO_CYCLE and REFLECT.
- *
- * <p>
- * <img src = "cyclic.jpg">
- *
- * <p> The colorSpace parameter allows the user to specify in which colorspace
- * the interpolation should be performed, default sRGB or linearized RGB.
- *
- *
- * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
- * @author <a href="mailto:vincent.hardy at eng.sun.com">Vincent Hardy</a>
- * @version $Id: LinearGradientPaint.java,v 1.2 2004/09/27 09:27:27 kitfox Exp $
- * @see java.awt.Paint
- * @see java.awt.Graphics2D#setPaint
- *
- */
-
-public final class LinearGradientPaint extends MultipleGradientPaint {
-
- /** Gradient start and end points. */
- private Point2D start, end;
-
- /**<p>
- * Constructs an <code>LinearGradientPaint</code> with the default
- * NO_CYCLE repeating method and SRGB colorspace.
- *
- * @param startX the x coordinate of the gradient axis start point
- * in user space
- *
- * @param startY the y coordinate of the gradient axis start point
- * in user space
- *
- * @param endX the x coordinate of the gradient axis end point
- * in user space
- *
- * @param endY the y coordinate of the gradient axis end point
- * in user space
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors corresponding to each fractional value
- *
- *
- * @throws IllegalArgumentException if start and end points are the
- * same points, or if fractions.length != colors.length, or if colors
- * is less than 2 in size.
- *
- */
- public LinearGradientPaint(float startX, float startY,
- float endX, float endY,
- float[] fractions, Color[] colors) {
-
- this(new Point2D.Float(startX, startY),
- new Point2D.Float(endX, endY),
- fractions,
- colors,
- NO_CYCLE,
- SRGB);
- }
-
- /**<p>
- * Constructs an <code>LinearGradientPaint</code> with default SRGB
- * colorspace.
- *
- * @param startX the x coordinate of the gradient axis start point
- * in user space
- *
- * @param startY the y coordinate of the gradient axis start point
- * in user space
- *
- * @param endX the x coordinate of the gradient axis end point
- * in user space
- *
- * @param endY the y coordinate of the gradient axis end point
- * in user space
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors corresponding to each fractional value
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @throws IllegalArgumentException if start and end points are the
- * same points, or if fractions.length != colors.length, or if colors
- * is less than 2 in size.
- *
- */
- public LinearGradientPaint(float startX, float startY,
- float endX, float endY,
- float[] fractions, Color[] colors,
- CycleMethodEnum cycleMethod) {
- this(new Point2D.Float(startX, startY),
- new Point2D.Float(endX, endY),
- fractions,
- colors,
- cycleMethod,
- SRGB);
- }
-
- /**<p>
- * Constructs a <code>LinearGradientPaint</code> with the default
- * NO_CYCLE repeating method and SRGB colorspace.
- *
- * @param start the gradient axis start <code>Point</code> in user space
- *
- * @param end the gradient axis end <code>Point</code> in user space
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors corresponding to each fractional value
- *
- * @throws NullPointerException if one of the points is null
- *
- * @throws IllegalArgumentException if start and end points are the
- * same points, or if fractions.length != colors.length, or if colors
- * is less than 2 in size.
- *
- */
- public LinearGradientPaint(Point2D start, Point2D end, float[] fractions,
- Color[] colors) {
-
- this(start, end, fractions, colors, NO_CYCLE, SRGB);
- }
-
- /**<p>
- * Constructs a <code>LinearGradientPaint</code>.
- *
- * @param start the gradient axis start <code>Point</code> in user space
- *
- * @param end the gradient axis end <code>Point</code> in user space
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors corresponding to each fractional value
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- * @throws NullPointerException if one of the points is null
- *
- * @throws IllegalArgumentException if start and end points are the
- * same points, or if fractions.length != colors.length, or if colors
- * is less than 2 in size.
- *
- */
- public LinearGradientPaint(Point2D start, Point2D end, float[] fractions,
- Color[] colors,
- CycleMethodEnum cycleMethod,
- ColorSpaceEnum colorSpace) {
-
- this(start, end, fractions, colors, cycleMethod, colorSpace,
- new AffineTransform());
-
- }
-
- /**<p>
- * Constructs a <code>LinearGradientPaint</code>.
- *
- * @param start the gradient axis start <code>Point</code> in user space
- *
- * @param end the gradient axis end <code>Point</code> in user space
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors corresponding to each fractional value
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- * @param gradientTransform transform to apply to the gradient
- *
- * @throws NullPointerException if one of the points is null,
- * or gradientTransform is null
- *
- * @throws IllegalArgumentException if start and end points are the
- * same points, or if fractions.length != colors.length, or if colors
- * is less than 2 in size.
- *
- */
- public LinearGradientPaint(Point2D start, Point2D end, float[] fractions,
- Color[] colors,
- CycleMethodEnum cycleMethod,
- ColorSpaceEnum colorSpace,
- AffineTransform gradientTransform) {
- super(fractions, colors, cycleMethod, colorSpace, gradientTransform);
-
- //
- // Check input parameters
- //
- if (start == null || end == null) {
- throw new NullPointerException("Start and end points must be" +
- "non-null");
- }
-
- if (start.equals(end)) {
- throw new IllegalArgumentException("Start point cannot equal" +
- "endpoint");
- }
-
- //copy the points...
- this.start = (Point2D)start.clone();
-
- this.end = (Point2D)end.clone();
-
- }
-
- /**
- * Creates and returns a PaintContext used to generate the color pattern,
- * for use by the internal rendering engine.
- *
- * @param cm {@link ColorModel} that receives
- * the <code>Paint</code> data. This is used only as a hint.
- *
- * @param deviceBounds the device space bounding box of the
- * graphics primitive being rendered
- *
- * @param userBounds the user space bounding box of the
- * graphics primitive being rendered
- *
- * @param transform the {@link AffineTransform} from user
- * space into device space
- *
- * @param hints the hints that the context object uses to choose
- * between rendering alternatives
- *
- * @return the {@link PaintContext} that generates color patterns.
- *
- * @see PaintContext
- */
- public PaintContext createContext(ColorModel cm,
- Rectangle deviceBounds,
- Rectangle2D userBounds,
- AffineTransform transform,
- RenderingHints hints) {
-
- // Can't modify the transform passed in...
- transform = new AffineTransform(transform);
- //incorporate the gradient transform
- transform.concatenate(gradientTransform);
-
- try {
- return new LinearGradientPaintContext(cm,
- deviceBounds,
- userBounds,
- transform,
- hints,
- start,
- end,
- fractions,
- this.getColors(),
- cycleMethod,
- colorSpace);
- }
-
- catch(NoninvertibleTransformException e) {
- e.printStackTrace();
- throw new IllegalArgumentException("transform should be" +
- "invertible");
- }
- }
-
- /**
- * Returns a copy of the start point of the gradient axis
- * @return a {@link Point2D} object that is a copy of the point
- * that anchors the first color of this
- * <code>LinearGradientPaint</code>.
- */
- public Point2D getStartPoint() {
- return new Point2D.Double(start.getX(), start.getY());
- }
-
- /** Returns a copy of the end point of the gradient axis
- * @return a {@link Point2D} object that is a copy of the point
- * that anchors the last color of this
- * <code>LinearGradientPaint</code>.
- */
- public Point2D getEndPoint() {
- return new Point2D.Double(end.getX(), end.getY());
- }
-
-}
-
-
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/LinearGradientPaintContext.java b/svg-core/src/main/java/com/kitfox/svg/batik/LinearGradientPaintContext.java
deleted file mode 100644
index c06d557..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/LinearGradientPaintContext.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ColorModel;
-
-/**
- * Provides the actual implementation for the LinearGradientPaint
- * This is where the pixel processing is done.
- *
- * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
- * @author <a href="mailto:vincent.hardy at eng.sun.com">Vincent Hardy</a>
- * @version $Id: LinearGradientPaintContext.java,v 1.2 2007/02/04 01:28:05 kitfox Exp $
- * @see java.awt.PaintContext
- * @see java.awt.Paint
- * @see java.awt.GradientPaint
- */
-final class LinearGradientPaintContext extends MultipleGradientPaintContext {
-
- /**
- * The following invariants are used to process the gradient value from
- * a device space coordinate, (X, Y):
- * g(X, Y) = dgdX*X + dgdY*Y + gc
- */
- private float dgdX, dgdY, gc, pixSz;
-
- private static final int DEFAULT_IMPL = 1;
- private static final int ANTI_ALIAS_IMPL = 3;
-
- private int fillMethod;
-
- /**
- * Constructor for LinearGradientPaintContext.
- *
- * @param cm {@link ColorModel} that receives
- * the <code>Paint</code> data. This is used only as a hint.
- *
- * @param deviceBounds the device space bounding box of the
- * graphics primitive being rendered
- *
- * @param userBounds the user space bounding box of the
- * graphics primitive being rendered
- *
- * @param t the {@link AffineTransform} from user
- * space into device space (gradientTransform should be
- * concatenated with this)
- *
- * @param hints the hints that the context object uses to choose
- * between rendering alternatives
- *
- * @param start gradient start point, in user space
- *
- * @param end gradient end point, in user space
- *
- * @param fractions the fractions specifying the gradient distribution
- *
- * @param colors the gradient colors
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- */
- public LinearGradientPaintContext(ColorModel cm,
- Rectangle deviceBounds,
- Rectangle2D userBounds,
- AffineTransform t,
- RenderingHints hints,
- Point2D dStart,
- Point2D dEnd,
- float[] fractions,
- Color[] colors,
- MultipleGradientPaint.CycleMethodEnum
- cycleMethod,
- MultipleGradientPaint.ColorSpaceEnum
- colorSpace)
- throws NoninvertibleTransformException
- {
- super(cm, deviceBounds, userBounds, t, hints, fractions,
- colors, cycleMethod, colorSpace);
-
- // Use single precision floating points
- Point2D.Float start = new Point2D.Float((float)dStart.getX(),
- (float)dStart.getY());
- Point2D.Float end = new Point2D.Float((float)dEnd.getX(),
- (float)dEnd.getY());
-
- // A given point in the raster should take on the same color as its
- // projection onto the gradient vector.
- // Thus, we want the projection of the current position vector
- // onto the gradient vector, then normalized with respect to the
- // length of the gradient vector, giving a value which can be mapped into
- // the range 0-1.
- // projection = currentVector dot gradientVector / length(gradientVector)
- // normalized = projection / length(gradientVector)
-
- float dx = end.x - start.x; // change in x from start to end
- float dy = end.y - start.y; // change in y from start to end
- float dSq = dx*dx + dy*dy; // total distance squared
-
- //avoid repeated calculations by doing these divides once.
- float constX = dx/dSq;
- float constY = dy/dSq;
-
- //incremental change along gradient for +x
- dgdX = a00*constX + a10*constY;
- //incremental change along gradient for +y
- dgdY = a01*constX + a11*constY;
-
- float dgdXAbs = Math.abs(dgdX);
- float dgdYAbs = Math.abs(dgdY);
- if (dgdXAbs > dgdYAbs) pixSz = dgdXAbs;
- else pixSz = dgdYAbs;
-
- //constant, incorporates the translation components from the matrix
- gc = (a02-start.x)*constX + (a12-start.y)*constY;
-
- Object colorRend = hints == null ? RenderingHints.VALUE_COLOR_RENDER_SPEED : hints.get(RenderingHints.KEY_COLOR_RENDERING);
- Object rend = hints == null ? RenderingHints.VALUE_RENDER_SPEED : hints.get(RenderingHints.KEY_RENDERING);
-
- fillMethod = DEFAULT_IMPL;
-
- if ((cycleMethod == MultipleGradientPaint.REPEAT) ||
- hasDiscontinuity) {
- if (rend == RenderingHints.VALUE_RENDER_QUALITY)
- fillMethod = ANTI_ALIAS_IMPL;
- // ColorRend overrides rend.
- if (colorRend == RenderingHints.VALUE_COLOR_RENDER_SPEED)
- fillMethod = DEFAULT_IMPL;
- else if (colorRend == RenderingHints.VALUE_COLOR_RENDER_QUALITY)
- fillMethod = ANTI_ALIAS_IMPL;
- }
- }
-
- protected void fillHardNoCycle(int[] pixels, int off, int adjust,
- int x, int y, int w, int h) {
-
- //constant which can be pulled out of the inner loop
- final float initConst = (dgdX*x) + gc;
-
- for(int i=0; i<h; i++) { //for every row
- //initialize current value to be start.
- float g = initConst + dgdY*(y+i);
- final int rowLimit = off+w; // end of row iteration
-
- if (dgdX == 0) {
- // System.out.println("In fillHard: " + g);
- final int val;
- if (g <= 0)
- val = gradientUnderflow;
- else if (g >= 1)
- val = gradientOverflow;
- else {
- // Could be a binary search...
- int gradIdx = 0;
- while (gradIdx < gradientsLength-1) {
- if (g < fractions[gradIdx+1])
- break;
- gradIdx++;
- }
- float delta = (g-fractions[gradIdx]);
- float idx = ((delta*GRADIENT_SIZE_INDEX)
- /normalizedIntervals[gradIdx])+0.5f;
- val = gradients[gradIdx][(int)idx];
- }
-
- while (off < rowLimit) {
- pixels[off++] = val;
- }
- } else {
- // System.out.println("In fillHard2: " + g);
- int gradSteps;
- int preGradSteps;
- final int preVal, postVal;
- if (dgdX >= 0) {
- gradSteps = (int) ((1-g)/dgdX);
- preGradSteps = (int)Math.ceil((0-g)/dgdX);
- preVal = gradientUnderflow;
- postVal = gradientOverflow;
- } else { // dgdX < 0
- gradSteps = (int) ((0-g)/dgdX);
- preGradSteps = (int)Math.ceil((1-g)/dgdX);
- preVal = gradientOverflow;
- postVal = gradientUnderflow;
- }
-
- if (gradSteps > w)
- gradSteps = w;
-
- final int gradLimit = off + gradSteps;
- if (preGradSteps > 0) {
- if (preGradSteps > w)
- preGradSteps = w;
- final int preGradLimit = off + preGradSteps;
-
- while (off < preGradLimit) {
- pixels[off++] = preVal;
- }
- g += dgdX*preGradSteps;
- }
-
- if (dgdX > 0) {
- // Could be a binary search...
- int gradIdx = 0;
- while (gradIdx < gradientsLength-1) {
- if (g < fractions[gradIdx+1])
- break;
- gradIdx++;
- }
-
- while (off < gradLimit) {
- float delta = (g-fractions[gradIdx]);
- final int [] grad = gradients[gradIdx];
-
- int steps =
- (int)Math.ceil((fractions[gradIdx+1]-g)/dgdX);
- int subGradLimit = off + steps;
- if (subGradLimit > gradLimit)
- subGradLimit = gradLimit;
-
- int idx = (int)(((delta*GRADIENT_SIZE_INDEX)
- /normalizedIntervals[gradIdx])
- *(1<<16)) + (1<<15);
- int step = (int)(((dgdX*GRADIENT_SIZE_INDEX)
- /normalizedIntervals[gradIdx])
- *(1<<16));
- while (off < subGradLimit) {
- pixels[off++] = grad[idx>>16];
- idx += step;
- }
- g+=dgdX*steps;
- gradIdx++;
- }
- } else {
- // Could be a binary search...
- int gradIdx = gradientsLength-1;
- while (gradIdx > 0) {
- if (g > fractions[gradIdx])
- break;
- gradIdx--;
- }
-
- while (off < gradLimit) {
- float delta = (g-fractions[gradIdx]);
- final int [] grad = gradients[gradIdx];
-
- int steps = (int)Math.ceil(delta/-dgdX);
- int subGradLimit = off + steps;
- if (subGradLimit > gradLimit)
- subGradLimit = gradLimit;
-
- int idx = (int)(((delta*GRADIENT_SIZE_INDEX)
- /normalizedIntervals[gradIdx])
- *(1<<16)) + (1<<15);
- int step = (int)(((dgdX*GRADIENT_SIZE_INDEX)
- /normalizedIntervals[gradIdx])
- *(1<<16));
- while (off < subGradLimit) {
- pixels[off++] = grad[idx>>16];
- idx += step;
- }
- g+=dgdX*steps;
- gradIdx--;
- }
- }
-
- while (off < rowLimit) {
- pixels[off++] = postVal;
- }
- }
- off += adjust; //change in off from row to row
- }
- }
-
- protected void fillSimpleNoCycle(int[] pixels, int off, int adjust,
- int x, int y, int w, int h) {
- //constant which can be pulled out of the inner loop
- final float initConst = (dgdX*x) + gc;
- final float step = dgdX*fastGradientArraySize;
- final int fpStep = (int)(step*(1<<16)); // fix point step
-
- final int [] grad = gradient;
-
- for(int i=0; i<h; i++){ //for every row
- //initialize current value to be start.
- float g = initConst + dgdY*(y+i);
- g *= fastGradientArraySize;
- g += 0.5; // rounding factor...
-
- final int rowLimit = off+w; // end of row iteration
-
- if (dgdX == 0) {
- // System.out.println("In fillSimpleNC: " + g);
- final int val;
- if (g<=0)
- val = gradientUnderflow;
- else if (g>=fastGradientArraySize)
- val = gradientOverflow;
- else
- val = grad[(int)g];
- while (off < rowLimit) {
- pixels[off++] = val;
- }
- } else {
- // System.out.println("In fillSimpleNC2: " + g);
- int gradSteps;
- int preGradSteps;
- final int preVal, postVal;
- if (dgdX > 0) {
- gradSteps = (int)((fastGradientArraySize-g)/step);
- preGradSteps = (int)Math.ceil(0-g/step);
- preVal = gradientUnderflow;
- postVal = gradientOverflow;
-
- } else { // dgdX < 0
- gradSteps = (int)((0-g)/step);
- preGradSteps =
- (int)Math.ceil((fastGradientArraySize-g)/step);
- preVal = gradientOverflow;
- postVal = gradientUnderflow;
- }
-
- if (gradSteps > w)
- gradSteps = w;
- final int gradLimit = off + gradSteps;
-
- if (preGradSteps > 0) {
- if (preGradSteps > w)
- preGradSteps = w;
- final int preGradLimit = off + preGradSteps;
-
- while (off < preGradLimit) {
- pixels[off++] = preVal;
- }
- g += step*preGradSteps;
- }
-
- int fpG = (int)(g*(1<<16));
- while (off < gradLimit) {
- pixels[off++] = grad[fpG>>16];
- fpG += fpStep;
- }
-
- while (off < rowLimit) {
- pixels[off++] = postVal;
- }
- }
- off += adjust; //change in off from row to row
- }
- }
-
- protected void fillSimpleRepeat(int[] pixels, int off, int adjust,
- int x, int y, int w, int h) {
-
- final float initConst = (dgdX*x) + gc;
-
- // Limit step to fractional part of
- // fastGradientArraySize (the non fractional part has
- // no affect anyways, and would mess up lots of stuff
- // below).
- float step = (dgdX - (int)dgdX)*fastGradientArraySize;
-
- // Make it a Positive step (a small negative step is
- // the same as a positive step slightly less than
- // fastGradientArraySize.
- if (step < 0)
- step += fastGradientArraySize;
-
- final int [] grad = gradient;
-
- for(int i=0; i<h; i++) { //for every row
- //initialize current value to be start.
- float g = initConst + dgdY*(y+i);
-
- // now Limited between -1 and 1.
- g = g-(int)g;
- // put in the positive side.
- if (g < 0)
- g += 1;
-
- // scale for gradient array...
- g *= fastGradientArraySize;
- g += 0.5; // rounding factor
- final int rowLimit = off+w; // end of row iteration
- while (off < rowLimit) {
- int idx = (int)g;
- if (idx >= fastGradientArraySize) {
- g -= fastGradientArraySize;
- idx -= fastGradientArraySize;
- }
- pixels[off++] = grad[idx];
- g += step;
- }
-
- off += adjust; //change in off from row to row
- }
- }
-
-
- protected void fillSimpleReflect(int[] pixels, int off, int adjust,
- int x, int y, int w, int h) {
- final float initConst = (dgdX*x) + gc;
-
- final int [] grad = gradient;
-
- for (int i=0; i<h; i++) { //for every row
- //initialize current value to be start.
- float g = initConst + dgdY*(y+i);
-
- // now limited g to -2<->2
- g = g - 2*((int)(g/2.0f));
-
- float step = dgdX;
- // Pull it into the positive half
- if (g < 0) {
- g = -g; //take absolute value
- step = - step; // Change direction..
- }
-
- // Now do the same for dgdX. This is safe because
- // any step that is a multiple of 2.0 has no
- // affect, hence we can remove it which the first
- // part does. The second part simply adds 2.0
- // (which has no affect due to the cylcle) to move
- // all negative step values into the positive
- // side.
- step = step - 2*((int)step/2.0f);
- if (step < 0)
- step += 2.0;
- final int reflectMax = 2*fastGradientArraySize;
-
- // Scale for gradient array.
- g *= fastGradientArraySize;
- g += 0.5;
- step *= fastGradientArraySize;
- final int rowLimit = off+w; // end of row iteration
- while (off < rowLimit) {
- int idx = (int)g;
- if (idx >= reflectMax) {
- g -= reflectMax;
- idx -= reflectMax;
- }
-
- if (idx <= fastGradientArraySize)
- pixels[off++] = grad[idx];
- else
- pixels[off++] = grad[reflectMax-idx];
- g+= step;
- }
-
- off += adjust; //change in off from row to row
- }
- }
-
- /**
- * Return a Raster containing the colors generated for the graphics
- * operation. This is where the area is filled with colors distributed
- * linearly.
- *
- * @param x,y,w,h The area in device space for which colors are
- * generated.
- *
- */
- protected void fillRaster(int[] pixels, int off, int adjust,
- int x, int y, int w, int h) {
-
- //constant which can be pulled out of the inner loop
- final float initConst = (dgdX*x) + gc;
-
- if (fillMethod == ANTI_ALIAS_IMPL) {
- //initialize current value to be start.
- for(int i=0; i<h; i++){ //for every row
- float g = initConst + dgdY*(y+i);
-
- final int rowLimit = off+w; // end of row iteration
- while(off < rowLimit){ //for every pixel in this row.
- //get the color
- pixels[off++] = indexGradientAntiAlias(g, pixSz);
- g += dgdX; //incremental change in g
- }
- off += adjust; //change in off from row to row
- }
- }
- else if (!isSimpleLookup) {
- if (cycleMethod == MultipleGradientPaint.NO_CYCLE) {
- fillHardNoCycle(pixels, off, adjust, x, y, w, h);
- }
- else {
- //initialize current value to be start.
- for(int i=0; i<h; i++){ //for every row
- float g = initConst + dgdY*(y+i);
-
- final int rowLimit = off+w; // end of row iteration
- while(off < rowLimit){ //for every pixel in this row.
- //get the color
- pixels[off++] = indexIntoGradientsArrays(g);
- g += dgdX; //incremental change in g
- }
- off += adjust; //change in off from row to row
- }
- }
- } else {
- // Simple implementations: just scale index by array size
-
- if (cycleMethod == MultipleGradientPaint.NO_CYCLE)
- fillSimpleNoCycle(pixels, off, adjust, x, y, w, h);
- else if (cycleMethod == MultipleGradientPaint.REPEAT)
- fillSimpleRepeat(pixels, off, adjust, x, y, w, h);
- else //cycleMethod == MultipleGradientPaint.REFLECT
- fillSimpleReflect(pixels, off, adjust, x, y, w, h);
- }
- }
-
-
-}
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/MultipleGradientPaint.java b/svg-core/src/main/java/com/kitfox/svg/batik/MultipleGradientPaint.java
deleted file mode 100644
index 9cd8c11..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/MultipleGradientPaint.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.Paint;
-import java.awt.geom.AffineTransform;
-
-/** This is the superclass for Paints which use a multiple color
- * gradient to fill in their raster. It provides storage for variables and
- * enumerated values common to LinearGradientPaint and RadialGradientPaint.
- *
- *
- * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
- * @author <a href="mailto:vincent.hardy at eng.sun.com">Vincent Hardy</a>
- * @version $Id: MultipleGradientPaint.java,v 1.2 2004/09/27 09:27:27 kitfox Exp $
- *
- */
-
-public abstract class MultipleGradientPaint implements Paint {
-
- /** Transparency. */
- protected int transparency;
-
- /** Gradient keyframe values in the range 0 to 1. */
- protected float[] fractions;
-
- /** Gradient colors. */
- protected Color[] colors;
-
- /** Transform to apply to gradient. */
- protected AffineTransform gradientTransform;
-
- /** The method to use when painting out of the gradient bounds. */
- protected CycleMethodEnum cycleMethod;
-
- /** The colorSpace in which to perform the interpolation. */
- protected ColorSpaceEnum colorSpace;
-
- /** Inner class to allow for typesafe enumerated ColorSpace values. */
- public static class ColorSpaceEnum {
- }
-
- /** Inner class to allow for typesafe enumerated CycleMethod values. */
- public static class CycleMethodEnum {
- }
-
- /** Indicates (if the gradient starts or ends inside the target region)
- * to use the terminal colors to fill the remaining area. (default)
- */
- public static final CycleMethodEnum NO_CYCLE = new CycleMethodEnum();
-
- /** Indicates (if the gradient starts or ends inside the target region),
- * to cycle the gradient colors start-to-end, end-to-start to fill the
- * remaining area.
- */
- public static final CycleMethodEnum REFLECT = new CycleMethodEnum();
-
- /** Indicates (if the gradient starts or ends inside the target region),
- * to cycle the gradient colors start-to-end, start-to-end to fill the
- * remaining area.
- */
- public static final CycleMethodEnum REPEAT = new CycleMethodEnum();
-
- /** Indicates that the color interpolation should occur in sRGB space.
- * (default)
- */
- public static final ColorSpaceEnum SRGB = new ColorSpaceEnum();
-
- /** Indicates that the color interpolation should occur in linearized
- * RGB space.
- */
- public static final ColorSpaceEnum LINEAR_RGB = new ColorSpaceEnum();
-
-
- /**
- * Superclass constructor, typical user should never have to call this.
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors corresponding to each fractional value
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- * @param gradientTransform transform to apply to the gradient
- *
- * @throws NullPointerException if arrays are null, or
- * gradientTransform is null
- *
- * @throws IllegalArgumentException if fractions.length != colors.length,
- * or if colors is less than 2 in size, or if an enumerated value is bad.
- *
- * @see java.awt.PaintContext
- */
- public MultipleGradientPaint(float[] fractions,
- Color[] colors,
- CycleMethodEnum cycleMethod,
- ColorSpaceEnum colorSpace,
- AffineTransform gradientTransform) {
-
- if (fractions == null) {
- throw new IllegalArgumentException("Fractions array cannot be " +
- "null");
- }
-
- if (colors == null) {
- throw new IllegalArgumentException("Colors array cannot be null");
- }
-
- if (fractions.length != colors.length) {
- throw new IllegalArgumentException("Colors and fractions must " +
- "have equal size");
- }
-
- if (colors.length < 2) {
- throw new IllegalArgumentException("User must specify at least " +
- "2 colors");
- }
-
- if ((colorSpace != LINEAR_RGB) &&
- (colorSpace != SRGB)) {
- throw new IllegalArgumentException("Invalid colorspace for " +
- "interpolation.");
- }
-
- if ((cycleMethod != NO_CYCLE) &&
- (cycleMethod != REFLECT) &&
- (cycleMethod != REPEAT)) {
- throw new IllegalArgumentException("Invalid cycle method.");
- }
-
- if (gradientTransform == null) {
- throw new IllegalArgumentException("Gradient transform cannot be "+
- "null.");
- }
-
- //copy the fractions array
- this.fractions = new float[fractions.length];
- System.arraycopy(fractions, 0, this.fractions, 0, fractions.length);
-
- //copy the colors array
- this.colors = new Color[colors.length];
- System.arraycopy(colors, 0, this.colors, 0, colors.length);
-
- //copy some flags
- this.colorSpace = colorSpace;
- this.cycleMethod = cycleMethod;
-
- //copy the gradient transform
- this.gradientTransform = (AffineTransform)gradientTransform.clone();
-
- // Process transparency
- boolean opaque = true;
- for(int i=0; i<colors.length; i++){
- opaque = opaque && (colors[i].getAlpha()==0xff);
- }
-
- if(opaque) {
- transparency = OPAQUE;
- }
-
- else {
- transparency = TRANSLUCENT;
- }
- }
-
- /**
- * Returns a copy of the array of colors used by this gradient.
- * @return a copy of the array of colors used by this gradient
- *
- */
- public Color[] getColors() {
- Color colors[] = new Color[this.colors.length];
- System.arraycopy(this.colors, 0, colors, 0, this.colors.length);
- return colors;
- }
-
- /**
- * Returns a copy of the array of floats used by this gradient
- * to calculate color distribution.
- * @return a copy of the array of floats used by this gradient to
- * calculate color distribution
- *
- */
- public float[] getFractions() {
- float fractions[] = new float[this.fractions.length];
- System.arraycopy(this.fractions, 0, fractions, 0, this.fractions.length);
- return fractions;
- }
-
- /**
- * Returns the transparency mode for this LinearGradientPaint.
- * @return an integer value representing this LinearGradientPaint object's
- * transparency mode.
- * @see java.awt.Transparency
- */
- public int getTransparency() {
- return transparency;
- }
-
- /**
- * Returns the enumerated type which specifies cycling behavior.
- * @return the enumerated type which specifies cycling behavior
- */
- public CycleMethodEnum getCycleMethod() {
- return cycleMethod;
- }
-
- /**
- * Returns the enumerated type which specifies color space for
- * interpolation.
- * @return the enumerated type which specifies color space for
- * interpolation
- */
- public ColorSpaceEnum getColorSpace() {
- return colorSpace;
- }
-
- /**
- * Returns a copy of the transform applied to the gradient.
- * @return a copy of the transform applied to the gradient.
- */
- public AffineTransform getTransform() {
- return (AffineTransform)gradientTransform.clone();
- }
-}
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/MultipleGradientPaintContext.java b/svg-core/src/main/java/com/kitfox/svg/batik/MultipleGradientPaintContext.java
deleted file mode 100644
index 85f3273..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/MultipleGradientPaintContext.java
+++ /dev/null
@@ -1,1421 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.PaintContext;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.color.ColorSpace;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferInt;
-import java.awt.image.DirectColorModel;
-import java.awt.image.Raster;
-import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.WritableRaster;
-import java.lang.ref.WeakReference;
-
-//import org.apache.batik.ext.awt.image.GraphicsUtil;
-
-/** This is the superclass for all PaintContexts which use a multiple color
- * gradient to fill in their raster. It provides the actual color interpolation
- * functionality. Subclasses only have to deal with using the gradient to fill
- * pixels in a raster.
- *
- * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
- * @author <a href="mailto:vincent.hardy at eng.sun.com">Vincent Hardy</a>
- * @version $Id: MultipleGradientPaintContext.java,v 1.1 2004/09/06 19:35:39 kitfox Exp $
- *
- */
-abstract class MultipleGradientPaintContext implements PaintContext {
-
- protected final static boolean DEBUG = false;
-
- /**
- * The color model data is generated in (always un premult).
- */
- protected ColorModel dataModel;
- /**
- * PaintContext's output ColorModel ARGB if colors are not all
- * opaque, RGB otherwise. Linear and premult are matched to
- * output ColorModel.
- */
- protected ColorModel model;
-
- /** Color model used if gradient colors are all opaque */
- private static ColorModel lrgbmodel_NA = new DirectColorModel
- (ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
- 24, 0xff0000, 0xFF00, 0xFF, 0x0,
- false, DataBuffer.TYPE_INT);
-
- private static ColorModel srgbmodel_NA = new DirectColorModel
- (ColorSpace.getInstance(ColorSpace.CS_sRGB),
- 24, 0xff0000, 0xFF00, 0xFF, 0x0,
- false, DataBuffer.TYPE_INT);
-
- /** Color model used if some gradient colors are transparent */
- private static ColorModel lrgbmodel_A = new DirectColorModel
- (ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
- 32, 0xff0000, 0xFF00, 0xFF, 0xFF000000,
- false, DataBuffer.TYPE_INT);
-
- private static ColorModel srgbmodel_A = new DirectColorModel
- (ColorSpace.getInstance(ColorSpace.CS_sRGB),
- 32, 0xff0000, 0xFF00, 0xFF, 0xFF000000,
- false, DataBuffer.TYPE_INT);
-
- /** The cached colorModel */
- protected static ColorModel cachedModel;
-
- /** The cached raster, which is reusable among instances */
- protected static WeakReference cached;
-
- /** Raster is reused whenever possible */
- protected WritableRaster saved;
-
- /** The method to use when painting out of the gradient bounds. */
- protected MultipleGradientPaint.CycleMethodEnum cycleMethod;
-
- /** The colorSpace in which to perform the interpolation */
- protected MultipleGradientPaint.ColorSpaceEnum colorSpace;
-
- /** Elements of the inverse transform matrix. */
- protected float a00, a01, a10, a11, a02, a12;
-
- /** This boolean specifies wether we are in simple lookup mode, where an
- * input value between 0 and 1 may be used to directly index into a single
- * array of gradient colors. If this boolean value is false, then we have
- * to use a 2-step process where we have to determine which gradient array
- * we fall into, then determine the index into that array.
- */
- protected boolean isSimpleLookup = true;
-
- /** This boolean indicates if the gradient appears to have sudden
- * discontinuities in it, this may be because of multiple stops
- * at the same location or use of the REPEATE mode.
- */
- protected boolean hasDiscontinuity = false;
-
- /** Size of gradients array for scaling the 0-1 index when looking up
- * colors the fast way. */
- protected int fastGradientArraySize;
-
- /**
- * Array which contains the interpolated color values for each interval,
- * used by calculateSingleArrayGradient(). It is protected for possible
- * direct access by subclasses.
- */
- protected int[] gradient;
-
- /** Array of gradient arrays, one array for each interval. Used by
- * calculateMultipleArrayGradient().
- */
- protected int[][] gradients;
-
- /** This holds the blend of all colors in the gradient.
- * we use this at extreamly low resolutions to ensure we
- * get a decent blend of the colors.
- */
- protected int gradientAverage;
-
- /** This holds the color to use when we are off the bottom of the
- * gradient */
- protected int gradientUnderflow;
-
- /** This holds the color to use when we are off the top of the
- * gradient */
- protected int gradientOverflow;
-
- /** Length of the 2D slow lookup gradients array. */
- protected int gradientsLength;
-
- /** Normalized intervals array */
- protected float[] normalizedIntervals;
-
- /** fractions array */
- protected float[] fractions;
-
- /** Used to determine if gradient colors are all opaque */
- private int transparencyTest;
-
- /** Colorspace conversion lookup tables */
- private static final int SRGBtoLinearRGB[] = new int[256];
- private static final int LinearRGBtoSRGB[] = new int[256];
-
- //build the tables
- static{
- for (int k = 0; k < 256; k++) {
- SRGBtoLinearRGB[k] = convertSRGBtoLinearRGB(k);
- LinearRGBtoSRGB[k] = convertLinearRGBtoSRGB(k);
- }
- }
-
- /** Constant number of max colors between any 2 arbitrary colors.
- * Used for creating and indexing gradients arrays.
- */
- protected static final int GRADIENT_SIZE = 256;
- protected static final int GRADIENT_SIZE_INDEX = GRADIENT_SIZE -1;
-
- /** Maximum length of the fast single-array. If the estimated array size
- * is greater than this, switch over to the slow lookup method.
- * No particular reason for choosing this number, but it seems to provide
- * satisfactory performance for the common case (fast lookup).
- */
- private static final int MAX_GRADIENT_ARRAY_SIZE = 5000;
-
- /** Constructor for superclass. Does some initialization, but leaves most
- * of the heavy-duty math for calculateGradient(), so the subclass may do
- * some other manipulation beforehand if necessary. This is not possible
- * if this computation is done in the superclass constructor which always
- * gets called first.
- **/
- public MultipleGradientPaintContext(ColorModel cm,
- Rectangle deviceBounds,
- Rectangle2D userBounds,
- AffineTransform t,
- RenderingHints hints,
- float[] fractions,
- Color[] colors,
- MultipleGradientPaint.CycleMethodEnum
- cycleMethod,
- MultipleGradientPaint.ColorSpaceEnum
- colorSpace)
- throws NoninvertibleTransformException
- {
- //We have to deal with the cases where the 1st gradient stop is not
- //equal to 0 and/or the last gradient stop is not equal to 1.
- //In both cases, create a new point and replicate the previous
- //extreme point's color.
-
- boolean fixFirst = false;
- boolean fixLast = false;
- int len = fractions.length;
-
- //if the first gradient stop is not equal to zero, fix this condition
- if (fractions[0] != 0f) {
- fixFirst = true;
- len++;
- }
-
- //if the last gradient stop is not equal to one, fix this condition
- if (fractions[fractions.length - 1] != 1f) {
- fixLast = true;
- len++;
- }
-
- for (int i=0; i<fractions.length-1; i++)
- if (fractions[i] == fractions[i+1])
- len--;
-
- this.fractions = new float[len];
- Color [] loColors = new Color[len-1];
- Color [] hiColors = new Color[len-1];
- normalizedIntervals = new float[len-1];
-
- gradientUnderflow = colors[0].getRGB();
- gradientOverflow = colors[colors.length-1].getRGB();
-
- int idx = 0;
- if (fixFirst) {
- this.fractions[0] = 0;
- loColors[0] = colors[0];
- hiColors[0] = colors[0];
- normalizedIntervals[0] = fractions[0];
- idx++;
- }
-
- for (int i=0; i<fractions.length-1; i++) {
- if (fractions[i] == fractions[i+1]) {
- // System.out.println("EQ Fracts");
- if (!colors[i].equals(colors[i+1])) {
- hasDiscontinuity = true;
- }
- continue;
- }
- this.fractions[idx] = fractions[i];
- loColors[idx] = colors[i];
- hiColors[idx] = colors[i+1];
- normalizedIntervals[idx] = fractions[i+1]-fractions[i];
- idx++;
- }
-
- this.fractions[idx] = fractions[fractions.length-1];
-
- if (fixLast) {
- loColors[idx] = hiColors[idx] = colors[colors.length-1];
- normalizedIntervals[idx] = 1-fractions[fractions.length-1];
- idx++;
- this.fractions[idx] = 1;
- }
-
- // The inverse transform is needed to from device to user space.
- // Get all the components of the inverse transform matrix.
- AffineTransform tInv = t.createInverse();
-
- double m[] = new double[6];
- tInv.getMatrix(m);
- a00 = (float)m[0];
- a10 = (float)m[1];
- a01 = (float)m[2];
- a11 = (float)m[3];
- a02 = (float)m[4];
- a12 = (float)m[5];
-
- //copy some flags
- this.cycleMethod = cycleMethod;
- this.colorSpace = colorSpace;
-
- // Setup an example Model, we may refine it later.
- if (cm.getColorSpace() == lrgbmodel_A.getColorSpace())
- dataModel = lrgbmodel_A;
- else if (cm.getColorSpace() == srgbmodel_A.getColorSpace())
- dataModel = srgbmodel_A;
- else
- throw new IllegalArgumentException
- ("Unsupported ColorSpace for interpolation");
-
- calculateGradientFractions(loColors, hiColors);
-
- model = GraphicsUtil.coerceColorModel(dataModel,
- cm.isAlphaPremultiplied());
- }
-
-
- /** This function is the meat of this class. It calculates an array of
- * gradient colors based on an array of fractions and color values at those
- * fractions.
- */
- protected final void calculateGradientFractions
- (Color []loColors, Color []hiColors) {
-
- //if interpolation should occur in Linear RGB space, convert the
- //colors using the lookup table
- if (colorSpace == LinearGradientPaint.LINEAR_RGB) {
- for (int i = 0; i < loColors.length; i++) {
- loColors[i] =
- new Color(SRGBtoLinearRGB[loColors[i].getRed()],
- SRGBtoLinearRGB[loColors[i].getGreen()],
- SRGBtoLinearRGB[loColors[i].getBlue()],
- loColors[i].getAlpha());
-
- hiColors[i] =
- new Color(SRGBtoLinearRGB[hiColors[i].getRed()],
- SRGBtoLinearRGB[hiColors[i].getGreen()],
- SRGBtoLinearRGB[hiColors[i].getBlue()],
- hiColors[i].getAlpha());
- }
- }
-
- //initialize to be fully opaque for ANDing with colors
- transparencyTest = 0xff000000;
-
- //array of interpolation arrays
- gradients = new int[fractions.length - 1][];
- gradientsLength = gradients.length;
-
- // Find smallest interval
- int n = normalizedIntervals.length;
-
- float Imin = 1;
-
- for(int i = 0; i < n; i++) {
- Imin = (Imin > normalizedIntervals[i]) ?
- normalizedIntervals[i] : Imin;
- }
-
- //estimate the size of the entire gradients array.
- //This is to prevent a tiny interval from causing the size of array to
- //explode. If the estimated size is too large, break to using
- //seperate arrays for each interval, and using an indexing scheme at
- //look-up time.
- int estimatedSize = 0;
-
- if (Imin == 0) {
- estimatedSize = Integer.MAX_VALUE;
- hasDiscontinuity = true;
- } else {
- for (int i = 0; i < normalizedIntervals.length; i++) {
- estimatedSize += (normalizedIntervals[i]/Imin) * GRADIENT_SIZE;
- }
- }
-
-
- if (estimatedSize > MAX_GRADIENT_ARRAY_SIZE) {
- //slow method
- calculateMultipleArrayGradient(loColors, hiColors);
- if ((cycleMethod == MultipleGradientPaint.REPEAT) &&
- (gradients[0][0] !=
- gradients[gradients.length-1][GRADIENT_SIZE_INDEX]))
- hasDiscontinuity = true;
- } else {
- //fast method
- calculateSingleArrayGradient(loColors, hiColors, Imin);
- if ((cycleMethod == MultipleGradientPaint.REPEAT) &&
- (gradient[0] != gradient[fastGradientArraySize]))
- hasDiscontinuity = true;
- }
-
- // Use the most 'economical' model (no alpha).
- if((transparencyTest >>> 24) == 0xff) {
- if (dataModel.getColorSpace() == lrgbmodel_NA.getColorSpace())
- dataModel = lrgbmodel_NA;
- else if (dataModel.getColorSpace() == srgbmodel_NA.getColorSpace())
- dataModel = srgbmodel_NA;
- model = dataModel;
- }
- }
-
-
- /**
- * FAST LOOKUP METHOD
- *
- * This method calculates the gradient color values and places them in a
- * single int array, gradient[]. It does this by allocating space for
- * each interval based on its size relative to the smallest interval in
- * the array. The smallest interval is allocated 255 interpolated values
- * (the maximum number of unique in-between colors in a 24 bit color
- * system), and all other intervals are allocated
- * size = (255 * the ratio of their size to the smallest interval).
- *
- * This scheme expedites a speedy retrieval because the colors are
- * distributed along the array according to their user-specified
- * distribution. All that is needed is a relative index from 0 to 1.
- *
- * The only problem with this method is that the possibility exists for
- * the array size to balloon in the case where there is a
- * disproportionately small gradient interval. In this case the other
- * intervals will be allocated huge space, but much of that data is
- * redundant. We thus need to use the space conserving scheme below.
- *
- * @param Imin the size of the smallest interval
- *
- */
- private void calculateSingleArrayGradient
- (Color [] loColors, Color [] hiColors, float Imin) {
-
- //set the flag so we know later it is a non-simple lookup
- isSimpleLookup = true;
-
- int rgb1; //2 colors to interpolate
- int rgb2;
-
- int gradientsTot = 1; //the eventual size of the single array
-
- // These are fixed point 8.16 (start with 0.5)
- int aveA = 0x008000;
- int aveR = 0x008000;
- int aveG = 0x008000;
- int aveB = 0x008000;
-
- //for every interval (transition between 2 colors)
- for(int i=0; i < gradients.length; i++){
-
- //create an array whose size is based on the ratio to the
- //smallest interval.
- int nGradients = (int)((normalizedIntervals[i]/Imin)*255f);
- gradientsTot += nGradients;
- gradients[i] = new int[nGradients];
-
- //the the 2 colors (keyframes) to interpolate between
- rgb1 = loColors[i].getRGB();
- rgb2 = hiColors[i].getRGB();
-
- //fill this array with the colors in between rgb1 and rgb2
- interpolate(rgb1, rgb2, gradients[i]);
-
- // Calculate Average of two colors...
- int argb = gradients[i][GRADIENT_SIZE/2];
- float norm = normalizedIntervals[i];
- aveA += (int)(((argb>> 8)&0xFF0000)*norm);
- aveR += (int)(((argb )&0xFF0000)*norm);
- aveG += (int)(((argb<< 8)&0xFF0000)*norm);
- aveB += (int)(((argb<<16)&0xFF0000)*norm);
-
- //if the colors are opaque, transparency should still be 0xff000000
- transparencyTest &= rgb1;
- transparencyTest &= rgb2;
- }
-
- gradientAverage = (((aveA & 0xFF0000)<< 8) |
- ((aveR & 0xFF0000) ) |
- ((aveG & 0xFF0000)>> 8) |
- ((aveB & 0xFF0000)>>16));
-
- // Put all gradients in a single array
- gradient = new int[gradientsTot];
- int curOffset = 0;
- for(int i = 0; i < gradients.length; i++){
- System.arraycopy(gradients[i], 0, gradient,
- curOffset, gradients[i].length);
- curOffset += gradients[i].length;
- }
- gradient[gradient.length-1] = hiColors[hiColors.length-1].getRGB();
-
- //if interpolation occurred in Linear RGB space, convert the
- //gradients back to SRGB using the lookup table
- if (colorSpace == LinearGradientPaint.LINEAR_RGB) {
- if (dataModel.getColorSpace() ==
- ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
- for (int i = 0; i < gradient.length; i++) {
- gradient[i] =
- convertEntireColorLinearRGBtoSRGB(gradient[i]);
- }
- gradientAverage =
- convertEntireColorLinearRGBtoSRGB(gradientAverage);
- }
- } else {
- if (dataModel.getColorSpace() ==
- ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) {
- for (int i = 0; i < gradient.length; i++) {
- gradient[i] =
- convertEntireColorSRGBtoLinearRGB(gradient[i]);
- }
- gradientAverage =
- convertEntireColorSRGBtoLinearRGB(gradientAverage);
- }
- }
-
- fastGradientArraySize = gradient.length - 1;
- }
-
-
- /**
- * SLOW LOOKUP METHOD
- *
- * This method calculates the gradient color values for each interval and
- * places each into its own 255 size array. The arrays are stored in
- * gradients[][]. (255 is used because this is the maximum number of
- * unique colors between 2 arbitrary colors in a 24 bit color system)
- *
- * This method uses the minimum amount of space (only 255 * number of
- * intervals), but it aggravates the lookup procedure, because now we
- * have to find out which interval to select, then calculate the index
- * within that interval. This causes a significant performance hit,
- * because it requires this calculation be done for every point in
- * the rendering loop.
- *
- * For those of you who are interested, this is a classic example of the
- * time-space tradeoff.
- *
- */
- private void calculateMultipleArrayGradient
- (Color [] loColors, Color [] hiColors) {
-
- //set the flag so we know later it is a non-simple lookup
- isSimpleLookup = false;
-
- int rgb1; //2 colors to interpolate
- int rgb2;
-
- // These are fixed point 8.16 (start with 0.5)
- int aveA = 0x008000;
- int aveR = 0x008000;
- int aveG = 0x008000;
- int aveB = 0x008000;
-
- //for every interval (transition between 2 colors)
- for(int i=0; i < gradients.length; i++){
-
- // This interval will never actually be used (zero size)
- if (normalizedIntervals[i] == 0)
- continue;
-
- //create an array of the maximum theoretical size for each interval
- gradients[i] = new int[GRADIENT_SIZE];
-
- //get the the 2 colors
- rgb1 = loColors[i].getRGB();
- rgb2 = hiColors[i].getRGB();
-
- //fill this array with the colors in between rgb1 and rgb2
- interpolate(rgb1, rgb2, gradients[i]);
-
- // Calculate Average of two colors...
- int argb = gradients[i][GRADIENT_SIZE/2];
- float norm = normalizedIntervals[i];
- aveA += (int)(((argb>> 8)&0xFF0000)*norm);
- aveR += (int)(((argb )&0xFF0000)*norm);
- aveG += (int)(((argb<< 8)&0xFF0000)*norm);
- aveB += (int)(((argb<<16)&0xFF0000)*norm);
-
- //if the colors are opaque, transparency should still be 0xff000000
- transparencyTest &= rgb1;
- transparencyTest &= rgb2;
- }
-
- gradientAverage = (((aveA & 0xFF0000)<< 8) |
- ((aveR & 0xFF0000) ) |
- ((aveG & 0xFF0000)>> 8) |
- ((aveB & 0xFF0000)>>16));
-
- //if interpolation occurred in Linear RGB space, convert the
- //gradients back to SRGB using the lookup table
- if (colorSpace == LinearGradientPaint.LINEAR_RGB) {
- if (dataModel.getColorSpace() ==
- ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
- for (int j = 0; j < gradients.length; j++) {
- for (int i = 0; i < gradients[j].length; i++) {
- gradients[j][i] =
- convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
- }
- }
- gradientAverage =
- convertEntireColorLinearRGBtoSRGB(gradientAverage);
- }
- } else {
- if (dataModel.getColorSpace() ==
- ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) {
- for (int j = 0; j < gradients.length; j++) {
- for (int i = 0; i < gradients[j].length; i++) {
- gradients[j][i] =
- convertEntireColorSRGBtoLinearRGB(gradients[j][i]);
- }
- }
- gradientAverage =
- convertEntireColorSRGBtoLinearRGB(gradientAverage);
- }
- }
- }
-
- /** Yet another helper function. This one linearly interpolates between
- * 2 colors, filling up the output array.
- *
- * @param rgb1 the start color
- * @param rgb2 the end color
- * @param output the output array of colors... assuming this is not null.
- *
- */
- private void interpolate(int rgb1, int rgb2, int[] output) {
-
- int a1, r1, g1, b1, da, dr, dg, db; //color components
-
- //step between interpolated values.
- float stepSize = 1/(float)output.length;
-
- //extract color components from packed integer
- a1 = (rgb1 >> 24) & 0xff;
- r1 = (rgb1 >> 16) & 0xff;
- g1 = (rgb1 >> 8) & 0xff;
- b1 = (rgb1 ) & 0xff;
- //calculate the total change in alpha, red, green, blue
- da = ((rgb2 >> 24) & 0xff) - a1;
- dr = ((rgb2 >> 16) & 0xff) - r1;
- dg = ((rgb2 >> 8) & 0xff) - g1;
- db = ((rgb2 ) & 0xff) - b1;
-
- //for each step in the interval calculate the in-between color by
- //multiplying the normalized current position by the total color change
- //(.5 is added to prevent truncation round-off error)
- for (int i = 0; i < output.length; i++) {
- output[i] =
- (((int) ((a1 + i * da * stepSize) + .5) << 24)) |
- (((int) ((r1 + i * dr * stepSize) + .5) << 16)) |
- (((int) ((g1 + i * dg * stepSize) + .5) << 8)) |
- (((int) ((b1 + i * db * stepSize) + .5) ));
- }
- }
-
-
- /** Yet another helper function. This one extracts the color components
- * of an integer RGB triple, converts them from LinearRGB to SRGB, then
- * recompacts them into an int.
- */
- private int convertEntireColorLinearRGBtoSRGB(int rgb) {
-
- int a1, r1, g1, b1; //color components
-
- //extract red, green, blue components
- a1 = (rgb >> 24) & 0xff;
- r1 = (rgb >> 16) & 0xff;
- g1 = (rgb >> 8) & 0xff;
- b1 = rgb & 0xff;
-
- //use the lookup table
- r1 = LinearRGBtoSRGB[r1];
- g1 = LinearRGBtoSRGB[g1];
- b1 = LinearRGBtoSRGB[b1];
-
- //re-compact the components
- return ((a1 << 24) |
- (r1 << 16) |
- (g1 << 8) |
- b1);
- }
-
- /** Yet another helper function. This one extracts the color components
- * of an integer RGB triple, converts them from LinearRGB to SRGB, then
- * recompacts them into an int.
- */
- private int convertEntireColorSRGBtoLinearRGB(int rgb) {
-
- int a1, r1, g1, b1; //color components
-
- //extract red, green, blue components
- a1 = (rgb >> 24) & 0xff;
- r1 = (rgb >> 16) & 0xff;
- g1 = (rgb >> 8) & 0xff;
- b1 = rgb & 0xff;
-
- //use the lookup table
- r1 = SRGBtoLinearRGB[r1];
- g1 = SRGBtoLinearRGB[g1];
- b1 = SRGBtoLinearRGB[b1];
-
- //re-compact the components
- return ((a1 << 24) |
- (r1 << 16) |
- (g1 << 8) |
- b1);
- }
-
-
- /** Helper function to index into the gradients array. This is necessary
- * because each interval has an array of colors with uniform size 255.
- * However, the color intervals are not necessarily of uniform length, so
- * a conversion is required.
- *
- * @param position the unmanipulated position. want to map this into the
- * range 0 to 1
- *
- * @returns integer color to display
- *
- */
- protected final int indexIntoGradientsArrays(float position) {
-
- //first, manipulate position value depending on the cycle method.
-
- if (cycleMethod == MultipleGradientPaint.NO_CYCLE) {
-
- if (position >= 1) { //upper bound is 1
- return gradientOverflow;
- }
-
- else if (position <= 0) { //lower bound is 0
- return gradientUnderflow;
- }
- }
-
- else if (cycleMethod == MultipleGradientPaint.REPEAT) {
- //get the fractional part
- //(modulo behavior discards integer component)
- position = position - (int)position;
-
- //position now be between -1 and 1
-
- if (position < 0) {
- position = position + 1; //force it to be in the range 0-1
- }
-
- int w=0, c1=0, c2=0;
- if (isSimpleLookup) {
- position *= gradient.length;
- int idx1 = (int)(position);
- if (idx1+1 < gradient.length)
- return gradient[idx1];
-
- w = (int)((position-idx1)*(1<<16));
- c1 = gradient[idx1];
- c2 = gradient[0];
- } else {
- //for all the gradient interval arrays
- for (int i = 0; i < gradientsLength; i++) {
-
- if (position < fractions[i+1]) { //this is the array we want
-
- float delta = position - fractions[i];
-
- delta = ((delta / normalizedIntervals[i]) * GRADIENT_SIZE);
- //this is the interval we want.
- int index = (int)delta;
- if ((index+1<gradients[i].length) ||
- (i+1 < gradientsLength))
- return gradients[i][index];
-
- w = (int)((delta-index)*(1<<16));
- c1 = gradients[i][index];
- c2 = gradients[0][0];
- break;
- }
- }
- }
-
- return
- (((( ( (c1>> 8) &0xFF0000)+
- ((((c2>>>24) )-((c1>>>24) ))*w))&0xFF0000)<< 8) |
-
- ((( ( (c1 ) &0xFF0000)+
- ((((c2>> 16)&0xFF)-((c1>> 16)&0xFF))*w))&0xFF0000) ) |
-
- ((( ( (c1<< 8) &0xFF0000)+
- ((((c2>> 8)&0xFF)-((c1>> 8)&0xFF))*w))&0xFF0000)>> 8) |
-
- ((( ( (c1<< 16) &0xFF0000)+
- ((((c2 )&0xFF)-((c1 )&0xFF))*w))&0xFF0000)>>16));
-
- // return c1 +
- // ((( ((((c2>>>24) )-((c1>>>24) ))*w)&0xFF0000)<< 8) |
- // (( ((((c2>> 16)&0xFF)-((c1>> 16)&0xFF))*w)&0xFF0000) ) |
- // (( ((((c2>> 8)&0xFF)-((c1>> 8)&0xFF))*w)&0xFF0000)>> 8) |
- // (( ((((c2 )&0xFF)-((c1 )&0xFF))*w)&0xFF0000)>>16));
- }
-
- else { //cycleMethod == MultipleGradientPaint.REFLECT
-
- if (position < 0) {
- position = -position; //take absolute value
- }
-
- int part = (int)position; //take the integer part
-
- position = position - part; //get the fractional part
-
- if ((part & 0x00000001) == 1) { //if integer part is odd
- position = 1 - position; //want the reflected color instead
- }
- }
-
- //now, get the color based on this 0-1 position:
-
- if (isSimpleLookup) { //easy to compute: just scale index by array size
- return gradient[(int)(position * fastGradientArraySize)];
- }
-
- else { //more complicated computation, to save space
-
- //for all the gradient interval arrays
- for (int i = 0; i < gradientsLength; i++) {
-
- if (position < fractions[i+1]) { //this is the array we want
-
- float delta = position - fractions[i];
-
- //this is the interval we want.
- int index = (int)((delta / normalizedIntervals[i])
- * (GRADIENT_SIZE_INDEX));
-
- return gradients[i][index];
- }
- }
-
- }
-
- return gradientOverflow;
- }
-
-
- /** Helper function to index into the gradients array. This is necessary
- * because each interval has an array of colors with uniform size 255.
- * However, the color intervals are not necessarily of uniform length, so
- * a conversion is required. This version also does anti-aliasing by
- * averaging the gradient over position+/-(sz/2).
- *
- * @param position the unmanipulated position. want to map this into the
- * range 0 to 1
- * @param sz the size in gradient space to average.
- *
- * @returns ARGB integer color to display
- */
- protected final int indexGradientAntiAlias(float position, float sz) {
- //first, manipulate position value depending on the cycle method.
- if (cycleMethod == MultipleGradientPaint.NO_CYCLE) {
- if (DEBUG) System.out.println("NO_CYCLE");
- float p1 = position-(sz/2);
- float p2 = position+(sz/2);
-
- if (p1 >= 1)
- return gradientOverflow;
-
- if (p2 <= 0)
- return gradientUnderflow;
-
- int interior;
- float top_weight=0, bottom_weight=0, frac;
- if (p2 >= 1) {
- top_weight = (p2-1)/sz;
- if (p1 <= 0) {
- bottom_weight = -p1/sz;
- frac=1;
- interior = gradientAverage;
- } else {
- frac=1-p1;
- interior = getAntiAlias(p1, true, 1, false, 1-p1, 1);
- }
- } else if (p1 <= 0) {
- bottom_weight = -p1/sz;
- frac = p2;
- interior = getAntiAlias(0, true, p2, false, p2, 1);
- } else
- return getAntiAlias(p1, true, p2, false, sz, 1);
-
- int norm = (int)((1<<16)*frac/sz);
- int pA = (((interior>>>20)&0xFF0)*norm)>>16;
- int pR = (((interior>> 12)&0xFF0)*norm)>>16;
- int pG = (((interior>> 4)&0xFF0)*norm)>>16;
- int pB = (((interior<< 4)&0xFF0)*norm)>>16;
-
- if (bottom_weight != 0) {
- int bPix = gradientUnderflow;
- // System.out.println("ave: " + gradientAverage);
- norm = (int)((1<<16)*bottom_weight);
- pA += (((bPix>>>20) & 0xFF0)*norm)>>16;
- pR += (((bPix>> 12) & 0xFF0)*norm)>>16;
- pG += (((bPix>> 4) & 0xFF0)*norm)>>16;
- pB += (((bPix<< 4) & 0xFF0)*norm)>>16;
- }
-
- if (top_weight != 0) {
- int tPix = gradientOverflow;
-
- norm = (int)((1<<16)*top_weight);
- pA += (((tPix>>>20) & 0xFF0)*norm)>>16;
- pR += (((tPix>> 12) & 0xFF0)*norm)>>16;
- pG += (((tPix>> 4) & 0xFF0)*norm)>>16;
- pB += (((tPix<< 4) & 0xFF0)*norm)>>16;
- }
-
- return (((pA&0xFF0)<<20) |
- ((pR&0xFF0)<<12) |
- ((pG&0xFF0)<< 4) |
- ((pB&0xFF0)>> 4));
- }
-
- // See how many times we are going to "wrap around" the gradient,
- // array.
- int intSz = (int)sz;
-
- float weight = 1f;
- if (intSz != 0) {
- // We need to make sure that sz is < 1.0 otherwise
- // p1 and p2 my pass each other which will cause no end of
- // trouble.
- sz -= intSz;
- weight = sz/(intSz+sz);
- if (weight < 0.1)
- // The part of the color from the location will be swamped
- // by the averaged part of the gradient so just use the
- // average color for the gradient.
- return gradientAverage;
- }
-
- // So close to full gradient just use the average value...
- if (sz > 0.99)
- return gradientAverage;
-
- // Go up and down from position by 1/2 sz.
- float p1 = position-(sz/2);
- float p2 = position+(sz/2);
- if (DEBUG) System.out.println("P1: " + p1 + " P2: " + p2);
-
- // These indicate the direction to go from p1 and p2 when
- // averaging...
- boolean p1_up=true;
- boolean p2_up=false;
-
- if (cycleMethod == MultipleGradientPaint.REPEAT) {
- if (DEBUG) System.out.println("REPEAT");
-
- // Get positions between -1 and 1
- p1=p1-(int)p1;
- p2=p2-(int)p2;
-
- // force to be in rage 0-1.
- if (p1 <0) p1 += 1;
- if (p2 <0) p2 += 1;
- }
-
- else { //cycleMethod == MultipleGradientPaint.REFLECT
- if (DEBUG) System.out.println("REFLECT");
-
- //take absolute values
- // Note when we reflect we change sense of p1/2_up.
- if (p2 < 0) {
- p1 = -p1; p1_up = !p1_up;
- p2 = -p2; p2_up = !p2_up;
- } else if (p1 < 0) {
- p1 = -p1; p1_up = !p1_up;
- }
-
- int part1, part2;
- part1 = (int)p1; // take the integer part
- p1 = p1 - part1; // get the fractional part
-
- part2 = (int)p2; // take the integer part
- p2 = p2 - part2; // get the fractional part
-
- // if integer part is odd we want the reflected color instead.
- // Note when we reflect we change sense of p1/2_up.
- if ((part1 & 0x01) == 1) {
- p1 = 1-p1;
- p1_up = !p1_up;
- }
-
- if ((part2 & 0x01) == 1) {
- p2 = 1-p2;
- p2_up = !p2_up;
- }
-
- // Check if in the end they just got switched around.
- // this commonly happens if they both end up negative.
- if ((p1 > p2) && !p1_up && p2_up) {
- float t = p1;
- p1 = p2;
- p2 = t;
- p1_up = true;
- p2_up = false;
- }
- }
-
- return getAntiAlias(p1, p1_up, p2, p2_up, sz, weight);
- }
-
-
- private final int getAntiAlias(float p1, boolean p1_up,
- float p2, boolean p2_up,
- float sz, float weight) {
-
- // Until the last set of ops these are 28.4 fixed point values.
- int ach=0, rch=0, gch=0, bch=0;
- if (isSimpleLookup) {
- p1 *= fastGradientArraySize;
- p2 *= fastGradientArraySize;
-
- int idx1 = (int)p1;
- int idx2 = (int)p2;
-
- int i, pix;
-
- if (p1_up && !p2_up && (idx1 <= idx2)) {
-
- if (idx1 == idx2)
- return gradient[idx1];
-
- // Sum between idx1 and idx2.
- for (i=idx1+1; i<idx2; i++) {
- pix = gradient[i];
- ach += ((pix>>>20)&0xFF0);
- rch += ((pix>>>12)&0xFF0);
- gch += ((pix>>> 4)&0xFF0);
- bch += ((pix<< 4)&0xFF0);
- }
- } else {
- // Do the bulk of the work, all the whole gradient entries
- // for idx1 and idx2.
- if (p1_up) {
- for (i=idx1+1; i<fastGradientArraySize; i++) {
- pix = gradient[i];
- ach += ((pix>>>20)&0xFF0);
- rch += ((pix>>>12)&0xFF0);
- gch += ((pix>>> 4)&0xFF0);
- bch += ((pix<< 4)&0xFF0);
- }
- } else {
- for (i=0; i<idx1; i++) {
- pix = gradient[i];
- ach += ((pix>>>20)&0xFF0);
- rch += ((pix>>>12)&0xFF0);
- gch += ((pix>>> 4)&0xFF0);
- bch += ((pix<< 4)&0xFF0);
- }
- }
-
- if (p2_up) {
- for (i=idx2+1; i<fastGradientArraySize; i++) {
- pix = gradient[i];
- ach += ((pix>>>20)&0xFF0);
- rch += ((pix>>>12)&0xFF0);
- gch += ((pix>>> 4)&0xFF0);
- bch += ((pix<< 4)&0xFF0);
- }
- } else {
- for (i=0; i<idx2; i++) {
- pix = gradient[i];
- ach += ((pix>>>20)&0xFF0);
- rch += ((pix>>>12)&0xFF0);
- gch += ((pix>>> 4)&0xFF0);
- bch += ((pix<< 4)&0xFF0);
- }
- }
- }
-
- int norm, isz;
-
- // Normalize the summation so far...
- isz = (int)((1<<16)/(sz*fastGradientArraySize));
- ach = (ach*isz)>>16;
- rch = (rch*isz)>>16;
- gch = (gch*isz)>>16;
- bch = (bch*isz)>>16;
-
- // Clean up with the partial buckets at each end.
- if (p1_up) norm = (int)((1-(p1-idx1))*isz);
- else norm = (int)( (p1-idx1) *isz);
- pix = gradient[idx1];
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
-
- if (p2_up) norm = (int)((1-(p2-idx2))*isz);
- else norm = (int)( (p2-idx2) *isz);
- pix = gradient[idx2];
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
-
- // Round and drop the 4bits frac.
- ach = (ach+0x08)>>4;
- rch = (rch+0x08)>>4;
- gch = (gch+0x08)>>4;
- bch = (bch+0x08)>>4;
-
- } else {
- int idx1=0, idx2=0;
- int i1=-1, i2=-1;
- float f1=0, f2=0;
- // Find which gradient interval our points fall into.
- for (int i = 0; i < gradientsLength; i++) {
- if ((p1 < fractions[i+1]) && (i1 == -1)) {
- //this is the array we want
- i1 = i;
- f1 = p1 - fractions[i];
-
- f1 = ((f1/normalizedIntervals[i])
- *GRADIENT_SIZE_INDEX);
- //this is the interval we want.
- idx1 = (int)f1;
- if (i2 != -1) break;
- }
- if ((p2 < fractions[i+1]) && (i2 == -1)) {
- //this is the array we want
- i2 = i;
- f2 = p2 - fractions[i];
-
- f2 = ((f2/normalizedIntervals[i])
- *GRADIENT_SIZE_INDEX);
- //this is the interval we want.
- idx2 = (int)f2;
- if (i1 != -1) break;
- }
- }
-
- if (i1 == -1) {
- i1 = gradients.length - 1;
- f1 = idx1 = GRADIENT_SIZE_INDEX;
- }
-
- if (i2 == -1) {
- i2 = gradients.length - 1;
- f2 = idx2 = GRADIENT_SIZE_INDEX;
- }
-
- if (DEBUG) System.out.println("I1: " + i1 + " Idx1: " + idx1 +
- " I2: " + i2 + " Idx2: " + idx2);
-
- // Simple case within one gradient array (so the average
- // of the two idx gives us the true average of colors).
- if ((i1 == i2) && (idx1 <= idx2) && p1_up && !p2_up)
- return gradients[i1][(idx1+idx2+1)>>1];
-
- // i1 != i2
-
- int pix, norm;
- int base = (int)((1<<16)/sz);
- if ((i1 < i2) && p1_up && !p2_up) {
- norm = (int)((base
- *normalizedIntervals[i1]
- *(GRADIENT_SIZE_INDEX-f1))
- /GRADIENT_SIZE_INDEX);
- pix = gradients[i1][(idx1+GRADIENT_SIZE)>>1];
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
-
- for (int i=i1+1; i<i2; i++) {
- norm = (int)(base*normalizedIntervals[i]);
- pix = gradients[i][GRADIENT_SIZE>>1];
-
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
- }
-
- norm = (int)((base*normalizedIntervals[i2]*f2)
- /GRADIENT_SIZE_INDEX);
- pix = gradients[i2][(idx2+1)>>1];
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
- } else {
- if (p1_up) {
- norm = (int)((base
- *normalizedIntervals[i1]
- *(GRADIENT_SIZE_INDEX-f1))
- /GRADIENT_SIZE_INDEX);
- pix = gradients[i1][(idx1+GRADIENT_SIZE)>>1];
- } else {
- norm = (int)((base*normalizedIntervals[i1]*f1)
- /GRADIENT_SIZE_INDEX);
- pix = gradients[i1][(idx1+1)>>1];
- }
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
-
- if (p2_up) {
- norm = (int)((base
- *normalizedIntervals[i2]
- *(GRADIENT_SIZE_INDEX-f2))
- /GRADIENT_SIZE_INDEX);
- pix = gradients[i2][(idx2+GRADIENT_SIZE)>>1];
- } else {
- norm = (int)((base*normalizedIntervals[i2]*f2)
- /GRADIENT_SIZE_INDEX);
- pix = gradients[i2][(idx2+1)>>1];
- }
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
-
- if (p1_up) {
- for (int i=i1+1; i<gradientsLength; i++) {
- norm = (int)(base*normalizedIntervals[i]);
- pix = gradients[i][GRADIENT_SIZE>>1];
-
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
- }
- } else {
- for (int i=0; i<i1; i++) {
- norm = (int)(base*normalizedIntervals[i]);
- pix = gradients[i][GRADIENT_SIZE>>1];
-
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
- }
- }
-
- if (p2_up) {
- for (int i=i2+1; i<gradientsLength; i++) {
- norm = (int)(base*normalizedIntervals[i]);
- pix = gradients[i][GRADIENT_SIZE>>1];
-
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
- }
- } else {
- for (int i=0; i<i2; i++) {
- norm = (int)(base*normalizedIntervals[i]);
- pix = gradients[i][GRADIENT_SIZE>>1];
-
- ach += (((pix>>>20)&0xFF0) *norm)>>16;
- rch += (((pix>>>12)&0xFF0) *norm)>>16;
- gch += (((pix>>> 4)&0xFF0) *norm)>>16;
- bch += (((pix<< 4)&0xFF0) *norm)>>16;
- }
- }
-
- }
- ach = (ach+0x08)>>4;
- rch = (rch+0x08)>>4;
- gch = (gch+0x08)>>4;
- bch = (bch+0x08)>>4;
- if (DEBUG) System.out.println("Pix: [" + ach + ", " + rch +
- ", " + gch + ", " + bch + "]");
- }
-
- if (weight != 1) {
- // System.out.println("ave: " + gradientAverage);
- int aveW = (int)((1<<16)*(1-weight));
- int aveA = ((gradientAverage>>>24) & 0xFF)*aveW;
- int aveR = ((gradientAverage>> 16) & 0xFF)*aveW;
- int aveG = ((gradientAverage>> 8) & 0xFF)*aveW;
- int aveB = ((gradientAverage ) & 0xFF)*aveW;
-
- int iw = (int)(weight*(1<<16));
- ach = ((ach*iw)+aveA)>>16;
- rch = ((rch*iw)+aveR)>>16;
- gch = ((gch*iw)+aveG)>>16;
- bch = ((bch*iw)+aveB)>>16;
- }
-
- return ((ach<<24) | (rch<<16) | (gch<<8) | bch);
- }
-
-
- /** Helper function to convert a color component in sRGB space to linear
- * RGB space. Used to build a static lookup table.
- */
- private static int convertSRGBtoLinearRGB(int color) {
-
- float input, output;
-
- input = ((float) color) / 255.0f;
- if (input <= 0.04045f) {
- output = input / 12.92f;
- }
- else {
- output = (float) Math.pow((input + 0.055) / 1.055, 2.4);
- }
- int o = Math.round(output * 255.0f);
-
- return o;
- }
-
- /** Helper function to convert a color component in linear RGB space to
- * SRGB space. Used to build a static lookup table.
- */
- private static int convertLinearRGBtoSRGB(int color) {
-
- float input, output;
-
- input = ((float) color) / 255.0f;
-
- if (input <= 0.0031308) {
- output = input * 12.92f;
- }
- else {
- output = (1.055f *
- ((float) Math.pow(input, (1.0 / 2.4)))) - 0.055f;
- }
-
- int o = Math.round(output * 255.0f);
-
- return o;
- }
-
-
- /** Superclass getRaster... */
- public final Raster getRaster(int x, int y, int w, int h) {
- if (w == 0 || h == 0) {
- return null;
- }
-
- //
- // If working raster is big enough, reuse it. Otherwise,
- // build a large enough new one.
- //
- WritableRaster raster = saved;
- if (raster == null || raster.getWidth() < w || raster.getHeight() < h)
- {
- raster = getCachedRaster(dataModel, w, h);
- saved = raster;
- }
-
- // Access raster internal int array. Because we use a DirectColorModel,
- // we know the DataBuffer is of type DataBufferInt and the SampleModel
- // is SinglePixelPackedSampleModel.
- // Adjust for initial offset in DataBuffer and also for the scanline
- // stride.
- //
- DataBufferInt rasterDB = (DataBufferInt)raster.getDataBuffer();
- int[] pixels = rasterDB.getBankData()[0];
- int off = rasterDB.getOffset();
- int scanlineStride = ((SinglePixelPackedSampleModel)
- raster.getSampleModel()).getScanlineStride();
- int adjust = scanlineStride - w;
-
- fillRaster(pixels, off, adjust, x, y, w, h); //delegate to subclass.
-
- GraphicsUtil.coerceData(raster, dataModel,
- model.isAlphaPremultiplied());
-
-
- return raster;
- }
-
- /** Subclasses should implement this. */
- protected abstract void fillRaster(int pixels[], int off, int adjust,
- int x, int y, int w, int h);
-
-
- /** Took this cacheRaster code from GradientPaint. It appears to recycle
- * rasters for use by any other instance, as long as they are sufficiently
- * large.
- */
- protected final
- static synchronized WritableRaster getCachedRaster
- (ColorModel cm, int w, int h) {
- if (cm == cachedModel) {
- if (cached != null) {
- WritableRaster ras = (WritableRaster) cached.get();
- if (ras != null &&
- ras.getWidth() >= w &&
- ras.getHeight() >= h)
- {
- cached = null;
- return ras;
- }
- }
- }
- // Don't create rediculously small rasters...
- if (w<32) w=32;
- if (h<32) h=32;
- return cm.createCompatibleWritableRaster(w, h);
- }
-
- /** Took this cacheRaster code from GradientPaint. It appears to recycle
- * rasters for use by any other instance, as long as they are sufficiently
- * large.
- */
- protected final
- static synchronized void putCachedRaster(ColorModel cm,
- WritableRaster ras) {
- if (cached != null) {
- WritableRaster cras = (WritableRaster) cached.get();
- if (cras != null) {
- int cw = cras.getWidth();
- int ch = cras.getHeight();
- int iw = ras.getWidth();
- int ih = ras.getHeight();
- if (cw >= iw && ch >= ih) {
- return;
- }
- if (cw * ch >= iw * ih) {
- return;
- }
- }
- }
- cachedModel = cm;
- cached = new WeakReference(ras);
- }
-
- /**
- * Release the resources allocated for the operation.
- */
- public final void dispose() {
- if (saved != null) {
- putCachedRaster(model, saved);
- saved = null;
- }
- }
-
- /**
- * Return the ColorModel of the output.
- */
- public final ColorModel getColorModel() {
- return model;
- }
-}
-
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/RadialGradientPaint.java b/svg-core/src/main/java/com/kitfox/svg/batik/RadialGradientPaint.java
deleted file mode 100644
index f5f629b..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/RadialGradientPaint.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.PaintContext;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ColorModel;
-
-/**
- * <p>
- * This class provides a way to fill a shape with a circular radial color
- * gradient pattern. The user may specify 2 or more gradient colors, and this
- * paint will provide an interpolation between each color.
- * <p>
- *
- * The user must provide an array of floats specifying how to distribute the
- * colors along the gradient. These values should range from 0.0 to 1.0 and
- * act like keyframes along the gradient (they mark where the gradient should
- * be exactly a particular color).
- *
- * <p>
- * This paint will map the first color of the gradient to a focus point within
- * the circle, and the last color to the perimeter of the circle, interpolating
- * smoothly for any inbetween colors specified by the user. Any line drawn
- * from the focus point to the circumference will span the all the gradient
- * colors. By default the focus is set to be the center of the circle.
- *
- * <p>
- * Specifying a focus point outside of the circle's radius will result in the
- * focus being set to the intersection point of the focus-center line and the
- * perimenter of the circle.
- * <p>
- *
- * Specifying a cycle method allows the user to control the painting behavior
- * outside of the bounds of the circle's radius. See LinearGradientPaint for
- * more details.
- *
- * <p>
- * The following code demonstrates typical usage of RadialGradientPaint:
- * <p>
- * <code>
- * Point2D center = new Point2D.Float(0, 0);<br>
- * float radius = 20;
- * float[] dist = {0.0, 0.2, 1.0};<br>
- * Color[] colors = {Color.red, Color.white, Color.blue};<br>
- * RadialGradientPaint p = new RadialGradientPaint(center, radius,
- * dist, colors);
- * </code>
- *
- * <p> In the event that the user does not set the first keyframe value equal
- * to 0 and the last keyframe value equal to 1, keyframes will be created at
- * these positions and the first and last colors will be replicated there.
- * So, if a user specifies the following arrays to construct a gradient:<br>
- * {Color.blue, Color.red}, {.3, .7}<br>
- * this will be converted to a gradient with the following keyframes:
- * {Color.blue, Color.blue, Color.red, Color.red}, {0, .3, .7, 1}
- *
- *
- * <p>
- * <img src = "radial.jpg">
- * <p>
- * This image demonstrates a radial gradient with NO_CYCLE and default focus.
- * <p>
- *
- * <img src = "radial2.jpg">
- * <p>
- * This image demonstrates a radial gradient with NO_CYCLE and non-centered
- * focus.
- * <p>
- *
- * <img src = "radial3.jpg">
- * <p>
- * This image demonstrates a radial gradient with REFLECT and non-centered
- * focus.
- *
- * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
- * @author <a href="mailto:vincent.hardy at eng.sun.com">Vincent Hardy</a>
- * @version $Id: RadialGradientPaint.java,v 1.1 2004/09/06 19:35:39 kitfox Exp $
- *
- */
-
-public final class RadialGradientPaint extends MultipleGradientPaint {
-
- /** Focus point which defines the 0% gradient stop x coordinate. */
- private Point2D focus;
-
- /** Center of the circle defining the 100% gradient stop x coordinate. */
- private Point2D center;
-
- /** Radius of the outermost circle defining the 100% gradient stop. */
- private float radius;
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>, using the center as the
- * focus point.
- *
- * @param cx the x coordinate in user space of the center point of the
- * circle defining the gradient. The last color of the gradient is mapped
- * to the perimeter of this circle
- *
- * @param cy the y coordinate in user space of the center point of the
- * circle defining the gradient. The last color of the gradient is mapped
- * to the perimeter of this circle
- *
- * @param radius the radius of the circle defining the extents of the
- * color gradient
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color
- * is used at the focus point, the last color around the perimeter of the
- * circle.
- *
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- *
- */
- public RadialGradientPaint(float cx, float cy, float radius,
- float[] fractions, Color[] colors) {
- this(cx, cy,
- radius,
- cx, cy,
- fractions,
- colors);
- }
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>, using the center as the
- * focus point.
- *
- * @param center the center point, in user space, of the circle defining
- * the gradient
- *
- * @param radius the radius of the circle defining the extents of the
- * color gradient
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color
- * is used at the focus point, the last color around the perimeter of the
- * circle.
- *
- * @throws NullPointerException if center point is null
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- *
- */
- public RadialGradientPaint(Point2D center, float radius,
- float[] fractions, Color[] colors) {
- this(center,
- radius,
- center,
- fractions,
- colors);
- }
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>.
- *
- * @param cx the x coordinate in user space of the center point of the
- * circle defining the gradient. The last color of the gradient is mapped
- * to the perimeter of this circle
- *
- * @param cy the y coordinate in user space of the center point of the
- * circle defining the gradient. The last color of the gradient is mapped
- * to the perimeter of this circle
- *
- * @param radius the radius of the circle defining the extents of the
- * color gradient
- *
- * @param fx the x coordinate of the point in user space to which the
- * first color is mapped
- *
- * @param fy the y coordinate of the point in user space to which the
- * first color is mapped
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color
- * is used at the focus point, the last color around the perimeter of the
- * circle.
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- *
- */
- public RadialGradientPaint(float cx, float cy, float radius,
- float fx, float fy,
- float[] fractions, Color[] colors) {
- this(new Point2D.Float(cx, cy),
- radius,
- new Point2D.Float(fx, fy),
- fractions,
- colors,
- NO_CYCLE,
- SRGB);
- }
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>.
- *
- * @param center the center point, in user space, of the circle defining
- * the gradient. The last color of the gradient is mapped to the perimeter
- * of this circle
- *
- * @param radius the radius of the circle defining the extents of the color
- * gradient
- *
- * @param focus the point, in user space, to which the first color is
- * mapped
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color
- * is used at the focus point, the last color around the perimeter of the
- * circle.
- *
- * @throws NullPointerException if one of the points is null
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- */
- public RadialGradientPaint(Point2D center, float radius,
- Point2D focus,
- float[] fractions, Color[] colors) {
- this(center,
- radius,
- focus,
- fractions,
- colors,
- NO_CYCLE,
- SRGB);
- }
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>.
- *
- * @param center the center point in user space of the circle defining the
- * gradient. The last color of the gradient is mapped to the perimeter of
- * this circle
- *
- * @param radius the radius of the circle defining the extents of the color
- * gradient
- *
- * @param focus the point in user space to which the first color is mapped
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color is
- * used at the focus point, the last color around the perimeter of the
- * circle.
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- * @throws NullPointerException if one of the points is null
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- */
- public RadialGradientPaint(Point2D center, float radius,
- Point2D focus,
- float[] fractions, Color[] colors,
- CycleMethodEnum cycleMethod,
- ColorSpaceEnum colorSpace) {
- this(center,
- radius,
- focus,
- fractions,
- colors,
- cycleMethod,
- colorSpace,
- new AffineTransform());
- }
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>.
- *
- * @param center the center point in user space of the circle defining the
- * gradient. The last color of the gradient is mapped to the perimeter of
- * this circle
- *
- * @param radius the radius of the circle defining the extents of the color
- * gradient.
- *
- * @param focus the point in user space to which the first color is mapped
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color is
- * used at the focus point, the last color around the perimeter of the
- * circle.
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- * @param gradientTransform transform to apply to the gradient
- *
- * @throws NullPointerException if one of the points is null,
- * or gradientTransform is null
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- */
- public RadialGradientPaint(Point2D center,
- float radius,
- Point2D focus,
- float[] fractions, Color[] colors,
- CycleMethodEnum cycleMethod,
- ColorSpaceEnum colorSpace,
- AffineTransform gradientTransform){
- super(fractions, colors, cycleMethod, colorSpace, gradientTransform);
-
- // Check input arguments
- if (center == null) {
- throw new NullPointerException("Center point should not be null.");
- }
-
- if (focus == null) {
- throw new NullPointerException("Focus point should not be null.");
- }
-
- if (radius <= 0) {
- throw new IllegalArgumentException("radius should be greater than zero");
- }
-
- //copy parameters
- this.center = (Point2D)center.clone();
- this.focus = (Point2D)focus.clone();
- this.radius = radius;
- }
-
- /**
- * <p>
- *
- * Constructs a <code>RadialGradientPaint</code>, the gradient circle is
- * defined by a bounding box.
- *
- * @param gradientBounds the bounding box, in user space, of the circle
- * defining outermost extent of the gradient.
- *
- * @param fractions numbers ranging from 0.0 to 1.0 specifying the
- * distribution of colors along the gradient
- *
- * @param colors array of colors to use in the gradient. The first color
- * is used at the focus point, the last color around the perimeter of the
- * circle.
- *
- * @throws NullPointerException if the gradientBounds is null
- *
- * @throws IllegalArgumentException
- * if fractions.length != colors.length, or if colors is less
- * than 2 in size, or if radius < 0
- *
- */
- public RadialGradientPaint(Rectangle2D gradientBounds,
- float[] fractions, Color[] colors) {
-
- //calculate center point and radius based on bounding box coordinates.
- this((float)gradientBounds.getX() +
- ( (float)gradientBounds.getWidth() / 2),
-
- (float)gradientBounds.getY() +
- ( (float)gradientBounds.getWidth() / 2),
-
- (float)gradientBounds.getWidth() / 2,
- fractions, colors);
- }
-
-
- /** <p>
- * Creates and returns a PaintContext used to generate the color pattern,
- * for use by the internal rendering engine.
- *
- * @param cm {@link ColorModel} that receives
- * the <code>Paint</code> data. This is used only as a hint.
- *
- * @param deviceBounds the device space bounding box of the
- * graphics primitive being rendered
- *
- * @param userBounds the user space bounding box of the
- * graphics primitive being rendered
- *
- * @param transform the {@link AffineTransform} from user
- * space into device space
- *
- * @param hints the hints that the context object uses to choose
- * between rendering alternatives
- *
- * @return the {@link PaintContext} that generates color patterns.
- *
- * @throws IllegalArgumentException if the transform is not invertible
- *
- * @see PaintContext
- */
- public PaintContext createContext(ColorModel cm,
- Rectangle deviceBounds,
- Rectangle2D userBounds,
- AffineTransform transform,
- RenderingHints hints) {
- // Can't modify the transform passed in...
- transform = new AffineTransform(transform);
- // incorporate the gradient transform
- transform.concatenate(gradientTransform);
-
- try{
- return new RadialGradientPaintContext
- (cm, deviceBounds, userBounds, transform, hints,
- (float)center.getX(), (float)center.getY(), radius,
- (float)focus.getX(), (float)focus.getY(),
- fractions, colors, cycleMethod, colorSpace);
- }
-
- catch(NoninvertibleTransformException e){
- throw new IllegalArgumentException("transform should be " +
- "invertible");
- }
- }
-
- /**
- * Returns a copy of the center point of the radial gradient.
- * @return a {@link Point2D} object that is a copy of the center point
- */
- public Point2D getCenterPoint() {
- return new Point2D.Double(center.getX(), center.getY());
- }
-
- /** Returns a copy of the end point of the gradient axis.
- * @return a {@link Point2D} object that is a copy of the focus point
- */
- public Point2D getFocusPoint() {
- return new Point2D.Double(focus.getX(), focus.getY());
- }
-
- /** Returns the radius of the circle defining the radial gradient.
- * @return the radius of the circle defining the radial gradient
- */
- public float getRadius() {
- return radius;
- }
-
-}
-
diff --git a/svg-core/src/main/java/com/kitfox/svg/batik/RadialGradientPaintContext.java b/svg-core/src/main/java/com/kitfox/svg/batik/RadialGradientPaintContext.java
deleted file mode 100644
index 5b097fd..0000000
--- a/svg-core/src/main/java/com/kitfox/svg/batik/RadialGradientPaintContext.java
+++ /dev/null
@@ -1,775 +0,0 @@
-/*****************************************************************************
- * Copyright (C) The Apache Software Foundation. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * This software is published under the terms of the Apache Software License *
- * version 1.1, a copy of which has been included with this distribution in *
- * the LICENSE file. *
- *****************************************************************************/
-
-package com.kitfox.svg.batik;
-
-import java.awt.Color;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ColorModel;
-
-/**
- * Provides the actual implementation for the RadialGradientPaint.
- * This is where the pixel processing is done. A RadialGradienPaint
- * only supports circular gradients, but it should be possible to scale
- * the circle to look approximately elliptical, by means of a
- * gradient transform passed into the RadialGradientPaint constructor.
- *
- * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
- * @author <a href="mailto:vincent.hardy at eng.sun.com">Vincent Hardy</a>
- * @version $Id: RadialGradientPaintContext.java,v 1.2 2005/10/12 20:36:55 kitfox Exp $
- *
- */
-final class RadialGradientPaintContext extends MultipleGradientPaintContext {
-
- /** True when (focus == center) */
- private boolean isSimpleFocus = false;
-
- /** True when (cycleMethod == NO_CYCLE) */
- private boolean isNonCyclic = false;
-
- /** Radius of the outermost circle defining the 100% gradient stop. */
- private float radius;
-
- /** Variables representing center and focus points. */
- private float centerX, centerY, focusX, focusY;
-
- /** Radius of the gradient circle squared. */
- private float radiusSq;
-
- /** Constant part of X, Y user space coordinates. */
- private float constA, constB;
-
- /** This value represents the solution when focusX == X. It is called
- * trivial because it is easier to calculate than the general case.
- */
- private float trivial;
-
- private static final int FIXED_POINT_IMPL = 1;
- private static final int DEFAULT_IMPL = 2;
- private static final int ANTI_ALIAS_IMPL = 3;
-
- private int fillMethod;
-
- /** Amount for offset when clamping focus. */
- private static final float SCALEBACK = .97f;
-
- /**
- * Constructor for RadialGradientPaintContext.
- *
- * @param cm {@link ColorModel} that receives
- * the <code>Paint</code> data. This is used only as a hint.
- *
- * @param deviceBounds the device space bounding box of the
- * graphics primitive being rendered
- *
- * @param userBounds the user space bounding box of the
- * graphics primitive being rendered
- *
- * @param t the {@link AffineTransform} from user
- * space into device space (gradientTransform should be
- * concatenated with this)
- *
- * @param hints the hints that the context object uses to choose
- * between rendering alternatives
- *
- * @param cx the center point in user space of the circle defining
- * the gradient. The last color of the gradient is mapped to the
- * perimeter of this circle X coordinate
- *
- * @param cy the center point in user space of the circle defining
- * the gradient. The last color of the gradient is mapped to the
- * perimeter of this circle Y coordinate
- *
- * @param r the radius of the circle defining the extents of the
- * color gradient
- *
- * @param fx the point in user space to which the first color is mapped
- * X coordinate
- *
- * @param fy the point in user space to which the first color is mapped
- * Y coordinate
- *
- * @param fractions the fractions specifying the gradient distribution
- *
- * @param colors the gradient colors
- *
- * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
- *
- * @param colorSpace which colorspace to use for interpolation,
- * either SRGB or LINEAR_RGB
- *
- */
- public RadialGradientPaintContext(ColorModel cm,
- Rectangle deviceBounds,
- Rectangle2D userBounds,
- AffineTransform t,
- RenderingHints hints,
- float cx, float cy,
- float r,
- float fx, float fy,
- float[] fractions,
- Color[] colors,
- MultipleGradientPaint.CycleMethodEnum
- cycleMethod,
- MultipleGradientPaint.ColorSpaceEnum
- colorSpace)
- throws NoninvertibleTransformException
- {
- super(cm, deviceBounds, userBounds, t, hints, fractions, colors,
- cycleMethod, colorSpace);
-
- //copy some parameters.
- centerX = cx;
- centerY = cy;
- focusX = fx;
- focusY = fy;
- radius = r;
-
- this.isSimpleFocus = (focusX == centerX) && (focusY == centerY);
- this.isNonCyclic = (cycleMethod == RadialGradientPaint.NO_CYCLE);
-
- //for use in the quadractic equation
- radiusSq = radius * radius;
-
- float dX = focusX - centerX;
- float dY = focusY - centerY;
-
- double dist = Math.sqrt((dX * dX) + (dY * dY));
-
- //test if distance from focus to center is greater than the radius
- if (dist > radius* SCALEBACK) { //clamp focus to radius
- double angle = Math.atan2(dY, dX);
-
- //x = r cos theta, y = r sin theta
- focusX = (float)(SCALEBACK * radius * Math.cos(angle)) + centerX;
-
- focusY = (float)(SCALEBACK * radius * Math.sin(angle)) + centerY;
- }
-
- //calculate the solution to be used in the case where X == focusX
- //in cyclicCircularGradientFillRaster
- dX = focusX - centerX;
- trivial = (float)Math.sqrt(radiusSq - (dX * dX));
-
- // constant parts of X, Y user space coordinates
- constA = a02 - centerX;
- constB = a12 - centerY;
-
- Object colorRend;
- Object rend;
- //hints can be null on Mac OSX
- if (hints == null)
- {
- colorRend = RenderingHints.VALUE_COLOR_RENDER_DEFAULT;
- rend = RenderingHints.VALUE_RENDER_DEFAULT;
- }
- else
- {
- colorRend = hints.get(RenderingHints.KEY_COLOR_RENDERING);
- rend = hints.get(RenderingHints.KEY_RENDERING);
- }
-
- fillMethod = 0;
-
- if ((rend == RenderingHints.VALUE_RENDER_QUALITY) ||
- (colorRend == RenderingHints.VALUE_COLOR_RENDER_QUALITY)) {
- // System.out.println("AAHints set: " + rend + ", " + colorRend);
- fillMethod = ANTI_ALIAS_IMPL;
- }
-
- if ((rend == RenderingHints.VALUE_RENDER_SPEED) ||
- (colorRend == RenderingHints.VALUE_COLOR_RENDER_SPEED)) {
- // System.out.println("SPHints set: " + rend + ", " + colorRend);
- fillMethod = DEFAULT_IMPL;
- }
-
- // We are in the 'default' case, no hint or hint set to
- // DEFAULT values...
- if (fillMethod == 0) {
- // For now we will always use the 'default' impl if
- // one is not specified.
- fillMethod = DEFAULT_IMPL;
-
- if (false) {
- // This could be used for a 'smart' choice in
- // the default case, if the gradient has obvious
- // discontinuites use AA, otherwise default
- if (hasDiscontinuity) {
- fillMethod = ANTI_ALIAS_IMPL;
- } else {
- fillMethod = DEFAULT_IMPL;
- }
- }
- }
-
- if ((fillMethod == DEFAULT_IMPL) &&
- (isSimpleFocus && isNonCyclic && isSimpleLookup)) {
- this.calculateFixedPointSqrtLookupTable();
- fillMethod = FIXED_POINT_IMPL;
- }
- }
-
- /**
- * Return a Raster containing the colors generated for the graphics
- * operation.
- * @param x,y,w,h The area in device space for which colors are
- * generated.
- */
- protected void fillRaster(int pixels[], int off, int adjust,
- int x, int y, int w, int h) {
- switch(fillMethod) {
- case FIXED_POINT_IMPL:
- // System.out.println("Calling FP");
- fixedPointSimplestCaseNonCyclicFillRaster(pixels, off, adjust, x,
- y, w, h);
- break;
- case ANTI_ALIAS_IMPL:
- // System.out.println("Calling AA");
- antiAliasFillRaster(pixels, off, adjust, x, y, w, h);
- break;
- case DEFAULT_IMPL:
- default:
- // System.out.println("Calling Default");
- cyclicCircularGradientFillRaster(pixels, off, adjust, x, y, w, h);
- }
- }
-
- /**
- * This code works in the simplest of cases, where the focus == center
- * point, the gradient is noncyclic, and the gradient lookup method is
- * fast (single array index, no conversion necessary).
- *
- */
- private void fixedPointSimplestCaseNonCyclicFillRaster(int pixels[],
- int off,
- int adjust,
- int x, int y,
- int w, int h) {
- float iSq=0; // Square distance index
- final float indexFactor = fastGradientArraySize / radius;
-
- //constant part of X and Y coordinates for the entire raster
- final float constX = (a00*x) + (a01*y) + constA;
- final float constY = (a10*x) + (a11*y) + constB;
- final float deltaX = indexFactor * a00; //incremental change in dX
- final float deltaY = indexFactor * a10; //incremental change in dY
- float dX, dY; //the current distance from center
- final int fixedArraySizeSq=
- (fastGradientArraySize * fastGradientArraySize);
- float g, gDelta, gDeltaDelta, temp; //gradient square value
- int gIndex; // integer number used to index gradient array
- int iSqInt; // Square distance index
-
- int end, j; //indexing variables
- int indexer = off;//used to index pixels array
-
- temp = ((deltaX * deltaX) + (deltaY * deltaY));
- gDeltaDelta = ((temp * 2));
-
- if (temp > fixedArraySizeSq) {
- // This combination of scale and circle radius means
- // essentially no pixels will be anything but the end
- // stop color. This also avoids math problems.
- final int val = gradientOverflow;
- for(j = 0; j < h; j++){ //for every row
- //for every column (inner loop begins here)
- for (end = indexer+w; indexer < end; indexer++)
- pixels[indexer] = val;
- indexer += adjust;
- }
- return;
- }
-
- // For every point in the raster, calculate the color at that point
- for(j = 0; j < h; j++){ //for every row
- //x and y (in user space) of the first pixel of this row
- dX = indexFactor * ((a01*j) + constX);
- dY = indexFactor * ((a11*j) + constY);
-
- // these values below here allow for an incremental calculation
- // of dX^2 + dY^2
-
- //initialize to be equal to distance squared
- g = (((dY * dY) + (dX * dX)) );
- gDelta = (((((deltaY * dY) + (deltaX * dX))* 2) +
- temp));
-
- //for every column (inner loop begins here)
- for (end = indexer+w; indexer < end; indexer++) {
- //determine the distance to the center
-
- //since this is a non cyclic fill raster, crop at "1" and 0
- if (g >= fixedArraySizeSq) {
- pixels[indexer] = gradientOverflow;
- }
-
- // This should not happen as gIndex is a square
- // quantity. Code commented out on purpose, can't underflow.
- // else if (g < 0) {
- // gIndex = 0;
- // }
-
- else {
- iSq = (g * invSqStepFloat);
-
- iSqInt = (int)iSq; //chop off fractional part
- iSq -= iSqInt;
- gIndex = sqrtLutFixed[iSqInt];
- gIndex += (int)(iSq * (sqrtLutFixed[iSqInt + 1]-gIndex));
- pixels[indexer] = gradient[gIndex];
- }
-
-
- //incremental calculation
- g += gDelta;
- gDelta += gDeltaDelta;
- }
- indexer += adjust;
- }
- }
-
- /** Length of a square distance intervale in the lookup table */
- private float invSqStepFloat;
-
- /** Used to limit the size of the square root lookup table */
- private int MAX_PRECISION = 256;
-
- /** Square root lookup table */
- private int sqrtLutFixed[] = new int[MAX_PRECISION];
-
- /**
- * Build square root lookup table
- */
- private void calculateFixedPointSqrtLookupTable() {
- float sqStepFloat;
- sqStepFloat = ((fastGradientArraySize * fastGradientArraySize)
- / (MAX_PRECISION - 2));
-
- // The last two values are the same so that linear square root
- // interpolation can happen on the maximum reachable element in the
- // lookup table (precision-2)
- int i;
- for (i = 0; i < MAX_PRECISION - 1; i++) {
- sqrtLutFixed[i] = (int)(Math.sqrt(i*sqStepFloat));
- }
- sqrtLutFixed[i] = sqrtLutFixed[i-1];
- invSqStepFloat = 1/sqStepFloat;
- }
-
- /** Fill the raster, cycling the gradient colors when a point falls outside
- * of the perimeter of the 100% stop circle.
- *
- * This calculation first computes the intersection point of the line
- * from the focus through the current point in the raster, and the
- * perimeter of the gradient circle.
- *
- * Then it determines the percentage distance of the current point along
- * that line (focus is 0%, perimeter is 100%).
- *
- * Equation of a circle centered at (a,b) with radius r:
- * (x-a)^2 + (y-b)^2 = r^2
- * Equation of a line with slope m and y-intercept b
- * y = mx + b
- * replacing y in the cirlce equation and solving using the quadratic
- * formula produces the following set of equations. Constant factors have
- * been extracted out of the inner loop.
- *
- */
- private void cyclicCircularGradientFillRaster(int pixels[], int off,
- int adjust,
- int x, int y,
- int w, int h) {
- // Constant part of the C factor of the quadratic equation
- final double constC =
- -(radiusSq) + (centerX * centerX) + (centerY * centerY);
- double A; //coefficient of the quadratic equation (Ax^2 + Bx + C = 0)
- double B; //coefficient of the quadratic equation
- double C; //coefficient of the quadratic equation
- double slope; //slope of the focus-perimeter line
- double yintcpt; //y-intercept of the focus-perimeter line
- double solutionX;//intersection with circle X coordinate
- double solutionY;//intersection with circle Y coordinate
- final float constX = (a00*x) + (a01*y) + a02;//const part of X coord
- final float constY = (a10*x) + (a11*y) + a12; //const part of Y coord
- final float precalc2 = 2 * centerY;//const in inner loop quad. formula
- final float precalc3 =-2 * centerX;//const in inner loop quad. formula
- float X; // User space point X coordinate
- float Y; // User space point Y coordinate
- float g;//value between 0 and 1 specifying position in the gradient
- float det; //determinant of quadratic formula (should always be >0)
- float currentToFocusSq;//sq distance from the current pt. to focus
- float intersectToFocusSq;//sq distance from the intersect pt. to focus
- float deltaXSq; //temp variable for a change in X squared.
- float deltaYSq; //temp variable for a change in Y squared.
- int indexer = off; //index variable for pixels array
- int i, j; //indexing variables for FOR loops
- int pixInc = w+adjust;//incremental index change for pixels array
-
- for (j = 0; j < h; j++) { //for every row
-
- X = (a01*j) + constX; //constants from column to column
- Y = (a11*j) + constY;
-
- //for every column (inner loop begins here)
- for (i = 0; i < w; i++) {
-
- // special case to avoid divide by zero or very near zero
- if (((X-focusX)>-0.000001) &&
- ((X-focusX)< 0.000001)) {
- solutionX = focusX;
-
- solutionY = centerY;
-
- solutionY += (Y > focusY)?trivial:-trivial;
- }
-
- else {
-
- //slope of the focus-current line
- slope = (Y - focusY) / (X - focusX);
-
- yintcpt = Y - (slope * X); //y-intercept of that same line
-
- //use the quadratic formula to calculate the intersection
- //point
- A = (slope * slope) + 1;
-
- B = precalc3 + (-2 * slope * (centerY - yintcpt));
-
- C = constC + (yintcpt* (yintcpt - precalc2));
-
- det = (float)Math.sqrt((B * B) - ( 4 * A * C));
-
- solutionX = -B;
-
- //choose the positive or negative root depending
- //on where the X coord lies with respect to the focus.
- solutionX += (X < focusX)?-det:det;
-
- solutionX = solutionX / (2 * A);//divisor
-
- solutionY = (slope * solutionX) + yintcpt;
- }
-
- //calculate the square of the distance from the current point
- //to the focus and the square of the distance from the
- //intersection point to the focus. Want the squares so we can
- //do 1 square root after division instead of 2 before.
-
- deltaXSq = (float)solutionX - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = (float)solutionY - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- intersectToFocusSq = deltaXSq + deltaYSq;
-
- deltaXSq = X - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = Y - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- currentToFocusSq = deltaXSq + deltaYSq;
-
- //want the percentage (0-1) of the current point along the
- //focus-circumference line
- g = (float)Math.sqrt(currentToFocusSq / intersectToFocusSq);
-
- //Get the color at this point
- pixels[indexer + i] = indexIntoGradientsArrays(g);
-
- X += a00; //incremental change in X, Y
- Y += a10;
- } //end inner loop
- indexer += pixInc;
- } //end outer loop
- }
-
-
- /** Fill the raster, cycling the gradient colors when a point
- * falls outside of the perimeter of the 100% stop circle. Use
- * the anti-aliased gradient lookup.
- *
- * This calculation first computes the intersection point of the line
- * from the focus through the current point in the raster, and the
- * perimeter of the gradient circle.
- *
- * Then it determines the percentage distance of the current point along
- * that line (focus is 0%, perimeter is 100%).
- *
- * Equation of a circle centered at (a,b) with radius r:
- * (x-a)^2 + (y-b)^2 = r^2
- * Equation of a line with slope m and y-intercept b
- * y = mx + b
- * replacing y in the cirlce equation and solving using the quadratic
- * formula produces the following set of equations. Constant factors have
- * been extracted out of the inner loop.
- * */
- private void antiAliasFillRaster(int pixels[], int off,
- int adjust,
- int x, int y,
- int w, int h) {
- // Constant part of the C factor of the quadratic equation
- final double constC =
- -(radiusSq) + (centerX * centerX) + (centerY * centerY);
- //coefficients of the quadratic equation (Ax^2 + Bx + C = 0)
- final float precalc2 = 2 * centerY;//const in inner loop quad. formula
- final float precalc3 =-2 * centerX;//const in inner loop quad. formula
-
- //const part of X,Y coord (shifted to bottom left corner of pixel.
- final float constX = (a00*(x-.5f)) + (a01*(y+.5f)) + a02;
- final float constY = (a10*(x-.5f)) + (a11*(y+.5f)) + a12;
- float X; // User space point X coordinate
- float Y; // User space point Y coordinate
- int i, j; //indexing variables for FOR loops
- int indexer = off-1; //index variable for pixels array
-
- // Size of a pixel in user space.
- double pixSzSq = (float)(a00*a00+a01*a01+a10*a10+a11*a11);
- double [] prevGs = new double[w+1];
- double deltaXSq, deltaYSq;
- double solutionX, solutionY;
- double slope, yintcpt, A, B, C, det;
- double intersectToFocusSq, currentToFocusSq;
- double g00, g01, g10, g11;
-
- // Set X,Y to top left corner of first pixel of first row.
- X = constX - a01;
- Y = constY - a11;
-
- // Calc top row of g's.
- for (i=0; i <= w; i++) {
- // special case to avoid divide by zero or very near zero
- if (((X-focusX)>-0.000001) &&
- ((X-focusX)< 0.000001)) {
- solutionX = focusX;
- solutionY = centerY;
- solutionY += (Y > focusY)?trivial:-trivial;
- }
- else {
- // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
- // Formula line: Y = Slope*x + Y0;
- //
- // So you substitue line into Circle and apply
- // Quadradic formula.
-
-
- //slope of the focus-current line
- slope = (Y - focusY) / (X - focusX);
-
- yintcpt = Y - (slope * X); //y-intercept of that same line
-
- //use the quadratic formula to calculate the intersection
- //point
- A = (slope * slope) + 1;
-
- B = precalc3 + (-2 * slope * (centerY - yintcpt));
-
- C = constC + (yintcpt* (yintcpt - precalc2));
-
- det = Math.sqrt((B * B) - ( 4 * A * C));
-
- solutionX = -B;
-
- //choose the positive or negative root depending
- //on where the X coord lies with respect to the focus.
- solutionX += (X < focusX)?-det:det;
-
- solutionX = solutionX / (2 * A);//divisor
-
- solutionY = (slope * solutionX) + yintcpt;
- }
-
- //calculate the square of the distance from the current point
- //to the focus and the square of the distance from the
- //intersection point to the focus. Want the squares so we can
- //do 1 square root after division instead of 2 before.
- deltaXSq = solutionX - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = solutionY - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- intersectToFocusSq = deltaXSq + deltaYSq;
-
- deltaXSq = X - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = Y - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- currentToFocusSq = deltaXSq + deltaYSq;
-
- //want the percentage (0-1) of the current point along the
- //focus-circumference line
- prevGs[i] = Math.sqrt(currentToFocusSq / intersectToFocusSq);
-
- X += a00; //incremental change in X, Y
- Y += a10;
- }
-
- for (j = 0; j < h; j++) { //for every row
-
- // Set X,Y to bottom edge of pixel row.
- X = (a01*j) + constX; //constants from row to row
- Y = (a11*j) + constY;
-
- g10 = prevGs[0];
- // special case to avoid divide by zero or very near zero
- if (((X-focusX)>-0.000001) &&
- ((X-focusX)< 0.000001)) {
- solutionX = focusX;
- solutionY = centerY;
- solutionY += (Y > focusY)?trivial:-trivial;
- }
- else {
- // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
- // Formula line: Y = Slope*x + Y0;
- //
- // So you substitue line into Circle and apply
- // Quadradic formula.
-
-
- //slope of the focus-current line
- slope = (Y - focusY) / (X - focusX);
-
- yintcpt = Y - (slope * X); //y-intercept of that same line
-
- //use the quadratic formula to calculate the intersection
- //point
- A = (slope * slope) + 1;
-
- B = precalc3 + (-2 * slope * (centerY - yintcpt));
-
- C = constC + (yintcpt* (yintcpt - precalc2));
-
- det = Math.sqrt((B * B) - ( 4 * A * C));
-
- solutionX = -B;
-
- //choose the positive or negative root depending
- //on where the X coord lies with respect to the focus.
- solutionX += (X < focusX)?-det:det;
-
- solutionX = solutionX / (2 * A);//divisor
-
- solutionY = (slope * solutionX) + yintcpt;
- }
-
- //calculate the square of the distance from the current point
- //to the focus and the square of the distance from the
- //intersection point to the focus. Want the squares so we can
- //do 1 square root after division instead of 2 before.
- deltaXSq = solutionX - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = solutionY - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- intersectToFocusSq = deltaXSq + deltaYSq;
-
- deltaXSq = X - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = Y - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- currentToFocusSq = deltaXSq + deltaYSq;
- g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
- prevGs[0] = g11;
-
- X += a00; //incremental change in X, Y
- Y += a10;
-
- //for every column (inner loop begins here)
- for (i=1; i <= w; i++) {
- g00 = g10;
- g01 = g11;
- g10 = prevGs[i];
-
- // special case to avoid divide by zero or very near zero
- if (((X-focusX)>-0.000001) &&
- ((X-focusX)< 0.000001)) {
- solutionX = focusX;
- solutionY = centerY;
- solutionY += (Y > focusY)?trivial:-trivial;
- }
- else {
- // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
- // Formula line: Y = Slope*x + Y0;
- //
- // So you substitue line into Circle and apply
- // Quadradic formula.
-
-
- //slope of the focus-current line
- slope = (Y - focusY) / (X - focusX);
-
- yintcpt = Y - (slope * X); //y-intercept of that same line
-
- //use the quadratic formula to calculate the intersection
- //point
- A = (slope * slope) + 1;
-
- B = precalc3 + (-2 * slope * (centerY - yintcpt));
-
- C = constC + (yintcpt* (yintcpt - precalc2));
-
- det = Math.sqrt((B * B) - ( 4 * A * C));
-
- solutionX = -B;
-
- //choose the positive or negative root depending
- //on where the X coord lies with respect to the focus.
- solutionX += (X < focusX)?-det:det;
-
- solutionX = solutionX / (2 * A);//divisor
-
- solutionY = (slope * solutionX) + yintcpt;
- }
-
- //calculate the square of the distance from the current point
- //to the focus and the square of the distance from the
- //intersection point to the focus. Want the squares so we can
- //do 1 square root after division instead of 2 before.
- deltaXSq = solutionX - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = solutionY - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- intersectToFocusSq = deltaXSq + deltaYSq;
-
- deltaXSq = X - focusX;
- deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = Y - focusY;
- deltaYSq = deltaYSq * deltaYSq;
-
- currentToFocusSq = deltaXSq + deltaYSq;
- g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
- prevGs[i] = g11;
-
- //Get the color at this point
- pixels[indexer+i] = indexGradientAntiAlias
- ((float)((g00+g01+g10+g11)/4),
- (float)Math.max(Math.abs(g11-g00),
- Math.abs(g10-g01)));
-
- X += a00; //incremental change in X, Y
- Y += a10;
- } //end inner loop
- indexer += (w+adjust);
- } //end outer loop
- }
-}
hooks/post-receive
--
SVGSalamander: SVG Library for Java
More information about the pkg-java-commits
mailing list