View Javadoc
1   /*
2    * Copyright (c) 1997, 2002, 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.pipe;
27  
28  import java.lang.ref.WeakReference;
29  import java.awt.Rectangle;
30  import java.awt.Shape;
31  import java.awt.PaintContext;
32  import java.awt.Transparency;
33  import java.awt.image.ColorModel;
34  import java.awt.image.Raster;
35  import java.awt.image.WritableRaster;
36  import java.awt.image.BufferedImage;
37  import sun.awt.image.BufImgSurfaceData;
38  import sun.java2d.SunGraphics2D;
39  import sun.java2d.SurfaceData;
40  import sun.java2d.loops.Blit;
41  import sun.java2d.loops.MaskBlit;
42  import sun.java2d.loops.CompositeType;
43  import sun.java2d.loops.GraphicsPrimitiveMgr;
44  
45  /**
46   * This class implements a CompositePipe that renders path alpha tiles
47   * into a destination according to the Composite attribute of a
48   * SunGraphics2D.
49   */
50  public class AlphaPaintPipe implements CompositePipe {
51      static WeakReference cachedLastRaster;
52      static WeakReference cachedLastColorModel;
53      static WeakReference cachedLastData;
54  
55      static class TileContext {
56          SunGraphics2D sunG2D;
57          PaintContext paintCtxt;
58          ColorModel paintModel;
59          WeakReference lastRaster;
60          WeakReference lastData;
61          MaskBlit lastMask;
62          Blit     lastBlit;
63          SurfaceData dstData;
64  
65          public TileContext(SunGraphics2D sg, PaintContext pc) {
66              sunG2D = sg;
67              paintCtxt = pc;
68              paintModel = pc.getColorModel();
69              dstData = sg.getSurfaceData();
70              synchronized (AlphaPaintPipe.class) {
71                  if (cachedLastColorModel != null &&
72                      cachedLastColorModel.get() == paintModel)
73                  {
74                      this.lastRaster = cachedLastRaster;
75                      this.lastData = cachedLastData;
76                  }
77              }
78          }
79      }
80  
81      public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
82                                  int[] abox) {
83          PaintContext paintContext =
84              sg.paint.createContext(sg.getDeviceColorModel(),
85                                     devR,
86                                     s.getBounds2D(),
87                                     sg.cloneTransform(),
88                                     sg.getRenderingHints());
89          return new TileContext(sg, paintContext);
90      }
91  
92      public boolean needTile(Object context, int x, int y, int w, int h) {
93          return true;
94      }
95  
96      private static final int TILE_SIZE = 32;
97  
98      public void renderPathTile(Object ctx,
99                                 byte[] atile, int offset, int tilesize,
100                                int x, int y, int w, int h) {
101         TileContext context = (TileContext) ctx;
102         PaintContext paintCtxt = context.paintCtxt;
103         SunGraphics2D sg = context.sunG2D;
104         SurfaceData dstData = context.dstData;
105         SurfaceData srcData = null;
106         Raster lastRas = null;
107         if (context.lastData != null && context.lastRaster != null) {
108             srcData = (SurfaceData) context.lastData.get();
109             lastRas = (Raster) context.lastRaster.get();
110             if (srcData == null || lastRas == null) {
111                 srcData = null;
112                 lastRas = null;
113             }
114         }
115         ColorModel paintModel = context.paintModel;
116 
117         for (int rely = 0; rely < h; rely += TILE_SIZE) {
118             int ty = y + rely;
119             int th = Math.min(h-rely, TILE_SIZE);
120             for (int relx = 0; relx < w; relx += TILE_SIZE) {
121                 int tx = x + relx;
122                 int tw = Math.min(w-relx, TILE_SIZE);
123 
124                 Raster srcRaster = paintCtxt.getRaster(tx, ty, tw, th);
125                 if ((srcRaster.getMinX() != 0) || (srcRaster.getMinY() != 0)) {
126                     srcRaster = srcRaster.createTranslatedChild(0, 0);
127                 }
128                 if (lastRas != srcRaster) {
129                     lastRas = srcRaster;
130                     context.lastRaster = new WeakReference(lastRas);
131                     // REMIND: This will fail for a non-Writable raster!
132                     BufferedImage bImg =
133                         new BufferedImage(paintModel,
134                                           (WritableRaster) srcRaster,
135                                           paintModel.isAlphaPremultiplied(),
136                                           null);
137                     srcData = BufImgSurfaceData.createData(bImg);
138                     context.lastData = new WeakReference(srcData);
139                     context.lastMask = null;
140                     context.lastBlit = null;
141                 }
142 
143                 if (atile == null) {
144                     if (context.lastBlit == null) {
145                         CompositeType comptype = sg.imageComp;
146                         if (CompositeType.SrcOverNoEa.equals(comptype) &&
147                             paintModel.getTransparency() == Transparency.OPAQUE)
148                         {
149                             comptype = CompositeType.SrcNoEa;
150                         }
151                         context.lastBlit =
152                             Blit.getFromCache(srcData.getSurfaceType(),
153                                               comptype,
154                                               dstData.getSurfaceType());
155                     }
156                     context.lastBlit.Blit(srcData, dstData,
157                                           sg.composite, null,
158                                           0, 0, tx, ty, tw, th);
159                 } else {
160                     if (context.lastMask == null) {
161                         CompositeType comptype = sg.imageComp;
162                         if (CompositeType.SrcOverNoEa.equals(comptype) &&
163                             paintModel.getTransparency() == Transparency.OPAQUE)
164                         {
165                             comptype = CompositeType.SrcNoEa;
166                         }
167                         context.lastMask =
168                             MaskBlit.getFromCache(srcData.getSurfaceType(),
169                                                   comptype,
170                                                   dstData.getSurfaceType());
171                     }
172 
173                     int toff = offset + rely * tilesize + relx;
174                     context.lastMask.MaskBlit(srcData, dstData,
175                                               sg.composite, null,
176                                               0, 0, tx, ty, tw, th,
177                                               atile, toff, tilesize);
178                 }
179             }
180         }
181     }
182 
183     public void skipTile(Object context, int x, int y) {
184         return;
185     }
186 
187     public void endSequence(Object ctx) {
188         TileContext context = (TileContext) ctx;
189         if (context.paintCtxt != null) {
190             context.paintCtxt.dispose();
191         }
192         synchronized (AlphaPaintPipe.class) {
193             if (context.lastData != null) {
194                 cachedLastRaster = context.lastRaster;
195                 if (cachedLastColorModel == null ||
196                     cachedLastColorModel.get() != context.paintModel)
197                 {
198                     // Avoid creating new WeakReference if possible
199                     cachedLastColorModel =
200                         new WeakReference(context.paintModel);
201                 }
202                 cachedLastData = context.lastData;
203             }
204         }
205     }
206 }