1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60:
61:
66: public class CairoSurface extends WritableRaster
67: {
68: int width = -1, height = -1;
69:
70:
73: long surfacePointer;
74:
75:
78: boolean sharedBuffer;
79:
80:
81:
82:
83:
84: static ColorModel cairoColorModel = new DirectColorModel(32, 0x00FF0000,
85: 0x0000FF00,
86: 0x000000FF,
87: 0xFF000000);
88:
89: static ColorModel cairoCM_pre = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
90: 32, 0x00FF0000,
91: 0x0000FF00,
92: 0x000000FF,
93: 0xFF000000,
94: true,
95: Buffers.smallestAppropriateTransferType(32));
96:
97:
98: static ColorModel cairoCM_opaque = new DirectColorModel(24, 0x00FF0000,
99: 0x0000FF00,
100: 0x000000FF);
101:
107: private native void create(int width, int height, int stride, int[] buf);
108:
109:
112: private native void destroy(long surfacePointer, int[] buf);
113:
114:
118: public native void nativeDrawSurface(long surfacePointer, long contextPointer,
119: double[] i2u, double alpha,
120: int interpolation);
121:
122:
128: native void syncNativeToJava(long surfacePointer, int[] buffer);
129:
130:
136: native void syncJavaToNative(long surfacePointer, int[] buffer);
137:
138:
145: native long getFlippedBuffer(long surfacePointer);
146:
147:
152: public CairoSurface(int width, int height)
153: {
154: this(0, 0, width, height);
155: }
156:
157: public CairoSurface(int x, int y, int width, int height)
158: {
159: super(createCairoSampleModel(width, height), null, new Point(x, y));
160:
161: if(width <= 0 || height <= 0)
162: throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
163:
164: this.width = width;
165: this.height = height;
166: dataBuffer = new DataBufferInt(width * height);
167: create(width, height, width, getData());
168:
169: if(surfacePointer == 0)
170: throw new Error("Could not allocate bitmap.");
171: }
172:
173:
176: public CairoSurface(SampleModel sm, CairoSurface parent, Rectangle bounds,
177: Point origin)
178: {
179: super(sm, parent.dataBuffer, bounds, origin, parent);
180:
181: this.width = super.width;
182: this.height = super.height;
183: this.surfacePointer = parent.surfacePointer;
184: this.sharedBuffer = parent.sharedBuffer;
185: this.dataBuffer = parent.dataBuffer;
186: }
187:
188:
192: CairoSurface(GtkImage image)
193: {
194: this(image.width, image.height);
195:
196:
197: int[] data = image.getPixels();
198:
199:
200: if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
201: {
202: for (int i = 0; i < data.length; i++ )
203: {
204:
205: int alpha = data[i] & 0xFF;
206: if( alpha == 0 )
207: data[i] = 0;
208: else
209: {
210:
211: data[i] = (data[i] >>> 8) | (alpha << 24);
212: }
213: }
214: }
215: else
216: {
217: for (int i = 0; i < data.length; i++ )
218: {
219:
220: int alpha = data[i] & 0xFF000000;
221: if( alpha == 0 )
222: data[i] = 0;
223: else
224: {
225: int b = (data[i] & 0xFF0000) >> 16;
226: int g = (data[i] & 0xFF00);
227: int r = (data[i] & 0xFF) << 16;
228:
229: data[i] = alpha | r | g | b;
230: }
231: }
232: }
233:
234: System.arraycopy(data, 0, getData(), 0, data.length);
235: }
236:
237:
240: public void dispose()
241: {
242: if(surfacePointer != 0 && parent == null)
243: destroy(surfacePointer, getData());
244: }
245:
246:
249: protected void finalize()
250: {
251: dispose();
252: }
253:
254:
257: public GtkImage getGtkImage()
258: {
259: return new GtkImage(width, height, getFlippedBuffer(surfacePointer));
260: }
261:
262:
267: public int[] getData()
268: {
269: return ((DataBufferInt)dataBuffer).getData();
270: }
271:
272:
275: public static BufferedImage getBufferedImage(int width, int height)
276: {
277: return getBufferedImage(new CairoSurface(width, height));
278: }
279:
280:
284: public static BufferedImage getBufferedImage(GtkImage image)
285: {
286: return getBufferedImage(new CairoSurface(image));
287: }
288:
289:
292: public static BufferedImage getBufferedImage(CairoSurface surface)
293: {
294: return new BufferedImage(cairoColorModel, surface,
295: cairoColorModel.isAlphaPremultiplied(),
296: new Hashtable());
297: }
298:
299:
302: public Graphics2D getGraphics()
303: {
304: return new CairoSurfaceGraphics(this);
305: }
306:
307:
308:
312: native long nativeNewCairoContext(long surfacePointer);
313:
314: public long newCairoContext()
315: {
316: return nativeNewCairoContext(surfacePointer);
317: }
318:
319:
331: public void copyAreaNative(int x, int y, int width,
332: int height, int dx, int dy, int stride)
333: {
334: copyAreaNative2(surfacePointer, x, y, width, height, dx, dy, stride);
335: }
336: native void copyAreaNative2(long surfacePointer,
337: int x, int y, int width, int height,
338: int dx, int dy, int stride);
339:
340:
343: protected static SampleModel createCairoSampleModel(int w, int h)
344: {
345: return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h,
346: new int[]{0x00FF0000, 0x0000FF00,
347: 0x000000FF, 0xFF000000});
348: }
349:
350:
356: public static boolean isCompatibleColorModel(ColorModel cm)
357: {
358: return (cm.equals(cairoCM_pre) || cm.equals(cairoCM_opaque) ||
359: cm.equals(cairoColorModel));
360: }
361:
362:
368: public static boolean isCompatibleSampleModel(SampleModel sm)
369: {
370: return (sm instanceof SinglePixelPackedSampleModel
371: && sm.getDataType() == DataBuffer.TYPE_INT
372: && Arrays.equals(((SinglePixelPackedSampleModel)sm).getBitMasks(),
373: new int[]{0x00FF0000, 0x0000FF00,
374: 0x000000FF, 0xFF000000}));
375: }
376:
377:
378: public Raster createChild(int parentX, int parentY, int width, int height,
379: int childMinX, int childMinY, int[] bandList)
380: {
381: return createWritableChild(parentX, parentY, width, height,
382: childMinX, childMinY, bandList);
383: }
384:
385: public WritableRaster createCompatibleWritableRaster()
386: {
387: return new CairoSurface(width, height);
388: }
389:
390: public WritableRaster createCompatibleWritableRaster (int x, int y,
391: int w, int h)
392: {
393: return new CairoSurface(x, y, w, h);
394: }
395:
396: public Raster createTranslatedChild(int childMinX, int childMinY)
397: {
398: return createWritableTranslatedChild(childMinX, childMinY);
399: }
400:
401: public WritableRaster createWritableChild(int parentX, int parentY,
402: int w, int h, int childMinX,
403: int childMinY, int[] bandList)
404: {
405: if (parentX < minX || parentX + w > minX + width
406: || parentY < minY || parentY + h > minY + height)
407: throw new RasterFormatException("Child raster extends beyond parent");
408:
409: SampleModel sm = (bandList == null) ?
410: sampleModel :
411: sampleModel.createSubsetSampleModel(bandList);
412:
413: return new CairoSurface(sm, this,
414: new Rectangle(childMinX, childMinY, w, h),
415: new Point(sampleModelTranslateX + childMinX - parentX,
416: sampleModelTranslateY + childMinY - parentY));
417: }
418:
419: public WritableRaster createWritableTranslatedChild(int x, int y)
420: {
421: int tcx = sampleModelTranslateX - minX + x;
422: int tcy = sampleModelTranslateY - minY + y;
423:
424: return new CairoSurface(sampleModel, this,
425: new Rectangle(x, y, width, height),
426: new Point(tcx, tcy));
427: }
428: }