154 |
{ |
{ |
155 |
paint = g.paint; |
paint = g.paint; |
156 |
stroke = g.stroke; |
stroke = g.stroke; |
157 |
hints = g.hints; |
setRenderingHints (g.hints); |
158 |
|
|
159 |
if (g.fg.getAlpha() != -1) |
if (g.fg.getAlpha() != -1) |
160 |
fg = new Color (g.fg.getRed (), g.fg.getGreen (), |
fg = new Color (g.fg.getRed (), g.fg.getGreen (), |
265 |
private native void cairoSave (); |
private native void cairoSave (); |
266 |
private native void cairoRestore (); |
private native void cairoRestore (); |
267 |
private native void cairoSetMatrix (double m[]); |
private native void cairoSetMatrix (double m[]); |
|
private native void cairoSetFont (GdkClasspathFontPeer peer); |
|
|
private native void cairoShowGlyphs (int codes[], |
|
|
float positions[]); |
|
268 |
private native void cairoSetOperator (int cairoOperator); |
private native void cairoSetOperator (int cairoOperator); |
269 |
private native void cairoSetRGBColor (double red, double green, double blue); |
private native void cairoSetRGBColor (double red, double green, double blue); |
270 |
private native void cairoSetAlpha (double alpha); |
private native void cairoSetAlpha (double alpha); |
344 |
cairoRestore (); |
cairoRestore (); |
345 |
} |
} |
346 |
|
|
347 |
|
// Some operations (drawing rather than filling) require that their |
348 |
|
// coords be shifted to land on 0.5-pixel boundaries, in order to land on |
349 |
|
// "middle of pixel" coordinates and light up complete pixels. |
350 |
|
|
351 |
double x; |
private boolean shiftDrawCalls = false; |
352 |
double y; |
private final double shifted(double coord, boolean doShift) |
|
private void setPos (double nx, double ny) |
|
353 |
{ |
{ |
354 |
x = nx; |
if (doShift) |
355 |
y = ny; |
return Math.floor(coord) + 0.5; |
356 |
|
else |
357 |
|
return coord; |
358 |
} |
} |
359 |
|
|
360 |
private void walkPath(PathIterator p) |
private final void walkPath(PathIterator p, boolean doShift) |
361 |
{ |
{ |
362 |
|
double x = 0; |
363 |
|
double y = 0; |
364 |
double coords[] = new double[6]; |
double coords[] = new double[6]; |
365 |
|
|
366 |
cairoSetFillRule (p.getWindingRule ()); |
cairoSetFillRule (p.getWindingRule ()); |
371 |
{ |
{ |
372 |
|
|
373 |
case PathIterator.SEG_MOVETO: |
case PathIterator.SEG_MOVETO: |
374 |
setPos(coords[0], coords[1]); |
x = shifted(coords[0], doShift); |
375 |
cairoMoveTo (coords[0], coords[1]); |
y = shifted(coords[1], doShift); |
376 |
|
cairoMoveTo (x, y); |
377 |
break; |
break; |
378 |
|
|
379 |
case PathIterator.SEG_LINETO: |
case PathIterator.SEG_LINETO: |
380 |
setPos(coords[0], coords[1]); |
x = shifted(coords[0], doShift); |
381 |
cairoLineTo (coords[0], coords[1]); |
y = shifted(coords[1], doShift); |
382 |
|
cairoLineTo (x, y); |
383 |
break; |
break; |
384 |
|
|
385 |
case PathIterator.SEG_QUADTO: |
case PathIterator.SEG_QUADTO: |
387 |
// splitting a quadratic bezier into a cubic: |
// splitting a quadratic bezier into a cubic: |
388 |
// see: http://pfaedit.sourceforge.net/bezier.html |
// see: http://pfaedit.sourceforge.net/bezier.html |
389 |
|
|
390 |
double x1 = x + (2.0/3.0) * (coords[0] - x); |
double x1 = x + (2.0/3.0) * (shifted(coords[0], doShift) - x); |
391 |
double y1 = y + (2.0/3.0) * (coords[1] - y); |
double y1 = y + (2.0/3.0) * (shifted(coords[1], doShift) - y); |
392 |
|
|
393 |
double x2 = x1 + (1.0/3.0) * (coords[2] - x); |
double x2 = x1 + (1.0/3.0) * (shifted(coords[2], doShift) - x); |
394 |
double y2 = y1 + (1.0/3.0) * (coords[3] - y); |
double y2 = y1 + (1.0/3.0) * (shifted(coords[3], doShift) - y); |
395 |
|
|
396 |
setPos(coords[2], coords[3]); |
x = shifted(coords[2], doShift); |
397 |
|
y = shifted(coords[3], doShift); |
398 |
cairoCurveTo (x1, y1, |
cairoCurveTo (x1, y1, |
399 |
x2, y2, |
x2, y2, |
400 |
coords[2], coords[3]); |
x, y); |
401 |
break; |
break; |
402 |
|
|
403 |
case PathIterator.SEG_CUBICTO: |
case PathIterator.SEG_CUBICTO: |
404 |
setPos(coords[4], coords[5]); |
x = shifted(coords[4], doShift); |
405 |
cairoCurveTo (coords[0], coords[1], |
y = shifted(coords[5], doShift); |
406 |
coords[2], coords[3], |
cairoCurveTo (shifted(coords[0], doShift), shifted(coords[1], doShift), |
407 |
coords[4], coords[5]); |
shifted(coords[2], doShift), shifted(coords[3], doShift), |
408 |
|
x, y); |
409 |
break; |
break; |
410 |
|
|
411 |
case PathIterator.SEG_CLOSE: |
case PathIterator.SEG_CLOSE: |
416 |
} |
} |
417 |
|
|
418 |
|
|
419 |
private Map getDefaultHints() |
private final Map getDefaultHints() |
420 |
{ |
{ |
421 |
HashMap defaultHints = new HashMap (); |
HashMap defaultHints = new HashMap (); |
422 |
|
|
436 |
RenderingHints.VALUE_RENDER_DEFAULT); |
RenderingHints.VALUE_RENDER_DEFAULT); |
437 |
|
|
438 |
return defaultHints; |
return defaultHints; |
439 |
|
|
440 |
} |
} |
441 |
|
|
442 |
private void updateBufferedImage() |
private final void updateBufferedImage() |
443 |
{ |
{ |
444 |
int[] pixels = getImagePixels(); |
int[] pixels = getImagePixels(); |
445 |
updateImagePixels(pixels); |
updateImagePixels(pixels); |
446 |
} |
} |
447 |
|
|
448 |
private boolean isBufferedImageGraphics () |
|
449 |
|
private final boolean isBufferedImageGraphics () |
450 |
{ |
{ |
451 |
return bimage != null; |
return bimage != null; |
452 |
} |
} |
453 |
|
|
454 |
private void updateImagePixels (int[] pixels) |
private final void updateImagePixels (int[] pixels) |
455 |
{ |
{ |
456 |
// This function can only be used if |
// This function can only be used if |
457 |
// this graphics object is used to draw into |
// this graphics object is used to draw into |
484 |
} |
} |
485 |
} |
} |
486 |
|
|
487 |
private boolean drawImage(Image img, |
private final boolean drawImage(Image img, |
488 |
AffineTransform xform, |
AffineTransform xform, |
489 |
Color bgcolor, |
Color bgcolor, |
490 |
ImageObserver obs) |
ImageObserver obs) |
533 |
} |
} |
534 |
else |
else |
535 |
{ |
{ |
536 |
// begin progressive loading in a separate thread |
return this.drawImage(GdkPixbufDecoder.createBufferedImage(img.getSource()), |
537 |
new PainterThread (this, img, invertedXform, bgcolor); |
xform, bgcolor,obs); |
|
return false; |
|
538 |
} |
} |
539 |
} |
} |
540 |
catch (NoninvertibleTransformException e) |
catch (NoninvertibleTransformException e) |
560 |
return; |
return; |
561 |
} |
} |
562 |
|
|
|
stateSave (); |
|
563 |
cairoNewPath (); |
cairoNewPath (); |
564 |
|
|
|
boolean normalize; |
|
|
normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE) |
|
|
|| hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT); |
|
|
|
|
|
if (normalize) |
|
|
translate (0.5,0.5); |
|
|
|
|
565 |
if (s instanceof Rectangle2D) |
if (s instanceof Rectangle2D) |
566 |
{ |
{ |
567 |
Rectangle2D r = (Rectangle2D)s; |
Rectangle2D r = (Rectangle2D)s; |
568 |
cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); |
cairoRectangle (shifted(r.getX (), shiftDrawCalls), |
569 |
|
shifted(r.getY (), shiftDrawCalls), |
570 |
|
r.getWidth (), r.getHeight ()); |
571 |
} |
} |
572 |
else |
else |
573 |
walkPath (s.getPathIterator (null)); |
walkPath (s.getPathIterator (null), shiftDrawCalls); |
574 |
cairoStroke (); |
cairoStroke (); |
575 |
|
|
|
if (normalize) |
|
|
translate (-0.5,-0.5); |
|
|
|
|
|
stateRestore (); |
|
|
|
|
576 |
if (isBufferedImageGraphics ()) |
if (isBufferedImageGraphics ()) |
577 |
updateBufferedImage(); |
updateBufferedImage(); |
|
|
|
578 |
} |
} |
579 |
|
|
580 |
public void fill (Shape s) |
public void fill (Shape s) |
581 |
{ |
{ |
|
stateSave(); |
|
582 |
cairoNewPath (); |
cairoNewPath (); |
583 |
if (s instanceof Rectangle2D) |
if (s instanceof Rectangle2D) |
584 |
{ |
{ |
586 |
cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); |
cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); |
587 |
} |
} |
588 |
else |
else |
589 |
walkPath (s.getPathIterator (null)); |
walkPath (s.getPathIterator (null), false); |
590 |
cairoFill (); |
cairoFill (); |
|
stateRestore (); |
|
591 |
|
|
592 |
if (isBufferedImageGraphics ()) |
if (isBufferedImageGraphics ()) |
593 |
updateBufferedImage(); |
updateBufferedImage(); |
621 |
r.getWidth (), r.getHeight ()); |
r.getWidth (), r.getHeight ()); |
622 |
} |
} |
623 |
else |
else |
624 |
walkPath (clip.getPathIterator (null)); |
walkPath (clip.getPathIterator (null), false); |
625 |
cairoClosePath (); |
// cairoClosePath (); |
626 |
cairoClip (); |
cairoClip (); |
627 |
} |
} |
628 |
} |
} |
768 |
{ |
{ |
769 |
BasicStroke bs = (BasicStroke) stroke; |
BasicStroke bs = (BasicStroke) stroke; |
770 |
cairoSetLineCap (bs.getEndCap()); |
cairoSetLineCap (bs.getEndCap()); |
771 |
cairoSetLineWidth (bs.getLineWidth() / 2.0); |
cairoSetLineWidth (bs.getLineWidth()); |
772 |
cairoSetLineJoin (bs.getLineJoin()); |
cairoSetLineJoin (bs.getLineJoin()); |
773 |
cairoSetMiterLimit (bs.getMiterLimit()); |
cairoSetMiterLimit (bs.getMiterLimit()); |
774 |
float dashes[] = bs.getDashArray(); |
float dashes[] = bs.getDashArray(); |
871 |
r.getWidth (), r.getHeight ()); |
r.getWidth (), r.getHeight ()); |
872 |
} |
} |
873 |
else |
else |
874 |
walkPath (s.getPathIterator (null)); |
walkPath (s.getPathIterator (null), false); |
875 |
cairoClosePath (); |
// cairoClosePath (); |
876 |
cairoClip (); |
cairoClip (); |
877 |
} |
} |
878 |
} |
} |
879 |
|
|
880 |
|
private static BasicStroke draw3DRectStroke = new BasicStroke(); |
881 |
|
|
882 |
public void draw3DRect(int x, int y, int width, |
public void draw3DRect(int x, int y, int width, |
883 |
int height, boolean raised) |
int height, boolean raised) |
884 |
{ |
{ |
885 |
Color std = fg; |
Stroke tmp = stroke; |
886 |
Color light = std.brighter(); |
setStroke(draw3DRectStroke); |
887 |
Color dark = std.darker(); |
super.draw3DRect(x, y, width, height, raised); |
888 |
|
setStroke(tmp); |
|
if (!raised) |
|
|
{ |
|
|
Color t = light; |
|
|
light = dark; |
|
|
dark = t; |
|
|
} |
|
|
|
|
|
double x1 = (double) x; |
|
|
double x2 = (double) x + width; |
|
|
|
|
|
double y1 = (double) y; |
|
|
double y2 = (double) y + height; |
|
|
|
|
|
stateSave (); |
|
|
|
|
|
cairoNewPath (); |
|
|
|
|
|
boolean normalize; |
|
|
normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE) |
|
|
|| hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT); |
|
|
|
|
|
if (normalize) |
|
|
{ |
|
|
x1 += 0.5; |
|
|
y1 += 0.5; |
|
|
x2 += 0.5; |
|
|
y2 += 0.5; |
|
|
} |
|
|
|
|
|
setColor (light); |
|
|
cairoMoveTo (x1, y1); |
|
|
cairoLineTo (x2, y1); |
|
|
cairoLineTo (x2, y2); |
|
|
cairoStroke (); |
|
|
|
|
|
cairoNewPath (); |
|
|
setColor (dark); |
|
|
cairoMoveTo (x1, y1); |
|
|
cairoLineTo (x1, y2); |
|
|
cairoLineTo (x2, y2); |
|
|
cairoStroke (); |
|
|
|
|
|
stateRestore (); |
|
|
|
|
889 |
if (isBufferedImageGraphics ()) |
if (isBufferedImageGraphics ()) |
890 |
updateBufferedImage(); |
updateBufferedImage(); |
|
|
|
891 |
} |
} |
892 |
|
|
893 |
public void fill3DRect(int x, int y, int width, |
public void fill3DRect(int x, int y, int width, |
894 |
int height, boolean raised) |
int height, boolean raised) |
895 |
{ |
{ |
896 |
double step = 1.0; |
Stroke tmp = stroke; |
897 |
if (stroke != null && stroke instanceof BasicStroke) |
setStroke(draw3DRectStroke); |
898 |
{ |
super.fill3DRect(x, y, width, height, raised); |
899 |
BasicStroke bs = (BasicStroke) stroke; |
setStroke(tmp); |
|
step = bs.getLineWidth(); |
|
|
} |
|
|
|
|
|
Color bright = fg.brighter (); |
|
|
Color dark = fg.darker (); |
|
|
|
|
|
draw3DRect (x, y, width, height, raised); |
|
|
|
|
|
stateSave (); |
|
|
translate (step/2.0, step/2.0); |
|
|
cairoNewPath (); |
|
|
cairoRectangle ((double) x, (double) y, |
|
|
((double) width) - step, |
|
|
((double) height) - step ); |
|
|
cairoClosePath (); |
|
|
cairoFill (); |
|
|
stateRestore (); |
|
|
|
|
900 |
if (isBufferedImageGraphics ()) |
if (isBufferedImageGraphics ()) |
901 |
updateBufferedImage(); |
updateBufferedImage(); |
|
|
|
902 |
} |
} |
903 |
|
|
904 |
|
|
909 |
|
|
910 |
public void fillRect (int x, int y, int width, int height) |
public void fillRect (int x, int y, int width, int height) |
911 |
{ |
{ |
912 |
fill(new Rectangle (x, y, width, height)); |
cairoNewPath (); |
913 |
|
cairoRectangle (x, y, width, height); |
914 |
|
cairoFill (); |
915 |
} |
} |
916 |
|
|
917 |
public void clearRect (int x, int y, int width, int height) |
public void clearRect (int x, int y, int width, int height) |
918 |
{ |
{ |
|
stateSave (); |
|
919 |
cairoSetRGBColor (bg.getRed() / 255.0, |
cairoSetRGBColor (bg.getRed() / 255.0, |
920 |
bg.getGreen() / 255.0, |
bg.getGreen() / 255.0, |
921 |
bg.getBlue() / 255.0); |
bg.getBlue() / 255.0); |
922 |
cairoSetAlpha (1.0); |
cairoSetAlpha (1.0); |
923 |
cairoNewPath (); |
cairoNewPath (); |
924 |
cairoRectangle (x, y, width, height); |
cairoRectangle (x, y, width, height); |
|
cairoClosePath (); |
|
925 |
cairoFill (); |
cairoFill (); |
926 |
stateRestore (); |
setColor (fg); |
927 |
|
|
928 |
if (isBufferedImageGraphics ()) |
if (isBufferedImageGraphics ()) |
929 |
updateBufferedImage(); |
updateBufferedImage(); |
940 |
return bg; |
return bg; |
941 |
} |
} |
942 |
|
|
943 |
private void doPolygon(int[] xPoints, int[] yPoints, int nPoints, |
private final void doPolygon(int[] xPoints, int[] yPoints, int nPoints, |
944 |
boolean close, boolean fill) |
boolean close, boolean fill) |
945 |
{ |
{ |
946 |
if (nPoints < 1) |
if (nPoints < 1) |
996 |
doPolygon (xPoints, yPoints, nPoints, false, false); |
doPolygon (xPoints, yPoints, nPoints, false, false); |
997 |
} |
} |
998 |
|
|
999 |
private boolean drawRaster (ColorModel cm, Raster r, |
private final boolean drawRaster (ColorModel cm, Raster r, |
1000 |
AffineTransform imageToUser, |
AffineTransform imageToUser, |
1001 |
Color bgcolor) |
Color bgcolor) |
1002 |
{ |
{ |
1057 |
} |
} |
1058 |
} |
} |
1059 |
|
|
|
stateSave (); |
|
|
translate (x, y); |
|
1060 |
drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth (), i2u); |
drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth (), i2u); |
|
stateRestore (); |
|
1061 |
|
|
1062 |
if (isBufferedImageGraphics ()) |
if (isBufferedImageGraphics ()) |
1063 |
updateBufferedImage(); |
updateBufferedImage(); |
1100 |
} |
} |
1101 |
|
|
1102 |
|
|
|
//////////////////////////////////////// |
|
|
////// Supporting Private Classes ////// |
|
|
//////////////////////////////////////// |
|
|
|
|
|
private class PainterThread implements Runnable, ImageConsumer |
|
|
{ |
|
|
|
|
|
// this is a helper which is spun off when someone tries to do |
|
|
// Graphics2D.drawImage on an image we cannot determine to be either |
|
|
// one of our own offscreen images or a BufferedImage; that is, when |
|
|
// someone wants to draw an image which is possibly still loading over |
|
|
// a network or something. you run it in a separate thread and it |
|
|
// writes through to the underlying Graphics2D as pixels becomg |
|
|
// available. |
|
|
|
|
|
GdkGraphics2D gr; |
|
|
Image image; |
|
|
ColorModel defaultModel; |
|
|
AffineTransform xform; |
|
|
Color bgcolor; |
|
|
|
|
|
public PainterThread (GdkGraphics2D g, Image im, |
|
|
AffineTransform xf, Color bg) |
|
|
{ |
|
|
image = im; |
|
|
xform = xf; |
|
|
bgcolor = bg; |
|
|
this.gr = (GdkGraphics2D) g.create (); |
|
|
new Thread (this).start (); |
|
|
} |
|
|
|
|
|
public void imageComplete (int status) |
|
|
{ |
|
|
} |
|
|
|
|
|
public void setColorModel (ColorModel model) |
|
|
{ |
|
|
defaultModel = model; |
|
|
} |
|
|
|
|
|
public void setDimensions (int width, int height) |
|
|
{ |
|
|
} |
|
|
|
|
|
public void setHints (int hintflags) |
|
|
{ |
|
|
} |
|
|
|
|
|
public void setPixels (int x, int y, int w, int h, ColorModel model, |
|
|
byte[] pixels, int off, int scansize) |
|
|
{ |
|
|
} |
|
|
|
|
|
public void setPixels (int x, int y, int w, int h, ColorModel model, |
|
|
int[] pixels, int off, int scansize) |
|
|
{ |
|
|
gr.stateSave (); |
|
|
gr.translate (x, y); |
|
|
|
|
|
if (model == null) |
|
|
model = defaultModel; |
|
|
|
|
|
int pixels2[]; |
|
|
if (model != null) |
|
|
{ |
|
|
pixels2 = new int[pixels.length]; |
|
|
for (int yy = 0; yy < h; yy++) |
|
|
for (int xx = 0; xx < w; xx++) |
|
|
{ |
|
|
int i = yy * scansize + xx; |
|
|
pixels2[i] = model.getRGB (pixels[i]); |
|
|
} |
|
|
} |
|
|
else |
|
|
pixels2 = pixels; |
|
|
|
|
|
// change all transparent pixels in the image to the |
|
|
// specified bgcolor |
|
|
|
|
|
if (bgcolor != null) |
|
|
{ |
|
|
for (int i = 0; i < pixels2.length; i++) |
|
|
{ |
|
|
if (model.getAlpha (pixels2[i]) == 0) |
|
|
pixels2[i] = bgcolor.getRGB (); |
|
|
} |
|
|
} |
|
|
|
|
|
double[] xf = new double[6]; |
|
|
xform.getMatrix(xf); |
|
|
gr.drawPixels (pixels2, w, h, scansize, xf); |
|
|
gr.stateRestore (); |
|
|
} |
|
|
|
|
|
public void setProperties (java.util.Hashtable props) |
|
|
{ |
|
|
} |
|
|
|
|
|
public void run () |
|
|
{ |
|
|
image.getSource ().startProduction (this); |
|
|
gr.dispose (); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
1103 |
/////////////////////////////////////////////// |
/////////////////////////////////////////////// |
1104 |
////// Unimplemented Stubs and Overloads ////// |
////// Unimplemented Stubs and Overloads ////// |
1105 |
/////////////////////////////////////////////// |
/////////////////////////////////////////////// |
1161 |
|
|
1162 |
} |
} |
1163 |
|
|
1164 |
|
shiftDrawCalls = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE) |
1165 |
|
|| hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT); |
1166 |
|
|
1167 |
} |
} |
1168 |
|
|
1169 |
public Object getRenderingHint(RenderingHints.Key hintKey) |
public Object getRenderingHint(RenderingHints.Key hintKey) |
1196 |
else if(hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) |
else if(hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) |
1197 |
cairoSurfaceSetFilter(4); |
cairoSurfaceSetFilter(4); |
1198 |
} |
} |
1199 |
|
|
1200 |
|
shiftDrawCalls = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE) |
1201 |
|
|| hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT); |
1202 |
} |
} |
1203 |
|
|
1204 |
public void addRenderingHints(Map hints) |
public void addRenderingHints(Map hints) |
1224 |
return new FontRenderContext (transform, true, true); |
return new FontRenderContext (transform, true, true); |
1225 |
} |
} |
1226 |
|
|
|
public void drawGlyphVector (GlyphVector g, float x, float y) |
|
|
{ |
|
|
stateSave (); |
|
|
setFont (g.getFont ()); |
|
|
translate ((double)x, (double)y); |
|
|
cairoMoveTo (0, 0); |
|
|
int nglyphs = g.getNumGlyphs (); |
|
|
int codes[] = g.getGlyphCodes (0, nglyphs, (int []) null); |
|
|
float posns[] = g.getGlyphPositions (0, nglyphs, (float []) null); |
|
|
cairoShowGlyphs (codes, posns); |
|
|
|
|
|
if (isBufferedImageGraphics ()) |
|
|
updateBufferedImage(); |
|
|
|
|
|
stateRestore (); |
|
|
} |
|
|
|
|
1227 |
public void copyArea (int x, int y, int width, int height, int dx, int dy) |
public void copyArea (int x, int y, int width, int height, int dx, int dy) |
1228 |
{ |
{ |
1229 |
throw new java.lang.UnsupportedOperationException (); |
throw new java.lang.UnsupportedOperationException (); |
1355 |
drawLine (x1, y + height, x2, y + height); |
drawLine (x1, y + height, x2, y + height); |
1356 |
} |
} |
1357 |
|
|
1358 |
public void drawString (String str, int x, int y) |
// these are the most accelerated painting paths |
1359 |
|
native void cairoDrawGdkGlyphVector (GdkFontPeer f, GdkGlyphVector gv, float x, float y); |
1360 |
|
native void cairoDrawGdkTextLayout (GdkFontPeer f, GdkTextLayout gl, float x, float y); |
1361 |
|
native void cairoDrawString (GdkFontPeer f, String str, float x, float y); |
1362 |
|
|
1363 |
|
GdkFontPeer getFontPeer() |
1364 |
{ |
{ |
1365 |
drawString (str, (float)x, (float)y); |
return (GdkFontPeer) getFont().getPeer(); |
1366 |
|
} |
1367 |
|
|
1368 |
|
public void drawGdkGlyphVector(GdkGlyphVector gv, float x, float y) |
1369 |
|
{ |
1370 |
|
cairoDrawGdkGlyphVector(getFontPeer(), gv, x, y); |
1371 |
|
if (isBufferedImageGraphics ()) |
1372 |
|
updateBufferedImage(); |
1373 |
|
} |
1374 |
|
|
1375 |
|
public void drawGdkTextLayout(GdkTextLayout gl, float x, float y) |
1376 |
|
{ |
1377 |
|
cairoDrawGdkTextLayout(getFontPeer(), gl, x, y); |
1378 |
|
if (isBufferedImageGraphics ()) |
1379 |
|
updateBufferedImage(); |
1380 |
} |
} |
1381 |
|
|
1382 |
public void drawString (String str, float x, float y) |
public void drawString (String str, float x, float y) |
1383 |
{ |
{ |
1384 |
GlyphVector gv = font.createGlyphVector (getFontRenderContext(), str); |
cairoDrawString(getFontPeer(), str, x, y); |
1385 |
drawGlyphVector (gv, x, y); |
if (isBufferedImageGraphics ()) |
1386 |
|
updateBufferedImage(); |
1387 |
|
} |
1388 |
|
|
1389 |
|
public void drawString (String str, int x, int y) |
1390 |
|
{ |
1391 |
|
drawString (str, (float)x, (float)y); |
1392 |
} |
} |
1393 |
|
|
1394 |
public void drawString (AttributedCharacterIterator ci, int x, int y) |
public void drawString (AttributedCharacterIterator ci, int x, int y) |
1396 |
drawString (ci, (float)x, (float)y); |
drawString (ci, (float)x, (float)y); |
1397 |
} |
} |
1398 |
|
|
1399 |
|
public void drawGlyphVector (GlyphVector gv, float x, float y) |
1400 |
|
{ |
1401 |
|
if (gv instanceof GdkGlyphVector) |
1402 |
|
drawGdkGlyphVector((GdkGlyphVector)gv, x, y); |
1403 |
|
else |
1404 |
|
throw new java.lang.UnsupportedOperationException (); |
1405 |
|
} |
1406 |
|
|
1407 |
public void drawString (AttributedCharacterIterator ci, float x, float y) |
public void drawString (AttributedCharacterIterator ci, float x, float y) |
1408 |
{ |
{ |
1409 |
GlyphVector gv = font.createGlyphVector (getFontRenderContext(), ci); |
GlyphVector gv = font.createGlyphVector (getFontRenderContext(), ci); |
1449 |
return font; |
return font; |
1450 |
} |
} |
1451 |
|
|
1452 |
|
// Until such time as pango is happy to talk directly to cairo, we |
1453 |
|
// actually need to redirect some calls from the GtkFontPeer and |
1454 |
|
// GtkFontMetrics into the drawing kit and ask cairo ourselves. |
1455 |
|
|
1456 |
|
static native void releasePeerGraphicResource (GdkFontPeer f); |
1457 |
|
static native void getPeerTextMetrics (GdkFontPeer f, String str, double [] metrics); |
1458 |
|
static native void getPeerFontMetrics (GdkFontPeer f, double [] metrics); |
1459 |
|
|
1460 |
public FontMetrics getFontMetrics () |
public FontMetrics getFontMetrics () |
1461 |
{ |
{ |
1462 |
|
// the reason we go via the toolkit here is to try to get |
1463 |
|
// a cached object. the toolkit keeps such a cache. |
1464 |
return Toolkit.getDefaultToolkit ().getFontMetrics (font); |
return Toolkit.getDefaultToolkit ().getFontMetrics (font); |
1465 |
} |
} |
1466 |
|
|
1467 |
public FontMetrics getFontMetrics (Font f) |
public FontMetrics getFontMetrics (Font f) |
1468 |
{ |
{ |
1469 |
|
// the reason we go via the toolkit here is to try to get |
1470 |
|
// a cached object. the toolkit keeps such a cache. |
1471 |
return Toolkit.getDefaultToolkit ().getFontMetrics (f); |
return Toolkit.getDefaultToolkit ().getFontMetrics (f); |
1472 |
} |
} |
1473 |
|
|
1474 |
public void setFont (Font f) |
public void setFont (Font f) |
1475 |
{ |
{ |
1476 |
if (f.getPeer() instanceof GdkClasspathFontPeer) |
if (f.getPeer() instanceof GdkFontPeer) |
1477 |
font = f; |
font = f; |
1478 |
else |
else |
1479 |
font = |
font = |
1480 |
((ClasspathToolkit)(Toolkit.getDefaultToolkit ())) |
((ClasspathToolkit)(Toolkit.getDefaultToolkit ())) |
1481 |
.getFont (f.getName(), f.getAttributes ()); |
.getFont (f.getName(), f.getAttributes ()); |
|
|
|
|
if (f != null && |
|
|
f.getPeer() instanceof GdkClasspathFontPeer) |
|
|
cairoSetFont ((GdkClasspathFontPeer) f.getPeer()); |
|
1482 |
} |
} |
1483 |
|
|
1484 |
public String toString() |
public String toString() |