001: /*
002: * Copyright 1999-2007 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.awt.image;
027:
028: import java.awt.Color;
029: import java.awt.Rectangle;
030: import java.awt.GraphicsConfiguration;
031: import java.awt.image.ColorModel;
032: import java.awt.image.SampleModel;
033: import java.awt.image.DirectColorModel;
034: import java.awt.image.IndexColorModel;
035: import java.awt.image.Raster;
036: import java.awt.image.BufferedImage;
037: import java.awt.image.DataBuffer;
038:
039: import sun.java2d.SurfaceData;
040: import sun.java2d.SunGraphics2D;
041: import sun.java2d.StateTrackable;
042: import sun.java2d.StateTracker;
043: import sun.java2d.loops.SurfaceType;
044: import sun.java2d.loops.CompositeType;
045: import sun.java2d.loops.RenderLoops;
046:
047: public class BufImgSurfaceData extends SurfaceData {
048: BufferedImage bufImg;
049: private BufferedImageGraphicsConfig graphicsConfig;
050: RenderLoops solidloops;
051:
052: private static native void initIDs(Class ICM);
053:
054: private static final int DCM_RGBX_RED_MASK = 0xff000000;
055: private static final int DCM_RGBX_GREEN_MASK = 0x00ff0000;
056: private static final int DCM_RGBX_BLUE_MASK = 0x0000ff00;
057: private static final int DCM_555X_RED_MASK = 0xF800;
058: private static final int DCM_555X_GREEN_MASK = 0x07C0;
059: private static final int DCM_555X_BLUE_MASK = 0x003E;
060: private static final int DCM_4444_RED_MASK = 0x0f00;
061: private static final int DCM_4444_GREEN_MASK = 0x00f0;
062: private static final int DCM_4444_BLUE_MASK = 0x000f;
063: private static final int DCM_4444_ALPHA_MASK = 0xf000;
064: private static final int DCM_ARGBBM_ALPHA_MASK = 0x01000000;
065: private static final int DCM_ARGBBM_RED_MASK = 0x00ff0000;
066: private static final int DCM_ARGBBM_GREEN_MASK = 0x0000ff00;
067: private static final int DCM_ARGBBM_BLUE_MASK = 0x000000ff;
068:
069: static {
070: initIDs(IndexColorModel.class);
071: }
072:
073: public static SurfaceData createData(BufferedImage bufImg) {
074: if (bufImg == null) {
075: throw new NullPointerException(
076: "BufferedImage cannot be null");
077: }
078: SurfaceData sData;
079: ColorModel cm = bufImg.getColorModel();
080: int type = bufImg.getType();
081: // REMIND: Check the image type and pick an appropriate subclass
082: switch (type) {
083: case BufferedImage.TYPE_INT_BGR:
084: sData = createDataIC(bufImg, SurfaceType.IntBgr);
085: break;
086: case BufferedImage.TYPE_INT_RGB:
087: sData = createDataIC(bufImg, SurfaceType.IntRgb);
088: break;
089: case BufferedImage.TYPE_INT_ARGB:
090: sData = createDataIC(bufImg, SurfaceType.IntArgb);
091: break;
092: case BufferedImage.TYPE_INT_ARGB_PRE:
093: sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
094: break;
095: case BufferedImage.TYPE_3BYTE_BGR:
096: sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
097: break;
098: case BufferedImage.TYPE_4BYTE_ABGR:
099: sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
100: break;
101: case BufferedImage.TYPE_4BYTE_ABGR_PRE:
102: sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
103: break;
104: case BufferedImage.TYPE_USHORT_565_RGB:
105: sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
106: break;
107: case BufferedImage.TYPE_USHORT_555_RGB:
108: sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
109: break;
110: case BufferedImage.TYPE_BYTE_INDEXED: {
111: SurfaceType sType;
112: switch (cm.getTransparency()) {
113: case OPAQUE:
114: if (isOpaqueGray((IndexColorModel) cm)) {
115: sType = SurfaceType.Index8Gray;
116: } else {
117: sType = SurfaceType.ByteIndexedOpaque;
118: }
119: break;
120: case BITMASK:
121: sType = SurfaceType.ByteIndexedBm;
122: break;
123: case TRANSLUCENT:
124: sType = SurfaceType.ByteIndexed;
125: break;
126: default:
127: throw new InternalError("Unrecognized transparency");
128: }
129: sData = createDataBC(bufImg, sType, 0);
130: }
131: break;
132: case BufferedImage.TYPE_BYTE_GRAY:
133: sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
134: break;
135: case BufferedImage.TYPE_USHORT_GRAY:
136: sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
137: break;
138: case BufferedImage.TYPE_BYTE_BINARY: {
139: SurfaceType sType;
140: SampleModel sm = bufImg.getRaster().getSampleModel();
141: switch (sm.getSampleSize(0)) {
142: case 1:
143: sType = SurfaceType.ByteBinary1Bit;
144: break;
145: case 2:
146: sType = SurfaceType.ByteBinary2Bit;
147: break;
148: case 4:
149: sType = SurfaceType.ByteBinary4Bit;
150: break;
151: default:
152: throw new InternalError("Unrecognized pixel size");
153: }
154: sData = createDataBP(bufImg, sType);
155: }
156: break;
157: case BufferedImage.TYPE_CUSTOM:
158: default: {
159: Raster raster = bufImg.getRaster();
160: int numBands = raster.getNumBands();
161: if (raster instanceof IntegerComponentRaster
162: && raster.getNumDataElements() == 1
163: && ((IntegerComponentRaster) raster)
164: .getPixelStride() == 1) {
165: SurfaceType sType = SurfaceType.AnyInt;
166: if (cm instanceof DirectColorModel) {
167: DirectColorModel dcm = (DirectColorModel) cm;
168: int aMask = dcm.getAlphaMask();
169: int rMask = dcm.getRedMask();
170: int gMask = dcm.getGreenMask();
171: int bMask = dcm.getBlueMask();
172: if (numBands == 3 && aMask == 0
173: && rMask == DCM_RGBX_RED_MASK
174: && gMask == DCM_RGBX_GREEN_MASK
175: && bMask == DCM_RGBX_BLUE_MASK) {
176: sType = SurfaceType.IntRgbx;
177: } else if (numBands == 4
178: && aMask == DCM_ARGBBM_ALPHA_MASK
179: && rMask == DCM_ARGBBM_RED_MASK
180: && gMask == DCM_ARGBBM_GREEN_MASK
181: && bMask == DCM_ARGBBM_BLUE_MASK) {
182: sType = SurfaceType.IntArgbBm;
183: } else {
184: sType = SurfaceType.AnyDcm;
185: }
186: }
187: sData = createDataIC(bufImg, sType);
188: break;
189: } else if (raster instanceof ShortComponentRaster
190: && raster.getNumDataElements() == 1
191: && ((ShortComponentRaster) raster).getPixelStride() == 1) {
192: SurfaceType sType = SurfaceType.AnyShort;
193: IndexColorModel icm = null;
194: if (cm instanceof DirectColorModel) {
195: DirectColorModel dcm = (DirectColorModel) cm;
196: int aMask = dcm.getAlphaMask();
197: int rMask = dcm.getRedMask();
198: int gMask = dcm.getGreenMask();
199: int bMask = dcm.getBlueMask();
200: if (numBands == 3 && aMask == 0
201: && rMask == DCM_555X_RED_MASK
202: && gMask == DCM_555X_GREEN_MASK
203: && bMask == DCM_555X_BLUE_MASK) {
204: sType = SurfaceType.Ushort555Rgbx;
205: } else if (numBands == 4
206: && aMask == DCM_4444_ALPHA_MASK
207: && rMask == DCM_4444_RED_MASK
208: && gMask == DCM_4444_GREEN_MASK
209: && bMask == DCM_4444_BLUE_MASK) {
210: sType = SurfaceType.Ushort4444Argb;
211: }
212: } else if (cm instanceof IndexColorModel) {
213: icm = (IndexColorModel) cm;
214: if (icm.getPixelSize() == 12) {
215: if (isOpaqueGray(icm)) {
216: sType = SurfaceType.Index12Gray;
217: } else {
218: sType = SurfaceType.UshortIndexed;
219: }
220: } else {
221: icm = null;
222: }
223: }
224: sData = createDataSC(bufImg, sType, icm);
225: break;
226: }
227: sData = new BufImgSurfaceData(raster.getDataBuffer(),
228: bufImg, SurfaceType.Custom);
229: }
230: break;
231: }
232: ((BufImgSurfaceData) sData).initSolidLoops();
233: return sData;
234: }
235:
236: public static SurfaceData createData(Raster ras, ColorModel cm) {
237: throw new InternalError(
238: "SurfaceData not implemented for Raster/CM");
239: }
240:
241: public static SurfaceData createDataIC(BufferedImage bImg,
242: SurfaceType sType) {
243: IntegerComponentRaster icRaster = (IntegerComponentRaster) bImg
244: .getRaster();
245: BufImgSurfaceData bisd = new BufImgSurfaceData(icRaster
246: .getDataBuffer(), bImg, sType);
247: bisd.initRaster(icRaster.getDataStorage(), icRaster
248: .getDataOffset(0) * 4, 0, icRaster.getWidth(), icRaster
249: .getHeight(), icRaster.getPixelStride() * 4, icRaster
250: .getScanlineStride() * 4, null);
251: return bisd;
252: }
253:
254: public static SurfaceData createDataSC(BufferedImage bImg,
255: SurfaceType sType, IndexColorModel icm) {
256: ShortComponentRaster scRaster = (ShortComponentRaster) bImg
257: .getRaster();
258: BufImgSurfaceData bisd = new BufImgSurfaceData(scRaster
259: .getDataBuffer(), bImg, sType);
260: bisd.initRaster(scRaster.getDataStorage(), scRaster
261: .getDataOffset(0) * 2, 0, scRaster.getWidth(), scRaster
262: .getHeight(), scRaster.getPixelStride() * 2, scRaster
263: .getScanlineStride() * 2, icm);
264: return bisd;
265: }
266:
267: public static SurfaceData createDataBC(BufferedImage bImg,
268: SurfaceType sType, int primaryBank) {
269: ByteComponentRaster bcRaster = (ByteComponentRaster) bImg
270: .getRaster();
271: BufImgSurfaceData bisd = new BufImgSurfaceData(bcRaster
272: .getDataBuffer(), bImg, sType);
273: ColorModel cm = bImg.getColorModel();
274: IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm
275: : null);
276: bisd.initRaster(bcRaster.getDataStorage(), bcRaster
277: .getDataOffset(primaryBank), 0, bcRaster.getWidth(),
278: bcRaster.getHeight(), bcRaster.getPixelStride(),
279: bcRaster.getScanlineStride(), icm);
280: return bisd;
281: }
282:
283: public static SurfaceData createDataBP(BufferedImage bImg,
284: SurfaceType sType) {
285: BytePackedRaster bpRaster = (BytePackedRaster) bImg.getRaster();
286: BufImgSurfaceData bisd = new BufImgSurfaceData(bpRaster
287: .getDataBuffer(), bImg, sType);
288: ColorModel cm = bImg.getColorModel();
289: IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm
290: : null);
291: bisd.initRaster(bpRaster.getDataStorage(), bpRaster
292: .getDataBitOffset() / 8,
293: bpRaster.getDataBitOffset() & 7, bpRaster.getWidth(),
294: bpRaster.getHeight(), 0, bpRaster.getScanlineStride(),
295: icm);
296: return bisd;
297: }
298:
299: public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
300: if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR
301: && sg2d.compositeState <= sg2d.COMP_ISCOPY) {
302: return solidloops;
303: }
304: return super .getRenderLoops(sg2d);
305: }
306:
307: public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
308: return bufImg.getRaster();
309: }
310:
311: /**
312: * Initializes the native Ops pointer.
313: */
314: protected native void initRaster(Object theArray, int offset,
315: int bitoffset, int width, int height, int pixStr,
316: int scanStr, IndexColorModel icm);
317:
318: public BufImgSurfaceData(DataBuffer db, BufferedImage bufImg,
319: SurfaceType sType) {
320: super (SunWritableRaster.stealTrackable(db), sType, bufImg
321: .getColorModel());
322: this .bufImg = bufImg;
323: }
324:
325: public void initSolidLoops() {
326: this .solidloops = getSolidLoops(getSurfaceType());
327: }
328:
329: private static final int CACHE_SIZE = 5;
330: private static RenderLoops loopcache[] = new RenderLoops[CACHE_SIZE];
331: private static SurfaceType typecache[] = new SurfaceType[CACHE_SIZE];
332:
333: public static synchronized RenderLoops getSolidLoops(
334: SurfaceType type) {
335: for (int i = CACHE_SIZE - 1; i >= 0; i--) {
336: SurfaceType t = typecache[i];
337: if (t == type) {
338: return loopcache[i];
339: } else if (t == null) {
340: break;
341: }
342: }
343: RenderLoops l = makeRenderLoops(SurfaceType.OpaqueColor,
344: CompositeType.SrcNoEa, type);
345: System.arraycopy(loopcache, 1, loopcache, 0, CACHE_SIZE - 1);
346: System.arraycopy(typecache, 1, typecache, 0, CACHE_SIZE - 1);
347: loopcache[CACHE_SIZE - 1] = l;
348: typecache[CACHE_SIZE - 1] = type;
349: return l;
350: }
351:
352: public SurfaceData getReplacement() {
353: // BufImgSurfaceData objects should never lose their contents,
354: // so this method should never be called.
355: return restoreContents(bufImg);
356: }
357:
358: public synchronized GraphicsConfiguration getDeviceConfiguration() {
359: if (graphicsConfig == null) {
360: graphicsConfig = BufferedImageGraphicsConfig
361: .getConfig(bufImg);
362: }
363: return graphicsConfig;
364: }
365:
366: public java.awt.Rectangle getBounds() {
367: return new Rectangle(bufImg.getWidth(), bufImg.getHeight());
368: }
369:
370: protected void checkCustomComposite() {
371: // BufferedImages always allow Custom Composite objects since
372: // their pixels are immediately retrievable anyway.
373: }
374:
375: public static native void freeNativeICMData(IndexColorModel icm);
376:
377: /**
378: * Returns destination Image associated with this SurfaceData.
379: */
380: public Object getDestination() {
381: return bufImg;
382: }
383: }
|