View Javadoc
1   /*
2    * Copyright (c) 1999, 2011, 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.CompositeContext;
30  import java.awt.RenderingHints;
31  import java.awt.image.ColorModel;
32  import java.awt.image.Raster;
33  import java.awt.image.WritableRaster;
34  import java.lang.ref.WeakReference;
35  import sun.java2d.loops.GraphicsPrimitive;
36  import sun.java2d.SurfaceData;
37  import sun.java2d.pipe.Region;
38  import sun.java2d.pipe.SpanIterator;
39  
40  /**
41   * Blit
42   * 1) copies rectangle of pixels from one surface to another
43   * 2) performs compositing of colors based upon a Composite
44   *    parameter
45   *
46   * precise behavior is undefined if the source surface
47   * and the destination surface are the same surface
48   * with overlapping regions of pixels
49   */
50  
51  public class Blit extends GraphicsPrimitive
52  {
53      public static final String methodSignature = "Blit(...)".toString();
54  
55      public static final int primTypeID = makePrimTypeID();
56  
57      private static RenderCache blitcache = new RenderCache(20);
58  
59      public static Blit locate(SurfaceType srctype,
60                                CompositeType comptype,
61                                SurfaceType dsttype)
62      {
63          return (Blit)
64              GraphicsPrimitiveMgr.locate(primTypeID,
65                                          srctype, comptype, dsttype);
66      }
67  
68      public static Blit getFromCache(SurfaceType src,
69                                      CompositeType comp,
70                                      SurfaceType dst)
71      {
72          Object o = blitcache.get(src, comp, dst);
73          if (o != null) {
74              return (Blit) o;
75          }
76  
77          Blit blit = locate(src, comp, dst);
78          if (blit == null) {
79              System.out.println("blit loop not found for:");
80              System.out.println("src:  "+src);
81              System.out.println("comp: "+comp);
82              System.out.println("dst:  "+dst);
83          } else {
84              blitcache.put(src, comp, dst, blit);
85          }
86          return blit;
87      }
88  
89      protected Blit(SurfaceType srctype,
90                     CompositeType comptype,
91                     SurfaceType dsttype)
92      {
93          super(methodSignature, primTypeID, srctype, comptype, dsttype);
94      }
95  
96      public Blit(long pNativePrim,
97                  SurfaceType srctype,
98                  CompositeType comptype,
99                  SurfaceType dsttype)
100     {
101         super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
102     }
103 
104     /**
105      * All Blit implementors must have this invoker method
106      */
107     public native void Blit(SurfaceData src, SurfaceData dst,
108                             Composite comp, Region clip,
109                             int srcx, int srcy,
110                             int dstx, int dsty,
111                             int width, int height);
112 
113     static {
114         GraphicsPrimitiveMgr.registerGeneral(new Blit(null, null, null));
115     }
116 
117     public GraphicsPrimitive makePrimitive(SurfaceType srctype,
118                                            CompositeType comptype,
119                                            SurfaceType dsttype)
120     {
121         /*
122         System.out.println("Constructing general blit for:");
123         System.out.println("src:  "+srctype);
124         System.out.println("comp: "+comptype);
125         System.out.println("dst:  "+dsttype);
126         */
127 
128         if (comptype.isDerivedFrom(CompositeType.Xor)) {
129             GeneralXorBlit gxb = new GeneralXorBlit(srctype,
130                                                     comptype,
131                                                     dsttype);
132             setupGeneralBinaryOp(gxb);
133             return gxb;
134         } else if (comptype.isDerivedFrom(CompositeType.AnyAlpha)) {
135             return new GeneralMaskBlit(srctype, comptype, dsttype);
136         } else {
137             return AnyBlit.instance;
138         }
139     }
140 
141     private static class AnyBlit extends Blit {
142         public static AnyBlit instance = new AnyBlit();
143 
144         public AnyBlit() {
145             super(SurfaceType.Any, CompositeType.Any, SurfaceType.Any);
146         }
147 
148         public void Blit(SurfaceData srcData,
149                          SurfaceData dstData,
150                          Composite comp,
151                          Region clip,
152                          int srcx, int srcy,
153                          int dstx, int dsty,
154                          int width, int height)
155         {
156             ColorModel srcCM = srcData.getColorModel();
157             ColorModel dstCM = dstData.getColorModel();
158             // REMIND: Should get RenderingHints from sg2d
159             CompositeContext ctx = comp.createContext(srcCM, dstCM,
160                                                       new RenderingHints(null));
161             Raster srcRas = srcData.getRaster(srcx, srcy, width, height);
162             WritableRaster dstRas =
163                 (WritableRaster) dstData.getRaster(dstx, dsty, width, height);
164 
165             if (clip == null) {
166                 clip = Region.getInstanceXYWH(dstx, dsty, width, height);
167             }
168             int span[] = {dstx, dsty, dstx+width, dsty+height};
169             SpanIterator si = clip.getSpanIterator(span);
170             srcx -= dstx;
171             srcy -= dsty;
172             while (si.nextSpan(span)) {
173                 int w = span[2] - span[0];
174                 int h = span[3] - span[1];
175                 Raster tmpSrcRas = srcRas.createChild(srcx + span[0], srcy + span[1],
176                                                       w, h, 0, 0, null);
177                 WritableRaster tmpDstRas = dstRas.createWritableChild(span[0], span[1],
178                                                                       w, h, 0, 0, null);
179                 ctx.compose(tmpSrcRas, tmpDstRas, tmpDstRas);
180             }
181             ctx.dispose();
182         }
183     }
184 
185     private static class GeneralMaskBlit extends Blit {
186         MaskBlit performop;
187 
188         public GeneralMaskBlit(SurfaceType srctype,
189                                CompositeType comptype,
190                                SurfaceType dsttype)
191         {
192             super(srctype, comptype, dsttype);
193             performop = MaskBlit.locate(srctype, comptype, dsttype);
194         }
195 
196         public void Blit(SurfaceData srcData,
197                          SurfaceData dstData,
198                          Composite comp,
199                          Region clip,
200                          int srcx, int srcy,
201                          int dstx, int dsty,
202                          int width, int height)
203         {
204             performop.MaskBlit(srcData, dstData, comp, clip,
205                                srcx, srcy, dstx, dsty,
206                                width, height,
207                                null, 0, 0);
208         }
209     }
210 
211     private static class GeneralXorBlit
212         extends Blit
213         implements GeneralBinaryOp
214     {
215         Blit convertsrc;
216         Blit convertdst;
217         Blit performop;
218         Blit convertresult;
219 
220         WeakReference srcTmp;
221         WeakReference dstTmp;
222 
223         public GeneralXorBlit(SurfaceType srctype,
224                               CompositeType comptype,
225                               SurfaceType dsttype)
226         {
227             super(srctype, comptype, dsttype);
228         }
229 
230         public void setPrimitives(Blit srcconverter,
231                                   Blit dstconverter,
232                                   GraphicsPrimitive genericop,
233                                   Blit resconverter)
234         {
235             this.convertsrc = srcconverter;
236             this.convertdst = dstconverter;
237             this.performop = (Blit) genericop;
238             this.convertresult = resconverter;
239         }
240 
241         public synchronized void Blit(SurfaceData srcData,
242                                       SurfaceData dstData,
243                                       Composite comp,
244                                       Region clip,
245                                       int srcx, int srcy,
246                                       int dstx, int dsty,
247                                       int width, int height)
248         {
249             SurfaceData src, dst;
250             Region opclip;
251             int sx, sy, dx, dy;
252 
253             if (convertsrc == null) {
254                 src = srcData;
255                 sx = srcx;
256                 sy = srcy;
257             } else {
258                 SurfaceData cachedSrc = null;
259                 if (srcTmp != null) {
260                     cachedSrc = (SurfaceData) srcTmp.get();
261                 }
262                 src = convertFrom(convertsrc, srcData, srcx, srcy,
263                                   width, height, cachedSrc);
264                 sx = 0;
265                 sy = 0;
266                 if (src != cachedSrc) {
267                     srcTmp = new WeakReference(src);
268                 }
269             }
270 
271             if (convertdst == null) {
272                 dst = dstData;
273                 dx = dstx;
274                 dy = dsty;
275                 opclip = clip;
276             } else {
277                 // assert: convertresult != null
278                 SurfaceData cachedDst = null;
279                 if (dstTmp != null) {
280                     cachedDst = (SurfaceData) dstTmp.get();
281                 }
282                 dst = convertFrom(convertdst, dstData, dstx, dsty,
283                                   width, height, cachedDst);
284                 dx = 0;
285                 dy = 0;
286                 opclip = null;
287                 if (dst != cachedDst) {
288                     dstTmp = new WeakReference(dst);
289                 }
290             }
291 
292             performop.Blit(src, dst, comp, opclip,
293                            sx, sy, dx, dy,
294                            width, height);
295 
296             if (convertresult != null) {
297                 // assert: convertdst != null
298                 convertTo(convertresult, dst, dstData, clip,
299                           dstx, dsty, width, height);
300             }
301         }
302     }
303 
304     public GraphicsPrimitive traceWrap() {
305         return new TraceBlit(this);
306     }
307 
308     private static class TraceBlit extends Blit {
309         Blit target;
310 
311         public TraceBlit(Blit target) {
312             super(target.getSourceType(),
313                   target.getCompositeType(),
314                   target.getDestType());
315             this.target = target;
316         }
317 
318         public GraphicsPrimitive traceWrap() {
319             return this;
320         }
321 
322         public void Blit(SurfaceData src, SurfaceData dst,
323                          Composite comp, Region clip,
324                          int srcx, int srcy, int dstx, int dsty,
325                          int width, int height)
326         {
327             tracePrimitive(target);
328             target.Blit(src, dst, comp, clip,
329                         srcx, srcy, dstx, dsty, width, height);
330         }
331     }
332 }