001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package java.awt;
018:
019: import java.awt.event.WindowAdapter;
020: import java.awt.event.WindowEvent;
021: import java.awt.geom.AffineTransform;
022: import java.awt.geom.CubicCurve2D;
023: import java.awt.geom.GeneralPath;
024: import java.awt.geom.Line2D;
025: import java.awt.geom.QuadCurve2D;
026: import java.awt.image.BufferedImage;
027: import java.io.File;
028: import java.io.FileReader;
029: import java.io.FileWriter;
030: import java.io.IOException;
031: import java.io.Reader;
032: import java.io.StreamTokenizer;
033: import java.io.Writer;
034: import java.util.Arrays;
035:
036: //import javax.imageio.ImageIO;
037:
038: import org.apache.harmony.awt.gl.MultiRectAreaOp;
039:
040: import junit.framework.Assert;
041:
042: public abstract class Tools {
043:
044: static String typeName[] = { "move", "line", "quad", "cubic",
045: "close" };
046:
047: static int findString(String buf[], String value) {
048: for (int i = 0; i < buf.length; i++) {
049: if (buf[i].equals(value)) {
050: return i;
051: }
052: }
053: Assert.fail("Unknown value " + value);
054: return -1;
055: }
056:
057: public static String getClasstPath(Class clazz) {
058: String name = clazz.getName();
059: name = name.substring(0, name.lastIndexOf('.'));
060:
061: return name.replace('.', '/') + '/';
062: }
063:
064: public static void checkDeadLoop(Component c, int[] count) {
065: final int DEAD_LOOP_TIMEOUT = 1000;
066: final int VALID_NUMBER_OF_PAINT_CALLS = 15;
067:
068: Frame f = new Frame();
069:
070: f.add(c);
071: f.setSize(300, 200);
072: f.setVisible(true);
073:
074: try {
075: Thread.sleep(DEAD_LOOP_TIMEOUT);
076: } catch (Exception e) {
077: }
078:
079: f.dispose();
080:
081: Assert.assertTrue("paint() called " + count[0]
082: + " times, a dead loop occurred",
083: count[0] <= VALID_NUMBER_OF_PAINT_CALLS);
084: }
085:
086: public static class Shape {
087:
088: static int pointCount[] = { 2, // MOVE
089: 2, // LINE
090: 4, // QUAD
091: 6, // CUBIC
092: 0 // CLOSE
093: };
094:
095: static final double IMAGE_REL_BORDER = 0.1;
096: static final double IMAGE_MIN_BORDER = 10.0;
097: static final double IMAGE_MAX_BORDER = 100.0;
098: static final Color backColor = Color.white;
099:
100: public static Frame show(final java.awt.Shape shape) {
101: Frame f = new Frame("Shape") {
102:
103: public void paint(Graphics g) {
104: // Background
105: g.setColor(Color.white);
106: g.fillRect(0, 0, getWidth(), getHeight());
107:
108: // Fill shape
109: g.setColor(Color.lightGray);
110: ((Graphics2D) g).fill(shape);
111:
112: // Draw shape
113: g.setColor(Color.black);
114: ((Graphics2D) g).draw(shape);
115:
116: // java.awt.image.BufferedImage img = Shape.createImage(shape, null, Color.gray, Color.lightGray);
117: // g.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null);
118: }
119:
120: };
121:
122: f.addWindowListener(new WindowAdapter() {
123: public void windowClosing(WindowEvent e) {
124: System.exit(0);
125: }
126: });
127:
128: f.setSize(600, 400);
129: f.show();
130: return f;
131: }
132:
133: public static void save(java.awt.Shape s, String fileName) {
134: try {
135: FileWriter f = new FileWriter(fileName);
136: java.awt.geom.PathIterator p = s.getPathIterator(null);
137: double coords[] = new double[6];
138: while (!p.isDone()) {
139: int type = p.currentSegment(coords);
140: f.write(typeName[type]
141: + getCoords(coords, pointCount[type])
142: + "\n");
143: p.next();
144: }
145: f.close();
146: } catch (IOException e) {
147: Assert.fail("Can''t write to file " + fileName);
148: }
149: }
150:
151: public static java.awt.Shape load(String fileName) {
152: GeneralPath s = null;
153: try {
154: FileReader f = new FileReader(fileName);
155: s = new GeneralPath();
156: StreamTokenizer t = new StreamTokenizer(f);
157: int count = 0;
158: int type = 0;
159: float coords[] = new float[6];
160: while (t.nextToken() != StreamTokenizer.TT_EOF) {
161: switch (t.ttype) {
162: case StreamTokenizer.TT_EOL:
163: break;
164: case StreamTokenizer.TT_WORD:
165: type = findString(typeName, t.sval);
166: if (type == java.awt.geom.PathIterator.SEG_CLOSE) {
167: s.closePath();
168: }
169: break;
170: case StreamTokenizer.TT_NUMBER:
171: coords[count++] = (float) t.nval;
172: if (count == pointCount[type]) {
173: count = 0;
174: switch (type) {
175: case java.awt.geom.PathIterator.SEG_MOVETO:
176: s.moveTo(coords[0], coords[1]);
177: break;
178: case java.awt.geom.PathIterator.SEG_LINETO:
179: s.lineTo(coords[0], coords[1]);
180: break;
181: case java.awt.geom.PathIterator.SEG_QUADTO:
182: s.quadTo(coords[0], coords[1],
183: coords[2], coords[3]);
184: break;
185: case java.awt.geom.PathIterator.SEG_CUBICTO:
186: s.curveTo(coords[0], coords[1],
187: coords[2], coords[3],
188: coords[4], coords[5]);
189: break;
190: }
191: }
192: break;
193: }
194: }
195: f.close();
196: } catch (IOException e) {
197: Assert.fail("Can''t read file " + fileName);
198: }
199: return s;
200: }
201:
202: static String getCoords(double coords[], int count) {
203: String s = "";
204: for (int i = 0; i < count; i++) {
205: s = s + " " + coords[i];
206: }
207: return s;
208: }
209:
210: public static java.awt.image.BufferedImage createImage(
211: java.awt.Shape shape, AffineTransform t, Color draw,
212: Color fill) {
213:
214: // Calculate image border
215: Rectangle r = shape.getBounds();
216: double border = r.getWidth() * IMAGE_REL_BORDER;
217: border = Math.min(IMAGE_MAX_BORDER, border);
218: border = Math.max(IMAGE_MIN_BORDER, border);
219:
220: // Shift shape in the center of the image
221: if (t == null) {
222: t = AffineTransform.getTranslateInstance(-r.getX()
223: + border, -r.getY() + border);
224: } else {
225: t.setToTranslation(-r.getX() + border, -r.getY()
226: + border);
227: }
228: java.awt.geom.GeneralPath dst = new java.awt.geom.GeneralPath();
229: dst.append(shape.getPathIterator(t), false);
230:
231: java.awt.image.BufferedImage img = new java.awt.image.BufferedImage(
232: (int) (r.getWidth() + border * 2.0), (int) (r
233: .getHeight() + border * 2.0),
234: java.awt.image.BufferedImage.TYPE_INT_RGB);
235:
236: Graphics g = img.getGraphics();
237:
238: // Background
239: g.setColor(backColor);
240: g.fillRect(0, 0, img.getWidth(), img.getHeight());
241:
242: // Fill shape
243: g.setColor(fill);
244: ((Graphics2D) g).fill(dst);
245:
246: // Draw shape
247: g.setColor(draw);
248: ((Graphics2D) g).draw(dst);
249:
250: return img;
251: }
252:
253: public static boolean equals(java.awt.Shape s1,
254: java.awt.Shape s2, double delta) {
255: return PathIterator.equals(s1.getPathIterator(null), s2
256: .getPathIterator(null), delta);
257: }
258:
259: public static boolean equals(java.awt.Shape s1,
260: java.awt.Shape s2, float delta) {
261: return PathIterator.equals(s1.getPathIterator(null), s2
262: .getPathIterator(null), delta);
263: }
264:
265: public static java.awt.Shape scale(java.awt.Shape shape,
266: double k) {
267: java.awt.geom.PathIterator path = shape
268: .getPathIterator(AffineTransform.getScaleInstance(
269: k, k));
270: java.awt.geom.GeneralPath dst = new java.awt.geom.GeneralPath(
271: path.getWindingRule());
272: dst.append(path, false);
273: return dst;
274: }
275:
276: public static java.awt.Shape flip(java.awt.Shape shape) {
277: java.awt.geom.PathIterator path = shape
278: .getPathIterator(new AffineTransform(0, 1, 1, 0, 0,
279: 0));
280: java.awt.geom.GeneralPath dst = new java.awt.geom.GeneralPath(
281: path.getWindingRule());
282: dst.append(path, false);
283: return dst;
284: }
285:
286: public static String toString(java.awt.Shape shape) {
287: return shape.getClass().getName()
288: + "\n"
289: + PathIterator
290: .toString(shape.getPathIterator(null));
291: }
292:
293: public static void drawColored(java.awt.Shape shape,
294: Graphics2D g) {
295: java.awt.geom.PathIterator path = shape
296: .getPathIterator(null);
297: float cx = 0;
298: float cy = 0;
299: float coords[] = new float[6];
300: while (!path.isDone()) {
301: switch (path.currentSegment(coords)) {
302: case java.awt.geom.PathIterator.SEG_MOVETO:
303: cx = coords[0];
304: cy = coords[1];
305: break;
306: case java.awt.geom.PathIterator.SEG_LINETO:
307: g.setColor(Color.blue);
308: g.draw(new Line2D.Float(cx, cy, cx = coords[0],
309: cy = coords[1]));
310: break;
311: case java.awt.geom.PathIterator.SEG_QUADTO:
312: g.setColor(Color.green);
313: g.draw(new QuadCurve2D.Float(cx, cy, coords[0],
314: coords[1], cx = coords[2], cy = coords[3]));
315: break;
316: case java.awt.geom.PathIterator.SEG_CUBICTO:
317: g.setColor(Color.red);
318: g.draw(new CubicCurve2D.Float(cx, cy, coords[0],
319: coords[1], coords[2], coords[3],
320: cx = coords[4], cy = coords[5]));
321: break;
322: case java.awt.geom.PathIterator.SEG_CLOSE:
323: break;
324: }
325: path.next();
326: }
327: }
328:
329: }
330:
331: public static class BasicStroke {
332:
333: static String propName[] = new String[] { "width", "cap",
334: "join", "miter", "dash", "phase" };
335: static String capName[] = new String[] { "BUTT", "ROUND",
336: "SQUARE" };
337: static String joinName[] = new String[] { "MITER", "ROUND",
338: "BEVEL" };
339:
340: public static void save(java.awt.BasicStroke bs, String fileName) {
341: try {
342: FileWriter f = new FileWriter(fileName);
343: save(bs, f);
344: f.close();
345: } catch (IOException e) {
346: Assert.fail("Can''t write to file " + fileName);
347: }
348: }
349:
350: public static void save(java.awt.BasicStroke bs, Writer f)
351: throws IOException {
352: f.write("width " + bs.getLineWidth() + "\n");
353: f.write("cap " + capName[bs.getEndCap()] + "\n");
354: f.write("join " + joinName[bs.getLineJoin()] + "\n");
355: f.write("miter " + bs.getMiterLimit() + "\n");
356: float dash[] = bs.getDashArray();
357: if (dash != null) {
358: String str = "";
359: for (float element : dash) {
360: str = str + element + " ";
361: }
362: f.write("dash " + str + "\n");
363: f.write("phase " + bs.getDashPhase());
364: }
365: }
366:
367: public static java.awt.BasicStroke load(String fileName) {
368: java.awt.BasicStroke bs = null;
369: try {
370: FileReader f = new FileReader(fileName);
371: bs = load(f);
372: f.close();
373: } catch (IOException e) {
374: Assert.fail("Can''t read file " + fileName);
375: }
376: return bs;
377: }
378:
379: public static java.awt.BasicStroke load(Reader f)
380: throws IOException {
381: // Set default values
382: java.awt.BasicStroke bs = new java.awt.BasicStroke();
383: float width = bs.getLineWidth();
384: int cap = bs.getEndCap();
385: int join = bs.getLineJoin();
386: float miterLimit = bs.getMiterLimit();
387: float dash[] = bs.getDashArray();
388: float dashPhase = bs.getDashPhase();
389:
390: int prop = -1;
391: int dashCount = 0;
392: StreamTokenizer t = new StreamTokenizer(f);
393:
394: while (t.nextToken() != StreamTokenizer.TT_EOF) {
395: switch (t.ttype) {
396: case StreamTokenizer.TT_EOL:
397: break;
398: case StreamTokenizer.TT_WORD:
399: switch (prop) {
400: case 4: // dash
401: float tmp[] = new float[dashCount];
402: System.arraycopy(dash, 0, tmp, 0, dashCount);
403: dash = tmp;
404: case -1:
405: prop = findString(propName, t.sval);
406: break;
407: case 1: // cap
408: cap = findString(capName, t.sval);
409: prop = -1;
410: break;
411: case 2: // join
412: join = findString(joinName, t.sval);
413: prop = -1;
414: break;
415: }
416: break;
417: case StreamTokenizer.TT_NUMBER:
418: switch (prop) {
419: case 0: // width
420: width = (float) t.nval;
421: prop = -1;
422: break;
423: case 3: // miterLimit
424: miterLimit = (float) t.nval;
425: prop = -1;
426: break;
427: case 4: // dash
428: if (dash == null) {
429: dash = new float[10];
430: dashCount = 0;
431: }
432: dash[dashCount++] = (float) t.nval;
433: break;
434: case 5: // dashPhase
435: dashPhase = (float) t.nval;
436: prop = -1;
437: break;
438: }
439: break;
440: }
441: }
442: return new java.awt.BasicStroke(width, cap, join,
443: miterLimit, dash, dashPhase);
444: }
445:
446: }
447:
448: public static class BufferedImage {
449:
450: public static java.awt.image.BufferedImage load(String filename) {
451: java.awt.image.BufferedImage img = null;
452: try {
453: // Code should be enabled when imageio is supported
454: // img = ImageIO.read(new java.io.File(filename));
455: return null;
456: } catch (Exception e) {
457: Assert.fail("Can't open file: " + filename);
458: }
459: return img;
460: }
461:
462: public static void save(java.awt.image.BufferedImage img,
463: String filename) {
464: try {
465: // Code should be enabled when imageio is supported
466: // ImageIO.write(img, "jpg", new java.io.File(filename));
467: } catch (Exception e) {
468: Assert.fail("Can't save file: " + filename);
469: }
470: }
471:
472: public static java.awt.image.BufferedImage loadIcon(
473: String filename) {
474: try {
475: // Code should be enabled when imageio is supported
476: // return ImageIO.read(new java.io.File(filename));
477: } catch (Exception e) {
478: Assert.fail("Can't open file: " + filename);
479: }
480: return null;
481: }
482:
483: public static void saveIcon(java.awt.image.BufferedImage img,
484: String filename) {
485: try {
486: // Code should be enabled when imageio is supported
487: // ImageIO.write(img, "png", new java.io.File(filename));
488: } catch (Exception e) {
489: Assert.fail("Can't save file: " + filename);
490: }
491: }
492:
493: }
494:
495: public static class File {
496:
497: public static String changeExt(String file, String newExt) {
498: int k = file.lastIndexOf(".");
499: return file.substring(0, k) + newExt;
500: }
501:
502: public static String extractFileName(String file) {
503: int k;
504: if ((k = file.lastIndexOf("/")) == -1) {
505: if ((k = file.lastIndexOf("\\")) == -1) {
506: k = 1;
507: }
508: }
509: return file.substring(k + 1);
510: }
511:
512: public static String extractFileExt(String file) {
513: int k = file.lastIndexOf(".");
514: return file.substring(k + 1);
515: }
516:
517: }
518:
519: public static class PathIterator {
520:
521: public static String equalsError = "";
522:
523: static boolean coordsEquals(double coords1[], double coords2[],
524: int count, double delta) {
525: for (int i = 0; i < count; i++) {
526: if (Math.abs(coords1[i] - coords2[i]) > delta) {
527: return false;
528: }
529: }
530: return true;
531: }
532:
533: static boolean coordsEquals(float coords1[], float coords2[],
534: int count, float delta) {
535: for (int i = 0; i < count; i++) {
536: if (Math.abs(coords1[i] - coords2[i]) > delta) {
537: return false;
538: }
539: }
540: return true;
541: }
542:
543: public static boolean equals(java.awt.geom.PathIterator p1,
544: java.awt.geom.PathIterator p2, double delta) {
545: equalsError = "";
546: if (p1.getWindingRule() != p2.getWindingRule()) {
547: equalsError = "WindingRule expected "
548: + p1.getWindingRule() + " but was "
549: + p2.getWindingRule();
550: return false;
551: }
552: int count = 0;
553: double coords1[] = new double[6];
554: double coords2[] = new double[6];
555: while (!p1.isDone() && !p2.isDone()) {
556: int type1 = p1.currentSegment(coords1);
557: int type2 = p2.currentSegment(coords2);
558: if (type1 != type2
559: || !coordsEquals(coords1, coords2,
560: Shape.pointCount[type1], delta)) {
561: equalsError = "Expected #" + count + " segment "
562: + typeName[type1]
563: + Arrays.toString(coords1) + " but was "
564: + typeName[type2]
565: + Arrays.toString(coords2);
566: return false;
567: }
568: p1.next();
569: p2.next();
570: count++;
571: }
572: if (p1.isDone() != p2.isDone()) {
573: equalsError = "Expected #" + count + " isDone "
574: + p1.isDone() + " but was " + p2.isDone();
575: return false;
576: }
577: return true;
578: }
579:
580: public static boolean equals(java.awt.geom.PathIterator p1,
581: java.awt.geom.PathIterator p2, float delta) {
582: if (p1.getWindingRule() != p2.getWindingRule()) {
583: return false;
584: }
585: float coords1[] = new float[6];
586: float coords2[] = new float[6];
587: while (!p1.isDone() && !p2.isDone()) {
588: int type1 = p1.currentSegment(coords1);
589: int type2 = p2.currentSegment(coords2);
590: if (type1 != type2
591: || !coordsEquals(coords1, coords2,
592: Shape.pointCount[type1], delta)) {
593: return false;
594: }
595: p1.next();
596: p2.next();
597: }
598: if (p1.isDone() != p2.isDone()) {
599: return false;
600: }
601: return true;
602: }
603:
604: public static String toString(java.awt.geom.PathIterator path) {
605: String out = "";
606: float coords[] = new float[6];
607: while (!path.isDone()) {
608: switch (path.currentSegment(coords)) {
609: case java.awt.geom.PathIterator.SEG_MOVETO:
610: out += "move(" + coords[0] + "," + coords[1]
611: + ")\n";
612: break;
613: case java.awt.geom.PathIterator.SEG_LINETO:
614: out += "line(" + coords[0] + "," + coords[1]
615: + ")\n";
616: break;
617: case java.awt.geom.PathIterator.SEG_QUADTO:
618: out += "quad(" + coords[0] + "," + coords[1] + ","
619: + coords[2] + "," + coords[3] + ")\n";
620: break;
621: case java.awt.geom.PathIterator.SEG_CUBICTO:
622: out += "cubic(" + coords[0] + "," + coords[1] + ","
623: + coords[2] + "," + coords[3] + ","
624: + coords[4] + "," + coords[5] + ")\n";
625: break;
626: case java.awt.geom.PathIterator.SEG_CLOSE:
627: out += "close\n";
628: break;
629: }
630: path.next();
631: }
632: out += "done\n";
633: return out;
634: }
635: }
636:
637: public static class MultiRectArea {
638:
639: public final static Color[] color = new Color[] { Color.blue,
640: Color.green, Color.red, Color.yellow, Color.MAGENTA,
641: Color.orange, Color.lightGray, Color.cyan, Color.pink };
642:
643: public final static Color[] colorBlue = new Color[] {
644: new Color(0x3F), new Color(0x5F), new Color(0x7F),
645: new Color(0x9F), new Color(0xBF), new Color(0xDF),
646: new Color(0xFF) };
647:
648: public final static Color[] colorGreen = new Color[] {
649: new Color(0x3F00), new Color(0x5F00),
650: new Color(0x7F00), new Color(0x9F00),
651: new Color(0xBF00), new Color(0xDF00), new Color(0xFF00) };
652:
653: static final int BORDER = 30;
654: static final Color colorBack = Color.white;
655:
656: public static void save(
657: org.apache.harmony.awt.gl.MultiRectArea area,
658: String fileName) {
659: try {
660: FileWriter f = new FileWriter(fileName);
661: Rectangle[] rect = area.getRectangles();
662: for (Rectangle element : rect) {
663: f.write(element.x + "," + element.y + ","
664: + (element.width + element.x - 1) + ","
665: + (element.height + element.y - 1) + "\n");
666: }
667: f.close();
668: } catch (IOException e) {
669: Assert.fail("Can''t write to file " + fileName);
670: }
671: }
672:
673: public static org.apache.harmony.awt.gl.MultiRectArea load(
674: String fileName) {
675: org.apache.harmony.awt.gl.MultiRectArea area = null;
676: try {
677: int[] buf = MultiRectAreaOp.createBuf(0);
678: int count = 1;
679:
680: FileReader f = new FileReader(fileName);
681: StreamTokenizer t = new StreamTokenizer(f);
682: while (t.nextToken() != StreamTokenizer.TT_EOF) {
683: if (t.ttype == StreamTokenizer.TT_NUMBER) {
684: buf = MultiRectAreaOp.checkBufSize(buf, 1);
685: buf[count++] = (int) t.nval;
686: }
687: }
688: f.close();
689:
690: int j = 0;
691: Rectangle[] rect = new Rectangle[(count - 1) / 4];
692: for (int i = 1; i < count; i += 4) {
693: rect[j++] = new Rectangle(buf[i], buf[i + 1],
694: buf[i + 2] - buf[i] + 1, buf[i + 3]
695: - buf[i + 1] + 1);
696: }
697: area = new org.apache.harmony.awt.gl.MultiRectArea(rect);
698: } catch (IOException e) {
699: Assert.fail("Can''t read file " + fileName);
700: }
701: return area;
702: }
703:
704: public static java.awt.image.BufferedImage createImage(
705: org.apache.harmony.awt.gl.MultiRectArea area) {
706: return createImage(area, color);
707: }
708:
709: public static java.awt.image.BufferedImage createImage(
710: org.apache.harmony.awt.gl.MultiRectArea area,
711: Color[] palette) {
712:
713: // Calculate image border
714: Rectangle bounds = area.getBounds();
715: int width = bounds.x + bounds.width + BORDER;
716: int height = bounds.y + bounds.height + BORDER;
717:
718: java.awt.image.BufferedImage img = new java.awt.image.BufferedImage(
719: width, height,
720: java.awt.image.BufferedImage.TYPE_INT_RGB);
721:
722: Graphics g = img.getGraphics();
723:
724: // Background
725: g.setColor(colorBack);
726: g.fillRect(0, 0, img.getWidth(), img.getHeight());
727:
728: Rectangle[] rect = area.getRectangles();
729: for (int i = 0; i < rect.length; i++) {
730: g.setColor(palette[i % palette.length]);
731: g.fillRect(rect[i].x, rect[i].y, rect[i].width,
732: rect[i].height);
733: }
734: return img;
735: }
736:
737: }
738:
739: }
|