You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cf...@apache.org on 2012/10/25 21:01:49 UTC

svn commit: r1402274 [30/31] - in /incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext: ./ awt/ awt/color/ awt/font/ awt/g2d/ awt/geom/ awt/image/ awt/image/codec/ awt/image/codec/jpeg/ awt/image/codec/p...

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileRed.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileRed.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileRed.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileRed.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,419 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.image.rendered;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBufferInt;
+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 org.apache.flex.forks.batik.ext.awt.image.GraphicsUtil;
+import org.apache.flex.forks.batik.util.HaltingThread;
+
+/**
+ * This filter simply tiles its tile starting from the upper
+ * left corner of the tiled region.
+ * 
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: TileRed.java 509851 2007-02-21 01:12:30Z deweese $
+ */
+public class TileRed extends AbstractRed implements TileGenerator {
+    static final AffineTransform IDENTITY = new AffineTransform();
+
+    /**
+     * Area tiled by this filter. 
+     */
+    Rectangle tiledRegion;
+
+    int xStep;
+    int yStep;
+
+    TileStore tiles;
+
+    private RenderingHints  hints;
+
+    final boolean is_INT_PACK;
+
+    /**
+     * Tile
+     */
+    RenderedImage  tile   = null;
+    WritableRaster raster = null;
+
+
+    public TileRed(RenderedImage tile,
+                   Rectangle tiledRegion) {
+        this(tile, tiledRegion, tile.getWidth(), tile.getHeight(), null);
+    }
+
+    public TileRed(RenderedImage tile,
+                   Rectangle tiledRegion,
+                   RenderingHints hints) {
+        this(tile, tiledRegion, tile.getWidth(), tile.getHeight(), hints);
+    }
+
+    public TileRed(RenderedImage tile, 
+                   Rectangle tiledRegion,
+                   int xStep, int yStep) {
+        this(tile, tiledRegion, xStep, yStep, null);
+    }
+
+    public TileRed(RenderedImage tile, 
+                   Rectangle tiledRegion,
+                   int xStep, int yStep,
+                   RenderingHints hints) {
+        if(tiledRegion == null){
+            throw new IllegalArgumentException();
+        }
+
+        if(tile == null){
+            throw new IllegalArgumentException();
+        }
+
+        // org.apache.flex.forks.batik.test.gvt.ImageDisplay.showImage("Tile: ", tile);
+        this.tiledRegion  = tiledRegion;
+        this.xStep        = xStep;
+        this.yStep        = yStep;
+        this.hints        = hints;
+
+        SampleModel sm = fixSampleModel(tile, xStep, yStep, 
+                                        tiledRegion.width,
+                                        tiledRegion.height);
+        ColorModel cm  = tile.getColorModel();
+
+        double smSz   = AbstractTiledRed.getDefaultTileSize();
+        smSz = smSz*smSz;
+
+        double stepSz = (xStep*(double)yStep);
+        // be prepaired to grow the default tile size quite a bit if
+        // it means the image tile will fit in it...
+        if (16.1*smSz > stepSz) {
+            int xSz = xStep;
+            int ySz = yStep;
+
+            // If the pattern size is small then have multiple copies
+            // in our tile.
+            if (4*stepSz <= smSz) {
+                int mult = (int)Math.ceil(Math.sqrt(smSz/stepSz));
+                xSz *= mult;
+                ySz *= mult;
+            }
+            // System.out.println("Using Raster for pattern");
+            sm = sm.createCompatibleSampleModel(xSz, ySz);
+            raster = Raster.createWritableRaster
+                (sm, new Point(tile.getMinX(), tile.getMinY()));
+        }
+        
+        is_INT_PACK = GraphicsUtil.is_INT_PACK_Data(sm, false);
+        // System.out.println("Is INT PACK: " + is_INT_PACK);
+
+        // Initialize our base class We set our bounds be we will
+        // respond with data for any area we cover.  This is needed
+        // because the userRegion passed into PatterPaintContext
+        // doesn't account for stroke So we use that as a basis but
+        // when the context asks us for stuff outside that region we
+        // complie.
+        init((CachableRed)null, tiledRegion, cm, sm, 
+             tile.getMinX(), tile.getMinY(), null);
+
+        if (raster != null) {
+            WritableRaster fromRaster = raster.createWritableChild
+                (tile.getMinX(), tile.getMinY(), 
+                 xStep, yStep, tile.getMinX(), tile.getMinY(), null);
+
+            // Fill one 'tile' of the input....
+            fillRasterFrom(fromRaster, tile);
+            fillOutRaster(raster);
+        }
+        else {
+            this.tile        = new TileCacheRed(GraphicsUtil.wrap(tile));
+        }
+    }
+
+    public WritableRaster copyData(WritableRaster wr) {
+        int xOff = ((int)Math.floor(wr.getMinX()/xStep))*xStep;
+        int yOff = ((int)Math.floor(wr.getMinY()/yStep))*yStep;
+        int x0   = wr.getMinX()-xOff;
+        int y0   = wr.getMinY()-yOff;
+        int tx0 = getXTile(x0);
+        int ty0 = getYTile(y0);
+        int tx1 = getXTile(x0+wr.getWidth() -1);
+        int ty1 = getYTile(y0+wr.getHeight()-1);
+
+        for (int y=ty0; y<=ty1; y++)
+            for (int x=tx0; x<=tx1; x++) {
+                Raster r = getTile(x, y);
+                r = r.createChild(r.getMinX(),      r.getMinY(), 
+                                  r.getWidth(),     r.getHeight(),
+                                  r.getMinX()+xOff, r.getMinY()+yOff, null);
+                if (is_INT_PACK)
+                    GraphicsUtil.copyData_INT_PACK(r, wr);
+                else
+                    GraphicsUtil.copyData_FALLBACK(r, wr);
+            }
+        return wr;
+    }
+
+
+    public Raster getTile(int x, int y) {
+        
+        if (raster!=null) {
+            // We have a Single raster that we translate where needed
+            // position.  So just offest appropriately.
+            int tx = tileGridXOff+x*tileWidth;
+            int ty = tileGridYOff+y*tileHeight;
+            return raster.createTranslatedChild(tx, ty);
+        }
+
+        // System.out.println("Checking Cache [" + x + "," + y + "]");
+        return genTile(x,y);
+    }
+
+    public Raster genTile(int x, int y) {
+      // System.out.println("Cache Miss     [" + x + "," + y + "]");
+        int tx = tileGridXOff+x*tileWidth;
+        int ty = tileGridYOff+y*tileHeight;
+        
+        if (raster!=null) {
+            // We have a Single raster that we translate where needed
+            // position.  So just offest appropriately.
+            return raster.createTranslatedChild(tx, ty);
+        }
+
+        Point pt = new Point(tx, ty);
+        WritableRaster wr = Raster.createWritableRaster(sm, pt);
+        fillRasterFrom(wr, tile);
+        return wr;
+    }
+
+    public WritableRaster fillRasterFrom(WritableRaster wr, RenderedImage src){
+        // System.out.println("Getting Raster : " + count + " " + wr.getMinX() + "/" + wr.getMinY() + "/" + wr.getWidth() + "/" + wr.getHeight());
+        // System.out.println("Tile           : " + tile.getMinX() + "/" + tile.getMinY() + "/" + tile.getWidth() + "/" + tile.getHeight());
+
+        ColorModel cm = getColorModel();
+        BufferedImage bi
+            = new BufferedImage(cm,
+                                wr.createWritableTranslatedChild(0, 0),
+                                cm.isAlphaPremultiplied(), null);
+
+        Graphics2D g = GraphicsUtil.createGraphics(bi, hints);
+
+        int minX = wr.getMinX();
+        int minY = wr.getMinY();
+        int maxX = wr.getWidth();
+        int maxY = wr.getHeight();
+
+
+        g.setComposite(AlphaComposite.Clear);
+        g.setColor(new Color(0, 0, 0, 0));
+        g.fillRect(0, 0, maxX, maxY);
+        g.setComposite(AlphaComposite.SrcOver);
+
+        g.translate(-minX, -minY);
+
+        // Process initial translate so that tile is
+        // painted to the left of the raster top-left 
+        // corner on the first drawRenderedImage
+        int x1 = src.getMinX()+src.getWidth()-1;
+        int y1 = src.getMinY()+src.getHeight()-1;
+
+        int tileTx = (int)Math.ceil(((minX-x1)/xStep))*xStep;
+        int tileTy = (int)Math.ceil(((minY-y1)/yStep))*yStep;
+
+        g.translate(tileTx, tileTy);
+
+        int curX = tileTx - wr.getMinX() + src.getMinX();
+        int curY = tileTy - wr.getMinY() + src.getMinY();
+
+        // System.out.println("Wr: " + wr.getBounds());
+        // System.out.println("Src : [" + src.getMinX() + ", " + 
+        //                    src.getMinY()  + ", " + 
+        //                    src.getWidth() + ", " +
+        //                    src.getHeight() + "]");
+        // System.out.println("tileTx/tileTy : " + tileTx + " / " + tileTy);
+        minX = curX;
+        while(curY < maxY) {
+            if (HaltingThread.hasBeenHalted())
+                return wr;
+
+            while (curX < maxX) {
+                // System.out.println("curX/curY : " + curX + " / " + curY);
+                // System.out.println("transform : " + 
+                //                    g.getTransform().getTranslateX() + 
+                //                    " / " + 
+                //                    g.getTransform().getTranslateY());
+                GraphicsUtil.drawImage(g, src);
+                curX += xStep;
+                g.translate(xStep, 0);
+            }
+            curY += yStep;
+            g.translate(minX-curX, yStep);
+            curX = minX;
+        }
+        
+        /*g.setTransform(new AffineTransform());
+        g.setPaint(colors[count++]);
+        count %= colors.length;
+
+        g.fillRect(0, 0, maxX, maxY);*/
+
+        // Don't coerceData since it will be in the proper alpha state
+        // due to the drawing.
+        // GraphicsUtil.coerceData(wr, src.getColorModel(), alphaPremult);
+        return wr;
+    }
+
+    protected void fillOutRaster(WritableRaster wr) {
+        if (is_INT_PACK)
+            fillOutRaster_INT_PACK(wr);
+        else
+            fillOutRaster_FALLBACK(wr);
+        
+    }
+
+    protected void fillOutRaster_INT_PACK(WritableRaster wr) {
+        // System.out.println("Fast copyData");
+        int x0 = wr.getMinX();
+        int y0 = wr.getMinY();
+        int width  = wr.getWidth();
+        int height = wr.getHeight();
+
+        SinglePixelPackedSampleModel sppsm;
+        sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
+
+        final int     scanStride = sppsm.getScanlineStride();
+        DataBufferInt db         = (DataBufferInt)wr.getDataBuffer();
+        final int []  pixels     = db.getBankData()[0];
+        final int     base =
+            (db.getOffset() +
+             sppsm.getOffset(x0-wr.getSampleModelTranslateX(),
+                             y0-wr.getSampleModelTranslateY()));
+        int step = xStep;
+        for (int x=xStep; x<width; x+=step, step*=2) {
+            int w = step;
+            if (x+w > width) w = width-x;
+            if (w >= 128) {
+                int srcSP = base;
+                int dstSP = base+x;
+                for(int y=0; y<yStep; y++) {
+                    System.arraycopy(pixels, srcSP, pixels, dstSP, w);
+                    srcSP += scanStride;
+                    dstSP += scanStride;
+                }
+            } else {
+                int srcSP = base;
+                int dstSP = base+x;
+                for(int y=0; y<yStep; y++) {
+                    int end = srcSP;
+                    srcSP += w-1;
+                    dstSP += w-1;
+                    while(srcSP>=end)
+                        pixels[dstSP--] = pixels[srcSP--];
+                    srcSP+=scanStride+1;
+                    dstSP+=scanStride+1;
+                }
+            }
+        }
+
+        step = yStep;
+        for (int y=yStep; y<height; y+=step, step*=2) {
+            int h = step;
+            if (y+h > height) h = height-y;
+            int dstSP = base+y*scanStride;
+            System.arraycopy(pixels, base, pixels, dstSP, h*scanStride);
+        }
+    }
+
+    protected void fillOutRaster_FALLBACK(WritableRaster wr) {
+        // System.out.println("Fast copyData");
+        int width  = wr.getWidth();
+        int height = wr.getHeight();
+
+        Object data = null;
+
+        int step = xStep;
+        for (int x=xStep; x<width; x+=step, step*=4) {
+            int w = step;
+            if (x+w > width) w = width-x;
+            data = wr.getDataElements(0, 0, w, yStep, data);
+            wr.setDataElements(x, 0, w, yStep, data);
+            x+=w;
+
+            if (x >= width) break;
+            if (x+w > width) w = width-x;
+            wr.setDataElements(x, 0, w, yStep, data);
+            x+=w;
+
+            if (x >= width) break;
+            if (x+w > width) w = width-x;
+            wr.setDataElements(x, 0, w, yStep, data);
+        }
+
+        step = yStep;
+        for (int y=yStep; y<height; y+=step, step*=4) {
+            int h = step;
+            if (y+h > height) h = height-y;
+            data = wr.getDataElements(0, 0, width, h, data);
+            wr.setDataElements(0, y, width, h, data);
+            y+=h;
+
+            if (h >= height) break;
+            if (y+h > height) h = height-y;
+            wr.setDataElements(0, y, width, h, data);
+            y+=h;
+
+            if (h >= height) break;
+            if (y+h > height) h = height-y;
+            wr.setDataElements(0, y, width, h, data);
+            y+=h;
+        }
+    }
+
+    /**
+     * This function 'fixes' the source's sample model.
+     * right now it just ensures that the sample model isn't
+     * much larger than my width.
+     */
+    protected static SampleModel fixSampleModel(RenderedImage src,
+                                                int stepX, int stepY,
+                                                int width, int height) {
+        int defSz = AbstractTiledRed.getDefaultTileSize();
+        SampleModel sm = src.getSampleModel();
+        int w = sm.getWidth();
+        if (w < defSz) w = defSz;
+        if (w > stepX)  w = stepX;
+        // if (w > width)  w = width;
+        int h = sm.getHeight();
+        if (h < defSz) h = defSz;
+        if (h > stepY) h = stepY;
+        // if (h > height) h = height;
+        return sm.createCompatibleSampleModel(w, h);
+    }
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileRed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileStore.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileStore.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileStore.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileStore.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,40 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.image.rendered;
+
+import  java.awt.image.Raster;
+
+
+/**
+ * This the generic interface for a TileStore.  This is used to
+ * store and retrieve tiles from the cache.
+ *
+ * @version $Id: TileStore.java 498740 2007-01-22 18:35:57Z dvholten $
+ */
+public interface TileStore {
+
+    void setTile(int x, int y, Raster ras);
+
+    Raster getTile(int x, int y);
+
+    // This is return the tile if it is available otherwise
+    // returns null.  It will not compute the tile if it is
+    // not present.
+    Raster getTileNoCompute(int x, int y);
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TileStore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TranslateRed.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TranslateRed.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TranslateRed.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TranslateRed.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,109 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.image.rendered;
+
+
+import java.awt.Rectangle;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/**
+ * This is a special case of an Affine that only contains integer
+ * translations, this allows it to do it's work by simply changing
+ * the coordinate system of the tiles.
+ *
+ * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
+ * @version $Id: TranslateRed.java 478363 2006-11-22 23:01:13Z dvholten $
+ */
+public class TranslateRed extends AbstractRed {
+
+    protected int deltaX;
+    protected int deltaY;
+
+    /**
+     * Construct an instance of TranslateRed
+     * @param xloc The new x coordinate of cr.getMinX().
+     * @param yloc The new y coordinate of cr.getMinY().
+     */
+    public TranslateRed(CachableRed cr, int xloc, int yloc) {
+        super(cr, new Rectangle(xloc,  yloc,
+                                cr.getWidth(), cr.getHeight()),
+              cr.getColorModel(), cr.getSampleModel(),
+              cr.getTileGridXOffset()+xloc-cr.getMinX(),
+              cr.getTileGridYOffset()+yloc-cr.getMinY(),
+              null);
+        deltaX = xloc-cr.getMinX();
+        deltaY = yloc-cr.getMinY();
+    }
+
+    /**
+     * The delata translation in x (absolute loc is available from getMinX())
+     */
+    public int getDeltaX() { return deltaX; }
+
+    /**
+     * The delata translation in y (absolute loc is available from getMinY())
+     */
+    public int getDeltaY() { return deltaY; }
+
+    /**
+     * fetch the source image for this node.
+     */
+    public CachableRed getSource() {
+        return (CachableRed)getSources().get(0);
+    }
+
+    public Object getProperty(String name) {
+        return getSource().getProperty(name);
+    }
+
+    public String [] getPropertyNames() {
+        return getSource().getPropertyNames();
+    }
+
+    public Raster getTile(int tileX, int tileY) {
+        Raster r = getSource().getTile(tileX, tileY);
+
+        return r.createTranslatedChild(r.getMinX()+deltaX,
+                                       r.getMinY()+deltaY);
+    }
+
+    public Raster getData() {
+        Raster r = getSource().getData();
+        return r.createTranslatedChild(r.getMinX()+deltaX,
+                                       r.getMinY()+deltaY);
+    }
+
+    public Raster getData(Rectangle rect) {
+        Rectangle r = (Rectangle)rect.clone();
+        r.translate(-deltaX, -deltaY);
+        Raster ret = getSource().getData(r);
+        return ret.createTranslatedChild(ret.getMinX()+deltaX,
+                                         ret.getMinY()+deltaY);
+    }
+
+    public WritableRaster copyData(WritableRaster wr) {
+        WritableRaster wr2 = wr.createWritableTranslatedChild
+            (wr.getMinX()-deltaX, wr.getMinY()-deltaY);
+
+        getSource().copyData(wr2);
+
+        return wr;
+    }
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TranslateRed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TurbulencePatternRed.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TurbulencePatternRed.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TurbulencePatternRed.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TurbulencePatternRed.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,1348 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.apache.flex.forks.batik.ext.awt.image.rendered;
+
+import java.awt.Rectangle;
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+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.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+/**
+ * This class creates a RenderedImage in conformance to the one
+ * defined for the feTurbulence filter of the SVG specification.  What
+ * follows is my high-level description of how the noise is generated.
+ * This is not contained in the SVG spec, just the algorithm for
+ * doing it.  This is provided in the hope that someone will figure
+ * out a clever way to accelerate parts of the function.
+ *
+ * gradient contains a long list of random unit vectors.  For each
+ * point we are to generate noise for we do two things.  first we use
+ * the latticeSelector to 'co-mingle' the integer portions of x and y
+ * (this allows us to have a one-dimensional array of gradients that
+ * appears 2 dimensional, by using the co-mingled index).
+ *
+ * We do this for [x,y], [x+1,y], [x,y+1], and [x+1, y+1], this gives
+ * us the four gradient vectors that surround the point (b00, b10, ...)
+ *
+ * Next we construct the four vectors from the grid points (where the
+ * gradient vectors are defined) [these are rx0, rx1, ry0, ry1].
+ *
+ * We then take the dot product between the gradient vectors and the
+ * grid point vectors (this gives the portion of the grid point vector
+ * that projects along the gradient vector for each grid point).
+ * These four dot projects are then combined with linear interpolation.
+ * The weight factor for the linear combination is the result of applying
+ * the 's' curve function to the fractional part of x and y (rx0, ry0).
+ * The S curve function get's it's name because it looks a bit like as
+ * 'S' from 0->1.
+ *
+ * @author     <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @author     <a href="mailto:DeWeese@apache.org">Thomas DeWeese</a>
+ * @version $Id: TurbulencePatternRed.java 478276 2006-11-22 18:33:37Z dvholten $ */
+public final class TurbulencePatternRed extends AbstractRed {
+    /**
+     * Inner class to store tile stitching info.
+     * #see
+     */
+    static final class StitchInfo {
+        /**
+         * Width of the integer lattice tile
+         */
+        int width;
+
+        /**
+         * Height of the integer lattice tile
+         */
+        int height;
+
+        /**
+         * Value beyond which values are wrapped on
+         * the x-axis.
+         * @see TurbulencePatternRed#noise2Stitch
+         */
+        int wrapX;
+
+        /**
+         * Value beyond which values are wrapped on
+         * the y-axis.
+         * @see TurbulencePatternRed#noise2Stitch
+         */
+        int wrapY;
+
+        /**
+         * Default constructor
+         */
+        StitchInfo(){
+        }
+
+        /**
+         * Copy constructor
+         */
+        StitchInfo(StitchInfo stitchInfo){
+            this.width = stitchInfo.width;
+            this.height = stitchInfo.height;
+            this.wrapX = stitchInfo.wrapX;
+            this.wrapY = stitchInfo.wrapY;
+        }
+
+        final void assign(StitchInfo stitchInfo) {
+            this.width  = stitchInfo.width;
+            this.height = stitchInfo.height;
+            this.wrapX  = stitchInfo.wrapX;
+            this.wrapY  = stitchInfo.wrapY;
+        }
+
+        /*
+         * Adjustst the StitchInfo for when the frequency has been
+         * doubled.
+         *
+         *  width = tileWidth*baseFrequencyX
+         *  height = tileHeight*baseFrequencyY
+         *  minY = tileY*baseFrequencyY + PerlinN
+         *  wrapX = tileX*baseFrequencyX + PerlinN + width
+         *  wrapY = tileY*baseFrequencyY + PerlinN + height
+         *
+         */
+        final void doubleFrequency(){
+            width *= 2;
+            height *= 2;
+            wrapX *= 2;
+            wrapY *= 2;
+            wrapX -= PerlinN;
+            wrapY -= PerlinN;
+        }
+    }
+
+    /**
+     * Used when stitching is on
+     */
+    private StitchInfo stitchInfo = null;
+
+    /**
+     * Identity transform, default used when null input in the constructor.
+     */
+    private static final AffineTransform IDENTITY = new AffineTransform();
+
+    /**
+     *  x-axis base frequency for the noise function along the x-axis
+     */
+    private double baseFrequencyX;
+
+    /**
+     * y-axis base frequency for the noise function along the y-axis
+     */
+    private double baseFrequencyY;
+
+    /**
+     * Number of octaves in the noise function
+     */
+    private int numOctaves;
+
+    /**
+     * Starting number for the pseudo random number generator
+     */
+    private int seed;
+
+    /**
+     * Defines the tile for the turbulence function, if non-null turns
+     * on stitching, so frequencies are adjusted to avoid
+     * discontinuities in case frequencies do not match tile
+     * boundaries.
+     */
+    private Rectangle2D tile;
+
+    /**
+     * Defines the tile for the turbulence function
+     */
+    private AffineTransform txf;
+
+    /**
+     * Defines whether the filter performs a fractal noise or a turbulence function
+     */
+    private boolean isFractalNoise;
+
+    /**
+     * List of channels that the generator produces.
+     */
+    private int[] channels;
+
+    // To avoid doing an inverse transform on each pixel, transform
+    // the image space unit vectors and process how much of a delta
+    // this is in filter space.
+    double[] tx = {1, 0};
+    double[] ty = {0, 1};
+
+    /**
+     * Produces results in the range [1, 2**31 - 2].
+     * Algorithm is: r = (a * r) mod m
+     * where a = 16807 and m = 2**31 - 1 = 2147483647
+     * See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
+     * To test: the algorithm should produce the result 1043618065
+     * as the 10,000th generated number if the original seed is 1.
+     */
+    private static final int RAND_m = 2147483647; /* 2**31 - 1 */
+    private static final int RAND_a = 16807; /* 7**5; primitive root of m */
+    private static final int RAND_q = 127773; /* m / a */
+    private static final int RAND_r = 2836; /* m % a */
+
+    private static final int BSize = 0x100;
+    private static final int BM = 0xff;
+    private static final double PerlinN = 0x1000;
+    private final int[] latticeSelector = new int[BSize + 1];
+    private final double[] gradient = new double[(BSize+1)*8];
+
+    public double getBaseFrequencyX(){
+        return baseFrequencyX;
+    }
+
+    public double getBaseFrequencyY(){
+        return baseFrequencyY;
+    }
+
+    public int getNumOctaves(){
+        return numOctaves;
+    }
+
+    public int getSeed(){
+        return seed;
+    }
+
+    public Rectangle2D getTile(){
+        return (Rectangle2D)tile.clone();
+    }
+
+    public boolean isFractalNoise(){
+        return isFractalNoise;
+    }
+
+    public boolean[] getChannels(){
+        boolean[] channels = new boolean[4];
+        for(int i=0; i<this.channels.length; i++)
+            channels[this.channels[i]] = true;
+
+        return channels;
+    }
+
+    public final int setupSeed(int seed) {
+        if (seed <= 0) seed = -(seed % (RAND_m - 1)) + 1;
+        if (seed > RAND_m - 1) seed = RAND_m - 1;
+        return seed;
+    }
+
+    public final int random(int seed) {
+      int result = RAND_a * (seed % RAND_q) - RAND_r * (seed / RAND_q);
+        if (result <= 0) result += RAND_m;
+        return result;
+    }
+
+    private void initLattice(int seed) {
+        double u, v, s;
+        int i, j, k, s1, s2;
+        seed = setupSeed(seed);
+
+        for(k = 0; k < 4; k++){
+            for(i = 0; i < BSize; i++){
+                u = (((seed = random(seed)) % (BSize + BSize)) - BSize);
+                v = (((seed = random(seed)) % (BSize + BSize)) - BSize);
+
+                s = 1/Math.sqrt(u*u + v*v);
+                gradient[i*8 + k*2    ] = u*s;
+                gradient[i*8 + k*2 + 1] = v*s;
+            }
+        }
+
+        for(i = 0; i < BSize; i++)
+            latticeSelector[i] = i;
+
+        while(--i > 0){
+            k = latticeSelector[i];
+            j = (seed = random(seed)) % BSize;
+            latticeSelector[i] = latticeSelector[j];
+            latticeSelector[j] = k;
+
+            // Now we apply the lattice to the gradient array, this
+            // lets us avoid one of the lattice lookups.
+            s1 = i<<3;
+            s2 = j<<3;
+            for (j=0; j<8; j++) {
+                s = gradient[s1+j];
+                gradient[s1+j] = gradient[s2+j];
+                gradient[s2+j] = s;
+            }
+        }
+        latticeSelector[BSize] = latticeSelector[0];
+        for (j=0; j<8; j++)
+            gradient[(BSize*8)+j] = gradient[j];
+    }
+
+
+    private static final double s_curve(final double t) {
+        return (t * t * (3 - 2 * t) );
+    }
+
+    private static final double lerp(double t, double a, double b) {
+        return ( a + t * (b - a) );
+    }
+
+    /**
+     * Generate a pixel of noise corresponding to the point vec0,vec1.
+     * See class description for a high level discussion of method.
+     * This handles cases where channels <= 4.
+     * @param noise The place to put the generated noise.
+     * @param vec0  The X coordiate to generate noise for
+     * @param vec1  The Y coordiate to generate noise for
+     */
+    private final void noise2(final double[] noise, double vec0, double vec1) {
+        int b0, b1;
+        final int i, j;
+        final double rx0, rx1, ry0, ry1, sx, sy;
+
+        vec0 += PerlinN;
+        b0 = ((int)vec0)&BM;
+
+        i = latticeSelector[b0];
+        j = latticeSelector[b0+1];
+
+        rx0 = vec0 - (int)vec0;
+        rx1 = rx0 - 1.0;
+        sx  = s_curve(rx0);
+
+        vec1 += PerlinN;
+        b0 = (int)vec1;
+
+        // The gradient array already has the latticeSelector applied
+        // to it, So we can avoid doing the last lookup.
+        b1 = ((j + b0)&BM)<<3;
+        b0 = ((i + b0)&BM)<<3;
+
+        ry0 = vec1 - (int)vec1;
+        ry1 = ry0 - 1.0;
+        sy = s_curve(ry0);
+
+        switch (channels.length) {
+            // Intentionally use 'fall through' in switch statement.
+        case 4:
+            noise[3] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+6] + ry0*gradient[b0+7],
+                          rx1*gradient[b1+6] + ry0*gradient[b1+7]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+6] + ry1*gradient[b0+8+7],
+                          rx1*gradient[b1+8+6] + ry1*gradient[b1+8+7]));
+        case 3:
+            noise[2] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+4] + ry0*gradient[b0+5],
+                          rx1*gradient[b1+4] + ry0*gradient[b1+5]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+4] + ry1*gradient[b0+8+5],
+                          rx1*gradient[b1+8+4] + ry1*gradient[b1+8+5]));
+        case 2:
+            noise[1] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+2] + ry0*gradient[b0+3],
+                          rx1*gradient[b1+2] + ry0*gradient[b1+3]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+2] + ry1*gradient[b0+8+3],
+                          rx1*gradient[b1+8+2] + ry1*gradient[b1+8+3]));
+        case 1:
+            noise[0] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+0] + ry0*gradient[b0+1],
+                          rx1*gradient[b1+0] + ry0*gradient[b1+1]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+0] + ry1*gradient[b0+8+1],
+                          rx1*gradient[b1+8+0] + ry1*gradient[b1+8+1]));
+        }
+    }
+
+    /**
+     * This version of the noise function implements stitching.
+     * If any of the lattice is on the right or bottom edge, the
+     * function uses the the latice on the other side of the
+     * tile, i.e., the left or right edge.
+     * @param noise The place to put the generated noise.
+     * @param vec0  The X coordiate to generate noise for
+     * @param vec1  The Y coordiate to generate noise for
+     * @param stitchInfo The stitching information for the noise function.
+     */
+    private final void noise2Stitch(final double[] noise,
+                                    final double vec0, final double vec1,
+                                    final StitchInfo stitchInfo){
+        int b0, b1;
+        final int i, j, b00, b10, b01, b11;
+        double t;
+        final double rx0, rx1, ry0, ry1, sx, sy;
+
+        t = vec0  + PerlinN;
+        b0 = ((int)t);
+        b1 = b0+1;
+        // Stitch lattice tile x coordinates
+        if (b1 >= stitchInfo.wrapX) {
+            if (b0 >= stitchInfo.wrapX) {
+                b0 -= stitchInfo.width;
+                b1 -= stitchInfo.width;
+            } else {
+                b1 -= stitchInfo.width;
+            }
+        }
+        i = latticeSelector[b0&BM];
+        j = latticeSelector[b1&BM];
+
+        rx0 = t - (int)t;
+        rx1 = rx0 - 1.0;
+        sx = s_curve(rx0);
+
+        t = vec1 + PerlinN;
+        b0 = ((int)t);
+        b1 = b0+1;
+        // Stitch lattice tile y coordinates
+        if (b1 >= stitchInfo.wrapY) {
+            if (b0 >= stitchInfo.wrapY) {
+                b0 -= stitchInfo.height;
+                b1 -= stitchInfo.height;
+            } else {
+                b1 -= stitchInfo.height;
+            }
+        }
+        // In this case we still need to keep all four indexes since
+        // we may have split y across the stitch boundry, in which
+        // case b0 and b1 do not have a fixed offset from one another.
+        // We still avoid a latticeSelector lookup for each index though...
+        b00 = ((i + b0)&BM)<<3;
+        b10 = ((j + b0)&BM)<<3;
+        b01 = ((i + b1)&BM)<<3;
+        b11 = ((j + b1)&BM)<<3;
+
+        ry0 = t - (int)t;
+        ry1 = ry0 - 1.0;
+        sy = s_curve(ry0);
+
+        switch (channels.length) {
+            // Intentionally use 'fall through' in switch statement.
+        case 4:
+            noise[3] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b00+6] + ry0*gradient[b00+7],
+                          rx1*gradient[b10+6] + ry0*gradient[b10+7]),
+                     lerp(sx,
+                          rx0*gradient[b01+6] + ry1*gradient[b01+7],
+                          rx1*gradient[b11+6] + ry1*gradient[b11+7]));
+        case 3:
+            noise[2] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b00+4] + ry0*gradient[b00+5],
+                          rx1*gradient[b10+4] + ry0*gradient[b10+5]),
+                     lerp(sx,
+                          rx0*gradient[b01+4] + ry1*gradient[b01+5],
+                          rx1*gradient[b11+4] + ry1*gradient[b11+5]));
+        case 2:
+            noise[1] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b00+2] + ry0*gradient[b00+3],
+                          rx1*gradient[b10+2] + ry0*gradient[b10+3]),
+                     lerp(sx,
+                          rx0*gradient[b01+2] + ry1*gradient[b01+3],
+                          rx1*gradient[b11+2] + ry1*gradient[b11+3]));
+        case 1:
+            noise[0] =
+                lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b00+0] + ry0*gradient[b00+1],
+                          rx1*gradient[b10+0] + ry0*gradient[b10+1]),
+                     lerp(sx,
+                          rx0*gradient[b01+0] + ry1*gradient[b01+1],
+                          rx1*gradient[b11+0] + ry1*gradient[b11+1]));
+        }
+    }
+
+    /**
+     * This is the heart of the turbulence calculation. It returns
+     * 'turbFunctionResult', as defined in the spec.  This is
+     * special case for 4 bands of output.
+     *
+     * @param pointX x coordinate of the point to process.
+     * @param pointY y coordinate of the point to process.
+     * @param fSum array used to avoid reallocating double array for each pixel
+     * @return The ARGB pixel value.
+     */
+    private final int turbulence_4(double pointX,
+                                   double pointY,
+                                   final double[] fSum) {
+        double n, ratio = 255;
+        int i, j, b0, b1, nOctave;
+        double px, py, rx0, rx1, ry0, ry1, sx, sy;
+
+        pointX *= baseFrequencyX;
+        pointY *= baseFrequencyY;
+        fSum[0] = fSum[1] = fSum[2] = fSum[3] = 0;
+
+        for (nOctave = numOctaves; nOctave > 0; nOctave--){
+            px = pointX+PerlinN;
+
+            b0 = ((int)px)&BM;
+            i = latticeSelector[b0 ];
+            j = latticeSelector[b0+1];
+
+            rx0 = px - (int)px;
+            rx1 = rx0 - 1.0;
+            sx  = s_curve(rx0);
+
+            py = pointY+PerlinN;
+            b0 = ((int)py) & BM;
+            b1 = (b0+1) & BM;
+
+            b1 = ((j + b0)&BM)<<3;
+            b0 = ((i + b0)&BM)<<3;
+
+            ry0 = py - (int)py;
+            ry1 = ry0 - 1.0;
+            sy = s_curve(ry0);
+
+            n = lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+0] + ry0*gradient[b0+1],
+                          rx1*gradient[b1+0] + ry0*gradient[b1+1]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+0] + ry1*gradient[b0+8+1],
+                          rx1*gradient[b1+8+0] + ry1*gradient[b1+8+1]));
+
+            if (n<0) fSum[0] -= (n * ratio);
+            else     fSum[0] += (n * ratio);
+
+            n = lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+2] + ry0*gradient[b0+3],
+                          rx1*gradient[b1+2] + ry0*gradient[b1+3]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+2] + ry1*gradient[b0+8+3],
+                          rx1*gradient[b1+8+2] + ry1*gradient[b1+8+3]));
+
+            if (n<0) fSum[1] -= (n * ratio);
+            else     fSum[1] += (n * ratio);
+
+            n = lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+4] + ry0*gradient[b0+5],
+                          rx1*gradient[b1+4] + ry0*gradient[b1+5]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+4] + ry1*gradient[b0+8+5],
+                          rx1*gradient[b1+8+4] + ry1*gradient[b1+8+5]));
+
+            if (n<0) fSum[2] -= (n * ratio);
+            else     fSum[2] += (n * ratio);
+
+            n = lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+6] + ry0*gradient[b0+7],
+                          rx1*gradient[b1+6] + ry0*gradient[b1+7]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+6] + ry1*gradient[b0+8+7],
+                          rx1*gradient[b1+8+6] + ry1*gradient[b1+8+7]));
+            if (n<0) fSum[3] -= (n * ratio);
+            else     fSum[3] += (n * ratio);
+
+            ratio *= .5;
+            pointX *= 2;
+            pointY *= 2;
+        }
+
+        i = (int)fSum[0];
+        if ((i & 0xFFFFFF00) == 0) j  = i<<16;
+        else                       j  = ((i & 0x80000000) != 0)?0:0xFF0000;
+
+        i = (int)fSum[1];
+        if ((i & 0xFFFFFF00) == 0) j |= i<<8;
+        else                       j |= ((i & 0x80000000) != 0)?0:0xFF00;
+
+        i = (int)fSum[2];
+        if ((i & 0xFFFFFF00) == 0) j |= i;
+        else                       j |= ((i & 0x80000000) != 0)?0:0xFF;
+
+        i = (int)fSum[3];
+        if ((i & 0xFFFFFF00) == 0) j |= i<<24;
+        else                       j |= ((i & 0x80000000) != 0)?0:0xFF000000;
+        return j;
+    }
+
+
+    /**
+     * This is the heart of the turbulence calculation. It returns
+     * 'turbFunctionResult', as defined in the spec.
+     * @param rgb array for the four color components
+     * @param pointX x coordinate of the point to process.
+     * @param pointY y coordinate of the point to process.
+     * @param fSum array used to avoid reallocating double array for each pixel
+     * @param noise array used to avoid reallocating double array for
+     *        each pixel
+     */
+    private final void turbulence(final int[] rgb,
+                                  double pointX,
+                                  double pointY,
+                                  final double[] fSum,
+                                  final double[] noise) {
+        fSum[0] = fSum[1] = fSum[2] = fSum[3] = 0;
+        double ratio = 255;
+        pointX *= baseFrequencyX;
+        pointY *= baseFrequencyY;
+        switch (channels.length) {
+        case 4:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2(noise, pointX, pointY);
+
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
+                else            fSum[1] += (noise[1] * ratio);
+                if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
+                else            fSum[2] += (noise[2] * ratio);
+                if (noise[3]<0) fSum[3] -= (noise[3] * ratio);
+                else            fSum[3] += (noise[3] * ratio);
+                ratio *= .5;
+                pointX *= 2;
+                pointY *= 2;
+            }
+
+            rgb[0] = (int)fSum[0];
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            rgb[1] = (int)fSum[1];
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+            rgb[2] = (int)fSum[2];
+            if ((rgb[2] & 0xFFFFFF00) != 0)
+                rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
+            rgb[3] = (int)fSum[3];
+            if ((rgb[3] & 0xFFFFFF00) != 0)
+                rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
+            break;
+        case 3:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2(noise, pointX, pointY);
+
+                if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
+                else            fSum[2] += (noise[2] * ratio);
+                if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
+                else            fSum[1] += (noise[1] * ratio);
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio *= .5;
+                pointX *= 2;
+                pointY *= 2;
+            }
+            rgb[2] = (int)fSum[2];
+            if ((rgb[2] & 0xFFFFFF00) != 0)
+                rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
+            rgb[1] = (int)fSum[1];
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+            rgb[0] = (int)fSum[0];
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        case 2:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2(noise, pointX, pointY);
+
+                if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
+                else            fSum[1] += (noise[1] * ratio);
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio *= .5;
+                pointX *= 2;
+                pointY *= 2;
+            }
+
+            rgb[1] = (int)fSum[1];
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+            rgb[0] = (int)fSum[0];
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        case 1:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2(noise, pointX, pointY);
+
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio *= .5;
+                pointX *= 2;
+                pointY *= 2;
+            }
+
+            rgb[0] = (int)fSum[0];
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        }
+    }
+
+    /**
+     * This is the heart of the turbulence calculation. It returns
+     * 'turbFunctionResult', as defined in the spec.
+     * @param rgb array for the four color components
+     * @param pointX x coordinate of the point to process.
+     * @param pointY y coordinate of the point to process.
+     * @param fSum array used to avoid reallocating double array for each pixel
+     * @param noise array used to avoid reallocating double array for
+     * each pixel
+     * @param stitchInfo The stitching information for the noise function
+     */
+    private final void turbulenceStitch(final int[] rgb,
+                                        double pointX, double pointY,
+                                        final double[] fSum,
+                                        final double[] noise,
+                                        StitchInfo stitchInfo){
+        double ratio = 1;
+        pointX *= baseFrequencyX;
+        pointY *= baseFrequencyY;
+        fSum[0] = fSum[1] = fSum[2] = fSum[3] = 0;
+        switch (channels.length) {
+        case 4:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2Stitch(noise, pointX, pointY, stitchInfo);
+
+                if (noise[3]<0) fSum[3] -= (noise[3] * ratio);
+                else            fSum[3] += (noise[3] * ratio);
+                if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
+                else            fSum[2] += (noise[2] * ratio);
+                if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
+                else            fSum[1] += (noise[1] * ratio);
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio  *= .5;
+                pointX *= 2;
+                pointY *= 2;
+
+                stitchInfo.doubleFrequency();
+            }
+            rgb[3] = (int)(fSum[3] * 255);
+            if ((rgb[3] & 0xFFFFFF00) != 0)
+                rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
+            rgb[2] = (int)(fSum[2] * 255);
+            if ((rgb[2] & 0xFFFFFF00) != 0)
+                rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
+            rgb[1] = (int)(fSum[1] * 255);
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+            rgb[0] = (int)(fSum[0] * 255);
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        case 3:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2Stitch(noise, pointX, pointY, stitchInfo);
+                if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
+                else            fSum[2] += (noise[2] * ratio);
+                if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
+                else            fSum[1] += (noise[1] * ratio);
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio  *= .5;
+                pointX *= 2;
+                pointY *= 2;
+
+                stitchInfo.doubleFrequency();
+            }
+            rgb[2] = (int)(fSum[2] * 255);
+            if ((rgb[2] & 0xFFFFFF00) != 0)
+                rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
+            rgb[1] = (int)(fSum[1] * 255);
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+            rgb[0] = (int)(fSum[0] * 255);
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        case 2:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2Stitch(noise, pointX, pointY, stitchInfo);
+                if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
+                else            fSum[1] += (noise[1] * ratio);
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio  *= .5;
+                pointX *= 2;
+                pointY *= 2;
+
+                stitchInfo.doubleFrequency();
+            }
+            rgb[1] = (int)(fSum[1] * 255);
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+            rgb[0] = (int)(fSum[0] * 255);
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        case 1:
+            for(int nOctave = 0; nOctave < numOctaves; nOctave++){
+                noise2Stitch(noise, pointX, pointY, stitchInfo);
+                if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
+                else            fSum[0] += (noise[0] * ratio);
+                ratio  *= .5;
+                pointX *= 2;
+                pointY *= 2;
+
+                stitchInfo.doubleFrequency();
+            }
+            rgb[0] = (int)(fSum[0] * 255);
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+            break;
+        }
+    }
+
+    /**
+     * This is the heart of the turbulence calculation. It returns
+     * 'turbFunctionResult', as defined in the spec.  This handles the
+     * case where we are generating 4 channels of noise.
+     * @param pointX x coordinate of the point to process.
+     * @param pointY y coordinate of the point to process.
+     * @param fSum array used to avoid reallocating double array for each pixel
+     * @return The ARGB pixel
+     */
+    private final int turbulenceFractal_4( double pointX,
+                                           double pointY,
+                                           final double[] fSum) {
+        int b0, b1, nOctave, i, j;
+        double px, py, rx0, rx1, ry0, ry1, sx, sy, ratio = 127.5;
+
+        pointX *= baseFrequencyX;
+        pointY *= baseFrequencyY;
+        fSum[0] = fSum[1] = fSum[2] = fSum[3] = 127.5;
+
+        for (nOctave = numOctaves; nOctave > 0; nOctave--){
+            px = pointX+PerlinN;
+
+            b0 = ((int)px)&BM;
+            i = latticeSelector[b0 ];
+            j = latticeSelector[b0+1];
+
+            rx0 = px - (int)px;
+            rx1 = rx0 - 1.0;
+            sx  = s_curve(rx0);
+
+            py = pointY+PerlinN;
+            b0 = ((int)py) & BM;
+            b1 = (b0+1) & BM;
+
+            b1 = ((j + b0)&BM)<<3;
+            b0 = ((i + b0)&BM)<<3;
+
+            ry0 = py - (int)py;
+            ry1 = ry0 - 1.0;
+            sy = s_curve(ry0);
+
+            fSum[0] += lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+0] + ry0*gradient[b0+1],
+                          rx1*gradient[b1+0] + ry0*gradient[b1+1]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+0] + ry1*gradient[b0+8+1],
+                          rx1*gradient[b1+8+0] + ry1*gradient[b1+8+1]))*ratio;
+
+            fSum[1] += lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+2] + ry0*gradient[b0+3],
+                          rx1*gradient[b1+2] + ry0*gradient[b1+3]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+2] + ry1*gradient[b0+8+3],
+                          rx1*gradient[b1+8+2] + ry1*gradient[b1+8+3]))*ratio;
+
+            fSum[2] += lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+4] + ry0*gradient[b0+5],
+                          rx1*gradient[b1+4] + ry0*gradient[b1+5]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+4] + ry1*gradient[b0+8+5],
+                          rx1*gradient[b1+8+4] + ry1*gradient[b1+8+5]))*ratio;
+
+            fSum[3] += lerp(sy,
+                     lerp(sx,
+                          rx0*gradient[b0+6] + ry0*gradient[b0+7],
+                          rx1*gradient[b1+6] + ry0*gradient[b1+7]),
+                     lerp(sx,
+                          rx0*gradient[b0+8+6] + ry1*gradient[b0+8+7],
+                          rx1*gradient[b1+8+6] + ry1*gradient[b1+8+7]))*ratio;
+
+            ratio  *= .5;
+            pointX *= 2;
+            pointY *= 2;
+        }
+
+        i = (int)fSum[0];
+        if ((i & 0xFFFFFF00) == 0) j  = i<<16;
+        else                       j  = ((i & 0x80000000) != 0)?0:0xFF0000;
+
+        i = (int)fSum[1];
+        if ((i & 0xFFFFFF00) == 0) j |= i<<8;
+        else                       j |= ((i & 0x80000000) != 0)?0:0xFF00;
+
+        i = (int)fSum[2];
+        if ((i & 0xFFFFFF00) == 0) j |= i;
+        else                       j |= ((i & 0x80000000) != 0)?0:0xFF;
+
+        i = (int)fSum[3];
+        if ((i & 0xFFFFFF00) == 0) j |= i<<24;
+        else                       j |= ((i & 0x80000000) != 0)?0:0xFF000000;
+        return j;
+    }
+
+    /**
+     * This is the heart of the turbulence calculation. It returns
+     * 'turbFunctionResult', as defined in the spec.
+     * @param rgb array for the four color components
+     * @param pointX x coordinate of the point to process.
+     * @param pointY y coordinate of the point to process.
+     * @param fSum array used to avoid reallocating double array for each pixel
+     * @param noise array used to avoid reallocating double array for
+     * each pixel
+     */
+    private final void turbulenceFractal(final int[] rgb,
+                                         double pointX,
+                                         double pointY,
+                                         final double[] fSum,
+                                         final double[] noise){
+        double ratio = 127.5;
+        int    nOctave;
+        fSum[0] = fSum[1] = fSum[2] = fSum[3] = 127.5;
+        pointX *= baseFrequencyX;
+        pointY *= baseFrequencyY;
+        for(nOctave = numOctaves; nOctave > 0; nOctave--){
+            noise2(noise, pointX, pointY);
+
+            switch (channels.length) {
+            case 4:
+                fSum[3] += (noise[3] * ratio);
+            case 3:
+                fSum[2] += (noise[2] * ratio);
+            case 2:
+                fSum[1] += (noise[1] * ratio);
+            case 1:
+                fSum[0] += (noise[0] * ratio);
+            }
+
+            ratio  *= .5;
+            pointX *= 2;
+            pointY *= 2;
+        }
+
+        switch (channels.length) {
+        case 4:
+            rgb[3] = (int)fSum[3];
+            if ((rgb[3] & 0xFFFFFF00) != 0)
+                rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
+        case 3:
+            rgb[2] = (int)fSum[2];
+            if ((rgb[2] & 0xFFFFFF00) != 0)
+                rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
+        case 2:
+            rgb[1] = (int)fSum[1];
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+        case 1:
+            rgb[0] = (int)fSum[0];
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+        }
+    }
+
+    /**
+     * This is the heart of the turbulence calculation. It returns
+     * 'turbFunctionResult', as defined in the spec.
+     * @param rgb array for the four color components
+     * @param pointX x coordinate of the point to process.
+     * @param pointY y coordinate of the point to process.
+     * @param fSum array used to avoid reallocating double array for each pixel
+     * @param noise array used to avoid reallocating double array for
+     * each pixel
+     * @param stitchInfo The stitching information for the noise function
+     */
+    private final void turbulenceFractalStitch(final int[] rgb,
+                                               double pointX,
+                                               double pointY,
+                                               final double[] fSum,
+                                               final double[] noise,
+                                               StitchInfo stitchInfo){
+        double ratio = 127.5;
+        int    nOctave;
+        fSum[0] = fSum[1] = fSum[2] = fSum[3] = 127.5;
+        pointX *= baseFrequencyX;
+        pointY *= baseFrequencyY;
+        for(nOctave = numOctaves; nOctave > 0; nOctave--){
+            noise2Stitch(noise, pointX, pointY, stitchInfo);
+
+            switch (channels.length) {
+            case 4:
+                fSum[3] += (noise[3] * ratio);
+            case 3:
+                fSum[2] += (noise[2] * ratio);
+            case 2:
+                fSum[1] += (noise[1] * ratio);
+            case 1:
+                fSum[0] += (noise[0] * ratio);
+            }
+
+            ratio  *= .5;
+            pointX *= 2;
+            pointY *= 2;
+            stitchInfo.doubleFrequency();
+        }
+
+        switch (channels.length) {
+        case 4:
+            rgb[3] = (int)fSum[3];
+            if ((rgb[3] & 0xFFFFFF00) != 0)
+                rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
+        case 3:
+            rgb[2] = (int)fSum[2];
+            if ((rgb[2] & 0xFFFFFF00) != 0)
+                rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
+        case 2:
+            rgb[1] = (int)fSum[1];
+            if ((rgb[1] & 0xFFFFFF00) != 0)
+                rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
+        case 1:
+            rgb[0] = (int)fSum[0];
+            if ((rgb[0] & 0xFFFFFF00) != 0)
+                rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
+        }
+    }
+
+    /**
+     * Generates a Perlin noise pattern into dest Raster.
+     * @param dest Raster to fill with the pattern.
+     */
+    public WritableRaster copyData(WritableRaster dest) {
+        //
+        // First, check input arguments
+        //
+        if(dest==null)
+            throw new IllegalArgumentException
+                ("Cannot generate a noise pattern into a null raster");
+
+
+        int w = dest.getWidth();
+        int h = dest.getHeight();
+
+        // Access the integer buffer for the destination Raster
+        DataBufferInt dstDB = (DataBufferInt)dest.getDataBuffer();
+        SinglePixelPackedSampleModel sppsm;
+        int minX = dest.getMinX();
+        int minY = dest.getMinY();
+        sppsm = (SinglePixelPackedSampleModel)dest.getSampleModel();
+        int dstOff = dstDB.getOffset() +
+            sppsm.getOffset(minX - dest.getSampleModelTranslateX(),
+                            minY - dest.getSampleModelTranslateY());
+
+        final int[] destPixels = dstDB.getBankData()[0];
+        int dstAdjust = sppsm.getScanlineStride() - w;
+
+        // Generate pixel pattern now
+        int i, end, dp=dstOff;
+        final int[] rgb = new int[4];
+        final double[] fSum = {0, 0, 0, 0};
+        final double[] noise = {0, 0, 0, 0};
+
+        final double tx0, tx1, ty0, ty1;
+        tx0 = tx[0];
+        tx1 = tx[1];
+        // Update for y step, (note we substract all the stuff we
+        // added while going across the scan line).
+        ty0 = ty[0]-(w*tx0);
+        ty1 = ty[1]-(w*tx1);
+
+        double[] p = {minX, minY};
+        txf.transform(p, 0, p, 0, 1);
+        double point_0 = p[0];
+        double point_1 = p[1];
+
+        if(isFractalNoise){
+            if(stitchInfo == null){
+                if (channels.length == 4) {
+                    for(i=0; i<h; i++){
+                        for(end=dp+w; dp<end; dp++) {
+                            destPixels[dp] = turbulenceFractal_4
+                                (point_0, point_1, fSum);
+                            point_0 += tx0;
+                            point_1 += tx1;
+                        }
+                        point_0 += ty0;
+                        point_1 += ty1;
+                        dp += dstAdjust;
+                    }
+                } else {
+                    for(i=0; i<h; i++){
+                        for(end=dp+w; dp<end; dp++){
+                            turbulenceFractal(rgb, point_0, point_1, fSum, noise);
+
+                            // Write RGB value.
+                            destPixels[dp] = ((rgb[3]<<24) |
+                                              (rgb[0]<<16) |
+                                              (rgb[1]<<8)  |
+                                              (rgb[2]   ));
+                            point_0 += tx0;
+                            point_1 += tx1;
+                        }
+                        point_0 += ty0;
+                        point_1 += ty1;
+                        dp += dstAdjust;
+                    }
+                }
+            }
+            else{
+                StitchInfo si = new StitchInfo();
+                for(i=0; i<h; i++){
+                    for(end=dp+w; dp<end; dp++){
+                        si.assign(this.stitchInfo);
+                        turbulenceFractalStitch(rgb, point_0, point_1,
+                                                fSum, noise, si);
+
+                        // Write RGB value.
+                        destPixels[dp] = ((rgb[3]<<24) |
+                                          (rgb[0]<<16) |
+                                          (rgb[1]<<8)  |
+                                          (rgb[2]   ));
+                        point_0 += tx0;
+                        point_1 += tx1;
+                    }
+                    point_0 += ty0;
+                    point_1 += ty1;
+                    dp += dstAdjust;
+                }
+            }
+        }
+        else{ // Loop for turbulence noise
+            if(stitchInfo == null){
+                if (channels.length == 4) {
+                    for(i=0; i<h; i++){
+                        for(end=dp+w; dp<end; dp++){
+                            destPixels[dp] = turbulence_4
+                                (point_0, point_1, fSum);
+
+                            point_0 += tx0;
+                            point_1 += tx1;
+                        }
+                        point_0 += ty0;
+                        point_1 += ty1;
+                        dp += dstAdjust;
+                    }
+                } else {
+                    for(i=0; i<h; i++){
+                        for(end=dp+w; dp<end; dp++){
+                            turbulence(rgb, point_0, point_1, fSum, noise);
+
+                            // Write RGB value.
+                            destPixels[dp] = ((rgb[3]<<24) |
+                                              (rgb[0]<<16) |
+                                              (rgb[1]<<8)  |
+                                              (rgb[2]   ));
+                            point_0 += tx0;
+                            point_1 += tx1;
+                        }
+                        point_0 += ty0;
+                        point_1 += ty1;
+                        dp += dstAdjust;
+                    }
+                }
+            }
+            else{
+                StitchInfo si = new StitchInfo();
+                for(i=0; i<h; i++){
+                    for(end=dp+w; dp<end; dp++){
+                        si.assign(this.stitchInfo);
+                        turbulenceStitch(rgb, point_0, point_1,
+                                         fSum, noise, si);
+
+                        // Write RGB value.
+                        destPixels[dp] = ((rgb[3]<<24) |
+                                          (rgb[0]<<16) |
+                                          (rgb[1]<<8)  |
+                                          (rgb[2]   ));
+                        point_0 += tx0;
+                        point_1 += tx1;
+                    }
+                    point_0 += ty0;
+                    point_1 += ty1;
+                    dp += dstAdjust;
+                }
+            }
+        }
+
+        return dest;
+    }
+
+    /**
+     * @param baseFrequencyX x-axis base frequency for the noise
+     * function along the x-axis
+     * @param baseFrequencyY y-axis base frequency for the noise
+     *        function along the x-axis
+     * @param numOctaves number of octaves in the noise
+     *        function. Positive integral value.
+     * @param seed starting number for the pseudo random number generator
+     * @param isFractalNoise defines whether the filter performs a
+     *        fractal noise or a turbulence function.
+     * @param tile defines the tile size. May be null if stitchTiles
+     *        is false. Otherwise, should not be null.
+     * @param txf The affine transform from device to user space.
+     * @param cs The Colorspace to output.
+     * @param alpha True if the data should have an alpha channel.
+     */
+    public TurbulencePatternRed(double baseFrequencyX,
+                                double baseFrequencyY,
+                                int     numOctaves,
+                                int     seed,
+                                boolean isFractalNoise,
+                                Rectangle2D tile,
+                                AffineTransform txf,
+                                Rectangle       devRect,
+                                ColorSpace      cs,
+                                boolean         alpha) {
+        this.baseFrequencyX = baseFrequencyX;
+        this.baseFrequencyY = baseFrequencyY;
+        this.seed = seed;
+        this.isFractalNoise = isFractalNoise;
+        this.tile = tile;
+        this.txf  = txf;
+
+        if(this.txf == null)
+            this.txf = IDENTITY;
+
+        int nChannels = cs.getNumComponents();
+        if (alpha) nChannels++;
+        channels = new int[nChannels];
+        for(int i=0; i<channels.length; i++)
+            channels[i] = i;
+
+        txf.deltaTransform(tx, 0, tx, 0, 1);
+        txf.deltaTransform(ty, 0, ty, 0, 1);
+
+        double[] vecX = {.5, 0};
+        double[] vecY = {0, .5};
+        txf.deltaTransform(vecX, 0, vecX, 0, 1);
+        txf.deltaTransform(vecY, 0, vecY, 0, 1);
+
+        //
+        // Now, limit the number of octaves so that we do not get frequencies
+        // below half a pixel.
+        //
+        // If d is the distance between to pixels in user space, then,
+        // numOctavesMax = -(log2(d) + log2(bf))
+        // along one axis.
+        //
+        // The maximum distance along each axis is processed by
+        // computing the inverse transform of 'maximum' vectors from
+        // device space to the filter space and determining the
+        // maximum component along each axis.
+
+        double dx = Math.max(Math.abs(vecX[0]), Math.abs(vecY[0]));
+        int maxX = -(int)Math.round((Math.log(dx) + Math.log(baseFrequencyX))/
+                                    Math.log(2));
+
+        double dy = Math.max(Math.abs(vecX[1]), Math.abs(vecY[1]));
+        int maxY = -(int)Math.round((Math.log(dy) + Math.log(baseFrequencyY))/
+                                    Math.log(2));
+
+        this.numOctaves = numOctaves > maxX? maxX : numOctaves;
+        this.numOctaves = this.numOctaves > maxY? maxY : this.numOctaves;
+
+        if(this.numOctaves < 1 && numOctaves > 1)
+            this.numOctaves = 1;
+
+        if (this.numOctaves > 8)
+            // beyond 8 octaves there is no significant contribution
+            // to the output pixel (contribution is halved for each
+            // octave so after 8 we are contributing less than half a
+            // code value _at_best_).
+            this.numOctaves = 8;
+
+        if (tile != null) {
+            //
+            // Adjust frequencies to the tile size
+            //
+            double lowFreq = Math.floor(tile.getWidth()*baseFrequencyX)/tile.getWidth();
+            double highFreq = Math.ceil(tile.getWidth()*baseFrequencyX)/tile.getWidth();
+            if(baseFrequencyX/lowFreq < highFreq/baseFrequencyX)
+                this.baseFrequencyX = lowFreq;
+            else
+                this.baseFrequencyX = highFreq;
+
+            lowFreq = Math.floor(tile.getHeight()*baseFrequencyY)/tile.getHeight();
+            highFreq = Math.ceil(tile.getHeight()*baseFrequencyY)/tile.getHeight();
+            if(baseFrequencyY/lowFreq < highFreq/baseFrequencyY)
+                this.baseFrequencyY = lowFreq;
+            else
+                this.baseFrequencyY = highFreq;
+
+            //
+            // Now, process the initial latice grid size to compute the minimum
+            // and maximum latice values on each axis.
+            //
+            stitchInfo = new StitchInfo();
+            stitchInfo.width = ((int)(tile.getWidth()*this.baseFrequencyX));
+            stitchInfo.height = ((int)(tile.getHeight()*this.baseFrequencyY));
+            stitchInfo.wrapX = ((int)(tile.getX()*this.baseFrequencyX +
+                                      PerlinN + stitchInfo.width));
+            stitchInfo.wrapY = ((int)(tile.getY()*this.baseFrequencyY +
+                                      PerlinN + stitchInfo.height));
+
+            // Protect agains zero frequencies.  Setting values to 1
+            // will not affect the result of the computations.
+            if(stitchInfo.width == 0) stitchInfo.width = 1;
+            if(stitchInfo.height == 0) stitchInfo.height = 1;
+
+            // System.out.println( "minLatticeX = " + minLatticeX +
+            //                    " minLatticeY = " + minLatticeY +
+            //                     " maxLatticeX = " + maxLatticeX +
+            //                     " maxLatticeY = " + maxLatticeY);
+        }
+
+        initLattice(seed);
+
+        ColorModel cm;
+        if (alpha)
+            cm = new DirectColorModel
+                (cs, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
+                 false, DataBuffer.TYPE_INT);
+        else
+            cm = new DirectColorModel
+                (cs, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x0,
+                 false, DataBuffer.TYPE_INT);
+
+        int tileSize = AbstractTiledRed.getDefaultTileSize();
+        init((CachableRed)null, devRect, cm,
+             cm.createCompatibleSampleModel(tileSize, tileSize),
+             0, 0, null);
+    }
+
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/rendered/TurbulencePatternRed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/AbstractRegistryEntry.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/AbstractRegistryEntry.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/AbstractRegistryEntry.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/AbstractRegistryEntry.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,87 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.image.spi;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @version $Id: AbstractRegistryEntry.java 501094 2007-01-29 16:35:37Z deweese $
+ */
+public abstract class AbstractRegistryEntry
+    implements RegistryEntry, ErrorConstants {
+
+    String name;
+    float  priority;
+    List   exts;
+    List   mimeTypes;
+
+    public AbstractRegistryEntry(String    name,
+                                 float     priority,
+                                 String [] exts,
+                                 String [] mimeTypes) {
+        this.name     = name;
+        this.priority = priority;
+
+        this.exts     = new ArrayList(exts.length);
+        for (int i=0; i<exts.length; i++)
+            this.exts.add(exts[i]);
+        this.exts = Collections.unmodifiableList(this.exts);
+
+        this.mimeTypes     = new ArrayList(mimeTypes.length);
+        for (int i=0; i<mimeTypes.length; i++)
+            this.mimeTypes.add(mimeTypes[i]);
+        this.mimeTypes = Collections.unmodifiableList(this.mimeTypes);
+    }
+
+    public AbstractRegistryEntry(String name,
+                                 float  priority,
+                                 String ext,
+                                 String mimeType) {
+        this.name = name;
+        this.priority = priority;
+
+        this.exts = new ArrayList(1);
+        this.exts.add(ext);
+        this.exts = Collections.unmodifiableList(exts);
+
+        this.mimeTypes = new ArrayList(1);
+        this.mimeTypes.add(mimeType);
+        this.mimeTypes = Collections.unmodifiableList(mimeTypes);
+    }
+
+
+    public String getFormatName() {
+        return name;
+    }
+
+    public List   getStandardExtensions() {
+        return exts;
+    }
+
+    public List   getMimeTypes() {
+        return mimeTypes;
+    }
+
+    public float  getPriority() {
+        return priority;
+    }
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/AbstractRegistryEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/BrokenLinkProvider.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/BrokenLinkProvider.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/BrokenLinkProvider.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/BrokenLinkProvider.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,69 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.image.spi;
+
+import java.awt.Image;
+
+import org.apache.flex.forks.batik.ext.awt.image.renderable.Filter;
+
+/**
+ * This interface is to be used to provide alternate ways of
+ * generating a placeholder image when the ImageTagRegistry
+ * fails to handle a given reference.
+ *
+ * @version $Id: BrokenLinkProvider.java 498740 2007-01-22 18:35:57Z dvholten $
+ */
+public abstract class BrokenLinkProvider {
+
+    /**
+     * The image returned by getBrokenLinkImage should always
+     * return some value when queried for the BROKEN_LINK_PROPERTY.
+     * This allows code the determine if the image is the 'real'
+     * image or the broken link image, which may be important for
+     * the application of profiles etc.
+     */
+    public static final String BROKEN_LINK_PROPERTY =
+        "org.apache.flex.forks.batik.BrokenLinkImage";
+
+    /**
+     * This method is responsbile for constructing an image that will
+     * represent the missing image in the document.  This method
+     * recives information about the reason a broken link image is
+     * being requested in the <tt>code</tt> and <tt>params</tt>
+     * parameters. These parameters may be used to generate nicely
+     * localized messages for insertion into the broken link image, or
+     * for selecting the broken link image returned.
+     *
+     * @param base The object to use for Message decoding.
+     * @param code This is the reason the image is unavailable should
+     *             be taken from ErrorConstants.
+     * @param params This is more detailed information about
+     *        the circumstances of the failure.
+     */
+    public abstract Filter getBrokenLinkImage(Object base,
+                                              String code, Object[] params);
+
+    public static boolean hasBrokenLinkProperty(Filter f) {
+        Object o = f.getProperty(BROKEN_LINK_PROPERTY);
+        if (o == null) return false;
+        if (o == Image.UndefinedProperty) return false;
+        return true;
+    }
+
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/BrokenLinkProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/DefaultBrokenLinkProvider.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/DefaultBrokenLinkProvider.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/DefaultBrokenLinkProvider.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/DefaultBrokenLinkProvider.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,91 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.image.spi;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.util.Hashtable;
+
+import org.apache.flex.forks.batik.ext.awt.image.GraphicsUtil;
+import org.apache.flex.forks.batik.ext.awt.image.renderable.Filter;
+import org.apache.flex.forks.batik.ext.awt.image.renderable.RedRable;
+import org.apache.flex.forks.batik.i18n.LocalizableSupport;
+
+/**
+ *
+ * @version $Id: DefaultBrokenLinkProvider.java 501094 2007-01-29 16:35:37Z deweese $
+ */
+public class DefaultBrokenLinkProvider
+    extends BrokenLinkProvider {
+
+    static Filter brokenLinkImg = null;
+    static final String MESSAGE_RSRC = "resources.Messages";
+
+    static final Color BROKEN_LINK_COLOR = new Color( 255,255,255,190 );
+
+    public static String formatMessage(Object base,
+                                       String code,
+                                       Object [] params) {
+        // Should probably cache these...
+        ClassLoader cl = null;
+        try {
+            // Should work always
+            cl = DefaultBrokenLinkProvider.class.getClassLoader();
+            // may not work (depends on security and relationship
+            // of base's class loader to this class's class loader.
+            cl = base.getClass().getClassLoader();
+        } catch (SecurityException se) {
+        }
+        LocalizableSupport ls;
+        ls = new LocalizableSupport(MESSAGE_RSRC, base.getClass(), cl);
+        return ls.formatMessage(code, params);
+    }
+
+    public Filter getBrokenLinkImage(Object base,
+                                     String code, Object [] params) {
+        synchronized (DefaultBrokenLinkProvider.class) {
+            if (brokenLinkImg != null)
+                return brokenLinkImg;
+
+            BufferedImage bi;
+            bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+
+            // Put the broken link property in the image so people know
+            // This isn't the "real" image.
+            Hashtable ht = new Hashtable();
+            ht.put(BROKEN_LINK_PROPERTY,
+                   formatMessage(base, code, params));
+            bi = new BufferedImage(bi.getColorModel(), bi.getRaster(),
+                                   bi.isAlphaPremultiplied(),
+                                   ht);
+            Graphics2D g2d = bi.createGraphics();
+
+            g2d.setColor( BROKEN_LINK_COLOR );
+            g2d.fillRect(0, 0, 100, 100);
+            g2d.setColor(Color.black);
+            g2d.drawRect(2, 2, 96, 96);
+            g2d.drawString("Broken Image", 6, 50);
+            g2d.dispose();
+
+            brokenLinkImg = new RedRable(GraphicsUtil.wrap(bi));
+            return brokenLinkImg;
+        }
+    }
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/image/spi/DefaultBrokenLinkProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native