001: /*
002: * Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.java2d.pipe;
027:
028: import java.lang.ref.WeakReference;
029: import java.awt.Rectangle;
030: import java.awt.Shape;
031: import java.awt.PaintContext;
032: import java.awt.Transparency;
033: import java.awt.image.ColorModel;
034: import java.awt.image.Raster;
035: import java.awt.image.WritableRaster;
036: import java.awt.image.BufferedImage;
037: import sun.awt.image.BufImgSurfaceData;
038: import sun.java2d.SunGraphics2D;
039: import sun.java2d.SurfaceData;
040: import sun.java2d.loops.Blit;
041: import sun.java2d.loops.MaskBlit;
042: import sun.java2d.loops.CompositeType;
043: import sun.java2d.loops.GraphicsPrimitiveMgr;
044:
045: /**
046: * This class implements a CompositePipe that renders path alpha tiles
047: * into a destination according to the Composite attribute of a
048: * SunGraphics2D.
049: */
050: public class AlphaPaintPipe implements CompositePipe {
051: static WeakReference cachedLastRaster;
052: static WeakReference cachedLastColorModel;
053: static WeakReference cachedLastData;
054:
055: static class TileContext {
056: SunGraphics2D sunG2D;
057: PaintContext paintCtxt;
058: ColorModel paintModel;
059: WeakReference lastRaster;
060: WeakReference lastData;
061: MaskBlit lastMask;
062: Blit lastBlit;
063: SurfaceData dstData;
064:
065: public TileContext(SunGraphics2D sg, PaintContext pc) {
066: sunG2D = sg;
067: paintCtxt = pc;
068: paintModel = pc.getColorModel();
069: dstData = sg.getSurfaceData();
070: synchronized (AlphaPaintPipe.class) {
071: if (cachedLastColorModel != null
072: && cachedLastColorModel.get() == paintModel) {
073: this .lastRaster = cachedLastRaster;
074: this .lastData = cachedLastData;
075: }
076: }
077: }
078: }
079:
080: public Object startSequence(SunGraphics2D sg, Shape s,
081: Rectangle devR, int[] abox) {
082: PaintContext paintContext = sg.paint.createContext(sg
083: .getDeviceColorModel(), devR, s.getBounds2D(), sg
084: .cloneTransform(), sg.getRenderingHints());
085: return new TileContext(sg, paintContext);
086: }
087:
088: public boolean needTile(Object context, int x, int y, int w, int h) {
089: return true;
090: }
091:
092: private static final int TILE_SIZE = 32;
093:
094: public void renderPathTile(Object ctx, byte[] atile, int offset,
095: int tilesize, int x, int y, int w, int h) {
096: TileContext context = (TileContext) ctx;
097: PaintContext paintCtxt = context.paintCtxt;
098: SunGraphics2D sg = context.sunG2D;
099: SurfaceData dstData = context.dstData;
100: SurfaceData srcData = null;
101: Raster lastRas = null;
102: if (context.lastData != null && context.lastRaster != null) {
103: srcData = (SurfaceData) context.lastData.get();
104: lastRas = (Raster) context.lastRaster.get();
105: if (srcData == null || lastRas == null) {
106: srcData = null;
107: lastRas = null;
108: }
109: }
110: ColorModel paintModel = context.paintModel;
111:
112: for (int rely = 0; rely < h; rely += TILE_SIZE) {
113: int ty = y + rely;
114: int th = Math.min(h - rely, TILE_SIZE);
115: for (int relx = 0; relx < w; relx += TILE_SIZE) {
116: int tx = x + relx;
117: int tw = Math.min(w - relx, TILE_SIZE);
118:
119: Raster srcRaster = paintCtxt.getRaster(tx, ty, tw, th);
120: if ((srcRaster.getMinX() != 0)
121: || (srcRaster.getMinY() != 0)) {
122: srcRaster = srcRaster.createTranslatedChild(0, 0);
123: }
124: if (lastRas != srcRaster) {
125: lastRas = srcRaster;
126: context.lastRaster = new WeakReference(lastRas);
127: // REMIND: This will fail for a non-Writable raster!
128: BufferedImage bImg = new BufferedImage(paintModel,
129: (WritableRaster) srcRaster, paintModel
130: .isAlphaPremultiplied(), null);
131: srcData = BufImgSurfaceData.createData(bImg);
132: context.lastData = new WeakReference(srcData);
133: context.lastMask = null;
134: context.lastBlit = null;
135: }
136:
137: if (atile == null) {
138: if (context.lastBlit == null) {
139: CompositeType comptype = sg.imageComp;
140: if (CompositeType.SrcOverNoEa.equals(comptype)
141: && paintModel.getTransparency() == Transparency.OPAQUE) {
142: comptype = CompositeType.SrcNoEa;
143: }
144: context.lastBlit = Blit.getFromCache(srcData
145: .getSurfaceType(), comptype, dstData
146: .getSurfaceType());
147: }
148: context.lastBlit.Blit(srcData, dstData,
149: sg.composite, null, 0, 0, tx, ty, tw, th);
150: } else {
151: if (context.lastMask == null) {
152: CompositeType comptype = sg.imageComp;
153: if (CompositeType.SrcOverNoEa.equals(comptype)
154: && paintModel.getTransparency() == Transparency.OPAQUE) {
155: comptype = CompositeType.SrcNoEa;
156: }
157: context.lastMask = MaskBlit.getFromCache(
158: srcData.getSurfaceType(), comptype,
159: dstData.getSurfaceType());
160: }
161:
162: int toff = offset + rely * tilesize + relx;
163: context.lastMask.MaskBlit(srcData, dstData,
164: sg.composite, null, 0, 0, tx, ty, tw, th,
165: atile, toff, tilesize);
166: }
167: }
168: }
169: }
170:
171: public void skipTile(Object context, int x, int y) {
172: return;
173: }
174:
175: public void endSequence(Object ctx) {
176: TileContext context = (TileContext) ctx;
177: if (context.paintCtxt != null) {
178: context.paintCtxt.dispose();
179: }
180: synchronized (AlphaPaintPipe.class) {
181: if (context.lastData != null) {
182: cachedLastRaster = context.lastRaster;
183: if (cachedLastColorModel == null
184: || cachedLastColorModel.get() != context.paintModel) {
185: // Avoid creating new WeakReference if possible
186: cachedLastColorModel = new WeakReference(
187: context.paintModel);
188: }
189: cachedLastData = context.lastData;
190: }
191: }
192: }
193: }
|