| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
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  | 
 | 
                  | 
 | 
                num = 0;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return num;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public void dispose() { | 
 | 
        dropRaster(colorModel, outRas);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public ColorModel getColorModel() { | 
 | 
        return colorModel;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Raster getRaster(int x, int y, int w, int h) { | 
 | 
        if (outRas == null ||  | 
 | 
            outRas.getWidth() < w ||  | 
 | 
            outRas.getHeight() < h)  | 
 | 
        { | 
 | 
              | 
 | 
            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 (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 (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 (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);  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static int blend(int rgbs[], int xmul, int ymul) { | 
 | 
        // xmul/ymul are 31 bits wide, (0 => 2^31-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  | 
 | 
              | 
 | 
            xmul = (1<<12) - xmul;  | 
 | 
            if ((i & 1) == 0) { | 
 | 
                ymul = (1<<12) - ymul;  | 
 | 
            }  | 
 | 
            // xmul and ymul are each 12 bits (0 => 2^12)  | 
 | 
              | 
 | 
            int factor = xmul * ymul;  | 
 | 
            if (factor != 0) { | 
 | 
                // accum variables will accumulate 32 bits  | 
 | 
                // bytes extracted from rgb fit in 8 bits (0 => 255)  | 
 | 
                  | 
 | 
                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  | 
 | 
              | 
 | 
            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;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |