blob: 5b633f55ee992982afb7cbe1391f37be26ec8fca [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.awt.image;
27
28import java.awt.Color;
29import java.awt.Rectangle;
30import java.awt.GraphicsConfiguration;
31import java.awt.image.ColorModel;
32import java.awt.image.SampleModel;
33import java.awt.image.DirectColorModel;
34import java.awt.image.IndexColorModel;
35import java.awt.image.Raster;
36import java.awt.image.BufferedImage;
37import java.awt.image.DataBuffer;
38
39import sun.java2d.SurfaceData;
40import sun.java2d.SunGraphics2D;
41import sun.java2d.StateTrackable;
42import sun.java2d.StateTracker;
43import sun.java2d.loops.SurfaceType;
44import sun.java2d.loops.CompositeType;
45import sun.java2d.loops.RenderLoops;
46
47public class BufImgSurfaceData extends SurfaceData {
48 BufferedImage bufImg;
49 private BufferedImageGraphicsConfig graphicsConfig;
50 RenderLoops solidloops;
51
52 private static native void initIDs(Class ICM);
53
54 private static final int DCM_RGBX_RED_MASK = 0xff000000;
55 private static final int DCM_RGBX_GREEN_MASK = 0x00ff0000;
56 private static final int DCM_RGBX_BLUE_MASK = 0x0000ff00;
57 private static final int DCM_555X_RED_MASK = 0xF800;
58 private static final int DCM_555X_GREEN_MASK = 0x07C0;
59 private static final int DCM_555X_BLUE_MASK = 0x003E;
60 private static final int DCM_4444_RED_MASK = 0x0f00;
61 private static final int DCM_4444_GREEN_MASK = 0x00f0;
62 private static final int DCM_4444_BLUE_MASK = 0x000f;
63 private static final int DCM_4444_ALPHA_MASK = 0xf000;
64 private static final int DCM_ARGBBM_ALPHA_MASK = 0x01000000;
65 private static final int DCM_ARGBBM_RED_MASK = 0x00ff0000;
66 private static final int DCM_ARGBBM_GREEN_MASK = 0x0000ff00;
67 private static final int DCM_ARGBBM_BLUE_MASK = 0x000000ff;
68
69 static {
70 initIDs(IndexColorModel.class);
71 }
72
73 public static SurfaceData createData(BufferedImage bufImg) {
74 if (bufImg == null) {
75 throw new NullPointerException("BufferedImage cannot be null");
76 }
77 SurfaceData sData;
78 ColorModel cm = bufImg.getColorModel();
79 int type = bufImg.getType();
80 // REMIND: Check the image type and pick an appropriate subclass
81 switch (type) {
82 case BufferedImage.TYPE_INT_BGR:
83 sData = createDataIC(bufImg, SurfaceType.IntBgr);
84 break;
85 case BufferedImage.TYPE_INT_RGB:
86 sData = createDataIC(bufImg, SurfaceType.IntRgb);
87 break;
88 case BufferedImage.TYPE_INT_ARGB:
89 sData = createDataIC(bufImg, SurfaceType.IntArgb);
90 break;
91 case BufferedImage.TYPE_INT_ARGB_PRE:
92 sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
93 break;
94 case BufferedImage.TYPE_3BYTE_BGR:
95 sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
96 break;
97 case BufferedImage.TYPE_4BYTE_ABGR:
98 sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
99 break;
100 case BufferedImage.TYPE_4BYTE_ABGR_PRE:
101 sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
102 break;
103 case BufferedImage.TYPE_USHORT_565_RGB:
104 sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
105 break;
106 case BufferedImage.TYPE_USHORT_555_RGB:
107 sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
108 break;
109 case BufferedImage.TYPE_BYTE_INDEXED:
110 {
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 {
140 SurfaceType sType;
141 SampleModel sm = bufImg.getRaster().getSampleModel();
142 switch (sm.getSampleSize(0)) {
143 case 1:
144 sType = SurfaceType.ByteBinary1Bit;
145 break;
146 case 2:
147 sType = SurfaceType.ByteBinary2Bit;
148 break;
149 case 4:
150 sType = SurfaceType.ByteBinary4Bit;
151 break;
152 default:
153 throw new InternalError("Unrecognized pixel size");
154 }
155 sData = createDataBP(bufImg, sType);
156 }
157 break;
158 case BufferedImage.TYPE_CUSTOM:
159 default:
160 {
161 Raster raster = bufImg.getRaster();
162 int numBands = raster.getNumBands();
163 if (raster instanceof IntegerComponentRaster &&
164 raster.getNumDataElements() == 1 &&
165 ((IntegerComponentRaster)raster).getPixelStride() == 1)
166 {
167 SurfaceType sType = SurfaceType.AnyInt;
168 if (cm instanceof DirectColorModel) {
169 DirectColorModel dcm = (DirectColorModel) cm;
170 int aMask = dcm.getAlphaMask();
171 int rMask = dcm.getRedMask();
172 int gMask = dcm.getGreenMask();
173 int bMask = dcm.getBlueMask();
174 if (numBands == 3 &&
175 aMask == 0 &&
176 rMask == DCM_RGBX_RED_MASK &&
177 gMask == DCM_RGBX_GREEN_MASK &&
178 bMask == DCM_RGBX_BLUE_MASK)
179 {
180 sType = SurfaceType.IntRgbx;
181 } else if (numBands == 4 &&
182 aMask == DCM_ARGBBM_ALPHA_MASK &&
183 rMask == DCM_ARGBBM_RED_MASK &&
184 gMask == DCM_ARGBBM_GREEN_MASK &&
185 bMask == DCM_ARGBBM_BLUE_MASK)
186 {
187 sType = SurfaceType.IntArgbBm;
188 } else {
189 sType = SurfaceType.AnyDcm;
190 }
191 }
192 sData = createDataIC(bufImg, sType);
193 break;
194 } else if (raster instanceof ShortComponentRaster &&
195 raster.getNumDataElements() == 1 &&
196 ((ShortComponentRaster)raster).getPixelStride() == 1)
197 {
198 SurfaceType sType = SurfaceType.AnyShort;
199 IndexColorModel icm = null;
200 if (cm instanceof DirectColorModel) {
201 DirectColorModel dcm = (DirectColorModel) cm;
202 int aMask = dcm.getAlphaMask();
203 int rMask = dcm.getRedMask();
204 int gMask = dcm.getGreenMask();
205 int bMask = dcm.getBlueMask();
206 if (numBands == 3 &&
207 aMask == 0 &&
208 rMask == DCM_555X_RED_MASK &&
209 gMask == DCM_555X_GREEN_MASK &&
210 bMask == DCM_555X_BLUE_MASK)
211 {
212 sType = SurfaceType.Ushort555Rgbx;
213 } else
214 if (numBands == 4 &&
215 aMask == DCM_4444_ALPHA_MASK &&
216 rMask == DCM_4444_RED_MASK &&
217 gMask == DCM_4444_GREEN_MASK &&
218 bMask == DCM_4444_BLUE_MASK)
219 {
220 sType = SurfaceType.Ushort4444Argb;
221 }
222 } else if (cm instanceof IndexColorModel) {
223 icm = (IndexColorModel)cm;
224 if (icm.getPixelSize() == 12) {
225 if (isOpaqueGray(icm)) {
226 sType = SurfaceType.Index12Gray;
227 } else {
228 sType = SurfaceType.UshortIndexed;
229 }
230 } else {
231 icm = null;
232 }
233 }
234 sData = createDataSC(bufImg, sType, icm);
235 break;
236 }
237 sData = new BufImgSurfaceData(raster.getDataBuffer(),
238 bufImg, SurfaceType.Custom);
239 }
240 break;
241 }
242 ((BufImgSurfaceData) sData).initSolidLoops();
243 return sData;
244 }
245
246 public static SurfaceData createData(Raster ras, ColorModel cm) {
247 throw new InternalError("SurfaceData not implemented for Raster/CM");
248 }
249
250 public static SurfaceData createDataIC(BufferedImage bImg,
251 SurfaceType sType) {
252 IntegerComponentRaster icRaster =
253 (IntegerComponentRaster)bImg.getRaster();
254 BufImgSurfaceData bisd =
255 new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType);
256 bisd.initRaster(icRaster.getDataStorage(),
257 icRaster.getDataOffset(0) * 4, 0,
258 icRaster.getWidth(),
259 icRaster.getHeight(),
260 icRaster.getPixelStride() * 4,
261 icRaster.getScanlineStride() * 4,
262 null);
263 return bisd;
264 }
265
266 public static SurfaceData createDataSC(BufferedImage bImg,
267 SurfaceType sType,
268 IndexColorModel icm) {
269 ShortComponentRaster scRaster =
270 (ShortComponentRaster)bImg.getRaster();
271 BufImgSurfaceData bisd =
272 new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType);
273 bisd.initRaster(scRaster.getDataStorage(),
274 scRaster.getDataOffset(0) * 2, 0,
275 scRaster.getWidth(),
276 scRaster.getHeight(),
277 scRaster.getPixelStride() * 2,
278 scRaster.getScanlineStride() * 2,
279 icm);
280 return bisd;
281 }
282
283 public static SurfaceData createDataBC(BufferedImage bImg,
284 SurfaceType sType,
285 int primaryBank) {
286 ByteComponentRaster bcRaster =
287 (ByteComponentRaster)bImg.getRaster();
288 BufImgSurfaceData bisd =
289 new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType);
290 ColorModel cm = bImg.getColorModel();
291 IndexColorModel icm = ((cm instanceof IndexColorModel)
292 ? (IndexColorModel) cm
293 : null);
294 bisd.initRaster(bcRaster.getDataStorage(),
295 bcRaster.getDataOffset(primaryBank), 0,
296 bcRaster.getWidth(),
297 bcRaster.getHeight(),
298 bcRaster.getPixelStride(),
299 bcRaster.getScanlineStride(),
300 icm);
301 return bisd;
302 }
303
304 public static SurfaceData createDataBP(BufferedImage bImg,
305 SurfaceType sType) {
306 BytePackedRaster bpRaster =
307 (BytePackedRaster)bImg.getRaster();
308 BufImgSurfaceData bisd =
309 new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType);
310 ColorModel cm = bImg.getColorModel();
311 IndexColorModel icm = ((cm instanceof IndexColorModel)
312 ? (IndexColorModel) cm
313 : null);
314 bisd.initRaster(bpRaster.getDataStorage(),
315 bpRaster.getDataBitOffset() / 8,
316 bpRaster.getDataBitOffset() & 7,
317 bpRaster.getWidth(),
318 bpRaster.getHeight(),
319 0,
320 bpRaster.getScanlineStride(),
321 icm);
322 return bisd;
323 }
324
325 public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
326 if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
327 sg2d.compositeState <= sg2d.COMP_ISCOPY)
328 {
329 return solidloops;
330 }
331 return super.getRenderLoops(sg2d);
332 }
333
334 public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
335 return bufImg.getRaster();
336 }
337
338 /**
339 * Initializes the native Ops pointer.
340 */
341 protected native void initRaster(Object theArray,
342 int offset,
343 int bitoffset,
344 int width,
345 int height,
346 int pixStr,
347 int scanStr,
348 IndexColorModel icm);
349
350 public BufImgSurfaceData(DataBuffer db,
351 BufferedImage bufImg, SurfaceType sType)
352 {
353 super(SunWritableRaster.stealTrackable(db),
354 sType, bufImg.getColorModel());
355 this.bufImg = bufImg;
356 }
357
358 public void initSolidLoops() {
359 this.solidloops = getSolidLoops(getSurfaceType());
360 }
361
362 private static final int CACHE_SIZE = 5;
363 private static RenderLoops loopcache[] = new RenderLoops[CACHE_SIZE];
364 private static SurfaceType typecache[] = new SurfaceType[CACHE_SIZE];
365 public static synchronized RenderLoops getSolidLoops(SurfaceType type) {
366 for (int i = CACHE_SIZE - 1; i >= 0; i--) {
367 SurfaceType t = typecache[i];
368 if (t == type) {
369 return loopcache[i];
370 } else if (t == null) {
371 break;
372 }
373 }
374 RenderLoops l = makeRenderLoops(SurfaceType.OpaqueColor,
375 CompositeType.SrcNoEa,
376 type);
377 System.arraycopy(loopcache, 1, loopcache, 0, CACHE_SIZE-1);
378 System.arraycopy(typecache, 1, typecache, 0, CACHE_SIZE-1);
379 loopcache[CACHE_SIZE - 1] = l;
380 typecache[CACHE_SIZE - 1] = type;
381 return l;
382 }
383
384 public SurfaceData getReplacement() {
385 // BufImgSurfaceData objects should never lose their contents,
386 // so this method should never be called.
387 return restoreContents(bufImg);
388 }
389
390 public synchronized GraphicsConfiguration getDeviceConfiguration() {
391 if (graphicsConfig == null) {
392 graphicsConfig = BufferedImageGraphicsConfig.getConfig(bufImg);
393 }
394 return graphicsConfig;
395 }
396
397 public java.awt.Rectangle getBounds() {
398 return new Rectangle(bufImg.getWidth(), bufImg.getHeight());
399 }
400
401 protected void checkCustomComposite() {
402 // BufferedImages always allow Custom Composite objects since
403 // their pixels are immediately retrievable anyway.
404 }
405
406 public static native void freeNativeICMData(IndexColorModel icm);
407
408 /**
409 * Returns destination Image associated with this SurfaceData.
410 */
411 public Object getDestination() {
412 return bufImg;
413 }
414}