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