/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.generation.asciiart; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.regexp.RE; import org.apache.regexp.RESyntaxException; /** * A drawing ascii art pad. * * @author huber@apache.org * @since 18. Dezember 2002 * @version CVS $Id$ */ public class AsciiArtPad { private int width; private int height; /** * List of AsciiArt elements */ private List pad; private double xGrid; private double yGrid; /** *Constructor for the AsciiArtPad object */ public AsciiArtPad() { pad = new ArrayList(); } /** *Constructor for the AsciiArtPad object * *@param w Description of the Parameter *@param h Description of the Parameter */ public AsciiArtPad(int w, int h) { width = w; height = h; pad = new ArrayList(); } /** * Sets the width attribute of the AsciiArtPad object * *@param width The new width value */ public void setWidth(int width) { this.width = width; } /** * Sets the height attribute of the AsciiArtPad object * *@param height The new height value */ public void setHeight(int height) { this.height = height; } /** * Sets the xGrid attribute of the AsciiArtPad object * *@param xGrid The new xGrid value */ public void setXGrid(double xGrid) { this.xGrid = xGrid; } /** * Sets the yGrid attribute of the AsciiArtPad object * *@param yGrid The new yGrid value */ public void setYGrid(double yGrid) { this.yGrid = yGrid; } /** * Gets the width attribute of the AsciiArtPad object * *@return The width value */ public int getWidth() { return width; } /** * Gets the height attribute of the AsciiArtPad object * *@return The height value */ public int getHeight() { return height; } /** * Gets the xGrid attribute of the AsciiArtPad object * *@return The xGrid value */ public double getXGrid() { return xGrid; } /** * Gets the yGrid attribute of the AsciiArtPad object * *@return The yGrid value */ public double getYGrid() { return yGrid; } /** * Add a AsciiArtElement * *@param o the AsciiArtElement object */ public void add(Object o) { pad.add(o); } /** * Iterator of AsciiArtPad * *@return Iterator iterating over all AsciiArtElements */ public Iterator iterator() { return pad.iterator(); } /** * An AsciiArtElement describing a line. * */ public static class AsciiArtLine implements AsciiArtElement { double xStart; double yStart; double xEnd; double yEnd; /** *Constructor for the AsciiArtLine object * *@param start Description of the Parameter *@param end Description of the Parameter */ public AsciiArtLine(AsciiArtCoordinate start, AsciiArtCoordinate end) { xStart = start.getXDouble(); yStart = start.getYDouble(); xEnd = end.getXDouble(); yEnd = end.getYDouble(); } /** * Sets the xStart attribute of the AsciiArtLine object * *@param xStart The new xStart value */ public void setXStart(double xStart) { this.xStart = xStart; } /** * Sets the yStart attribute of the AsciiArtLine object * *@param yStart The new yStart value */ public void setYStart(double yStart) { this.yStart = yStart; } /** * Sets the xEnd attribute of the AsciiArtLine object * *@param xEnd The new xEnd value */ public void setXEnd(double xEnd) { this.xEnd = xEnd; } /** * Sets the yEnd attribute of the AsciiArtLine object * *@param yEnd The new yEnd value */ public void setYEnd(double yEnd) { this.yEnd = yEnd; } /** * Gets the xStart attribute of the AsciiArtLine object * *@return The xStart value */ public double getXStart() { return xStart; } /** * Gets the yStart attribute of the AsciiArtLine object * *@return The yStart value */ public double getYStart() { return yStart; } /** * Gets the xEnd attribute of the AsciiArtLine object * *@return The xEnd value */ public double getXEnd() { return xEnd; } /** * Gets the yEnd attribute of the AsciiArtLine object * *@return The yEnd value */ public double getYEnd() { return yEnd; } /** * Descriptive string * *@return String */ public String toString() { String s = "[xStart:" + String.valueOf(xStart) + "]" + "[yStart:" + String.valueOf(yStart) + "]" + "[xEnd:" + String.valueOf(xEnd) + "]" + "[yEnd:" + String.valueOf(yEnd) + "]"; return s; } } /** * An AsciiArtElement describing a rectangle. * */ public static class AsciiArtRect implements AsciiArtElement { double xUpperLeft; double yUpperLeft; double xLowerRight; double yLowerRight; /** *Constructor for the AsciiArtRect object * *@param upperLeft Description of the Parameter *@param lowerRight Description of the Parameter */ public AsciiArtRect(AsciiArtCoordinate upperLeft, AsciiArtCoordinate lowerRight) { xUpperLeft = upperLeft.getXDouble(); yUpperLeft = upperLeft.getYDouble(); xLowerRight = lowerRight.getXDouble(); yLowerRight = lowerRight.getYDouble(); } /** * Sets the xUpperLeft attribute of the AsciiArtRect object * *@param xUpperLeft The new xUpperLeft value */ public void setXUpperLeft(double xUpperLeft) { this.xUpperLeft = xUpperLeft; } /** * Sets the yUpperLeft attribute of the AsciiArtRect object * *@param yUpperLeft The new yUpperLeft value */ public void setYUpperLeft(double yUpperLeft) { this.yUpperLeft = yUpperLeft; } /** * Sets the xLowerRight attribute of the AsciiArtRect object * *@param xLowerRight The new xLowerRight value */ public void setXLowerRight(double xLowerRight) { this.xLowerRight = xLowerRight; } /** * Sets the yLowerRight attribute of the AsciiArtRect object * *@param yLowerRight The new yLowerRight value */ public void setYLowerRight(double yLowerRight) { this.yLowerRight = yLowerRight; } /** * Gets the xUpperLeft attribute of the AsciiArtRect object * *@return The xUpperLeft value */ public double getXUpperLeft() { return xUpperLeft; } /** * Gets the yUpperLeft attribute of the AsciiArtRect object * *@return The yUpperLeft value */ public double getYUpperLeft() { return yUpperLeft; } /** * Gets the xLowerRight attribute of the AsciiArtRect object * *@return The xLowerRight value */ public double getXLowerRight() { return xLowerRight; } /** * Gets the yLowerRight attribute of the AsciiArtRect object * *@return The yLowerRight value */ public double getYLowerRight() { return yLowerRight; } /** * Gets the width attribute of the AsciiArtRect object * *@return The width value */ public double getWidth() { return Math.abs(xUpperLeft - xLowerRight); } /** * Gets the height attribute of the AsciiArtRect object * *@return The height value */ public double getHeight() { return Math.abs(yUpperLeft - yLowerRight); } /** * Descriptive string * *@return String */ public String toString() { String s = "[xUpperLeft:" + String.valueOf(xUpperLeft) + "]" + "[yUpperLeft:" + String.valueOf(yUpperLeft) + "]" + "[xLowerRight:" + String.valueOf(xLowerRight) + "]" + "[yLowerRight:" + String.valueOf(yLowerRight) + "]"; return s; } } /** * An AsciiArtElement describing a string of text. * */ public static class AsciiArtString implements AsciiArtElement { private double x; private double y; private String s; /** *Constructor for the AsciiArtString object * *@param s Description of the Parameter *@param aac Description of the Parameter */ public AsciiArtString(AsciiArtCoordinate aac, String s) { this.x = aac.getXDouble(); this.y = aac.getYDouble(); this.s = s; } /** * Sets the x attribute of the AsciiArtString object * *@param x The new x value */ public void setX(double x) { this.x = x; } /** * Sets the y attribute of the AsciiArtString object * *@param y The new y value */ public void setY(double y) { this.y = y; } /** * Sets the s attribute of the AsciiArtString object * *@param s The new s value */ public void setS(String s) { this.s = s; } /** * Gets the x attribute of the AsciiArtString object * *@return The x value */ public double getX() { return x; } /** * Gets the y attribute of the AsciiArtString object * *@return The y value */ public double getY() { return y; } /** * Gets the s attribute of the AsciiArtString object * *@return The s value */ public String getS() { return s; } /** * Descriptive string * *@return String */ public String toString() { String s = "[x:" + String.valueOf(x) + "]" + "[y:" + String.valueOf(y) + "]" + "[s:" + String.valueOf(this.s) + "]"; return s; } } /** * Helper class describing a coordinate of AsciiArtPad elements. * */ public static class AsciiArtCoordinate { int x, y; AsciiArtPad asciiArtPad; double tx, ty; /** *Constructor for the AsciiArtCoordinate object */ public AsciiArtCoordinate() { } /** *Constructor for the AsciiArtCoordinate object * *@param asciiArtPad Description of the Parameter */ public AsciiArtCoordinate(AsciiArtPad asciiArtPad) { setAsciiArtPad(asciiArtPad); } /** *Constructor for the AsciiArtCoordinate object * *@param x Description of the Parameter *@param y Description of the Parameter */ public AsciiArtCoordinate(int x, int y) { setXY(x, y); } /** * Sets the asciiArtPad attribute of the AsciiArtCoordinate object * *@param asciiArtPad The new asciiArtPad value */ public void setAsciiArtPad(AsciiArtPad asciiArtPad) { this.asciiArtPad = asciiArtPad; } /** * Sets the xY attribute of the AsciiArtCoordinate object * *@param tx The new transXY value *@param ty The new transXY value */ public void setTransXY(double tx, double ty) { this.tx = tx; this.ty = ty; } /** * Sets the xY attribute of the AsciiArtCoordinate object * *@param x The new xY value *@param y The new xY value */ public void setXY(int x, int y) { this.x = x; this.y = y; } /** * Gets the xDouble attribute of the AsciiArtCoordinate object * *@return The xDouble value */ public double getXDouble() { return x * asciiArtPad.getXGrid() + tx; } /** * Gets the yDouble attribute of the AsciiArtCoordinate object * *@return The yDouble value */ public double getYDouble() { return y * asciiArtPad.getYGrid() + ty; } } /** * Helper class containing the ascii text data, * acting as input of an AsciiArtPad * */ public static class AsciiArt { private String[] s; private int w; private int h; /** *Constructor for the AsciiArt object * *@param s Description of the Parameter */ public AsciiArt(String[] s) { this.s = s; int length = s.length; h = length; w = 0; for (int i = 0; i < length; i++) { String line = s[i]; if (line != null && line.length() > w) { w = line.length(); } } } /** * Gets the w attribute of the AsciiArt object * *@return The w value */ public int getW() { return w; } /** * Gets the h attribute of the AsciiArt object * *@return The h value */ public int getH() { return h; } /** * Gets the row attribute of the AsciiArt object * *@param r Description of the Parameter *@return The row value */ public String getRow(int r) { String row = this.s[r]; return row; } /** * Gets the column attribute of the AsciiArt object * *@param c Description of the Parameter *@return The column value */ public String getColumn(int c) { StringBuffer column = new StringBuffer(); final String EMPTY_CHAR = " "; for (int i = 0; i < s.length; i++) { if (s[i] != null && c < s[i].length()) { column.append(s[i].charAt(c)); } else { column.append(EMPTY_CHAR); } } return column.toString(); } } /** * Builder of AsciiArtElements from an AsciiArt input. * */ public static class AsciiArtPadBuilder { private AsciiArtPad asciiArtPad; private AsciiArt aa; final static String EDGE_GROUP = "[+\\\\/]"; final static String HLINE_GROUP = "[\\-~=+]"; final static String VLINE_GROUP = "[|+]"; final static String STRING_SUFFIX_GROUP = "[^\\-|~=\\/+ \\\\]"; //final static String STRING_PREFIX_GROUP = "[a-zA-Z0-9_\\*;\\.#]"; final static String STRING_PREFIX_GROUP = STRING_SUFFIX_GROUP; /** *Constructor for the AsciiArtPadBuilder object * *@param asciiArtPad Description of the Parameter */ public AsciiArtPadBuilder(AsciiArtPad asciiArtPad) { this.asciiArtPad = asciiArtPad; } /** * Build AsciiArtElement from an asciiArt * *@param asciiArt Description of the Parameter */ public void build(String[] asciiArt) { aa = new AsciiArt(asciiArt); asciiArtPad.setWidth(aa.getW()); asciiArtPad.setHeight(aa.getH()); // find asciiArt patterns findRectPattern(); findCornerPattern(); findLinePattern(); findStringPattern(); } /** * Find rectangles in the AsciiArt. * not implemented yet. */ protected void findRectPattern() { } /** * Find corners in the AsciiArt */ protected void findCornerPattern() { AsciiArtCoordinate aacStart = new AsciiArtCoordinate(this.asciiArtPad); aacStart.setTransXY(0, asciiArtPad.getYGrid() / 2); AsciiArtCoordinate aacEnd = new AsciiArtCoordinate(this.asciiArtPad); aacEnd.setTransXY(0, asciiArtPad.getYGrid() / 2); // hor line try { final RE reCorner = new RE(EDGE_GROUP); for (int r = 0; r < aa.getH(); r++) { String row = aa.getRow(r); int startIndex = 0; while (reCorner.match(row, startIndex)) { String s = reCorner.getParen(0); int mStart = reCorner.getParenStart(0); int mEnd = reCorner.getParenEnd(0); if (s.equals("\\")) { aacStart.setXY(mStart, r - 1); aacEnd.setXY(mStart + 1, r); } else if (s.equals("/")) { aacStart.setXY(mStart + 1, r - 1); aacEnd.setXY(mStart, r); } else { aacStart.setXY(mStart, r); aacEnd.setXY(mStart, r); } AsciiArtLine aal = new AsciiArtLine(aacStart, aacEnd); this.asciiArtPad.add(aal); if (startIndex >= mEnd) { break; } startIndex = mEnd; } } } catch (RESyntaxException rese) { rese.printStackTrace(); } } /** * Find lines in the AsciiArt */ protected void findLinePattern() { AsciiArtCoordinate aacStart = new AsciiArtCoordinate(this.asciiArtPad); aacStart.setTransXY(0, asciiArtPad.getYGrid() / 2); AsciiArtCoordinate aacEnd = new AsciiArtCoordinate(this.asciiArtPad); aacEnd.setTransXY(0, asciiArtPad.getYGrid() / 2); // hor line try { final RE reHorLine = new RE(HLINE_GROUP + "+"); for (int r = 0; r < aa.getH(); r++) { String row = aa.getRow(r); int startIndex = 0; while (reHorLine.match(row, startIndex)) { int mStart = reHorLine.getParenStart(0); int mEnd = reHorLine.getParenEnd(0); aacStart.setXY(mStart, r); aacEnd.setXY(mEnd - 1, r); AsciiArtLine aal = new AsciiArtLine(aacStart, aacEnd); this.asciiArtPad.add(aal); if (startIndex >= mEnd) { break; } startIndex = mEnd; } } } catch (RESyntaxException rese) { rese.printStackTrace(); } // ver line try { RE reVerLine = new RE(VLINE_GROUP + "+"); for (int c = 0; c < aa.getW(); c++) { String col = aa.getColumn(c); int startIndex = 0; while (reVerLine.match(col, startIndex)) { int mStart = reVerLine.getParenStart(0); int mEnd = reVerLine.getParenEnd(0); aacStart.setXY(c, mStart); aacEnd.setXY(c, mEnd - 1); AsciiArtLine aal = new AsciiArtLine(aacStart, aacEnd); this.asciiArtPad.add(aal); if (startIndex >= mEnd) { break; } startIndex = mEnd; } } } catch (RESyntaxException rese) { rese.printStackTrace(); } } /** * Find string text in the AsciiArt. */ protected void findStringPattern() { AsciiArtCoordinate aacStart = new AsciiArtCoordinate(this.asciiArtPad); aacStart.setTransXY(0, 3 * asciiArtPad.getYGrid() / 4); // string try { final RE reString = new RE(STRING_PREFIX_GROUP + STRING_SUFFIX_GROUP + "*"); for (int r = 0; r < aa.getH(); r++) { String row = aa.getRow(r); int startIndex = 0; while (reString.match(row, startIndex)) { String s = reString.getParen(0); int mStart = reString.getParenStart(0); int mEnd = reString.getParenEnd(0); aacStart.setXY(mStart, r); AsciiArtString aas = new AsciiArtString(aacStart, s); this.asciiArtPad.add(aas); if (startIndex >= mEnd) { break; } startIndex = mEnd; } } } catch (RESyntaxException rese) { rese.printStackTrace(); } } } /** * Marker interface of objects addable to the AsciiArtPad * */ public static interface AsciiArtElement { } }