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 }