1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
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: import ;
63: import ;
64: import ;
65:
66: public class XGraphics
67: extends Graphics
68: implements Cloneable
69: {
70:
71:
74: private Drawable xdrawable;
75:
76:
79: private GC xgc;
80:
81:
84: private int translateX;
85: private int translateY;
86:
87:
90: private Rectangle clip;
91:
92:
95: private Font font;
96:
97:
100: private Color foreground;
101:
102:
105: private boolean disposed = false;
106:
107:
108: private Pixmap.Format pixmapFormat;
109: private int imageByteOrder;
110: private int pixelByteCount;
111:
112:
117: XGraphics(Drawable d)
118: {
119: xdrawable = d;
120: xgc = new GC(d);
121: translateX = 0;
122: translateY = 0;
123: clip = new Rectangle(0, 0, d.width, d.height);
124:
125: Display display = xdrawable.display;
126: pixmapFormat = display.default_pixmap_format;
127: imageByteOrder = display.image_byte_order;
128: pixelByteCount = pixmapFormat.bits_per_pixel () / 8;
129: }
130:
131:
136: public Graphics create()
137: {
138: XGraphics copy = (XGraphics) clone();
139: return copy;
140: }
141:
142:
145: public void translate(int x, int y)
146: {
147: translateX += x;
148: translateY += y;
149: if (clip != null)
150: {
151: clip.x -= x;
152: clip.y -= y;
153: }
154: }
155:
156:
161: public Color getColor()
162: {
163: return foreground;
164: }
165:
166:
172: public void setColor(Color c)
173: {
174: if (c != null)
175: {
176: XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
177: HashMap colorMap = tk.colorMap;
178: gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c);
179: if (col == null)
180: {
181: Colormap map = xdrawable.display.default_colormap;
182: col = map.alloc_color (c.getRed() * 256,
183: c.getGreen() * 256,
184: c.getBlue() * 256);
185: colorMap.put(c, col);
186: }
187: xgc.set_foreground(col);
188: foreground = c;
189: }
190: }
191:
192: public void setPaintMode()
193: {
194:
195: throw new UnsupportedOperationException("Not yet implemented");
196: }
197:
198: public void setXORMode(Color color)
199: {
200:
201: throw new UnsupportedOperationException("Not yet implemented");
202: }
203:
204:
209: public Font getFont()
210: {
211: return font;
212: }
213:
214:
220: public void setFont(Font f)
221: {
222: if (f != null)
223: {
224: XFontPeer xFontPeer = (XFontPeer) f.getPeer();
225: xgc.set_font(xFontPeer.getXFont());
226: font = f;
227: }
228: }
229:
230:
237: public FontMetrics getFontMetrics(Font font)
238: {
239: if (font == null)
240: {
241: if (this.font == null)
242: setFont(new Font("Dialog", Font.PLAIN, 12));
243: font = this.font;
244: }
245: XFontPeer xFontPeer = (XFontPeer) font.getPeer();
246: return xFontPeer.getFontMetrics(font);
247: }
248:
249:
254: public Rectangle getClipBounds()
255: {
256: return clip != null ? clip.getBounds() : null;
257: }
258:
259:
262: public void clipRect(int x, int y, int width, int height)
263: {
264: if (clip == null)
265: {
266: clip = new Rectangle(x, y, width, height);
267: }
268: else
269: {
270: computeIntersection(x, y, width, height, clip);
271: }
272:
273: setXClip(clip.x, clip.y, clip.width, clip.height);
274: }
275:
276:
289: public boolean hitClip(int x, int y, int w, int h)
290: {
291: boolean hit;
292: if (clip == null)
293: {
294: hit = true;
295: }
296: else
297: {
298:
299:
300:
301: int x2 = x + w;
302: int y2 = y + h;
303: int clipX2 = clip.x + clip.width;
304: int clipY2 = clip.y + clip.height;
305: boolean outside = (x < clip.x && x2 < clip.x)
306: || (x > clipX2 && x2 > clipX2)
307: || (y < clip.y && y2 < clip.y)
308: || (y > clipY2 && y2 > clipY2);
309: hit = ! outside;
310: }
311: return hit;
312: }
313:
314: public void setClip(int x, int y, int width, int height)
315: {
316: if (clip != null)
317: clip.setBounds(x, y, width, height);
318: else
319: clip = new Rectangle(x, y, width, height);
320: setXClip(clip.x, clip.y, clip.width, clip.height);
321: }
322:
323:
332: private void setXClip(int x, int y, int w, int h)
333: {
334: gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] {
335: new gnu.x11.Rectangle(x, y, w, h) };
336: xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED);
337: }
338:
339: public Shape getClip()
340: {
341:
342: return clip == null ? null : clip.getBounds();
343: }
344:
345:
350: public void setClip(Shape c)
351: {
352: if (c != null)
353: {
354: Rectangle b;
355: if (c instanceof Rectangle)
356: {
357: b = (Rectangle) c;
358: }
359: else
360: {
361: b = c.getBounds();
362: }
363: clip.setBounds(b);
364: setXClip(b.x, b.y, b.width, b.height);
365: }
366: else
367: {
368: clip.setBounds(0, 0, xdrawable.width, xdrawable.height);
369: setXClip(0, 0, xdrawable.width, xdrawable.height);
370: }
371: }
372:
373: public void copyArea(int x, int y, int width, int height, int dx, int dy)
374: {
375:
376: int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width)
377: + translateX;
378: int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height)
379: + translateY;
380: int srcWidth = Math.min(Math.max(x + width, clip.x),
381: clip.x + clip.width) - x;
382: int srcHeight = Math.min(Math.max(y + height, clip.y),
383: clip.y + clip.height) - y;
384: xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight,
385: srcX + dx, srcY + dy);
386: }
387:
388:
391: public void drawLine(int x1, int y1, int x2, int y2)
392: {
393:
394: xdrawable.line(xgc, x1 + translateX, y1 + translateY,
395: x2 + translateX, y2 + translateY);
396: }
397:
398:
401: public void fillRect(int x, int y, int width, int height)
402: {
403: xdrawable.rectangle(xgc, x + translateX, y + translateY,
404: width, height, true);
405: }
406:
407: public void clearRect(int x, int y, int width, int height)
408: {
409: xgc.set_foreground(Color.WHITE.getRGB());
410: xdrawable.rectangle(xgc, x, y, width, height, true);
411: if (foreground != null)
412: xgc.set_foreground(foreground.getRGB());
413: }
414:
415: public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
416: int arcHeight)
417: {
418:
419: int arcRadiusX = arcWidth / 2;
420: int arcRadiusY = arcHeight / 2;
421: drawLine(x + arcRadiusX, y, x + width - arcRadiusX, y);
422: drawLine(x, y + arcRadiusY, x, y + height - arcRadiusY);
423: drawLine(x + arcRadiusX, y + height, x + width - arcRadiusX, y + height);
424: drawLine(x + width, y + arcRadiusY, x + width, y + height - arcRadiusY);
425:
426:
427:
428: drawArc(x, y, arcWidth, arcHeight, 90, 90);
429:
430: drawArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90);
431:
432: drawArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90);
433:
434: drawArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight,
435: 270, 90);
436: }
437:
438: public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
439: int arcHeight)
440: {
441:
442: int arcRadiusX = arcWidth / 2;
443: int arcRadiusY = arcHeight / 2;
444:
445: fillRect(x, y + arcRadiusY, arcRadiusX, height - arcHeight);
446:
447: fillRect(x + arcRadiusX, y, width - arcWidth, height);
448:
449: fillRect(x + width - arcRadiusX, y + arcRadiusY, arcRadiusX,
450: height - arcHeight);
451:
452:
453:
454: fillArc(x, y, arcWidth, arcHeight, 90, 90);
455:
456: fillArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90);
457:
458: fillArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90);
459:
460: fillArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight,
461: 270, 90);
462: }
463:
464: public void drawOval(int x, int y, int width, int height)
465: {
466: xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, false);
467: }
468:
469: public void fillOval(int x, int y, int width, int height)
470: {
471: xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, true);
472: }
473:
474: public void drawArc(int x, int y, int width, int height, int arcStart,
475: int arcAngle)
476: {
477: xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, false);
478: }
479:
480: public void fillArc(int x, int y, int width, int height, int arcStart,
481: int arcAngle)
482: {
483: xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, true);
484: }
485:
486: public void drawPolyline(int[] xPoints, int[] yPoints, int npoints)
487: {
488: int numPoints = Math.min(xPoints.length, yPoints.length);
489: Point[] points = new Point[numPoints];
490:
491:
492: for (int i = 0; i < numPoints; i++)
493: points[i] = new Point(xPoints[i], yPoints[i]);
494: xdrawable.poly_line(xgc, points, Drawable.ORIGIN);
495: }
496:
497: public void drawPolygon(int[] xPoints, int[] yPoints, int npoints)
498: {
499: int numPoints = Math.min(xPoints.length, yPoints.length);
500: Point[] points = new Point[numPoints];
501:
502:
503: for (int i = 0; i < numPoints; i++)
504: points[i] = new Point(xPoints[i], yPoints[i]);
505: xdrawable.poly_line(xgc, points, Drawable.ORIGIN);
506: }
507:
508: public void fillPolygon(int[] xPoints, int[] yPoints, int npoints)
509: {
510: int numPoints = Math.min(xPoints.length, yPoints.length);
511: Point[] points = new Point[numPoints];
512:
513:
514: for (int i = 0; i < numPoints; i++)
515: points[i] = new Point(xPoints[i], yPoints[i]);
516: xdrawable.fill_poly(xgc, points, Drawable.COMPLEX, Drawable.ORIGIN);
517: }
518:
519:
522: public void drawString(String string, int x, int y)
523: {
524: if (disposed)
525: throw new AWTError("XGraphics already disposed");
526:
527: xdrawable.text(xgc, x + translateX, y + translateY, string);
528: }
529:
530: public void drawString(AttributedCharacterIterator ci, int x, int y)
531: {
532:
533: throw new UnsupportedOperationException("Not yet implemented");
534: }
535:
536:
539: public boolean drawImage(Image image, int x, int y, ImageObserver observer)
540: {
541: if (image instanceof XImage)
542: {
543: XImage xim = (XImage) image;
544: Pixmap pm = xim.pixmap;
545: xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
546: x + translateX, y + translateY);
547: }
548: else if (image instanceof BufferedImage
549: && ((BufferedImage) image).getTransparency() != Transparency.OPAQUE)
550: {
551: BufferedImage bi = (BufferedImage) image;
552: int width = bi.getWidth();
553: int height = bi.getHeight();
554: Data img = xdrawable.image(x + translateX, y + translateY,
555: width, height, 0xFFFFFFFF, 2);
556:
557:
558: int lineBitCount = width * pixmapFormat.bits_per_pixel ();
559: int rem = lineBitCount % pixmapFormat.scanline_pad ();
560: int linePadCount = lineBitCount / pixmapFormat.scanline_pad ()
561: + (rem == 0 ? 0 : 1);
562: int lineByteCount = linePadCount * pixmapFormat.scanline_pad () / 8;
563:
564:
565: int[] trgb = new int[3];
566: for (int yy = 0; yy < height; yy++)
567: {
568: for (int xx = 0; xx < width; xx++)
569: {
570: getRGB(xx, yy, img, trgb, lineByteCount);
571: int srgb = bi.getRGB(xx, yy);
572: float alpha = ((srgb >> 24) & 0xff) / 256F;
573: float tAlpha = 1.F - alpha;
574: int red = (srgb >> 16) & 0xFF;
575: int green = (srgb >> 8) & 0xFF;
576: int blue = (srgb) & 0xFF;
577: trgb[0] = (int) (trgb[0] * tAlpha + red * alpha);
578: trgb[1] = (int) (trgb[1] * tAlpha + green * alpha);
579: trgb[2] = (int) (trgb[2] * tAlpha + blue * alpha);
580: setRGB(xx, yy, img, trgb, lineByteCount);
581: }
582: }
583:
584:
585:
586: ZPixmap pm = new ZPixmap(xdrawable.display);
587: pm.width = width;
588: pm.height = height;
589: pm.init();
590: System.arraycopy(img.data, 32, pm.data, 0, img.data.length - 32);
591: xdrawable.put_image(xgc, pm, x + translateX, y + translateY);
592: }
593: else
594: {
595:
596: ImageProducer source = image.getSource();
597: ImageConverter conv = new ImageConverter();
598: source.startProduction(conv);
599: XImage xim = conv.getXImage();
600: Pixmap pm = xim.pixmap;
601: xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
602: x + translateX, y + translateY);
603: }
604: return true;
605: }
606:
607:
615: private void getRGB(int x, int y, Data img, int[] rgb, int lineByteCount)
616: {
617:
618: int i = y * lineByteCount + pixelByteCount * x;
619: if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST)
620: {
621: rgb[2] = img.data[32 + i];
622: rgb[1] = img.data[32 + i + 1];
623: rgb[0] = img.data[32 + i + 2];
624: }
625: else
626: {
627: rgb[0] = img.data[32 + i];
628: rgb[1] = img.data[32 + i + 1];
629: rgb[2] = img.data[32 + i + 2];
630: }
631:
632: }
633:
634:
642: private void setRGB(int x, int y, Data img, int[] rgb, int lineByteCount)
643: {
644:
645: int i = y * lineByteCount + pixelByteCount * x;
646: if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST)
647: {
648: img.data[32 + i] = (byte) rgb[2];
649: img.data[32 + i + 1] = (byte) rgb[1];
650: img.data[32 + i + 2] = (byte) rgb[0];
651: }
652: else
653: {
654: img.data[32 + i] = (byte) rgb[0];
655: img.data[32 + i + 1] = (byte) rgb[1];
656: img.data[32 + i + 2] = (byte) rgb[2];
657: }
658: }
659:
660: public boolean drawImage(Image image, int x, int y, int width, int height,
661: ImageObserver observer)
662: {
663:
664: throw new UnsupportedOperationException("Not yet implemented");
665: }
666:
667: public boolean drawImage(Image image, int x, int y, Color bgcolor,
668: ImageObserver observer)
669: {
670:
671: throw new UnsupportedOperationException("Not yet implemented");
672: }
673:
674: public boolean drawImage(Image image, int x, int y, int width, int height,
675: Color bgcolor, ImageObserver observer)
676: {
677:
678: throw new UnsupportedOperationException("Not yet implemented");
679: }
680:
681: public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
682: int sx1, int sy1, int sx2, int sy2,
683: ImageObserver observer)
684: {
685: return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null,
686: observer);
687: }
688:
689: public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
690: int sx1, int sy1, int sx2, int sy2, Color bgcolor,
691: ImageObserver observer)
692: {
693:
694:
695:
696:
697: int sw = image.getWidth(observer);
698: int sh = image.getHeight(observer);
699: double scaleX = Math.abs(dx2 - dx1) / (double) Math.abs(sx2 - sx1);
700: double scaleY = Math.abs(dy2 - dy1) / (double) Math.abs(sy2 - sy1);
701: Image scaled = image.getScaledInstance((int) (scaleX * sw),
702: (int) (scaleY * sh),
703: Image.SCALE_FAST);
704:
705:
706: int sx1s = (int) (scaleX * Math.min(sx1, sx2));
707: int sx2s = (int) (scaleX * Math.max(sx1, sx2));
708:
709:
710: Rectangle old = clip;
711: clipRect(dx1, dy1, dx2 - dx1, dy2 - dy1);
712:
713:
714: boolean res = drawImage(scaled, dx1 - sx1s, dy1 - sx2s, observer);
715:
716:
717: setClip(old);
718:
719: return res;
720: }
721:
722:
725: public void dispose()
726: {
727: if (! disposed)
728: {
729: xgc.free();
730: xdrawable.display.flush();
731: disposed = true;
732: }
733: }
734:
735:
736:
737:
740: protected Object clone()
741: {
742: try
743: {
744: XGraphics copy = (XGraphics) super.clone();
745: copy.xgc = xgc.copy();
746: if (clip != null)
747: {
748: copy.clip = new Rectangle(clip);
749: copy.setXClip(clip.x, clip.y, clip.width, clip.height);
750: }
751: return copy;
752: }
753: catch (CloneNotSupportedException ex)
754: {
755: assert false;
756: }
757: return null;
758: }
759:
760:
772: private static void computeIntersection(int x, int y, int w, int h,
773: Rectangle rect)
774: {
775: int x2 = (int) rect.x;
776: int y2 = (int) rect.y;
777: int w2 = (int) rect.width;
778: int h2 = (int) rect.height;
779:
780: int dx = (x > x2) ? x : x2;
781: int dy = (y > y2) ? y : y2;
782: int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
783: int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);
784:
785: if (dw >= 0 && dh >= 0)
786: rect.setBounds(dx, dy, dw, dh);
787: else
788: rect.setBounds(0, 0, 0, 0);
789: }
790:
791:
792: }