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 org.apache.cocoon.generation.asciiart;
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021: import java.util.List;
022: import org.apache.regexp.RE;
023: import org.apache.regexp.RESyntaxException;
024:
025: /**
026: * A drawing ascii art pad.
027: *
028: * @author huber@apache.org
029: * @since 18. Dezember 2002
030: * @version CVS $Id: AsciiArtPad.java 433543 2006-08-22 06:22:54Z crossley $
031: */
032: public class AsciiArtPad {
033:
034: private int width;
035: private int height;
036:
037: /**
038: * List of AsciiArt elements
039: */
040: private List pad;
041:
042: private double xGrid;
043: private double yGrid;
044:
045: /**
046: *Constructor for the AsciiArtPad object
047: */
048: public AsciiArtPad() {
049: pad = new ArrayList();
050: }
051:
052: /**
053: *Constructor for the AsciiArtPad object
054: *
055: *@param w Description of the Parameter
056: *@param h Description of the Parameter
057: */
058: public AsciiArtPad(int w, int h) {
059: width = w;
060: height = h;
061:
062: pad = new ArrayList();
063: }
064:
065: /**
066: * Sets the width attribute of the AsciiArtPad object
067: *
068: *@param width The new width value
069: */
070: public void setWidth(int width) {
071: this .width = width;
072: }
073:
074: /**
075: * Sets the height attribute of the AsciiArtPad object
076: *
077: *@param height The new height value
078: */
079: public void setHeight(int height) {
080: this .height = height;
081: }
082:
083: /**
084: * Sets the xGrid attribute of the AsciiArtPad object
085: *
086: *@param xGrid The new xGrid value
087: */
088: public void setXGrid(double xGrid) {
089: this .xGrid = xGrid;
090: }
091:
092: /**
093: * Sets the yGrid attribute of the AsciiArtPad object
094: *
095: *@param yGrid The new yGrid value
096: */
097: public void setYGrid(double yGrid) {
098: this .yGrid = yGrid;
099: }
100:
101: /**
102: * Gets the width attribute of the AsciiArtPad object
103: *
104: *@return The width value
105: */
106: public int getWidth() {
107: return width;
108: }
109:
110: /**
111: * Gets the height attribute of the AsciiArtPad object
112: *
113: *@return The height value
114: */
115: public int getHeight() {
116: return height;
117: }
118:
119: /**
120: * Gets the xGrid attribute of the AsciiArtPad object
121: *
122: *@return The xGrid value
123: */
124: public double getXGrid() {
125: return xGrid;
126: }
127:
128: /**
129: * Gets the yGrid attribute of the AsciiArtPad object
130: *
131: *@return The yGrid value
132: */
133: public double getYGrid() {
134: return yGrid;
135: }
136:
137: /**
138: * Add a AsciiArtElement
139: *
140: *@param o the AsciiArtElement object
141: */
142: public void add(Object o) {
143: pad.add(o);
144: }
145:
146: /**
147: * Iterator of AsciiArtPad
148: *
149: *@return Iterator iterating over all AsciiArtElements
150: */
151: public Iterator iterator() {
152: return pad.iterator();
153: }
154:
155: /**
156: * An AsciiArtElement describing a line.
157: *
158: */
159: public static class AsciiArtLine implements AsciiArtElement {
160: double xStart;
161: double yStart;
162: double xEnd;
163: double yEnd;
164:
165: /**
166: *Constructor for the AsciiArtLine object
167: *
168: *@param start Description of the Parameter
169: *@param end Description of the Parameter
170: */
171: public AsciiArtLine(AsciiArtCoordinate start,
172: AsciiArtCoordinate end) {
173: xStart = start.getXDouble();
174: yStart = start.getYDouble();
175: xEnd = end.getXDouble();
176: yEnd = end.getYDouble();
177: }
178:
179: /**
180: * Sets the xStart attribute of the AsciiArtLine object
181: *
182: *@param xStart The new xStart value
183: */
184: public void setXStart(double xStart) {
185: this .xStart = xStart;
186: }
187:
188: /**
189: * Sets the yStart attribute of the AsciiArtLine object
190: *
191: *@param yStart The new yStart value
192: */
193: public void setYStart(double yStart) {
194: this .yStart = yStart;
195: }
196:
197: /**
198: * Sets the xEnd attribute of the AsciiArtLine object
199: *
200: *@param xEnd The new xEnd value
201: */
202: public void setXEnd(double xEnd) {
203: this .xEnd = xEnd;
204: }
205:
206: /**
207: * Sets the yEnd attribute of the AsciiArtLine object
208: *
209: *@param yEnd The new yEnd value
210: */
211: public void setYEnd(double yEnd) {
212: this .yEnd = yEnd;
213: }
214:
215: /**
216: * Gets the xStart attribute of the AsciiArtLine object
217: *
218: *@return The xStart value
219: */
220: public double getXStart() {
221: return xStart;
222: }
223:
224: /**
225: * Gets the yStart attribute of the AsciiArtLine object
226: *
227: *@return The yStart value
228: */
229: public double getYStart() {
230: return yStart;
231: }
232:
233: /**
234: * Gets the xEnd attribute of the AsciiArtLine object
235: *
236: *@return The xEnd value
237: */
238: public double getXEnd() {
239: return xEnd;
240: }
241:
242: /**
243: * Gets the yEnd attribute of the AsciiArtLine object
244: *
245: *@return The yEnd value
246: */
247: public double getYEnd() {
248: return yEnd;
249: }
250:
251: /**
252: * Descriptive string
253: *
254: *@return String
255: */
256: public String toString() {
257: String s = "[xStart:" + String.valueOf(xStart) + "]"
258: + "[yStart:" + String.valueOf(yStart) + "]"
259: + "[xEnd:" + String.valueOf(xEnd) + "]" + "[yEnd:"
260: + String.valueOf(yEnd) + "]";
261: return s;
262: }
263: }
264:
265: /**
266: * An AsciiArtElement describing a rectangle.
267: *
268: */
269: public static class AsciiArtRect implements AsciiArtElement {
270: double xUpperLeft;
271: double yUpperLeft;
272: double xLowerRight;
273: double yLowerRight;
274:
275: /**
276: *Constructor for the AsciiArtRect object
277: *
278: *@param upperLeft Description of the Parameter
279: *@param lowerRight Description of the Parameter
280: */
281: public AsciiArtRect(AsciiArtCoordinate upperLeft,
282: AsciiArtCoordinate lowerRight) {
283: xUpperLeft = upperLeft.getXDouble();
284: yUpperLeft = upperLeft.getYDouble();
285: xLowerRight = lowerRight.getXDouble();
286: yLowerRight = lowerRight.getYDouble();
287: }
288:
289: /**
290: * Sets the xUpperLeft attribute of the AsciiArtRect object
291: *
292: *@param xUpperLeft The new xUpperLeft value
293: */
294: public void setXUpperLeft(double xUpperLeft) {
295: this .xUpperLeft = xUpperLeft;
296: }
297:
298: /**
299: * Sets the yUpperLeft attribute of the AsciiArtRect object
300: *
301: *@param yUpperLeft The new yUpperLeft value
302: */
303: public void setYUpperLeft(double yUpperLeft) {
304: this .yUpperLeft = yUpperLeft;
305: }
306:
307: /**
308: * Sets the xLowerRight attribute of the AsciiArtRect object
309: *
310: *@param xLowerRight The new xLowerRight value
311: */
312: public void setXLowerRight(double xLowerRight) {
313: this .xLowerRight = xLowerRight;
314: }
315:
316: /**
317: * Sets the yLowerRight attribute of the AsciiArtRect object
318: *
319: *@param yLowerRight The new yLowerRight value
320: */
321: public void setYLowerRight(double yLowerRight) {
322: this .yLowerRight = yLowerRight;
323: }
324:
325: /**
326: * Gets the xUpperLeft attribute of the AsciiArtRect object
327: *
328: *@return The xUpperLeft value
329: */
330: public double getXUpperLeft() {
331: return xUpperLeft;
332: }
333:
334: /**
335: * Gets the yUpperLeft attribute of the AsciiArtRect object
336: *
337: *@return The yUpperLeft value
338: */
339: public double getYUpperLeft() {
340: return yUpperLeft;
341: }
342:
343: /**
344: * Gets the xLowerRight attribute of the AsciiArtRect object
345: *
346: *@return The xLowerRight value
347: */
348: public double getXLowerRight() {
349: return xLowerRight;
350: }
351:
352: /**
353: * Gets the yLowerRight attribute of the AsciiArtRect object
354: *
355: *@return The yLowerRight value
356: */
357: public double getYLowerRight() {
358: return yLowerRight;
359: }
360:
361: /**
362: * Gets the width attribute of the AsciiArtRect object
363: *
364: *@return The width value
365: */
366: public double getWidth() {
367: return Math.abs(xUpperLeft - xLowerRight);
368: }
369:
370: /**
371: * Gets the height attribute of the AsciiArtRect object
372: *
373: *@return The height value
374: */
375: public double getHeight() {
376: return Math.abs(yUpperLeft - yLowerRight);
377: }
378:
379: /**
380: * Descriptive string
381: *
382: *@return String
383: */
384: public String toString() {
385: String s = "[xUpperLeft:" + String.valueOf(xUpperLeft)
386: + "]" + "[yUpperLeft:" + String.valueOf(yUpperLeft)
387: + "]" + "[xLowerRight:"
388: + String.valueOf(xLowerRight) + "]"
389: + "[yLowerRight:" + String.valueOf(yLowerRight)
390: + "]";
391: return s;
392: }
393: }
394:
395: /**
396: * An AsciiArtElement describing a string of text.
397: *
398: */
399: public static class AsciiArtString implements AsciiArtElement {
400: private double x;
401: private double y;
402: private String s;
403:
404: /**
405: *Constructor for the AsciiArtString object
406: *
407: *@param s Description of the Parameter
408: *@param aac Description of the Parameter
409: */
410: public AsciiArtString(AsciiArtCoordinate aac, String s) {
411: this .x = aac.getXDouble();
412: this .y = aac.getYDouble();
413: this .s = s;
414: }
415:
416: /**
417: * Sets the x attribute of the AsciiArtString object
418: *
419: *@param x The new x value
420: */
421: public void setX(double x) {
422: this .x = x;
423: }
424:
425: /**
426: * Sets the y attribute of the AsciiArtString object
427: *
428: *@param y The new y value
429: */
430: public void setY(double y) {
431: this .y = y;
432: }
433:
434: /**
435: * Sets the s attribute of the AsciiArtString object
436: *
437: *@param s The new s value
438: */
439: public void setS(String s) {
440: this .s = s;
441: }
442:
443: /**
444: * Gets the x attribute of the AsciiArtString object
445: *
446: *@return The x value
447: */
448: public double getX() {
449: return x;
450: }
451:
452: /**
453: * Gets the y attribute of the AsciiArtString object
454: *
455: *@return The y value
456: */
457: public double getY() {
458: return y;
459: }
460:
461: /**
462: * Gets the s attribute of the AsciiArtString object
463: *
464: *@return The s value
465: */
466: public String getS() {
467: return s;
468: }
469:
470: /**
471: * Descriptive string
472: *
473: *@return String
474: */
475: public String toString() {
476: String s = "[x:" + String.valueOf(x) + "]" + "[y:"
477: + String.valueOf(y) + "]" + "[s:"
478: + String.valueOf(this .s) + "]";
479: return s;
480: }
481: }
482:
483: /**
484: * Helper class describing a coordinate of AsciiArtPad elements.
485: *
486: */
487: public static class AsciiArtCoordinate {
488: int x, y;
489: AsciiArtPad asciiArtPad;
490: double tx, ty;
491:
492: /**
493: *Constructor for the AsciiArtCoordinate object
494: */
495: public AsciiArtCoordinate() {
496: }
497:
498: /**
499: *Constructor for the AsciiArtCoordinate object
500: *
501: *@param asciiArtPad Description of the Parameter
502: */
503: public AsciiArtCoordinate(AsciiArtPad asciiArtPad) {
504: setAsciiArtPad(asciiArtPad);
505: }
506:
507: /**
508: *Constructor for the AsciiArtCoordinate object
509: *
510: *@param x Description of the Parameter
511: *@param y Description of the Parameter
512: */
513: public AsciiArtCoordinate(int x, int y) {
514: setXY(x, y);
515: }
516:
517: /**
518: * Sets the asciiArtPad attribute of the AsciiArtCoordinate object
519: *
520: *@param asciiArtPad The new asciiArtPad value
521: */
522: public void setAsciiArtPad(AsciiArtPad asciiArtPad) {
523: this .asciiArtPad = asciiArtPad;
524: }
525:
526: /**
527: * Sets the xY attribute of the AsciiArtCoordinate object
528: *
529: *@param tx The new transXY value
530: *@param ty The new transXY value
531: */
532: public void setTransXY(double tx, double ty) {
533: this .tx = tx;
534: this .ty = ty;
535: }
536:
537: /**
538: * Sets the xY attribute of the AsciiArtCoordinate object
539: *
540: *@param x The new xY value
541: *@param y The new xY value
542: */
543: public void setXY(int x, int y) {
544: this .x = x;
545: this .y = y;
546: }
547:
548: /**
549: * Gets the xDouble attribute of the AsciiArtCoordinate object
550: *
551: *@return The xDouble value
552: */
553: public double getXDouble() {
554: return x * asciiArtPad.getXGrid() + tx;
555: }
556:
557: /**
558: * Gets the yDouble attribute of the AsciiArtCoordinate object
559: *
560: *@return The yDouble value
561: */
562: public double getYDouble() {
563: return y * asciiArtPad.getYGrid() + ty;
564: }
565: }
566:
567: /**
568: * Helper class containing the ascii text data,
569: * acting as input of an AsciiArtPad
570: *
571: */
572: public static class AsciiArt {
573: private String[] s;
574: private int w;
575: private int h;
576:
577: /**
578: *Constructor for the AsciiArt object
579: *
580: *@param s Description of the Parameter
581: */
582: public AsciiArt(String[] s) {
583: this .s = s;
584: int length = s.length;
585: h = length;
586: w = 0;
587: for (int i = 0; i < length; i++) {
588: String line = s[i];
589: if (line != null && line.length() > w) {
590: w = line.length();
591: }
592: }
593: }
594:
595: /**
596: * Gets the w attribute of the AsciiArt object
597: *
598: *@return The w value
599: */
600: public int getW() {
601: return w;
602: }
603:
604: /**
605: * Gets the h attribute of the AsciiArt object
606: *
607: *@return The h value
608: */
609: public int getH() {
610: return h;
611: }
612:
613: /**
614: * Gets the row attribute of the AsciiArt object
615: *
616: *@param r Description of the Parameter
617: *@return The row value
618: */
619: public String getRow(int r) {
620: String row = this .s[r];
621: return row;
622: }
623:
624: /**
625: * Gets the column attribute of the AsciiArt object
626: *
627: *@param c Description of the Parameter
628: *@return The column value
629: */
630: public String getColumn(int c) {
631: StringBuffer column = new StringBuffer();
632:
633: final String EMPTY_CHAR = " ";
634: for (int i = 0; i < s.length; i++) {
635: if (s[i] != null && c < s[i].length()) {
636: column.append(s[i].charAt(c));
637: } else {
638: column.append(EMPTY_CHAR);
639: }
640: }
641: return column.toString();
642: }
643: }
644:
645: /**
646: * Builder of AsciiArtElements from an AsciiArt input.
647: *
648: */
649: public static class AsciiArtPadBuilder {
650: private AsciiArtPad asciiArtPad;
651: private AsciiArt aa;
652:
653: final static String EDGE_GROUP = "[+\\\\/]";
654: final static String HLINE_GROUP = "[\\-~=+]";
655: final static String VLINE_GROUP = "[|+]";
656:
657: final static String STRING_SUFFIX_GROUP = "[^\\-|~=\\/+ \\\\]";
658: //final static String STRING_PREFIX_GROUP = "[a-zA-Z0-9_\\*;\\.#]";
659: final static String STRING_PREFIX_GROUP = STRING_SUFFIX_GROUP;
660:
661: /**
662: *Constructor for the AsciiArtPadBuilder object
663: *
664: *@param asciiArtPad Description of the Parameter
665: */
666: public AsciiArtPadBuilder(AsciiArtPad asciiArtPad) {
667: this .asciiArtPad = asciiArtPad;
668: }
669:
670: /**
671: * Build AsciiArtElement from an asciiArt
672: *
673: *@param asciiArt Description of the Parameter
674: */
675: public void build(String[] asciiArt) {
676: aa = new AsciiArt(asciiArt);
677: asciiArtPad.setWidth(aa.getW());
678: asciiArtPad.setHeight(aa.getH());
679:
680: // find asciiArt patterns
681: findRectPattern();
682: findCornerPattern();
683: findLinePattern();
684: findStringPattern();
685: }
686:
687: /**
688: * Find rectangles in the AsciiArt.
689: * not implemented yet.
690: */
691: protected void findRectPattern() {
692: }
693:
694: /**
695: * Find corners in the AsciiArt
696: */
697: protected void findCornerPattern() {
698: AsciiArtCoordinate aacStart = new AsciiArtCoordinate(
699: this .asciiArtPad);
700: aacStart.setTransXY(0, asciiArtPad.getYGrid() / 2);
701: AsciiArtCoordinate aacEnd = new AsciiArtCoordinate(
702: this .asciiArtPad);
703: aacEnd.setTransXY(0, asciiArtPad.getYGrid() / 2);
704:
705: // hor line
706: try {
707: final RE reCorner = new RE(EDGE_GROUP);
708: for (int r = 0; r < aa.getH(); r++) {
709: String row = aa.getRow(r);
710: int startIndex = 0;
711: while (reCorner.match(row, startIndex)) {
712: String s = reCorner.getParen(0);
713: int mStart = reCorner.getParenStart(0);
714: int mEnd = reCorner.getParenEnd(0);
715:
716: if (s.equals("\\")) {
717: aacStart.setXY(mStart, r - 1);
718: aacEnd.setXY(mStart + 1, r);
719: } else if (s.equals("/")) {
720: aacStart.setXY(mStart + 1, r - 1);
721: aacEnd.setXY(mStart, r);
722: } else {
723: aacStart.setXY(mStart, r);
724: aacEnd.setXY(mStart, r);
725: }
726: AsciiArtLine aal = new AsciiArtLine(aacStart,
727: aacEnd);
728: this .asciiArtPad.add(aal);
729:
730: if (startIndex >= mEnd) {
731: break;
732: }
733: startIndex = mEnd;
734: }
735: }
736: } catch (RESyntaxException rese) {
737: rese.printStackTrace();
738: }
739:
740: }
741:
742: /**
743: * Find lines in the AsciiArt
744: */
745: protected void findLinePattern() {
746: AsciiArtCoordinate aacStart = new AsciiArtCoordinate(
747: this .asciiArtPad);
748: aacStart.setTransXY(0, asciiArtPad.getYGrid() / 2);
749: AsciiArtCoordinate aacEnd = new AsciiArtCoordinate(
750: this .asciiArtPad);
751: aacEnd.setTransXY(0, asciiArtPad.getYGrid() / 2);
752:
753: // hor line
754: try {
755: final RE reHorLine = new RE(HLINE_GROUP + "+");
756: for (int r = 0; r < aa.getH(); r++) {
757: String row = aa.getRow(r);
758: int startIndex = 0;
759: while (reHorLine.match(row, startIndex)) {
760: int mStart = reHorLine.getParenStart(0);
761: int mEnd = reHorLine.getParenEnd(0);
762:
763: aacStart.setXY(mStart, r);
764: aacEnd.setXY(mEnd - 1, r);
765: AsciiArtLine aal = new AsciiArtLine(aacStart,
766: aacEnd);
767: this .asciiArtPad.add(aal);
768:
769: if (startIndex >= mEnd) {
770: break;
771: }
772: startIndex = mEnd;
773: }
774: }
775: } catch (RESyntaxException rese) {
776: rese.printStackTrace();
777: }
778:
779: // ver line
780: try {
781: RE reVerLine = new RE(VLINE_GROUP + "+");
782: for (int c = 0; c < aa.getW(); c++) {
783: String col = aa.getColumn(c);
784: int startIndex = 0;
785: while (reVerLine.match(col, startIndex)) {
786: int mStart = reVerLine.getParenStart(0);
787: int mEnd = reVerLine.getParenEnd(0);
788:
789: aacStart.setXY(c, mStart);
790: aacEnd.setXY(c, mEnd - 1);
791: AsciiArtLine aal = new AsciiArtLine(aacStart,
792: aacEnd);
793: this .asciiArtPad.add(aal);
794:
795: if (startIndex >= mEnd) {
796: break;
797: }
798: startIndex = mEnd;
799: }
800: }
801: } catch (RESyntaxException rese) {
802: rese.printStackTrace();
803: }
804: }
805:
806: /**
807: * Find string text in the AsciiArt.
808: */
809: protected void findStringPattern() {
810: AsciiArtCoordinate aacStart = new AsciiArtCoordinate(
811: this .asciiArtPad);
812: aacStart.setTransXY(0, 3 * asciiArtPad.getYGrid() / 4);
813: // string
814: try {
815: final RE reString = new RE(STRING_PREFIX_GROUP
816: + STRING_SUFFIX_GROUP + "*");
817: for (int r = 0; r < aa.getH(); r++) {
818: String row = aa.getRow(r);
819: int startIndex = 0;
820: while (reString.match(row, startIndex)) {
821: String s = reString.getParen(0);
822: int mStart = reString.getParenStart(0);
823: int mEnd = reString.getParenEnd(0);
824:
825: aacStart.setXY(mStart, r);
826: AsciiArtString aas = new AsciiArtString(
827: aacStart, s);
828: this .asciiArtPad.add(aas);
829:
830: if (startIndex >= mEnd) {
831: break;
832: }
833: startIndex = mEnd;
834: }
835: }
836: } catch (RESyntaxException rese) {
837: rese.printStackTrace();
838: }
839: }
840:
841: }
842:
843: /**
844: * Marker interface of objects addable to the AsciiArtPad
845: *
846: */
847: public static interface AsciiArtElement {
848: }
849: }
|