001: /*
002: * Copyright (c) 2005, 2006 data2c GmbH (www.data2c.com)
003: *
004: * Author: Wolfgang S. Kechel - wolfgang.kechel@data2c.com
005: */
006:
007: package org.graphics;
008:
009: import java.io.IOException;
010:
011: import java.util.Hashtable; //#ifdef j2se
012: import java.awt.BasicStroke;
013: import java.awt.Color;
014: import java.awt.Dimension;
015: import java.awt.Font;
016: import java.awt.Graphics;
017: import java.awt.Graphics2D;
018: import java.awt.geom.Point2D;
019: import java.awt.Image;
020: import java.awt.image.ImageObserver;
021: import java.awt.Point;
022: import java.awt.Rectangle; //#else
023: import org.awt.Color;
024: import org.awt.Dimension;
025: import org.awt.geom.Point2D;
026: import org.awt.image.ImageObserver;
027: import org.awt.Point;
028: import org.awt.Rectangle;
029:
030: import javax.microedition.lcdui.Font;
031: import javax.microedition.lcdui.Graphics;
032: import javax.microedition.lcdui.Image; //#endif
033:
034: import org.graphics.Draw;
035: import org.graphics.VFont;
036:
037: /*
038: * A Drawable operates on virtual device coordinates with 0,0 in the lower
039: * left corner!
040: */
041: public class Drawable {
042: public static final short LT_SOLID = (short) 0xffff;
043: public static final short LT_DOTTED = (short) 0xaaaa;
044:
045: public Drawable(Graphics agraphics, int width, int height) {
046: super ();
047: g = agraphics;
048: resize(width, height);
049: setColor(Color.BLACK);
050: bgcol = Color.WHITE;
051: tx = ty = .0;
052: setDrawParams();
053: //Draw.translate(g,0,0);
054: currvf = null;
055: //#ifdef j2se
056: setFont(new Font("SansSerif", Font.PLAIN, 12));
057: //#else
058: setFont(Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN,
059: Font.SIZE_SMALL));
060: //#endif
061: try {
062: // currvf = loadVFont(defvfont,null);
063: } catch (Exception e) {
064: }
065: }
066:
067: public void clear() {
068: //System.err.println("-->Drawable.clear()");
069:
070: // save status, erase, restore status
071: Rectangle r = getClipBounds();
072: //System.err.println("old clip=" + r.x + "," + r.y + "," + r.width + "," + r.height);
073: //double x = getTranslateX();
074: //double y = getTranslateY();
075: Color oldfg = getColor();
076: setColor(bgcol);
077: //translate(0,0);
078: g.setClip(0, 0, w, h);
079: g.fillRect(0, 0, w, h);
080: setColor(oldfg);
081: //translate(x,y);
082: setClip(r);
083: //System.err.println("trans="+x+","+y +", clip=("+r.x+","+r.y+","+r.width+","+r.height+")");
084: this .needflush = true;
085: }
086:
087: public void clipRect(int x, int y, int width, int height) {
088: g.clipRect(toX(x), toY(y), width, height);
089: }
090:
091: public void clipRect(Rectangle r) {
092: clipRect(r.x, r.y, r.width, r.height);
093: }
094:
095: public void copyArea(Point2D p, Dimension d, Point2D dst, int anchor) {
096: //#ifdef j2se
097: g.copyArea(toX(p), toY(p), d.width, d.height, toX(dst),
098: toY(dst));
099: //#else
100: g.copyArea(toX(p), toY(p), d.width, d.height, toX(dst),
101: toY(dst), anchor);
102: //#endif
103: this .needflush = true;
104: }
105:
106: public void drawArc(Point2D p, Dimension d, int startAngle,
107: int arcAngle, boolean filled) {
108: int x = toX(p);
109: int y = toY(p);
110:
111: if (filled)
112: g.fillArc(x, y, d.width, d.height, startAngle, arcAngle);
113: g.drawArc(x, y, d.width, d.height, startAngle, arcAngle);
114: this .needflush = true;
115: }
116:
117: public void drawChar(char character, int x, int y, int anchor) {
118: //#ifdef j2se
119: // ignore anchor
120: char[] cbuf = new char[1];
121: cbuf[0] = character;
122: g.drawChars(cbuf, 0, 1, toX(x), toY(y));
123: //#else
124: g.drawChar(character, toX(x), toY(y), anchor);
125: //#endif
126: }
127:
128: public void drawChar(char character, Point2D p, int anchor) {
129: drawChar(character, round(p.getX()), round(p.getY()), anchor);
130: }
131:
132: public void drawChars(char[] data, int offset, int length, int x,
133: int y, int anchor) {
134: //#ifdef j2se
135: // ignore anchor
136: g.drawChars(data, offset, length, toX(x), toY(y));
137: //#else
138: g.drawChars(data, offset, length, toX(x), toY(y), anchor);
139: //#endif
140: }
141:
142: public void drawChars(char[] data, int offset, int length,
143: Point2D p, int anchor) {
144: drawChars(data, offset, length, round(p.getX()),
145: round(p.getY()), anchor);
146: }
147:
148: public void drawImage(Image img, int x, int y,
149: ImageObserver observer) {
150: //#ifdef j2se
151: g.drawImage(img, toX(x), toY(y), observer);
152: //#else
153: g.drawImage(img, toX(x), toY(y), Graphics.TOP | Graphics.LEFT);
154: //#endif
155: this .needflush = true;
156: }
157:
158: public void drawImage(Image img, Point2D p, ImageObserver observer) {
159: drawImage(img, round(p.getX()), round(p.getY()), observer);
160: }
161:
162: public void drawImage(Image img, int x, int y, int anchor) {
163: //#ifdef j2se
164: drawImage(img, x, y, null);
165: //#else
166: g.drawImage(img, toX(x), toY(y), anchor);
167: //#endif
168: }
169:
170: public void drawImage(Image img, Point2D p, int anchor) {
171: drawImage(img, round(p.getX()), round(p.getY()), anchor);
172: }
173:
174: public void drawPoint(Point2D p) {
175: int x = toX(p);
176: int y = toY(p);
177: g.drawLine(x, y, x, y);
178: this .needflush = true;
179: }
180:
181: public void drawLine(int fromx, int fromy, int tox, int toy) {
182: g.drawLine(toX(fromx), toY(fromy), toX(tox), toY(toy));
183: this .needflush = true;
184: }
185:
186: public void drawLine(Point2D from, Point2D to) {
187: g.drawLine(toX(from), toY(from), toX(to), toY(to));
188: this .needflush = true;
189: }
190:
191: public void xline(Point2D from, Point2D to) {
192: xline(round(from.getX()), round(from.getY()), round(to.getX()),
193: round(to.getY()));
194: }
195:
196: public void xline(int fromx, int fromy, int tox, int toy) {
197: g.drawLine(fromx, fromy, tox, toy);
198: this .needflush = true;
199: }
200:
201: public void drawPolygon(int n, Point2D[] points, boolean filled) {
202: Point[] p = new Point[n];
203: for (int i = 0; i < n; ++i) {
204: p[i] = new Point(toX(points[i]), toY(points[i]));
205: }
206: Draw.drawPolygon(g, n, p, filled);
207: }
208:
209: public void drawRect(int x, int y, int width, int height,
210: boolean filled) {
211: int dx = toX(x);
212: int dy = toY(y + height);
213: if (filled)
214: g.fillRect(dx, dy, width, height);
215: g.drawRect(dx, dy, width, height);
216: this .needflush = true;
217: }
218:
219: public void drawRect(Point2D p, Dimension d, boolean filled) {
220: drawRect(round(p.getX()), round(p.getY()), d.width, d.height,
221: filled);
222: }
223:
224: public void drawRoundRect(int x, int y, int width, int height,
225: int arcWidth, int arcHeight) {
226: g.drawRoundRect(toX(x), toY(y + height), width, height,
227: arcHeight, arcHeight);
228: this .needflush = true;
229: }
230:
231: public void drawRoundRect(Point2D p, Dimension d, int arcWidth,
232: int arcHeight) {
233: drawRoundRect(round(p.getX()), round(p.getY()), d.width,
234: d.height, arcHeight, arcHeight);
235: }
236:
237: public void drawString(String str, int x, int y, int anchor) {
238: //#ifdef j2se
239: // ignore anchor
240: g.drawString(str, toX(x), toY(y));
241: //#else
242: g.drawString(str, toX(x), toY(y), anchor);
243: //#endif
244: this .needflush = true;
245: }
246:
247: public void drawString(String str, Point2D p, int anchor) {
248: //#ifdef j2se
249: // ignore anchor
250: g.drawString(str, toX(p), toY(p));
251: //#else
252: g.drawString(str, toX(p), toY(p), anchor);
253: //#endif
254: this .needflush = true;
255: }
256:
257: public void fillRoundRect(int x, int y, int width, int height,
258: int arcWidth, int arcHeight) {
259: g.fillRoundRect(toX(x), toY(y + height - 1), width, height,
260: arcHeight, arcHeight);
261: this .needflush = true;
262: }
263:
264: public void fillRoundRect(Point2D p, Dimension d, int arcWidth,
265: int arcHeight) {
266: fillRoundRect(round(p.getX()), round(p.getY()), d.width,
267: d.height, arcHeight, arcHeight);
268: }
269:
270: public Font getFont() {
271: return g.getFont();
272: }
273:
274: public VFont getVFont() {
275: return currvf;
276: }
277:
278: //#ifndef j2se
279: public void drawRegion(Image src, int srcx, int srcy, int width,
280: int height, int transform, int dstx, int dsty, int anchor) {
281: g.drawRegion(src, srcx, srcy, width, height, transform,
282: toX(dstx), toY(dsty), anchor);
283: this .needflush = true;
284: }
285:
286: public void drawRegion(Image src, Point2D psrc, Dimension d,
287: int transform, Point2D dest, int anchor) {
288: drawRegion(src, round(psrc.getX()), round(psrc.getY()),
289: d.width, d.height, transform, round(dest.getX()),
290: round(dest.getY()), anchor);
291: }
292:
293: public void drawRGB(int[] rgbData, int offset, int scanlength,
294: int x, int y, int width, int height, boolean processAlpha) {
295: g.drawRGB(rgbData, offset, scanlength, toX(x), toY(y), width,
296: height, processAlpha);
297: this .needflush = true;
298: }
299:
300: public void drawRGB(int[] rgbData, int offset, int scanlength,
301: Point2D p, Dimension d, boolean processAlpha) {
302: drawRGB(rgbData, offset, scanlength, round(p.getX()), round(p
303: .getY()), d.width, d.height, processAlpha);
304: }
305:
306: public Rectangle getClipBounds(Rectangle r) {
307: r.width = g.getClipWidth();
308: r.height = g.getClipHeight();
309: r.x = fromX(g.getClipX());
310: r.y = fromY(g.getClipY() + (r.height > 0 ? r.height - 1 : 0));
311: //#ifdef DEBUG
312: System.err.println("Drawable.getclipbounds clip=" + r.x + ", "
313: + r.y + " - " + g.getClipY() + ", " + r.width + ", "
314: + r.height);
315: //#endif
316: return r;
317: }
318:
319: public int getGrayScale() {
320: return g.getGrayScale();
321: }
322:
323: public Graphics getGraphics() {
324: return g;
325: }
326:
327: public int getLineType() {
328: return g.getStrokeStyle();
329: }
330:
331: public void fillTriangle(int x1, int y1, int x2, int y2, int x3,
332: int y3) {
333: g.fillTriangle(toX(x1), toY(y1), toX(x2), toY(y2), toX(x3),
334: toY(y3));
335: this .needflush = true;
336: }
337:
338: public void fillTriangle(Point p1, Point p2, Point p3) {
339: fillTriangle(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
340: }
341:
342: public void resize(int newWidth, int newHeight) {
343: w = newWidth;
344: h = newHeight;
345: h1 = h - 1;
346: setClip(0, 0, w, h);
347: }
348:
349: public void setGrayScale(int value) {
350: g.setGrayScale(value);
351: }
352:
353: //#else
354: public Rectangle getClipBounds(Rectangle r) {
355: Rectangle r = g.getClipBounds(r);
356: r.y = fromY(g.getClipY()) + (r.height > 0 ? r.height - 1 : 0);
357: return r;
358: }
359:
360: //#endif
361:
362: public void drawVString(String str, Point2D p) {
363: drawVString(str, p, VFont.BOTTOM | VFont.LEFT);
364: }
365:
366: public void drawVString(String str, Point2D p, int anchor) {
367: if (currvf == null)
368: return;
369: currvf.drawString(str, toX(p), toY(p), null, g);
370: this .needflush = true;
371: }
372:
373: public void drawVString(String str, Point2D p, int anchor,
374: double sx, double sy, double rotindegree,
375: double slantintanrad) {
376: if (currvf == null)
377: return;
378: currvf.drawString(str, toX(p), toY(p), anchor, sx, sy,
379: rotindegree, slantintanrad, null, g);
380: this .needflush = true;
381: }
382:
383: public Rectangle extentVString(String str, Point2D p, int anchor,
384: Rectangle r) {
385: if (currvf == null)
386: return null;
387: r = currvf.extent(str, toX(p), toY(p), anchor, r);
388: r.y = fromY(r.y);
389: return r;
390: }
391:
392: public Color getBackground() {
393: return bgcol;
394: }
395:
396: public Rectangle getClipBounds() {
397: return getClipBounds(new Rectangle());
398: }
399:
400: public Color getColor() {
401: return fgcol;
402: }
403:
404: public short getLineStipple() {
405: return linestipple;
406: }
407:
408: public int getLineWidth() {
409: return linewidth;
410: }
411:
412: /*
413: public double getTranslateX() {
414: return tx;
415: }
416:
417:
418: public double getTranslateY() {
419: return ty;
420: }
421: */
422:
423: public boolean needsFlush() {
424: return needflush;
425: }
426:
427: public void flush() {
428: needflush = false;
429: }
430:
431: public void setClip(int x, int y, int width, int height) {
432: //#ifdef DEBUG
433: SYSTEM.err.println("Drawable.setClip to: " + x + " - " + toX(x)
434: + ", " + y + " - "
435: + toY(y + (height > 0 ? height - 1 : 0)) + ", " + width
436: + ", " + height);
437: //#endif
438: g.setClip(toX(x), toY(y + (height > 0 ? height - 1 : 0)),
439: width, height);
440: }
441:
442: public void setClip(Rectangle r) {
443: setClip(r.x, r.y, r.width, r.height);
444: }
445:
446: public void setColor(Color c) {
447: fgcol = c;
448: //#ifdef j2se
449: g.setColor(c);
450: //#else
451: g.setColor(c.getRGB());
452: //#endif
453: }
454:
455: public void setBackground(Color c) {
456: if (c != bgcol) {
457: bgcol = c;
458: }
459: }
460:
461: public void setFont(Font f) {
462: g.setFont(f);
463: }
464:
465: public void setVFont(String name) {
466: VFont vf = loadVFont(name, null);
467: }
468:
469: public void setVFont(VFont vf) {
470: if (vf != null)
471: currvf = vf;
472: }
473:
474: public void setLineStipple(short stipple) {
475: setLineStipple(linestipplefactor, stipple);
476: }
477:
478: public void setLineStipple(int factor, short stipple) {
479: if (stipple != linestipple || factor != linestipplefactor) {
480: linestipple = stipple;
481: factor = factor;
482: setDrawParams();
483: }
484: }
485:
486: public void setLineWidth(int width) {
487: if (width != linewidth) {
488: linewidth = width;
489: setDrawParams();
490: }
491: }
492:
493: /*
494: public void translate(int x, int y) {
495: translate((double)x,(double)y);
496: }
497:
498:
499: public void translate(double x, double y) {
500: tx = x;
501: ty = y;
502: Draw.translate(g,round(tx),toY(round(ty)));
503: }
504:
505: public void translate(Point2D p) {
506: translate(p.getX(),p.getY());
507: }
508: */
509:
510: private static VFont loadVFont(String name, String resname) {
511: VFont vf = (VFont) vfonttab.get(name);
512: if (vf == null) {
513: String myname = resname;
514: if (resname == null)
515: myname = "/" + name + ".vf";
516: try {
517: vf = new VFont(name, myname);
518: } catch (IOException e) {
519: e.printStackTrace();
520: }
521: if (vf != null)
522: vfonttab.put(name, vf);
523: }
524: return vf;
525: }
526:
527: protected int toX(Point2D p) {
528: return round(p.getX());
529: }
530:
531: protected int toX(int x) {
532: return x;
533: }
534:
535: protected int fromX(int x) {
536: return x;
537: }
538:
539: protected int toY(Point2D p) {
540: return toY(round(p.getY()));
541: }
542:
543: protected int toY(int y) {
544: //System.err.println("toY("+y+") - h="+h+ ", h1="+h1+ " --> " + (h1-y));
545: return h1 - y;
546: }
547:
548: protected int fromY(int y) {
549: return y - h1;
550: }
551:
552: protected static int round(double x) {
553: return (int) Math.floor(.5 + x);
554: }
555:
556: private void setDrawParams() {
557: //#ifdef j2se
558: if (linestipple == LT_SOLID)
559: ((Graphics2D) g).setStroke(new BasicStroke(linewidth));
560: else {
561: // everything else is dotted!
562: float[] dashes = new float[2];
563: dashes[0] = linestipplefactor;
564: dashes[1] = linestipplefactor;
565: ((Graphics2D) g).setStroke(new BasicStroke(linewidth,
566: BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER,
567: 10.0f, dashes, .0f));
568: }
569: //#else
570: g.setStrokeStyle(linestipple == LT_SOLID ? Graphics.SOLID
571: : Graphics.DOTTED);
572: //#endif
573: }
574:
575: public static final String defvfont = "futural";
576: //public static final String defvfont = "timesr";
577: protected static Hashtable vfonttab = new Hashtable();
578:
579: protected Graphics g = null;
580: protected int w = 1; // screen width
581: protected int h = 1; // screen height
582: private int h1 = 0; // screen height-1
583: protected short linestipple = LT_SOLID; // line stipple
584: protected int linestipplefactor = 1;
585: protected int linewidth = 1;
586: protected double tx = 0; // x translation
587: protected double ty = 0; // y translation
588: protected Color fgcol = Color.black; // foreground color
589: protected Color bgcol = Color.white; // background color
590: protected VFont currvf = null;
591: protected Font currf = null;
592: protected boolean needflush = true;
593: }
|