View Javadoc
1   /*
2    * Copyright (c) 1999, 2013, 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  import sun.java2d.pipe.Region;
40  
41  /**
42   * MaskFill
43   * 1) fills rectangles of pixels on a surface
44   * 2) performs compositing of colors based upon a Composite
45   *    parameter
46   * 3) blends result of composite with destination using an
47   *    alpha coverage mask
48   * 4) the mask may be null in which case it should be treated
49   *    as if it were an array of all opaque values (0xff)
50   */
51  public class MaskFill extends GraphicsPrimitive
52  {
53      public static final String methodSignature = "MaskFill(...)".toString();
54      public static final String fillPgramSignature =
55          "FillAAPgram(...)".toString();
56      public static final String drawPgramSignature =
57          "DrawAAPgram(...)".toString();
58  
59      public static final int primTypeID = makePrimTypeID();
60  
61      private static RenderCache fillcache = new RenderCache(10);
62  
63      public static MaskFill locate(SurfaceType srctype,
64                                    CompositeType comptype,
65                                    SurfaceType dsttype)
66      {
67          return (MaskFill)
68              GraphicsPrimitiveMgr.locate(primTypeID,
69                                          srctype, comptype, dsttype);
70      }
71  
72      public static MaskFill locatePrim(SurfaceType srctype,
73                                        CompositeType comptype,
74                                        SurfaceType dsttype)
75      {
76          return (MaskFill)
77              GraphicsPrimitiveMgr.locatePrim(primTypeID,
78                                              srctype, comptype, dsttype);
79      }
80  
81      /*
82       * Note that this uses locatePrim, not locate, so it can return
83       * null if there is no specific loop to handle this op...
84       */
85      public static MaskFill getFromCache(SurfaceType src,
86                                          CompositeType comp,
87                                          SurfaceType dst)
88      {
89          Object o = fillcache.get(src, comp, dst);
90          if (o != null) {
91              return (MaskFill) o;
92          }
93          MaskFill fill = locatePrim(src, comp, dst);
94          if (fill != null) {
95              fillcache.put(src, comp, dst, fill);
96          }
97          return fill;
98      }
99  
100     protected MaskFill(String alternateSignature,
101                        SurfaceType srctype,
102                        CompositeType comptype,
103                        SurfaceType dsttype)
104     {
105         super(alternateSignature, primTypeID, srctype, comptype, dsttype);
106     }
107 
108     protected MaskFill(SurfaceType srctype,
109                        CompositeType comptype,
110                        SurfaceType dsttype)
111     {
112         super(methodSignature, primTypeID, srctype, comptype, dsttype);
113     }
114 
115     public MaskFill(long pNativePrim,
116                     SurfaceType srctype,
117                     CompositeType comptype,
118                     SurfaceType dsttype)
119     {
120         super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
121     }
122 
123     /**
124      * All MaskFill implementors must have this invoker method
125      */
126     public native void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
127                                 Composite comp,
128                                 int x, int y, int w, int h,
129                                 byte[] mask, int maskoff, int maskscan);
130 
131     public native void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
132                                    Composite comp,
133                                    double x, double y,
134                                    double dx1, double dy1,
135                                    double dx2, double dy2);
136 
137     public native void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
138                                    Composite comp,
139                                    double x, double y,
140                                    double dx1, double dy1,
141                                    double dx2, double dy2,
142                                    double lw1, double lw2);
143 
144     public boolean canDoParallelograms() {
145         return (getNativePrim() != 0);
146     }
147 
148     static {
149         GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null));
150     }
151 
152     public GraphicsPrimitive makePrimitive(SurfaceType srctype,
153                                            CompositeType comptype,
154                                            SurfaceType dsttype)
155     {
156         if (SurfaceType.OpaqueColor.equals(srctype) ||
157             SurfaceType.AnyColor.equals(srctype))
158         {
159             if (CompositeType.Xor.equals(comptype)) {
160                 throw new InternalError("Cannot construct MaskFill for " +
161                                         "XOR mode");
162             } else {
163                 return new General(srctype, comptype, dsttype);
164             }
165         } else {
166             throw new InternalError("MaskFill can only fill with colors");
167         }
168     }
169 
170     private static class General extends MaskFill {
171         FillRect fillop;
172         MaskBlit maskop;
173 
174         public General(SurfaceType srctype,
175                        CompositeType comptype,
176                        SurfaceType dsttype)
177         {
178             super(srctype, comptype, dsttype);
179             fillop = FillRect.locate(srctype,
180                                      CompositeType.SrcNoEa,
181                                      SurfaceType.IntArgb);
182             maskop = MaskBlit.locate(SurfaceType.IntArgb, comptype, dsttype);
183         }
184 
185         public void MaskFill(SunGraphics2D sg2d,
186                              SurfaceData sData,
187                              Composite comp,
188                              int x, int y, int w, int h,
189                              byte mask[], int offset, int scan)
190         {
191             BufferedImage dstBI =
192                 new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
193             SurfaceData tmpData = BufImgSurfaceData.createData(dstBI);
194 
195             // REMIND: This is not pretty.  It would be nicer if we
196             // passed a "FillData" object to the Pixel loops, instead
197             // of a SunGraphics2D parameter...
198             Region clip = sg2d.clipRegion;
199             sg2d.clipRegion = null;
200             int pixel = sg2d.pixel;
201             sg2d.pixel = tmpData.pixelFor(sg2d.getColor());
202             fillop.FillRect(sg2d, tmpData, 0, 0, w, h);
203             sg2d.pixel = pixel;
204             sg2d.clipRegion = clip;
205 
206             maskop.MaskBlit(tmpData, sData, comp, null,
207                             0, 0, x, y, w, h,
208                             mask, offset, scan);
209         }
210     }
211 
212     public GraphicsPrimitive traceWrap() {
213         return new TraceMaskFill(this);
214     }
215 
216     private static class TraceMaskFill extends MaskFill {
217         MaskFill target;
218         MaskFill fillPgramTarget;
219         MaskFill drawPgramTarget;
220 
221         public TraceMaskFill(MaskFill target) {
222             super(target.getSourceType(),
223                   target.getCompositeType(),
224                   target.getDestType());
225             this.target = target;
226             this.fillPgramTarget = new MaskFill(fillPgramSignature,
227                                                 target.getSourceType(),
228                                                 target.getCompositeType(),
229                                                 target.getDestType());
230             this.drawPgramTarget = new MaskFill(drawPgramSignature,
231                                                 target.getSourceType(),
232                                                 target.getCompositeType(),
233                                                 target.getDestType());
234         }
235 
236         public GraphicsPrimitive traceWrap() {
237             return this;
238         }
239 
240         public void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
241                              Composite comp,
242                              int x, int y, int w, int h,
243                              byte[] mask, int maskoff, int maskscan)
244         {
245             tracePrimitive(target);
246             target.MaskFill(sg2d, sData, comp, x, y, w, h,
247                             mask, maskoff, maskscan);
248         }
249 
250         public void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
251                                 Composite comp,
252                                 double x, double y,
253                                 double dx1, double dy1,
254                                 double dx2, double dy2)
255         {
256             tracePrimitive(fillPgramTarget);
257             target.FillAAPgram(sg2d, sData, comp,
258                                x, y, dx1, dy1, dx2, dy2);
259         }
260 
261         public void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
262                                 Composite comp,
263                                 double x, double y,
264                                 double dx1, double dy1,
265                                 double dx2, double dy2,
266                                 double lw1, double lw2)
267         {
268             tracePrimitive(drawPgramTarget);
269             target.DrawAAPgram(sg2d, sData, comp,
270                                x, y, dx1, dy1, dx2, dy2, lw1, lw2);
271         }
272 
273         public boolean canDoParallelograms() {
274             return target.canDoParallelograms();
275         }
276     }
277 }