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