78 |
import java.awt.image.CropImageFilter; |
import java.awt.image.CropImageFilter; |
79 |
import java.awt.image.DataBuffer; |
import java.awt.image.DataBuffer; |
80 |
import java.awt.image.DataBufferInt; |
import java.awt.image.DataBufferInt; |
81 |
|
import java.awt.image.DirectColorModel; |
82 |
import java.awt.image.FilteredImageSource; |
import java.awt.image.FilteredImageSource; |
83 |
import java.awt.image.ImageConsumer; |
import java.awt.image.ImageConsumer; |
84 |
import java.awt.image.ImageObserver; |
import java.awt.image.ImageObserver; |
100 |
////////////////////////////////////// |
////////////////////////////////////// |
101 |
////// State Management Methods ////// |
////// State Management Methods ////// |
102 |
////////////////////////////////////// |
////////////////////////////////////// |
|
static |
|
|
{ |
|
|
if (Configuration.INIT_LOAD_LIBRARY) |
|
|
System.loadLibrary("gtkpeer"); |
|
103 |
|
|
104 |
if (GtkToolkit.useGraphics2D()) |
static |
105 |
initStaticState(); |
{ |
106 |
} |
if (Configuration.INIT_LOAD_LIBRARY) |
107 |
|
System.loadLibrary("gtkpeer"); |
108 |
|
|
109 |
|
if (GtkToolkit.useGraphics2D()) |
110 |
|
initStaticState(); |
111 |
|
} |
112 |
|
|
113 |
static native void initStaticState(); |
static native void initStaticState(); |
114 |
|
|
115 |
|
private final int native_state = GtkGenericPeer.getUniqueInteger(); |
116 |
|
|
|
private final int native_state = GtkGenericPeer.getUniqueInteger(); |
|
117 |
private Paint paint; |
private Paint paint; |
118 |
private Stroke stroke; |
private Stroke stroke; |
119 |
private Color fg; |
private Color fg; |
124 |
private Font font; |
private Font font; |
125 |
private RenderingHints hints; |
private RenderingHints hints; |
126 |
private BufferedImage bimage; |
private BufferedImage bimage; |
127 |
|
private boolean pixelConversionRequired; |
128 |
|
private int[] pixelBuffer; |
129 |
private Composite comp; |
private Composite comp; |
130 |
private Stack stateStack; |
private Stack stateStack; |
131 |
|
|
132 |
private native void initState(GtkComponentPeer component); |
private native void initState(GtkComponentPeer component); |
|
|
|
133 |
private native void initState(int width, int height); |
private native void initState(int width, int height); |
134 |
|
private native void initState(int[] pixes, int width, int height); |
135 |
private native void copyState(GdkGraphics2D g); |
private native void copyState(GdkGraphics2D g); |
|
|
|
136 |
public native void dispose(); |
public native void dispose(); |
|
|
|
|
private native int[] getImagePixels(); |
|
|
|
|
137 |
private native void cairoSurfaceSetFilter(int filter); |
private native void cairoSurfaceSetFilter(int filter); |
|
|
|
138 |
native void connectSignals(GtkComponentPeer component); |
native void connectSignals(GtkComponentPeer component); |
139 |
|
|
140 |
public void finalize() |
public void finalize() |
237 |
GdkGraphics2D(BufferedImage bimage) |
GdkGraphics2D(BufferedImage bimage) |
238 |
{ |
{ |
239 |
this.bimage = bimage; |
this.bimage = bimage; |
240 |
initState(bimage.getWidth(), bimage.getHeight()); |
this.pixelBuffer = findSimpleIntegerArray(bimage.getColorModel(), |
241 |
|
bimage.getRaster()); |
242 |
|
if (this.pixelBuffer == null) |
243 |
|
{ |
244 |
|
this.pixelBuffer = new int[bimage.getRaster().getWidth() * bimage.getRaster() |
245 |
|
.getHeight()]; |
246 |
|
this.pixelConversionRequired = true; |
247 |
|
} |
248 |
|
else |
249 |
|
{ |
250 |
|
this.pixelConversionRequired = false; |
251 |
|
} |
252 |
|
|
253 |
|
initState(this.pixelBuffer, bimage.getWidth(), bimage.getHeight()); |
254 |
|
|
255 |
setColor(Color.black); |
setColor(Color.black); |
256 |
setBackground(Color.black); |
setBackground(Color.black); |
263 |
stateStack = new Stack(); |
stateStack = new Stack(); |
264 |
|
|
265 |
// draw current buffered image to the pixmap associated |
// draw current buffered image to the pixmap associated |
266 |
// with it. |
// with it, if the image is not equal to our paint buffer. |
267 |
drawImage(bimage, new AffineTransform(1, 0, 0, 1, 0, 0), bg, null); |
if (pixelConversionRequired) |
268 |
|
drawImage(bimage, new AffineTransform(1, 0, 0, 1, 0, 0), bg, null); |
269 |
} |
} |
270 |
|
|
271 |
//////////////////////////////////// |
//////////////////////////////////// |
272 |
////// Native Drawing Methods ////// |
////// Native Drawing Methods ////// |
273 |
//////////////////////////////////// |
//////////////////////////////////// |
274 |
|
|
275 |
// GDK drawing methods |
// GDK drawing methods |
276 |
private native void gdkDrawDrawable(GdkGraphics2D other, int x, int y); |
private native void gdkDrawDrawable(GdkGraphics2D other, int x, int y); |
277 |
|
|
278 |
// drawing utility methods |
// drawing utility methods |
279 |
private native void drawPixels(int[] pixels, int w, int h, int stride, |
private native void drawPixels(int[] pixels, int w, int h, int stride, |
280 |
double[] i2u); |
double[] i2u); |
|
|
|
281 |
private native void setTexturePixels(int[] pixels, int w, int h, int stride); |
private native void setTexturePixels(int[] pixels, int w, int h, int stride); |
|
|
|
282 |
private native void setGradient(double x1, double y1, double x2, double y2, |
private native void setGradient(double x1, double y1, double x2, double y2, |
283 |
int r1, int g1, int b1, int a1, int r2, |
int r1, int g1, int b1, int a1, int r2, |
284 |
int g2, int b2, int a2, boolean cyclic); |
int g2, int b2, int a2, boolean cyclic); |
285 |
|
|
286 |
// simple passthroughs to cairo |
// simple passthroughs to cairo |
287 |
private native void cairoSave(); |
private native void cairoSave(); |
|
|
|
288 |
private native void cairoRestore(); |
private native void cairoRestore(); |
|
|
|
289 |
private native void cairoSetMatrix(double[] m); |
private native void cairoSetMatrix(double[] m); |
|
|
|
290 |
private native void cairoSetOperator(int cairoOperator); |
private native void cairoSetOperator(int cairoOperator); |
|
|
|
291 |
private native void cairoSetRGBColor(double red, double green, double blue); |
private native void cairoSetRGBColor(double red, double green, double blue); |
|
|
|
292 |
private native void cairoSetAlpha(double alpha); |
private native void cairoSetAlpha(double alpha); |
|
|
|
293 |
private native void cairoSetFillRule(int cairoFillRule); |
private native void cairoSetFillRule(int cairoFillRule); |
|
|
|
294 |
private native void cairoSetLineWidth(double width); |
private native void cairoSetLineWidth(double width); |
|
|
|
295 |
private native void cairoSetLineCap(int cairoLineCap); |
private native void cairoSetLineCap(int cairoLineCap); |
|
|
|
296 |
private native void cairoSetLineJoin(int cairoLineJoin); |
private native void cairoSetLineJoin(int cairoLineJoin); |
|
|
|
297 |
private native void cairoSetDash(double[] dashes, int ndash, double offset); |
private native void cairoSetDash(double[] dashes, int ndash, double offset); |
298 |
|
|
299 |
private native void cairoSetMiterLimit(double limit); |
private native void cairoSetMiterLimit(double limit); |
|
|
|
300 |
private native void cairoNewPath(); |
private native void cairoNewPath(); |
|
|
|
301 |
private native void cairoMoveTo(double x, double y); |
private native void cairoMoveTo(double x, double y); |
|
|
|
302 |
private native void cairoLineTo(double x, double y); |
private native void cairoLineTo(double x, double y); |
|
|
|
303 |
private native void cairoCurveTo(double x1, double y1, double x2, double y2, |
private native void cairoCurveTo(double x1, double y1, double x2, double y2, |
304 |
double x3, double y3); |
double x3, double y3); |
|
|
|
305 |
private native void cairoRelMoveTo(double dx, double dy); |
private native void cairoRelMoveTo(double dx, double dy); |
|
|
|
306 |
private native void cairoRelLineTo(double dx, double dy); |
private native void cairoRelLineTo(double dx, double dy); |
|
|
|
307 |
private native void cairoRelCurveTo(double dx1, double dy1, double dx2, |
private native void cairoRelCurveTo(double dx1, double dy1, double dx2, |
308 |
double dy2, double dx3, double dy3); |
double dy2, double dx3, double dy3); |
|
|
|
309 |
private native void cairoRectangle(double x, double y, double width, |
private native void cairoRectangle(double x, double y, double width, |
310 |
double height); |
double height); |
|
|
|
311 |
private native void cairoClosePath(); |
private native void cairoClosePath(); |
|
|
|
312 |
private native void cairoStroke(); |
private native void cairoStroke(); |
|
|
|
313 |
private native void cairoFill(); |
private native void cairoFill(); |
|
|
|
314 |
private native void cairoClip(); |
private native void cairoClip(); |
315 |
|
|
316 |
///////////////////////////////////////////// |
///////////////////////////////////////////// |
317 |
////// General Drawing Support Methods ////// |
////// General Drawing Support Methods ////// |
318 |
///////////////////////////////////////////// |
///////////////////////////////////////////// |
319 |
|
|
320 |
private class DrawState |
private class DrawState |
321 |
{ |
{ |
322 |
private Paint paint; |
private Paint paint; |
451 |
return defaultHints; |
return defaultHints; |
452 |
} |
} |
453 |
|
|
454 |
private final void updateBufferedImage() |
public static final int[] findSimpleIntegerArray (ColorModel cm, Raster raster) |
455 |
{ |
{ |
456 |
int[] pixels = getImagePixels(); |
if (cm == null || raster == null) |
457 |
updateImagePixels(pixels); |
return null; |
|
} |
|
458 |
|
|
459 |
private final boolean isBufferedImageGraphics() |
if (! cm.getColorSpace().isCS_sRGB()) |
460 |
{ |
return null; |
|
return bimage != null; |
|
|
} |
|
461 |
|
|
462 |
private final void updateImagePixels(int[] pixels) |
if (! (cm instanceof DirectColorModel)) |
463 |
{ |
return null; |
|
// This function can only be used if |
|
|
// this graphics object is used to draw into |
|
|
// buffered image |
|
|
if (! isBufferedImageGraphics()) |
|
|
return; |
|
464 |
|
|
465 |
WritableRaster raster = bimage.getRaster(); |
DirectColorModel dcm = (DirectColorModel) cm; |
|
DataBuffer db = raster.getDataBuffer(); |
|
466 |
|
|
467 |
// update pixels in the bufferedImage |
if (dcm.getRedMask() != 0x00FF0000 || dcm.getGreenMask() != 0x0000FF00 |
468 |
if (raster.getSampleModel().getDataType() == DataBuffer.TYPE_INT |
|| dcm.getBlueMask() != 0x000000FF) |
469 |
&& db instanceof DataBufferInt && db.getNumBanks() == 1) |
return null; |
470 |
{ |
|
471 |
// single bank, ARGB-ints buffer in sRGB space |
if (! (raster instanceof WritableRaster)) |
472 |
DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer(); |
return null; |
473 |
|
|
474 |
|
if (raster.getSampleModel().getDataType() != DataBuffer.TYPE_INT) |
475 |
|
return null; |
476 |
|
|
477 |
|
if (! (raster.getDataBuffer() instanceof DataBufferInt)) |
478 |
|
return null; |
479 |
|
|
480 |
|
DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); |
481 |
|
|
482 |
for (int i = 0; i < pixels.length; i++) |
if (db.getNumBanks() != 1) |
483 |
dbi.setElem(i, pixels[i]); |
return null; |
484 |
|
|
485 |
|
// Finally, we have determined that this is a single bank, [A]RGB-int |
486 |
|
// buffer in sRGB space. It's worth checking all this, because it means |
487 |
|
// that cairo can paint directly into the data buffer, which is very |
488 |
|
// fast compared to all the normal copying and converting. |
489 |
|
|
490 |
|
return db.getData(); |
491 |
|
} |
492 |
|
|
493 |
|
private final void updateBufferedImage() |
494 |
|
{ |
495 |
|
if (bimage != null && pixelConversionRequired) |
496 |
|
{ |
497 |
|
int height = bimage.getHeight(); |
498 |
|
int width = bimage.getWidth(); |
499 |
|
for (int y = 0; y < height; ++y) |
500 |
|
for (int x = 0; x < width; ++x) |
501 |
|
bimage.setRGB(x, y, pixelBuffer[y*width+height]); |
502 |
} |
} |
|
else |
|
|
bimage.getRaster().setPixels(0, 0, raster.getWidth(), |
|
|
raster.getHeight(), pixels); |
|
503 |
} |
} |
504 |
|
|
505 |
private final boolean drawImage(Image img, AffineTransform xform, |
private final boolean drawImage(Image img, AffineTransform xform, |
518 |
gdkDrawDrawable(g2, (int) xform.getTranslateX(), |
gdkDrawDrawable(g2, (int) xform.getTranslateX(), |
519 |
(int) xform.getTranslateY()); |
(int) xform.getTranslateY()); |
520 |
|
|
521 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
522 |
|
|
523 |
return true; |
return true; |
524 |
} |
} |
560 |
////////////////////////////////////////////////// |
////////////////////////////////////////////////// |
561 |
////// Implementation of Graphics2D Methods ////// |
////// Implementation of Graphics2D Methods ////// |
562 |
////////////////////////////////////////////////// |
////////////////////////////////////////////////// |
563 |
|
|
564 |
public void draw(Shape s) |
public void draw(Shape s) |
565 |
{ |
{ |
566 |
if (stroke != null && ! (stroke instanceof BasicStroke)) |
if (stroke != null && ! (stroke instanceof BasicStroke)) |
582 |
walkPath(s.getPathIterator(null), shiftDrawCalls); |
walkPath(s.getPathIterator(null), shiftDrawCalls); |
583 |
cairoStroke(); |
cairoStroke(); |
584 |
|
|
585 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
586 |
} |
} |
587 |
|
|
588 |
public void fill(Shape s) |
public void fill(Shape s) |
595 |
} |
} |
596 |
else |
else |
597 |
walkPath(s.getPathIterator(null), false); |
walkPath(s.getPathIterator(null), false); |
598 |
|
|
599 |
cairoFill(); |
cairoFill(); |
600 |
|
|
601 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
602 |
} |
} |
603 |
|
|
604 |
public void clip(Shape s) |
public void clip(Shape s) |
649 |
|
|
650 |
paint = p; |
paint = p; |
651 |
if (paint instanceof Color) |
if (paint instanceof Color) |
652 |
setColor((Color) paint); |
{ |
653 |
|
setColor((Color) paint); |
654 |
|
} |
655 |
else if (paint instanceof TexturePaint) |
else if (paint instanceof TexturePaint) |
656 |
{ |
{ |
657 |
TexturePaint tp = (TexturePaint) paint; |
TexturePaint tp = (TexturePaint) paint; |
786 |
//////////////////////////////////////////////// |
//////////////////////////////////////////////// |
787 |
////// Implementation of Graphics Methods ////// |
////// Implementation of Graphics Methods ////// |
788 |
//////////////////////////////////////////////// |
//////////////////////////////////////////////// |
789 |
|
|
790 |
public void setPaintMode() |
public void setPaintMode() |
791 |
{ |
{ |
792 |
setComposite(java.awt.AlphaComposite.SrcOver); |
setComposite(java.awt.AlphaComposite.SrcOver); |
821 |
|
|
822 |
public Shape getClip() |
public Shape getClip() |
823 |
{ |
{ |
824 |
return getClipInDevSpace(); |
return clip.getBounds2D(); //getClipInDevSpace(); |
825 |
} |
} |
826 |
|
|
827 |
public Rectangle getClipBounds() |
public Rectangle getClipBounds() |
885 |
setStroke(draw3DRectStroke); |
setStroke(draw3DRectStroke); |
886 |
super.draw3DRect(x, y, width, height, raised); |
super.draw3DRect(x, y, width, height, raised); |
887 |
setStroke(tmp); |
setStroke(tmp); |
888 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
889 |
} |
} |
890 |
|
|
891 |
public void fill3DRect(int x, int y, int width, int height, boolean raised) |
public void fill3DRect(int x, int y, int width, int height, boolean raised) |
894 |
setStroke(draw3DRectStroke); |
setStroke(draw3DRectStroke); |
895 |
super.fill3DRect(x, y, width, height, raised); |
super.fill3DRect(x, y, width, height, raised); |
896 |
setStroke(tmp); |
setStroke(tmp); |
897 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
898 |
} |
} |
899 |
|
|
900 |
public void drawRect(int x, int y, int width, int height) |
public void drawRect(int x, int y, int width, int height) |
919 |
cairoFill(); |
cairoFill(); |
920 |
setColor(fg); |
setColor(fg); |
921 |
|
|
922 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
923 |
} |
} |
924 |
|
|
925 |
public void setBackground(Color c) |
public void setBackground(Color c) |
1014 |
i2u[5] = 0; |
i2u[5] = 0; |
1015 |
} |
} |
1016 |
|
|
1017 |
int[] pixels = null; |
int[] pixels = findSimpleIntegerArray(cm, r); |
1018 |
|
|
1019 |
if (sm.getDataType() == DataBuffer.TYPE_INT && db instanceof DataBufferInt |
if (pixels == null) |
|
&& db.getNumBanks() == 1) |
|
|
{ |
|
|
// single bank, ARGB-ints buffer in sRGB space |
|
|
DataBufferInt dbi = (DataBufferInt) db; |
|
|
pixels = dbi.getData(); |
|
|
} |
|
|
else |
|
1020 |
{ |
{ |
1021 |
// FIXME: I don't think this code will work correctly with a non-RGB |
// FIXME: I don't think this code will work correctly with a non-RGB |
1022 |
// MultiPixelPackedSampleModel. Although this entire method should |
// MultiPixelPackedSampleModel. Although this entire method should |
1036 |
} |
} |
1037 |
} |
} |
1038 |
|
|
1039 |
// change all transparent pixels in the image to the |
// Change all transparent pixels in the image to the specified bgcolor, |
1040 |
// specified bgcolor |
// or (if there's no alpha) fill in an alpha channel so that it paints |
1041 |
|
// correctly. |
1042 |
if (cm.hasAlpha()) |
if (cm.hasAlpha()) |
1043 |
{ |
{ |
1044 |
if (bgcolor != null && cm.hasAlpha()) |
if (bgcolor != null && cm.hasAlpha()) |
1054 |
|
|
1055 |
drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u); |
drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u); |
1056 |
|
|
1057 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
1058 |
|
|
1059 |
return true; |
return true; |
1060 |
} |
} |
1089 |
/////////////////////////////////////////////// |
/////////////////////////////////////////////// |
1090 |
////// Unimplemented Stubs and Overloads ////// |
////// Unimplemented Stubs and Overloads ////// |
1091 |
/////////////////////////////////////////////// |
/////////////////////////////////////////////// |
1092 |
|
|
1093 |
public boolean hit(Rectangle rect, Shape text, boolean onStroke) |
public boolean hit(Rectangle rect, Shape text, boolean onStroke) |
1094 |
{ |
{ |
1095 |
throw new java.lang.UnsupportedOperationException(); |
throw new java.lang.UnsupportedOperationException(); |
1257 |
|
|
1258 |
// Get the subimage of the source enclosed in the |
// Get the subimage of the source enclosed in the |
1259 |
// rectangle specified by sx1, sy1, sx2, sy2 |
// rectangle specified by sx1, sy1, sx2, sy2 |
1260 |
|
|
1261 |
if (img instanceof BufferedImage) |
if (img instanceof BufferedImage) |
1262 |
{ |
{ |
1263 |
BufferedImage b = (BufferedImage) img; |
BufferedImage b = (BufferedImage) img; |
1338 |
public void drawGdkGlyphVector(GdkGlyphVector gv, float x, float y) |
public void drawGdkGlyphVector(GdkGlyphVector gv, float x, float y) |
1339 |
{ |
{ |
1340 |
cairoDrawGdkGlyphVector(getFontPeer(), gv, x, y); |
cairoDrawGdkGlyphVector(getFontPeer(), gv, x, y); |
1341 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
1342 |
} |
} |
1343 |
|
|
1344 |
public void drawGdkTextLayout(GdkTextLayout gl, float x, float y) |
public void drawGdkTextLayout(GdkTextLayout gl, float x, float y) |
1345 |
{ |
{ |
1346 |
cairoDrawGdkTextLayout(getFontPeer(), gl, x, y); |
cairoDrawGdkTextLayout(getFontPeer(), gl, x, y); |
1347 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
1348 |
} |
} |
1349 |
|
|
1350 |
public void drawString(String str, float x, float y) |
public void drawString(String str, float x, float y) |
1351 |
{ |
{ |
1352 |
cairoDrawString(getFontPeer(), str, x, y); |
cairoDrawString(getFontPeer(), str, x, y); |
1353 |
if (isBufferedImageGraphics()) |
updateBufferedImage(); |
|
updateBufferedImage(); |
|
1354 |
} |
} |
1355 |
|
|
1356 |
public void drawString(String str, int x, int y) |
public void drawString(String str, int x, int y) |
1418 |
// Until such time as pango is happy to talk directly to cairo, we |
// Until such time as pango is happy to talk directly to cairo, we |
1419 |
// actually need to redirect some calls from the GtkFontPeer and |
// actually need to redirect some calls from the GtkFontPeer and |
1420 |
// GtkFontMetrics into the drawing kit and ask cairo ourselves. |
// GtkFontMetrics into the drawing kit and ask cairo ourselves. |
1421 |
|
|
1422 |
static native void releasePeerGraphicsResource(GdkFontPeer f); |
static native void releasePeerGraphicsResource(GdkFontPeer f); |
1423 |
|
|
1424 |
static native void getPeerTextMetrics(GdkFontPeer f, String str, |
static native void getPeerTextMetrics(GdkFontPeer f, String str, |
1445 |
if (f.getPeer() instanceof GdkFontPeer) |
if (f.getPeer() instanceof GdkFontPeer) |
1446 |
font = f; |
font = f; |
1447 |
else |
else |
1448 |
font = ((ClasspathToolkit) (Toolkit.getDefaultToolkit())).getFont(f |
font = |
1449 |
.getName(), |
((ClasspathToolkit)(Toolkit.getDefaultToolkit())) |
1450 |
f |
.getFont(f.getName(), f.getAttributes()); |
|
.getAttributes()); |
|
1451 |
} |
} |
1452 |
|
|
1453 |
public String toString() |
public String toString() |
1454 |
{ |
{ |
1455 |
return getClass().getName() + "[font=" + font.toString() + ",color=" |
return (getClass().getName() |
1456 |
+ fg.toString() + "]"; |
+ "[font=" + font.toString() |
1457 |
|
+ ",color=" + fg.toString() |
1458 |
|
+ "]"); |
1459 |
} |
} |
1460 |
} |
} |