1 /*
   2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.loops;
  27 
  28 import java.awt.Paint;
  29 import java.awt.PaintContext;
  30 import java.awt.Composite;
  31 import java.awt.Rectangle;
  32 import java.awt.image.ColorModel;
  33 import java.awt.image.BufferedImage;
  34 import java.awt.image.WritableRaster;
  35 import sun.awt.image.BufImgSurfaceData;
  36 import sun.java2d.loops.GraphicsPrimitive;
  37 import sun.java2d.SunGraphics2D;
  38 import sun.java2d.SurfaceData;
  39 
  40 /**
  41  * MaskFill
  42  * 1) fills rectangles of pixels on a surface
  43  * 2) performs compositing of colors based upon a Composite
  44  *    parameter
  45  * 3) blends result of composite with destination using an
  46  *    alpha coverage mask
  47  * 4) the mask may be null in which case it should be treated
  48  *    as if it were an array of all opaque values (0xff)
  49  */
  50 public class MaskFill extends GraphicsPrimitive
  51 {
  52     public static final String methodSignature = "MaskFill(...)".toString();
  53     public static final String fillPgramSignature =
  54         "FillAAPgram(...)".toString();
  55     public static final String drawPgramSignature =
  56         "DrawAAPgram(...)".toString();
  57 
  58     public static final int primTypeID = makePrimTypeID();
  59 
  60     private static RenderCache fillcache = new RenderCache(10);
  61 
  62     public static MaskFill locate(SurfaceType srctype,
  63                                   CompositeType comptype,
  64                                   SurfaceType dsttype)
  65     {
  66         return (MaskFill)
  67             GraphicsPrimitiveMgr.locate(primTypeID,
  68                                         srctype, comptype, dsttype);
  69     }
  70 
  71     public static MaskFill locatePrim(SurfaceType srctype,
  72                                       CompositeType comptype,
  73                                       SurfaceType dsttype)
  74     {
  75         return (MaskFill)
  76             GraphicsPrimitiveMgr.locatePrim(primTypeID,
  77                                             srctype, comptype, dsttype);
  78     }
  79 
  80     /*
  81      * Note that this uses locatePrim, not locate, so it can return
  82      * null if there is no specific loop to handle this op...
  83      */
  84     public static MaskFill getFromCache(SurfaceType src,
  85                                         CompositeType comp,
  86                                         SurfaceType dst)
  87     {
  88         Object o = fillcache.get(src, comp, dst);
  89         if (o != null) {
  90             return (MaskFill) o;
  91         }
  92         MaskFill fill = locatePrim(src, comp, dst);
  93         if (fill != null) {
  94             fillcache.put(src, comp, dst, fill);
  95         }
  96         return fill;
  97     }
  98 
  99     protected MaskFill(String alternateSignature,
 100                        SurfaceType srctype,
 101                        CompositeType comptype,
 102                        SurfaceType dsttype)
 103     {
 104         super(alternateSignature, primTypeID, srctype, comptype, dsttype);
 105     }
 106 
 107     protected MaskFill(SurfaceType srctype,
 108                        CompositeType comptype,
 109                        SurfaceType dsttype)
 110     {
 111         super(methodSignature, primTypeID, srctype, comptype, dsttype);
 112     }
 113 
 114     public MaskFill(long pNativePrim,
 115                     SurfaceType srctype,
 116                     CompositeType comptype,
 117                     SurfaceType dsttype)
 118     {
 119         super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
 120     }
 121 
 122     /**
 123      * All MaskFill implementors must have this invoker method
 124      */
 125     public native void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
 126                                 Composite comp,
 127                                 int x, int y, int w, int h,
 128                                 byte[] mask, int maskoff, int maskscan);
 129 
 130     public native void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
 131                                    Composite comp,
 132                                    double x, double y,
 133                                    double dx1, double dy1,
 134                                    double dx2, double dy2);
 135 
 136     public native void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
 137                                    Composite comp,
 138                                    double x, double y,
 139                                    double dx1, double dy1,
 140                                    double dx2, double dy2,
 141                                    double lw1, double lw2);
 142 
 143     public boolean canDoParallelograms() {
 144         return (getNativePrim() != 0);
 145     }
 146 
 147     static {
 148         GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null));
 149     }
 150 
 151     public GraphicsPrimitive makePrimitive(SurfaceType srctype,
 152                                            CompositeType comptype,
 153                                            SurfaceType dsttype)
 154     {
 155         if (SurfaceType.OpaqueColor.equals(srctype) ||
 156             SurfaceType.AnyColor.equals(srctype))
 157         {
 158             if (CompositeType.Xor.equals(comptype)) {
 159                 throw new InternalError("Cannot construct MaskFill for " +
 160                                         "XOR mode");
 161             } else {
 162                 return new General(srctype, comptype, dsttype);
 163             }
 164         } else {
 165             throw new InternalError("MaskFill can only fill with colors");
 166         }
 167     }
 168 
 169     private static class General extends MaskFill {
 170         FillRect fillop;
 171         MaskBlit maskop;
 172 
 173         public General(SurfaceType srctype,
 174                        CompositeType comptype,
 175                        SurfaceType dsttype)
 176         {
 177             super(srctype, comptype, dsttype);
 178             fillop = FillRect.locate(srctype,
 179                                      CompositeType.SrcNoEa,
 180                                      SurfaceType.IntArgb);
 181             maskop = MaskBlit.locate(SurfaceType.IntArgb, comptype, dsttype);
 182         }
 183 
 184         public void MaskFill(SunGraphics2D sg2d,
 185                              SurfaceData sData,
 186                              Composite comp,
 187                              int x, int y, int w, int h,
 188                              byte mask[], int offset, int scan)
 189         {
 190             BufferedImage dstBI =
 191                 new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
 192             SurfaceData tmpData = BufImgSurfaceData.createData(dstBI);
 193 
 194             // REMIND: This is not pretty.  It would be nicer if we
 195             // passed a "FillData" object to the Pixel loops, instead
 196             // of a SunGraphics2D parameter...
 197             int pixel = sg2d.pixel;
 198             sg2d.pixel = tmpData.pixelFor(sg2d.getColor());
 199             fillop.FillRect(sg2d, tmpData, 0, 0, w, h);
 200             sg2d.pixel = pixel;
 201 
 202             maskop.MaskBlit(tmpData, sData, comp, null,
 203                             0, 0, x, y, w, h,
 204                             mask, offset, scan);
 205         }
 206     }
 207 
 208     public GraphicsPrimitive traceWrap() {
 209         return new TraceMaskFill(this);
 210     }
 211 
 212     private static class TraceMaskFill extends MaskFill {
 213         MaskFill target;
 214         MaskFill fillPgramTarget;
 215         MaskFill drawPgramTarget;
 216 
 217         public TraceMaskFill(MaskFill target) {
 218             super(target.getSourceType(),
 219                   target.getCompositeType(),
 220                   target.getDestType());
 221             this.target = target;
 222             this.fillPgramTarget = new MaskFill(fillPgramSignature,
 223                                                 target.getSourceType(),
 224                                                 target.getCompositeType(),
 225                                                 target.getDestType());
 226             this.drawPgramTarget = new MaskFill(drawPgramSignature,
 227                                                 target.getSourceType(),
 228                                                 target.getCompositeType(),
 229                                                 target.getDestType());
 230         }
 231 
 232         public GraphicsPrimitive traceWrap() {
 233             return this;
 234         }
 235 
 236         public void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
 237                              Composite comp,
 238                              int x, int y, int w, int h,
 239                              byte[] mask, int maskoff, int maskscan)
 240         {
 241             tracePrimitive(target);
 242             target.MaskFill(sg2d, sData, comp, x, y, w, h,
 243                             mask, maskoff, maskscan);
 244         }
 245 
 246         public void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
 247                                 Composite comp,
 248                                 double x, double y,
 249                                 double dx1, double dy1,
 250                                 double dx2, double dy2)
 251         {
 252             tracePrimitive(fillPgramTarget);
 253             target.FillAAPgram(sg2d, sData, comp,
 254                                x, y, dx1, dy1, dx2, dy2);
 255         }
 256 
 257         public void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
 258                                 Composite comp,
 259                                 double x, double y,
 260                                 double dx1, double dy1,
 261                                 double dx2, double dy2,
 262                                 double lw1, double lw2)
 263         {
 264             tracePrimitive(drawPgramTarget);
 265             target.DrawAAPgram(sg2d, sData, comp,
 266                                x, y, dx1, dy1, dx2, dy2, lw1, lw2);
 267         }
 268 
 269         public boolean canDoParallelograms() {
 270             return target.canDoParallelograms();
 271         }
 272     }
 273 }