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