You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							828 lines
						
					
					
						
							30 KiB
						
					
					
				
			
		
		
	
	
							828 lines
						
					
					
						
							30 KiB
						
					
					
				/*
 | 
						|
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 | 
						|
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
package java.awt;
 | 
						|
 | 
						|
import java.awt.image.BufferedImage;
 | 
						|
import java.awt.image.Raster;
 | 
						|
import java.awt.image.WritableRaster;
 | 
						|
import java.awt.image.ColorModel;
 | 
						|
import java.awt.image.DirectColorModel;
 | 
						|
import java.awt.image.IndexColorModel;
 | 
						|
import java.awt.geom.AffineTransform;
 | 
						|
import java.awt.geom.NoninvertibleTransformException;
 | 
						|
import java.lang.ref.WeakReference;
 | 
						|
import sun.awt.image.SunWritableRaster;
 | 
						|
import sun.awt.image.IntegerInterleavedRaster;
 | 
						|
import sun.awt.image.ByteInterleavedRaster;
 | 
						|
 | 
						|
abstract class TexturePaintContext implements PaintContext {
 | 
						|
    public static ColorModel xrgbmodel =
 | 
						|
        new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
 | 
						|
    public static ColorModel argbmodel = ColorModel.getRGBdefault();
 | 
						|
 | 
						|
    ColorModel colorModel;
 | 
						|
    int bWidth;
 | 
						|
    int bHeight;
 | 
						|
    int maxWidth;
 | 
						|
 | 
						|
    WritableRaster outRas;
 | 
						|
 | 
						|
    double xOrg;
 | 
						|
    double yOrg;
 | 
						|
    double incXAcross;
 | 
						|
    double incYAcross;
 | 
						|
    double incXDown;
 | 
						|
    double incYDown;
 | 
						|
 | 
						|
    int colincx;
 | 
						|
    int colincy;
 | 
						|
    int colincxerr;
 | 
						|
    int colincyerr;
 | 
						|
    int rowincx;
 | 
						|
    int rowincy;
 | 
						|
    int rowincxerr;
 | 
						|
    int rowincyerr;
 | 
						|
 | 
						|
    public static PaintContext getContext(BufferedImage bufImg,
 | 
						|
                                          AffineTransform xform,
 | 
						|
                                          RenderingHints hints,
 | 
						|
                                          Rectangle devBounds) {
 | 
						|
        WritableRaster raster = bufImg.getRaster();
 | 
						|
        ColorModel cm = bufImg.getColorModel();
 | 
						|
        int maxw = devBounds.width;
 | 
						|
        Object val = hints.get(RenderingHints.KEY_INTERPOLATION);
 | 
						|
        boolean filter =
 | 
						|
            (val == null
 | 
						|
             ? (hints.get(RenderingHints.KEY_RENDERING) == RenderingHints.VALUE_RENDER_QUALITY)
 | 
						|
             : (val != RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR));
 | 
						|
        if (raster instanceof IntegerInterleavedRaster &&
 | 
						|
            (!filter || isFilterableDCM(cm)))
 | 
						|
        {
 | 
						|
            IntegerInterleavedRaster iir = (IntegerInterleavedRaster) raster;
 | 
						|
            if (iir.getNumDataElements() == 1 && iir.getPixelStride() == 1) {
 | 
						|
                return new Int(iir, cm, xform, maxw, filter);
 | 
						|
            }
 | 
						|
        } else if (raster instanceof ByteInterleavedRaster) {
 | 
						|
            ByteInterleavedRaster bir = (ByteInterleavedRaster) raster;
 | 
						|
            if (bir.getNumDataElements() == 1 && bir.getPixelStride() == 1) {
 | 
						|
                if (filter) {
 | 
						|
                    if (isFilterableICM(cm)) {
 | 
						|
                        return new ByteFilter(bir, cm, xform, maxw);
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    return new Byte(bir, cm, xform, maxw);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return new Any(raster, cm, xform, maxw, filter);
 | 
						|
    }
 | 
						|
 | 
						|
    public static boolean isFilterableICM(ColorModel cm) {
 | 
						|
        if (cm instanceof IndexColorModel) {
 | 
						|
            IndexColorModel icm = (IndexColorModel) cm;
 | 
						|
            if (icm.getMapSize() <= 256) {
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    public static boolean isFilterableDCM(ColorModel cm) {
 | 
						|
        if (cm instanceof DirectColorModel) {
 | 
						|
            DirectColorModel dcm = (DirectColorModel) cm;
 | 
						|
            return (isMaskOK(dcm.getAlphaMask(), true) &&
 | 
						|
                    isMaskOK(dcm.getRedMask(), false) &&
 | 
						|
                    isMaskOK(dcm.getGreenMask(), false) &&
 | 
						|
                    isMaskOK(dcm.getBlueMask(), false));
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    public static boolean isMaskOK(int mask, boolean canbezero) {
 | 
						|
        if (canbezero && mask == 0) {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        return (mask == 0xff ||
 | 
						|
                mask == 0xff00 ||
 | 
						|
                mask == 0xff0000 ||
 | 
						|
                mask == 0xff000000);
 | 
						|
    }
 | 
						|
 | 
						|
    public static ColorModel getInternedColorModel(ColorModel cm) {
 | 
						|
        if (xrgbmodel == cm || xrgbmodel.equals(cm)) {
 | 
						|
            return xrgbmodel;
 | 
						|
        }
 | 
						|
        if (argbmodel == cm || argbmodel.equals(cm)) {
 | 
						|
            return argbmodel;
 | 
						|
        }
 | 
						|
        return cm;
 | 
						|
    }
 | 
						|
 | 
						|
    TexturePaintContext(ColorModel cm, AffineTransform xform,
 | 
						|
                        int bWidth, int bHeight, int maxw) {
 | 
						|
        this.colorModel = getInternedColorModel(cm);
 | 
						|
        this.bWidth = bWidth;
 | 
						|
        this.bHeight = bHeight;
 | 
						|
        this.maxWidth = maxw;
 | 
						|
 | 
						|
        try {
 | 
						|
            xform = xform.createInverse();
 | 
						|
        } catch (NoninvertibleTransformException e) {
 | 
						|
            xform.setToScale(0, 0);
 | 
						|
        }
 | 
						|
        this.incXAcross = mod(xform.getScaleX(), bWidth);
 | 
						|
        this.incYAcross = mod(xform.getShearY(), bHeight);
 | 
						|
        this.incXDown = mod(xform.getShearX(), bWidth);
 | 
						|
        this.incYDown = mod(xform.getScaleY(), bHeight);
 | 
						|
        this.xOrg = xform.getTranslateX();
 | 
						|
        this.yOrg = xform.getTranslateY();
 | 
						|
        this.colincx = (int) incXAcross;
 | 
						|
        this.colincy = (int) incYAcross;
 | 
						|
        this.colincxerr = fractAsInt(incXAcross);
 | 
						|
        this.colincyerr = fractAsInt(incYAcross);
 | 
						|
        this.rowincx = (int) incXDown;
 | 
						|
        this.rowincy = (int) incYDown;
 | 
						|
        this.rowincxerr = fractAsInt(incXDown);
 | 
						|
        this.rowincyerr = fractAsInt(incYDown);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    static int fractAsInt(double d) {
 | 
						|
        return (int) ((d % 1.0) * Integer.MAX_VALUE);
 | 
						|
    }
 | 
						|
 | 
						|
    static double mod(double num, double den) {
 | 
						|
        num = num % den;
 | 
						|
        if (num < 0) {
 | 
						|
            num += den;
 | 
						|
            if (num >= den) {
 | 
						|
                // For very small negative numerators, the answer might
 | 
						|
                // be such a tiny bit less than den that the difference
 | 
						|
                // is smaller than the mantissa of a double allows and
 | 
						|
                // the result would then be rounded to den.  If that is
 | 
						|
                // the case then we map that number to 0 as the nearest
 | 
						|
                // modulus representation.
 | 
						|
                num = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return num;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Release the resources allocated for the operation.
 | 
						|
     */
 | 
						|
    public void dispose() {
 | 
						|
        dropRaster(colorModel, outRas);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return the ColorModel of the output.
 | 
						|
     */
 | 
						|
    public ColorModel getColorModel() {
 | 
						|
        return colorModel;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return a Raster containing the colors generated for the graphics
 | 
						|
     * operation.
 | 
						|
     * @param x,y,w,h The area in device space for which colors are
 | 
						|
     * generated.
 | 
						|
     */
 | 
						|
    public Raster getRaster(int x, int y, int w, int h) {
 | 
						|
        if (outRas == null ||
 | 
						|
            outRas.getWidth() < w ||
 | 
						|
            outRas.getHeight() < h)
 | 
						|
        {
 | 
						|
            // If h==1, we will probably get lots of "scanline" rects
 | 
						|
            outRas = makeRaster((h == 1 ? Math.max(w, maxWidth) : w), h);
 | 
						|
        }
 | 
						|
        double X = mod(xOrg + x * incXAcross + y * incXDown, bWidth);
 | 
						|
        double Y = mod(yOrg + x * incYAcross + y * incYDown, bHeight);
 | 
						|
 | 
						|
        setRaster((int) X, (int) Y, fractAsInt(X), fractAsInt(Y),
 | 
						|
                  w, h, bWidth, bHeight,
 | 
						|
                  colincx, colincxerr,
 | 
						|
                  colincy, colincyerr,
 | 
						|
                  rowincx, rowincxerr,
 | 
						|
                  rowincy, rowincyerr);
 | 
						|
 | 
						|
        SunWritableRaster.markDirty(outRas);
 | 
						|
 | 
						|
        return outRas;
 | 
						|
    }
 | 
						|
 | 
						|
    private static WeakReference<Raster> xrgbRasRef;
 | 
						|
    private static WeakReference<Raster> argbRasRef;
 | 
						|
 | 
						|
    synchronized static WritableRaster makeRaster(ColorModel cm,
 | 
						|
                                                  Raster srcRas,
 | 
						|
                                                  int w, int h)
 | 
						|
    {
 | 
						|
        if (xrgbmodel == cm) {
 | 
						|
            if (xrgbRasRef != null) {
 | 
						|
                WritableRaster wr = (WritableRaster) xrgbRasRef.get();
 | 
						|
                if (wr != null && wr.getWidth() >= w && wr.getHeight() >= h) {
 | 
						|
                    xrgbRasRef = null;
 | 
						|
                    return wr;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            // If we are going to cache this Raster, make it non-tiny
 | 
						|
            if (w <= 32 && h <= 32) {
 | 
						|
                w = h = 32;
 | 
						|
            }
 | 
						|
        } else if (argbmodel == cm) {
 | 
						|
            if (argbRasRef != null) {
 | 
						|
                WritableRaster wr = (WritableRaster) argbRasRef.get();
 | 
						|
                if (wr != null && wr.getWidth() >= w && wr.getHeight() >= h) {
 | 
						|
                    argbRasRef = null;
 | 
						|
                    return wr;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            // If we are going to cache this Raster, make it non-tiny
 | 
						|
            if (w <= 32 && h <= 32) {
 | 
						|
                w = h = 32;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (srcRas != null) {
 | 
						|
            return srcRas.createCompatibleWritableRaster(w, h);
 | 
						|
        } else {
 | 
						|
            return cm.createCompatibleWritableRaster(w, h);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    synchronized static void dropRaster(ColorModel cm, Raster outRas) {
 | 
						|
        if (outRas == null) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        if (xrgbmodel == cm) {
 | 
						|
            xrgbRasRef = new WeakReference<>(outRas);
 | 
						|
        } else if (argbmodel == cm) {
 | 
						|
            argbRasRef = new WeakReference<>(outRas);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private static WeakReference<Raster> byteRasRef;
 | 
						|
 | 
						|
    synchronized static WritableRaster makeByteRaster(Raster srcRas,
 | 
						|
                                                      int w, int h)
 | 
						|
    {
 | 
						|
        if (byteRasRef != null) {
 | 
						|
            WritableRaster wr = (WritableRaster) byteRasRef.get();
 | 
						|
            if (wr != null && wr.getWidth() >= w && wr.getHeight() >= h) {
 | 
						|
                byteRasRef = null;
 | 
						|
                return wr;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        // If we are going to cache this Raster, make it non-tiny
 | 
						|
        if (w <= 32 && h <= 32) {
 | 
						|
            w = h = 32;
 | 
						|
        }
 | 
						|
        return srcRas.createCompatibleWritableRaster(w, h);
 | 
						|
    }
 | 
						|
 | 
						|
    synchronized static void dropByteRaster(Raster outRas) {
 | 
						|
        if (outRas == null) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        byteRasRef = new WeakReference<>(outRas);
 | 
						|
    }
 | 
						|
 | 
						|
    public abstract WritableRaster makeRaster(int w, int h);
 | 
						|
    public abstract void setRaster(int x, int y, int xerr, int yerr,
 | 
						|
                                   int w, int h, int bWidth, int bHeight,
 | 
						|
                                   int colincx, int colincxerr,
 | 
						|
                                   int colincy, int colincyerr,
 | 
						|
                                   int rowincx, int rowincxerr,
 | 
						|
                                   int rowincy, int rowincyerr);
 | 
						|
 | 
						|
    /*
 | 
						|
     * Blends the four ARGB values in the rgbs array using the factors
 | 
						|
     * described by xmul and ymul in the following ratio:
 | 
						|
     *
 | 
						|
     *     rgbs[0] * (1-xmul) * (1-ymul) +
 | 
						|
     *     rgbs[1] * (  xmul) * (1-ymul) +
 | 
						|
     *     rgbs[2] * (1-xmul) * (  ymul) +
 | 
						|
     *     rgbs[3] * (  xmul) * (  ymul)
 | 
						|
     *
 | 
						|
     * xmul and ymul are integer values in the half-open range [0, 2^31)
 | 
						|
     * where 0 == 0.0 and 2^31 == 1.0.
 | 
						|
     *
 | 
						|
     * Note that since the range is half-open, the values are always
 | 
						|
     * logically less than 1.0.  This makes sense because while choosing
 | 
						|
     * pixels to blend, when the error values reach 1.0 we move to the
 | 
						|
     * next pixel and reset them to 0.0.
 | 
						|
     */
 | 
						|
    public static int blend(int rgbs[], int xmul, int ymul) {
 | 
						|
        // xmul/ymul are 31 bits wide, (0 => 2^31-1)
 | 
						|
        // shift them to 12 bits wide, (0 => 2^12-1)
 | 
						|
        xmul = (xmul >>> 19);
 | 
						|
        ymul = (ymul >>> 19);
 | 
						|
        int accumA, accumR, accumG, accumB;
 | 
						|
        accumA = accumR = accumG = accumB = 0;
 | 
						|
        for (int i = 0; i < 4; i++) {
 | 
						|
            int rgb = rgbs[i];
 | 
						|
            // The complement of the [xy]mul values (1-[xy]mul) can result
 | 
						|
            // in new values in the range (1 => 2^12).  Thus for any given
 | 
						|
            // loop iteration, the values could be anywhere in (0 => 2^12).
 | 
						|
            xmul = (1<<12) - xmul;
 | 
						|
            if ((i & 1) == 0) {
 | 
						|
                ymul = (1<<12) - ymul;
 | 
						|
            }
 | 
						|
            // xmul and ymul are each 12 bits (0 => 2^12)
 | 
						|
            // factor is thus 24 bits (0 => 2^24)
 | 
						|
            int factor = xmul * ymul;
 | 
						|
            if (factor != 0) {
 | 
						|
                // accum variables will accumulate 32 bits
 | 
						|
                // bytes extracted from rgb fit in 8 bits (0 => 255)
 | 
						|
                // byte * factor thus fits in 32 bits (0 => 255 * 2^24)
 | 
						|
                accumA += (((rgb >>> 24)       ) * factor);
 | 
						|
                accumR += (((rgb >>> 16) & 0xff) * factor);
 | 
						|
                accumG += (((rgb >>>  8) & 0xff) * factor);
 | 
						|
                accumB += (((rgb       ) & 0xff) * factor);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return ((((accumA + (1<<23)) >>> 24) << 24) |
 | 
						|
                (((accumR + (1<<23)) >>> 24) << 16) |
 | 
						|
                (((accumG + (1<<23)) >>> 24) <<  8) |
 | 
						|
                (((accumB + (1<<23)) >>> 24)      ));
 | 
						|
    }
 | 
						|
 | 
						|
    static class Int extends TexturePaintContext {
 | 
						|
        IntegerInterleavedRaster srcRas;
 | 
						|
        int inData[];
 | 
						|
        int inOff;
 | 
						|
        int inSpan;
 | 
						|
        int outData[];
 | 
						|
        int outOff;
 | 
						|
        int outSpan;
 | 
						|
        boolean filter;
 | 
						|
 | 
						|
        public Int(IntegerInterleavedRaster srcRas, ColorModel cm,
 | 
						|
                   AffineTransform xform, int maxw, boolean filter)
 | 
						|
        {
 | 
						|
            super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
 | 
						|
            this.srcRas = srcRas;
 | 
						|
            this.inData = srcRas.getDataStorage();
 | 
						|
            this.inSpan = srcRas.getScanlineStride();
 | 
						|
            this.inOff = srcRas.getDataOffset(0);
 | 
						|
            this.filter = filter;
 | 
						|
        }
 | 
						|
 | 
						|
        public WritableRaster makeRaster(int w, int h) {
 | 
						|
            WritableRaster ras = makeRaster(colorModel, srcRas, w, h);
 | 
						|
            IntegerInterleavedRaster iiRas = (IntegerInterleavedRaster) ras;
 | 
						|
            outData = iiRas.getDataStorage();
 | 
						|
            outSpan = iiRas.getScanlineStride();
 | 
						|
            outOff = iiRas.getDataOffset(0);
 | 
						|
            return ras;
 | 
						|
        }
 | 
						|
 | 
						|
        public void setRaster(int x, int y, int xerr, int yerr,
 | 
						|
                              int w, int h, int bWidth, int bHeight,
 | 
						|
                              int colincx, int colincxerr,
 | 
						|
                              int colincy, int colincyerr,
 | 
						|
                              int rowincx, int rowincxerr,
 | 
						|
                              int rowincy, int rowincyerr) {
 | 
						|
            int[] inData = this.inData;
 | 
						|
            int[] outData = this.outData;
 | 
						|
            int out = outOff;
 | 
						|
            int inSpan = this.inSpan;
 | 
						|
            int inOff = this.inOff;
 | 
						|
            int outSpan = this.outSpan;
 | 
						|
            boolean filter = this.filter;
 | 
						|
            boolean normalx = (colincx == 1 && colincxerr == 0 &&
 | 
						|
                               colincy == 0 && colincyerr == 0) && !filter;
 | 
						|
            int rowx = x;
 | 
						|
            int rowy = y;
 | 
						|
            int rowxerr = xerr;
 | 
						|
            int rowyerr = yerr;
 | 
						|
            if (normalx) {
 | 
						|
                outSpan -= w;
 | 
						|
            }
 | 
						|
            int rgbs[] = filter ? new int[4] : null;
 | 
						|
            for (int j = 0; j < h; j++) {
 | 
						|
                if (normalx) {
 | 
						|
                    int in = inOff + rowy * inSpan + bWidth;
 | 
						|
                    x = bWidth - rowx;
 | 
						|
                    out += w;
 | 
						|
                    if (bWidth >= 32) {
 | 
						|
                        int i = w;
 | 
						|
                        while (i > 0) {
 | 
						|
                            int copyw = (i < x) ? i : x;
 | 
						|
                            System.arraycopy(inData, in - x,
 | 
						|
                                             outData, out - i,
 | 
						|
                                             copyw);
 | 
						|
                            i -= copyw;
 | 
						|
                            if ((x -= copyw) == 0) {
 | 
						|
                                x = bWidth;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        for (int i = w; i > 0; i--) {
 | 
						|
                            outData[out - i] = inData[in - x];
 | 
						|
                            if (--x == 0) {
 | 
						|
                                x = bWidth;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    x = rowx;
 | 
						|
                    y = rowy;
 | 
						|
                    xerr = rowxerr;
 | 
						|
                    yerr = rowyerr;
 | 
						|
                    for (int i = 0; i < w; i++) {
 | 
						|
                        if (filter) {
 | 
						|
                            int nextx, nexty;
 | 
						|
                            if ((nextx = x + 1) >= bWidth) {
 | 
						|
                                nextx = 0;
 | 
						|
                            }
 | 
						|
                            if ((nexty = y + 1) >= bHeight) {
 | 
						|
                                nexty = 0;
 | 
						|
                            }
 | 
						|
                            rgbs[0] = inData[inOff + y * inSpan + x];
 | 
						|
                            rgbs[1] = inData[inOff + y * inSpan + nextx];
 | 
						|
                            rgbs[2] = inData[inOff + nexty * inSpan + x];
 | 
						|
                            rgbs[3] = inData[inOff + nexty * inSpan + nextx];
 | 
						|
                            outData[out + i] =
 | 
						|
                                TexturePaintContext.blend(rgbs, xerr, yerr);
 | 
						|
                        } else {
 | 
						|
                            outData[out + i] = inData[inOff + y * inSpan + x];
 | 
						|
                        }
 | 
						|
                        if ((xerr += colincxerr) < 0) {
 | 
						|
                            xerr &= Integer.MAX_VALUE;
 | 
						|
                            x++;
 | 
						|
                        }
 | 
						|
                        if ((x += colincx) >= bWidth) {
 | 
						|
                            x -= bWidth;
 | 
						|
                        }
 | 
						|
                        if ((yerr += colincyerr) < 0) {
 | 
						|
                            yerr &= Integer.MAX_VALUE;
 | 
						|
                            y++;
 | 
						|
                        }
 | 
						|
                        if ((y += colincy) >= bHeight) {
 | 
						|
                            y -= bHeight;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ((rowxerr += rowincxerr) < 0) {
 | 
						|
                    rowxerr &= Integer.MAX_VALUE;
 | 
						|
                    rowx++;
 | 
						|
                }
 | 
						|
                if ((rowx += rowincx) >= bWidth) {
 | 
						|
                    rowx -= bWidth;
 | 
						|
                }
 | 
						|
                if ((rowyerr += rowincyerr) < 0) {
 | 
						|
                    rowyerr &= Integer.MAX_VALUE;
 | 
						|
                    rowy++;
 | 
						|
                }
 | 
						|
                if ((rowy += rowincy) >= bHeight) {
 | 
						|
                    rowy -= bHeight;
 | 
						|
                }
 | 
						|
                out += outSpan;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    static class Byte extends TexturePaintContext {
 | 
						|
        ByteInterleavedRaster srcRas;
 | 
						|
        byte inData[];
 | 
						|
        int inOff;
 | 
						|
        int inSpan;
 | 
						|
        byte outData[];
 | 
						|
        int outOff;
 | 
						|
        int outSpan;
 | 
						|
 | 
						|
        public Byte(ByteInterleavedRaster srcRas, ColorModel cm,
 | 
						|
                    AffineTransform xform, int maxw)
 | 
						|
        {
 | 
						|
            super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
 | 
						|
            this.srcRas = srcRas;
 | 
						|
            this.inData = srcRas.getDataStorage();
 | 
						|
            this.inSpan = srcRas.getScanlineStride();
 | 
						|
            this.inOff = srcRas.getDataOffset(0);
 | 
						|
        }
 | 
						|
 | 
						|
        public WritableRaster makeRaster(int w, int h) {
 | 
						|
            WritableRaster ras = makeByteRaster(srcRas, w, h);
 | 
						|
            ByteInterleavedRaster biRas = (ByteInterleavedRaster) ras;
 | 
						|
            outData = biRas.getDataStorage();
 | 
						|
            outSpan = biRas.getScanlineStride();
 | 
						|
            outOff = biRas.getDataOffset(0);
 | 
						|
            return ras;
 | 
						|
        }
 | 
						|
 | 
						|
        public void dispose() {
 | 
						|
            dropByteRaster(outRas);
 | 
						|
        }
 | 
						|
 | 
						|
        public void setRaster(int x, int y, int xerr, int yerr,
 | 
						|
                              int w, int h, int bWidth, int bHeight,
 | 
						|
                              int colincx, int colincxerr,
 | 
						|
                              int colincy, int colincyerr,
 | 
						|
                              int rowincx, int rowincxerr,
 | 
						|
                              int rowincy, int rowincyerr) {
 | 
						|
            byte[] inData = this.inData;
 | 
						|
            byte[] outData = this.outData;
 | 
						|
            int out = outOff;
 | 
						|
            int inSpan = this.inSpan;
 | 
						|
            int inOff = this.inOff;
 | 
						|
            int outSpan = this.outSpan;
 | 
						|
            boolean normalx = (colincx == 1 && colincxerr == 0 &&
 | 
						|
                               colincy == 0 && colincyerr == 0);
 | 
						|
            int rowx = x;
 | 
						|
            int rowy = y;
 | 
						|
            int rowxerr = xerr;
 | 
						|
            int rowyerr = yerr;
 | 
						|
            if (normalx) {
 | 
						|
                outSpan -= w;
 | 
						|
            }
 | 
						|
            for (int j = 0; j < h; j++) {
 | 
						|
                if (normalx) {
 | 
						|
                    int in = inOff + rowy * inSpan + bWidth;
 | 
						|
                    x = bWidth - rowx;
 | 
						|
                    out += w;
 | 
						|
                    if (bWidth >= 32) {
 | 
						|
                        int i = w;
 | 
						|
                        while (i > 0) {
 | 
						|
                            int copyw = (i < x) ? i : x;
 | 
						|
                            System.arraycopy(inData, in - x,
 | 
						|
                                             outData, out - i,
 | 
						|
                                             copyw);
 | 
						|
                            i -= copyw;
 | 
						|
                            if ((x -= copyw) == 0) {
 | 
						|
                                x = bWidth;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        for (int i = w; i > 0; i--) {
 | 
						|
                            outData[out - i] = inData[in - x];
 | 
						|
                            if (--x == 0) {
 | 
						|
                                x = bWidth;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    x = rowx;
 | 
						|
                    y = rowy;
 | 
						|
                    xerr = rowxerr;
 | 
						|
                    yerr = rowyerr;
 | 
						|
                    for (int i = 0; i < w; i++) {
 | 
						|
                        outData[out + i] = inData[inOff + y * inSpan + x];
 | 
						|
                        if ((xerr += colincxerr) < 0) {
 | 
						|
                            xerr &= Integer.MAX_VALUE;
 | 
						|
                            x++;
 | 
						|
                        }
 | 
						|
                        if ((x += colincx) >= bWidth) {
 | 
						|
                            x -= bWidth;
 | 
						|
                        }
 | 
						|
                        if ((yerr += colincyerr) < 0) {
 | 
						|
                            yerr &= Integer.MAX_VALUE;
 | 
						|
                            y++;
 | 
						|
                        }
 | 
						|
                        if ((y += colincy) >= bHeight) {
 | 
						|
                            y -= bHeight;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ((rowxerr += rowincxerr) < 0) {
 | 
						|
                    rowxerr &= Integer.MAX_VALUE;
 | 
						|
                    rowx++;
 | 
						|
                }
 | 
						|
                if ((rowx += rowincx) >= bWidth) {
 | 
						|
                    rowx -= bWidth;
 | 
						|
                }
 | 
						|
                if ((rowyerr += rowincyerr) < 0) {
 | 
						|
                    rowyerr &= Integer.MAX_VALUE;
 | 
						|
                    rowy++;
 | 
						|
                }
 | 
						|
                if ((rowy += rowincy) >= bHeight) {
 | 
						|
                    rowy -= bHeight;
 | 
						|
                }
 | 
						|
                out += outSpan;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    static class ByteFilter extends TexturePaintContext {
 | 
						|
        ByteInterleavedRaster srcRas;
 | 
						|
        int inPalette[];
 | 
						|
        byte inData[];
 | 
						|
        int inOff;
 | 
						|
        int inSpan;
 | 
						|
        int outData[];
 | 
						|
        int outOff;
 | 
						|
        int outSpan;
 | 
						|
 | 
						|
        public ByteFilter(ByteInterleavedRaster srcRas, ColorModel cm,
 | 
						|
                          AffineTransform xform, int maxw)
 | 
						|
        {
 | 
						|
            super((cm.getTransparency() == Transparency.OPAQUE
 | 
						|
                   ? xrgbmodel : argbmodel),
 | 
						|
                  xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
 | 
						|
            this.inPalette = new int[256];
 | 
						|
            ((IndexColorModel) cm).getRGBs(this.inPalette);
 | 
						|
            this.srcRas = srcRas;
 | 
						|
            this.inData = srcRas.getDataStorage();
 | 
						|
            this.inSpan = srcRas.getScanlineStride();
 | 
						|
            this.inOff = srcRas.getDataOffset(0);
 | 
						|
        }
 | 
						|
 | 
						|
        public WritableRaster makeRaster(int w, int h) {
 | 
						|
            // Note that we do not pass srcRas to makeRaster since it
 | 
						|
            // is a Byte Raster and this colorModel needs an Int Raster
 | 
						|
            WritableRaster ras = makeRaster(colorModel, null, w, h);
 | 
						|
            IntegerInterleavedRaster iiRas = (IntegerInterleavedRaster) ras;
 | 
						|
            outData = iiRas.getDataStorage();
 | 
						|
            outSpan = iiRas.getScanlineStride();
 | 
						|
            outOff = iiRas.getDataOffset(0);
 | 
						|
            return ras;
 | 
						|
        }
 | 
						|
 | 
						|
        public void setRaster(int x, int y, int xerr, int yerr,
 | 
						|
                              int w, int h, int bWidth, int bHeight,
 | 
						|
                              int colincx, int colincxerr,
 | 
						|
                              int colincy, int colincyerr,
 | 
						|
                              int rowincx, int rowincxerr,
 | 
						|
                              int rowincy, int rowincyerr) {
 | 
						|
            byte[] inData = this.inData;
 | 
						|
            int[] outData = this.outData;
 | 
						|
            int out = outOff;
 | 
						|
            int inSpan = this.inSpan;
 | 
						|
            int inOff = this.inOff;
 | 
						|
            int outSpan = this.outSpan;
 | 
						|
            int rowx = x;
 | 
						|
            int rowy = y;
 | 
						|
            int rowxerr = xerr;
 | 
						|
            int rowyerr = yerr;
 | 
						|
            int rgbs[] = new int[4];
 | 
						|
            for (int j = 0; j < h; j++) {
 | 
						|
                x = rowx;
 | 
						|
                y = rowy;
 | 
						|
                xerr = rowxerr;
 | 
						|
                yerr = rowyerr;
 | 
						|
                for (int i = 0; i < w; i++) {
 | 
						|
                    int nextx, nexty;
 | 
						|
                    if ((nextx = x + 1) >= bWidth) {
 | 
						|
                        nextx = 0;
 | 
						|
                    }
 | 
						|
                    if ((nexty = y + 1) >= bHeight) {
 | 
						|
                        nexty = 0;
 | 
						|
                    }
 | 
						|
                    rgbs[0] = inPalette[0xff & inData[inOff + x +
 | 
						|
                                                      inSpan * y]];
 | 
						|
                    rgbs[1] = inPalette[0xff & inData[inOff + nextx +
 | 
						|
                                                      inSpan * y]];
 | 
						|
                    rgbs[2] = inPalette[0xff & inData[inOff + x +
 | 
						|
                                                      inSpan * nexty]];
 | 
						|
                    rgbs[3] = inPalette[0xff & inData[inOff + nextx +
 | 
						|
                                                      inSpan * nexty]];
 | 
						|
                    outData[out + i] =
 | 
						|
                        TexturePaintContext.blend(rgbs, xerr, yerr);
 | 
						|
                    if ((xerr += colincxerr) < 0) {
 | 
						|
                        xerr &= Integer.MAX_VALUE;
 | 
						|
                        x++;
 | 
						|
                    }
 | 
						|
                    if ((x += colincx) >= bWidth) {
 | 
						|
                        x -= bWidth;
 | 
						|
                    }
 | 
						|
                    if ((yerr += colincyerr) < 0) {
 | 
						|
                        yerr &= Integer.MAX_VALUE;
 | 
						|
                        y++;
 | 
						|
                    }
 | 
						|
                    if ((y += colincy) >= bHeight) {
 | 
						|
                        y -= bHeight;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ((rowxerr += rowincxerr) < 0) {
 | 
						|
                    rowxerr &= Integer.MAX_VALUE;
 | 
						|
                    rowx++;
 | 
						|
                }
 | 
						|
                if ((rowx += rowincx) >= bWidth) {
 | 
						|
                    rowx -= bWidth;
 | 
						|
                }
 | 
						|
                if ((rowyerr += rowincyerr) < 0) {
 | 
						|
                    rowyerr &= Integer.MAX_VALUE;
 | 
						|
                    rowy++;
 | 
						|
                }
 | 
						|
                if ((rowy += rowincy) >= bHeight) {
 | 
						|
                    rowy -= bHeight;
 | 
						|
                }
 | 
						|
                out += outSpan;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    static class Any extends TexturePaintContext {
 | 
						|
        WritableRaster srcRas;
 | 
						|
        boolean filter;
 | 
						|
 | 
						|
        public Any(WritableRaster srcRas, ColorModel cm,
 | 
						|
                   AffineTransform xform, int maxw, boolean filter)
 | 
						|
        {
 | 
						|
            super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
 | 
						|
            this.srcRas = srcRas;
 | 
						|
            this.filter = filter;
 | 
						|
        }
 | 
						|
 | 
						|
        public WritableRaster makeRaster(int w, int h) {
 | 
						|
            return makeRaster(colorModel, srcRas, w, h);
 | 
						|
        }
 | 
						|
 | 
						|
        public void setRaster(int x, int y, int xerr, int yerr,
 | 
						|
                              int w, int h, int bWidth, int bHeight,
 | 
						|
                              int colincx, int colincxerr,
 | 
						|
                              int colincy, int colincyerr,
 | 
						|
                              int rowincx, int rowincxerr,
 | 
						|
                              int rowincy, int rowincyerr) {
 | 
						|
            Object data = null;
 | 
						|
            int rowx = x;
 | 
						|
            int rowy = y;
 | 
						|
            int rowxerr = xerr;
 | 
						|
            int rowyerr = yerr;
 | 
						|
            WritableRaster srcRas = this.srcRas;
 | 
						|
            WritableRaster outRas = this.outRas;
 | 
						|
            int rgbs[] = filter ? new int[4] : null;
 | 
						|
            for (int j = 0; j < h; j++) {
 | 
						|
                x = rowx;
 | 
						|
                y = rowy;
 | 
						|
                xerr = rowxerr;
 | 
						|
                yerr = rowyerr;
 | 
						|
                for (int i = 0; i < w; i++) {
 | 
						|
                    data = srcRas.getDataElements(x, y, data);
 | 
						|
                    if (filter) {
 | 
						|
                        int nextx, nexty;
 | 
						|
                        if ((nextx = x + 1) >= bWidth) {
 | 
						|
                            nextx = 0;
 | 
						|
                        }
 | 
						|
                        if ((nexty = y + 1) >= bHeight) {
 | 
						|
                            nexty = 0;
 | 
						|
                        }
 | 
						|
                        rgbs[0] = colorModel.getRGB(data);
 | 
						|
                        data = srcRas.getDataElements(nextx, y, data);
 | 
						|
                        rgbs[1] = colorModel.getRGB(data);
 | 
						|
                        data = srcRas.getDataElements(x, nexty, data);
 | 
						|
                        rgbs[2] = colorModel.getRGB(data);
 | 
						|
                        data = srcRas.getDataElements(nextx, nexty, data);
 | 
						|
                        rgbs[3] = colorModel.getRGB(data);
 | 
						|
                        int rgb =
 | 
						|
                            TexturePaintContext.blend(rgbs, xerr, yerr);
 | 
						|
                        data = colorModel.getDataElements(rgb, data);
 | 
						|
                    }
 | 
						|
                    outRas.setDataElements(i, j, data);
 | 
						|
                    if ((xerr += colincxerr) < 0) {
 | 
						|
                        xerr &= Integer.MAX_VALUE;
 | 
						|
                        x++;
 | 
						|
                    }
 | 
						|
                    if ((x += colincx) >= bWidth) {
 | 
						|
                        x -= bWidth;
 | 
						|
                    }
 | 
						|
                    if ((yerr += colincyerr) < 0) {
 | 
						|
                        yerr &= Integer.MAX_VALUE;
 | 
						|
                        y++;
 | 
						|
                    }
 | 
						|
                    if ((y += colincy) >= bHeight) {
 | 
						|
                        y -= bHeight;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if ((rowxerr += rowincxerr) < 0) {
 | 
						|
                    rowxerr &= Integer.MAX_VALUE;
 | 
						|
                    rowx++;
 | 
						|
                }
 | 
						|
                if ((rowx += rowincx) >= bWidth) {
 | 
						|
                    rowx -= bWidth;
 | 
						|
                }
 | 
						|
                if ((rowyerr += rowincyerr) < 0) {
 | 
						|
                    rowyerr &= Integer.MAX_VALUE;
 | 
						|
                    rowy++;
 | 
						|
                }
 | 
						|
                if ((rowy += rowincy) >= bHeight) {
 | 
						|
                    rowy -= bHeight;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |