View Javadoc
1   /*
2    * Copyright (c) 1999, 2004, 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.lang.ref.WeakReference;
30  import sun.java2d.loops.GraphicsPrimitive;
31  import sun.java2d.SurfaceData;
32  import sun.java2d.pipe.Region;
33  
34  /**
35   * MaskBlit
36   * 1) copies rectangle of pixels from one surface to another
37   * 2) performs compositing of colors based upon a Composite
38   *    parameter
39   * 3) blends result of composite with destination using an
40   *    alpha coverage mask
41   * 4) the mask may be null in which case it should be treated
42   *    as if it were an array of all opaque values (0xff)
43   *
44   * precise behavior is undefined if the source surface
45   * and the destination surface are the same surface
46   * with overlapping regions of pixels
47   */
48  
49  public class MaskBlit extends GraphicsPrimitive
50  {
51      public static final String methodSignature = "MaskBlit(...)".toString();
52  
53      public static final int primTypeID = makePrimTypeID();
54  
55      private static RenderCache blitcache = new RenderCache(20);
56  
57      public static MaskBlit locate(SurfaceType srctype,
58                                    CompositeType comptype,
59                                    SurfaceType dsttype)
60      {
61          return (MaskBlit)
62              GraphicsPrimitiveMgr.locate(primTypeID,
63                                          srctype, comptype, dsttype);
64      }
65  
66      public static MaskBlit getFromCache(SurfaceType src,
67                                          CompositeType comp,
68                                          SurfaceType dst)
69      {
70          Object o = blitcache.get(src, comp, dst);
71          if (o != null) {
72              return (MaskBlit) o;
73          }
74          MaskBlit blit = locate(src, comp, dst);
75          if (blit == null) {
76              System.out.println("mask blit loop not found for:");
77              System.out.println("src:  "+src);
78              System.out.println("comp: "+comp);
79              System.out.println("dst:  "+dst);
80          } else {
81              blitcache.put(src, comp, dst, blit);
82          }
83          return blit;
84      }
85  
86      protected MaskBlit(SurfaceType srctype,
87                         CompositeType comptype,
88                         SurfaceType dsttype)
89      {
90          super(methodSignature, primTypeID, srctype, comptype, dsttype);
91      }
92  
93      public MaskBlit(long pNativePrim,
94                      SurfaceType srctype,
95                      CompositeType comptype,
96                      SurfaceType dsttype)
97      {
98          super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
99      }
100 
101     /**
102      * All MaskBlit implementors must have this invoker method
103      */
104     public native void MaskBlit(SurfaceData src, SurfaceData dst,
105                                 Composite comp, Region clip,
106                                 int srcx, int srcy,
107                                 int dstx, int dsty,
108                                 int width, int height,
109                                 byte[] mask, int maskoff, int maskscan);
110 
111     static {
112         GraphicsPrimitiveMgr.registerGeneral(new MaskBlit(null, null, null));
113     }
114 
115     public GraphicsPrimitive makePrimitive(SurfaceType srctype,
116                                            CompositeType comptype,
117                                            SurfaceType dsttype)
118     {
119         /*
120         new Throwable().printStackTrace();
121         System.out.println("Constructing general maskblit for:");
122         System.out.println("src:  "+srctype);
123         System.out.println("comp: "+comptype);
124         System.out.println("dst:  "+dsttype);
125         */
126 
127         if (CompositeType.Xor.equals(comptype)) {
128             throw new InternalError("Cannot construct MaskBlit for " +
129                                     "XOR mode");
130         }
131 
132         General ob = new General(srctype, comptype, dsttype);
133         setupGeneralBinaryOp(ob);
134         return ob;
135     }
136 
137     private static class General
138         extends MaskBlit
139         implements GeneralBinaryOp
140     {
141         Blit convertsrc;
142         Blit convertdst;
143         MaskBlit performop;
144         Blit convertresult;
145 
146         WeakReference srcTmp;
147         WeakReference dstTmp;
148 
149         public General(SurfaceType srctype,
150                        CompositeType comptype,
151                        SurfaceType dsttype)
152         {
153             super(srctype, comptype, dsttype);
154         }
155 
156         public void setPrimitives(Blit srcconverter,
157                                   Blit dstconverter,
158                                   GraphicsPrimitive genericop,
159                                   Blit resconverter)
160         {
161             this.convertsrc = srcconverter;
162             this.convertdst = dstconverter;
163             this.performop = (MaskBlit) genericop;
164             this.convertresult = resconverter;
165         }
166 
167         public synchronized void MaskBlit(SurfaceData srcData,
168                                           SurfaceData dstData,
169                                           Composite comp,
170                                           Region clip,
171                                           int srcx, int srcy,
172                                           int dstx, int dsty,
173                                           int width, int height,
174                                           byte mask[], int offset, int scan)
175         {
176             SurfaceData src, dst;
177             Region opclip;
178             int sx, sy, dx, dy;
179 
180             if (convertsrc == null) {
181                 src = srcData;
182                 sx = srcx;
183                 sy = srcy;
184             } else {
185                 SurfaceData cachedSrc = null;
186                 if (srcTmp != null) {
187                     cachedSrc = (SurfaceData) srcTmp.get();
188                 }
189                 src = convertFrom(convertsrc, srcData, srcx, srcy,
190                                   width, height, cachedSrc);
191                 sx = 0;
192                 sy = 0;
193                 if (src != cachedSrc) {
194                     srcTmp = new WeakReference(src);
195                 }
196             }
197 
198             if (convertdst == null) {
199                 dst = dstData;
200                 dx = dstx;
201                 dy = dsty;
202                 opclip = clip;
203             } else {
204                 // assert: convertresult != null
205                 SurfaceData cachedDst = null;
206                 if (dstTmp != null) {
207                     cachedDst = (SurfaceData) dstTmp.get();
208                 }
209                 dst = convertFrom(convertdst, dstData, dstx, dsty,
210                                   width, height, cachedDst);
211                 dx = 0;
212                 dy = 0;
213                 opclip = null;
214                 if (dst != cachedDst) {
215                     dstTmp = new WeakReference(dst);
216                 }
217             }
218 
219             performop.MaskBlit(src, dst, comp, opclip,
220                                sx, sy, dx, dy, width, height,
221                                mask, offset, scan);
222 
223             if (convertresult != null) {
224                 // assert: convertdst != null
225                 convertTo(convertresult, dst, dstData, clip,
226                           dstx, dsty, width, height);
227             }
228         }
229     }
230 
231     public GraphicsPrimitive traceWrap() {
232         return new TraceMaskBlit(this);
233     }
234 
235     private static class TraceMaskBlit extends MaskBlit {
236         MaskBlit target;
237 
238         public TraceMaskBlit(MaskBlit target) {
239             // We need to have the same NativePrim as our
240             // target in case we are used with a TransformHelper
241             super(target.getNativePrim(),
242                   target.getSourceType(),
243                   target.getCompositeType(),
244                   target.getDestType());
245             this.target = target;
246         }
247 
248         public GraphicsPrimitive traceWrap() {
249             return this;
250         }
251 
252         public void MaskBlit(SurfaceData src, SurfaceData dst,
253                              Composite comp, Region clip,
254                              int srcx, int srcy, int dstx, int dsty,
255                              int width, int height,
256                              byte[] mask, int maskoff, int maskscan)
257         {
258             tracePrimitive(target);
259             target.MaskBlit(src, dst, comp, clip,
260                             srcx, srcy, dstx, dsty, width, height,
261                             mask, maskoff, maskscan);
262         }
263     }
264 }