ASF Bugzilla – Attachment 16812 Details for
Bug 37253
[PATCH] At present rendering to TXT is unimplemented.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
[PATCH] TXT rendering is supported
txt.patch (text/plain), 63.55 KB, created by
Sergey Simonchik
on 2005-10-26 13:33:20 UTC
(
hide
)
Description:
[PATCH] TXT rendering is supported
Filename:
MIME Type:
Creator:
Sergey Simonchik
Created:
2005-10-26 13:33:20 UTC
Size:
63.55 KB
patch
obsolete
>Index: src/java/org/apache/fop/fo/flow/TableColumn.java >=================================================================== >--- src/java/org/apache/fop/fo/flow/TableColumn.java (revision 328623) >+++ src/java/org/apache/fop/fo/flow/TableColumn.java (working copy) >@@ -30,6 +30,7 @@ > import org.apache.fop.fo.ValidationException; > import org.apache.fop.fo.expr.PropertyException; > import org.apache.fop.fo.properties.CommonBorderPaddingBackground; >+import org.apache.fop.fo.properties.FixedLength; > > /** > * Class modelling the fo:table-column object. >@@ -176,5 +177,13 @@ > sb.append(" column-width=").append(getColumnWidth()); > return sb.toString(); > } >+ >+ /** >+ * Sets a column width. >+ * @param length >+ */ >+ public void setColumnWidth(Length columnWidth) { >+ this.columnWidth = columnWidth; >+ } > } > >Index: src/java/org/apache/fop/render/RendererFactory.java >=================================================================== >--- src/java/org/apache/fop/render/RendererFactory.java (revision 328623) >+++ src/java/org/apache/fop/render/RendererFactory.java (working copy) >@@ -33,6 +33,7 @@ > import org.apache.fop.fo.FOEventHandler; > import org.apache.fop.render.mif.MIFHandler; > import org.apache.fop.render.rtf.RTFHandler; >+import org.apache.fop.render.txt.TXTHandler; > > /** > * Factory for FOEventHandlers and Renderers. >@@ -132,6 +133,8 @@ > return new MIFHandler(userAgent, out); > } else if (renderType == Constants.RENDER_RTF) { > return new RTFHandler(userAgent, out); >+ } else if (renderType == Constants.RENDER_TXT) { >+ return new TXTHandler(userAgent, out); > } else { > if (renderType < Constants.RENDER_MIN_CONST > || renderType > Constants.RENDER_MAX_CONST) { >Index: src/java/org/apache/fop/render/txt/border/DashedBorderElement.java >=================================================================== >--- src/java/org/apache/fop/render/txt/border/DashedBorderElement.java (revision 0) >+++ src/java/org/apache/fop/render/txt/border/DashedBorderElement.java (revision 0) >@@ -0,0 +1,105 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt.border; >+ >+import java.util.Arrays; >+ >+/** >+ * This class is responsible for managing of dashed border elements. >+ */ >+public class DashedBorderElement extends AbstractBorderElement { >+ >+ public static final char DASH_HORIZONTAL = '-'; >+ >+ public static final char DASH_VERTICAL = '|'; >+ >+ public static final char UNDEFINED = '?'; >+ >+ private static final int UP2 = 1; >+ >+ private static final int RIGHT2 = 2; >+ >+ private static final int DOWN2 = 4; >+ >+ private static final int LEFT2 = 8; >+ >+ private static char[] map = new char[20]; >+ >+ static { >+ Arrays.fill(map, UNDEFINED); >+ map[0] = ' '; >+ map[UP2] = DASH_VERTICAL; >+ map[DOWN2] = DASH_VERTICAL; >+ map[UP2 + DOWN2] = DASH_VERTICAL; >+ >+ map[LEFT2] = DASH_HORIZONTAL; >+ map[RIGHT2] = DASH_HORIZONTAL; >+ map[LEFT2 + RIGHT2] = DASH_HORIZONTAL; >+ } >+ >+ public DashedBorderElement(int type) { >+ super(type); >+ } >+ >+ private AbstractBorderElement mergeSolid(SolidAndDoubleBorderElement sdb) { >+ AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0); >+ for (int i = 0; i < 4; i++) { >+ e.setData(i, Math.max(data[i], sdb.getData(i))); >+ } >+ return e; >+ } >+ >+ private AbstractBorderElement toSolidAndDouble() { >+ AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0); >+ for (int i = 0; i < 4; i++) { >+ e.setData(i, data[i]); >+ } >+ return e; >+ } >+ >+ private AbstractBorderElement mergeDashed(DashedBorderElement dbe) { >+ for (int i = 0; i < 4; i++) { >+ data[i] = Math.max(data[i], dbe.getData(i)); >+ } >+ return this; >+ } >+ >+ public AbstractBorderElement merge(AbstractBorderElement e) { >+ AbstractBorderElement abe = this; >+ if (e instanceof SolidAndDoubleBorderElement) { >+ abe = mergeSolid((SolidAndDoubleBorderElement) e); >+ } else if (e instanceof DashedBorderElement) { >+ abe = mergeDashed((DashedBorderElement) e); >+ } else { >+ abe = e; >+ } >+ return abe; >+ } >+ >+ public char convert2Char() { >+ int key = 0; >+ key += data[UP] * UP2; >+ key += data[DOWN] * DOWN2; >+ key += data[LEFT] * LEFT2; >+ key += data[RIGHT] * RIGHT2; >+ char ch = map[key]; >+ if (ch == UNDEFINED) { >+ ch = toSolidAndDouble().convert2Char(); >+ } >+ return ch; >+ } >+} >Index: src/java/org/apache/fop/render/txt/border/SolidAndDoubleBorderElement.java >=================================================================== >--- src/java/org/apache/fop/render/txt/border/SolidAndDoubleBorderElement.java (revision 0) >+++ src/java/org/apache/fop/render/txt/border/SolidAndDoubleBorderElement.java (revision 0) >@@ -0,0 +1,257 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt.border; >+ >+import java.util.Arrays; >+ >+/** >+ * This class is responsible for managing of solid and double border elements. >+ */ >+public class SolidAndDoubleBorderElement extends AbstractBorderElement { >+ >+ public static final char LIGHT_HORIZONTAL = '\u2500'; >+ >+ public static final char LIGHT_VERTICAL = '\u2502'; >+ >+ public static final char LIGHT_DOWN_AND_RIGHT = '\u250C'; >+ >+ public static final char LIGHT_DOWN_AND_LEFT = '\u2510'; >+ >+ public static final char LIGHT_UP_AND_RIGHT = '\u2514'; >+ >+ public static final char LIGHT_UP_AND_LEFT = '\u2518'; >+ >+ public static final char LIGHT_VERTICAL_AND_RIGHT = '\u251C'; >+ >+ public static final char LIGHT_VERTICAL_AND_LEFT = '\u2524'; >+ >+ public static final char LIGHT_DOWN_AND_HORIZONTAL = '\u252C'; >+ >+ public static final char LIGHT_UP_AND_HORIZONTAL = '\u2534'; >+ >+ public static final char LIGHT_VERTICAL_AND_HORIZONTAL = '\u253C'; >+ >+ public static final char DOUBLE_HORIZONTAL = '\u2550'; >+ >+ public static final char DOUBLE_VERTICAL = '\u2551'; >+ >+ public static final char DOUBLE_DOWN_AND_RIGHT = '\u2554'; >+ >+ public static final char DOUBLE_DOWN_AND_LEFT = '\u2557'; >+ >+ public static final char DOUBLE_UP_AND_RIGHT = '\u255A'; >+ >+ public static final char DOUBLE_UP_AND_LEFT = '\u255D'; >+ >+ public static final char DOUBLE_VERTICAL_AND_RIGHT = '\u2560'; >+ >+ public static final char DOUBLE_VERTICAL_AND_LEFT = '\u2563'; >+ >+ public static final char DOUBLE_DOWN_AND_HORIZONTAL = '\u2566'; >+ >+ public static final char DOUBLE_UP_AND_HORIZONTAL = '\u2569'; >+ >+ public static final char DOUBLE_VERTICAL_AND_HORIZONTAL = '\u256C'; >+ >+ public static final char DOWN_SINGLE_AND_RIGHT_DOUBLE = '\u2552'; >+ >+ public static final char DOWN_DOUBLE_AND_RIGHT_SINGLE = '\u2553'; >+ >+ public static final char DOWN_SINGLE_AND_LEFT_DOUBLE = '\u2555'; >+ >+ public static final char DOWN_DOUBLE_AND_LEFT_SINGLE = '\u2556'; >+ >+ public static final char UP_SINGLE_AND_RIGHT_DOUBLE = '\u2558'; >+ >+ public static final char UP_DOUBLE_AND_RIGHT_SINGLE = '\u2559'; >+ >+ public static final char UP_SINGLE_AND_LEFT_DOUBLE = '\u255B'; >+ >+ public static final char UP_DOUBLE_AND_LEFT_SINGLE = '\u255C'; >+ >+ public static final char VERTICAL_SINGLE_AND_RIGHT_DOUBLE = '\u255E'; >+ >+ public static final char VERTICAL_DOUBLE_AND_RIGHT_SINGLE = '\u255F'; >+ >+ public static final char VERTICAL_SINGLE_AND_LEFT_DOUBLE = '\u2561'; >+ >+ public static final char VERTICAL_DOUBLE_AND_LEFT_SINGLE = '\u2562'; >+ >+ public static final char DOWN_SINGLE_AND_HORIZONTAL_DOUBLE = '\u2564'; >+ >+ public static final char DOWN_DOUBLE_AND_HORIZONTAL_SINGLE = '\u2565'; >+ >+ public static final char UP_SINGLE_AND_HORIZONTAL_DOUBLE = '\u2567'; >+ >+ public static final char UP_DOUBLE_AND_HORIZONTAL_SINGLE = '\u2568'; >+ >+ public static final char VERTICAL_SINGLE_AND_HORIZONTAL_DOUBLE = '\u256A'; >+ >+ public static final char VERTICAL_DOUBLE_AND_HORIZONTAL_SINGLE = '\u256B'; >+ >+ private static final char UNDEFINED = '?'; >+ >+ private static final int UP3 = 1; >+ >+ private static final int DOWN3 = 3; >+ >+ private static final int LEFT3 = 9; >+ >+ private static final int RIGHT3 = 27; >+ >+ private static final char[] map = new char[100]; >+ >+ static { >+ Arrays.fill(map, UNDEFINED); >+ map[0] = ' '; >+ map[UP3] = LIGHT_VERTICAL; >+ map[DOWN3] = LIGHT_VERTICAL; >+ map[RIGHT3] = LIGHT_HORIZONTAL; >+ map[LEFT3] = LIGHT_HORIZONTAL; >+ map[UP3 + DOWN3] = LIGHT_VERTICAL; >+ map[LEFT3 + RIGHT3] = LIGHT_HORIZONTAL; >+ map[UP3 + LEFT3] = LIGHT_UP_AND_LEFT; >+ map[LEFT3 + DOWN3] = LIGHT_DOWN_AND_LEFT; >+ map[DOWN3 + RIGHT3] = LIGHT_DOWN_AND_RIGHT; >+ map[UP3 + RIGHT3] = LIGHT_UP_AND_RIGHT; >+ map[UP3 + DOWN3 + RIGHT3] = LIGHT_VERTICAL_AND_RIGHT; >+ map[UP3 + LEFT3 + DOWN3] = LIGHT_VERTICAL_AND_LEFT; >+ map[LEFT3 + DOWN3 + RIGHT3] = LIGHT_DOWN_AND_HORIZONTAL; >+ map[UP3 + LEFT3 + RIGHT3] = LIGHT_UP_AND_HORIZONTAL; >+ map[UP3 + LEFT3 + DOWN3 + RIGHT3] = LIGHT_VERTICAL_AND_HORIZONTAL; >+ //DOUBLE >+ map[2*UP3] = DOUBLE_VERTICAL; >+ map[2*DOWN3] = DOUBLE_VERTICAL; >+ map[2*RIGHT3] = DOUBLE_HORIZONTAL; >+ map[2*LEFT3] = DOUBLE_HORIZONTAL; >+ map[2*UP3 + 2*DOWN3] = DOUBLE_VERTICAL; >+ map[2*LEFT3 + 2*RIGHT3] = DOUBLE_HORIZONTAL; >+ map[2*UP3 + 2*LEFT3] = DOUBLE_UP_AND_LEFT; >+ map[2*LEFT3 + 2*DOWN3] = DOUBLE_DOWN_AND_LEFT; >+ map[2*DOWN3 + 2*RIGHT3] = DOUBLE_DOWN_AND_RIGHT; >+ map[2*UP3 + 2*RIGHT3] = DOUBLE_UP_AND_RIGHT; >+ map[2*UP3 + 2*DOWN3 + 2*RIGHT3] = DOUBLE_VERTICAL_AND_RIGHT; >+ map[2*UP3 + 2*DOWN3 + 2*LEFT3] = DOUBLE_VERTICAL_AND_LEFT; >+ map[2*DOWN3 + 2*RIGHT3 + 2*LEFT3] = DOUBLE_DOWN_AND_HORIZONTAL; >+ map[2*UP3 + 2*RIGHT3 + 2*LEFT3] = DOUBLE_UP_AND_HORIZONTAL; >+ map[2*UP3 + 2*DOWN3 + 2*RIGHT3 + 2*LEFT3] = DOUBLE_VERTICAL_AND_HORIZONTAL; >+ //DOUBLE&SINGLE >+ map[DOWN3 + 2*RIGHT3] = DOWN_SINGLE_AND_RIGHT_DOUBLE; >+ map[2*DOWN3 + RIGHT3] = DOWN_DOUBLE_AND_RIGHT_SINGLE; >+ map[DOWN3 + 2*LEFT3] = DOWN_SINGLE_AND_LEFT_DOUBLE; >+ map[2*DOWN3 + LEFT3] = DOWN_DOUBLE_AND_LEFT_SINGLE; >+ map[UP3 + 2*RIGHT3] = UP_SINGLE_AND_RIGHT_DOUBLE; >+ map[2*UP3 + RIGHT3] = UP_DOUBLE_AND_RIGHT_SINGLE; >+ map[UP3 + 2*LEFT3] = UP_SINGLE_AND_LEFT_DOUBLE; >+ map[2*UP3 + LEFT3] = UP_DOUBLE_AND_LEFT_SINGLE; >+ map[UP3 + DOWN3 + 2*RIGHT3] = VERTICAL_SINGLE_AND_RIGHT_DOUBLE; >+ map[2*UP3 + 2*DOWN3 + RIGHT3] = VERTICAL_DOUBLE_AND_RIGHT_SINGLE; >+ map[UP3 + DOWN3 + 2*LEFT3] = VERTICAL_SINGLE_AND_LEFT_DOUBLE; >+ map[2*UP3 + 2*DOWN3 + LEFT3] = VERTICAL_DOUBLE_AND_LEFT_SINGLE; >+ map[DOWN3 + 2*LEFT3 + 2*RIGHT3] = DOWN_SINGLE_AND_HORIZONTAL_DOUBLE; >+ map[2*DOWN3 + LEFT3 + RIGHT3] = DOWN_DOUBLE_AND_HORIZONTAL_SINGLE; >+ map[UP3 + 2*LEFT3 + 2*RIGHT3] = UP_SINGLE_AND_HORIZONTAL_DOUBLE; >+ map[2*UP3 + LEFT3 + RIGHT3] = UP_DOUBLE_AND_HORIZONTAL_SINGLE; >+ map[UP3 + DOWN3 + 2*LEFT3 + 2*RIGHT3] = VERTICAL_SINGLE_AND_HORIZONTAL_DOUBLE; >+ map[2*UP3 + 2*DOWN3 + LEFT3 + RIGHT3] = VERTICAL_DOUBLE_AND_HORIZONTAL_SINGLE; >+ } >+ >+ public SolidAndDoubleBorderElement() { >+ } >+ >+ public SolidAndDoubleBorderElement(int style, int type) { >+ super(type); >+ if (style == EN_DOUBLE) { >+ for (int i = 0; i < 4; i++) { >+ data[i] *= 2; >+ } >+ } >+ } >+ >+ /** >+ * Merges with <code>sde</code>. >+ * @param sde instance of SolidAndDoubleBorderElement >+ * @return instance of AbstractBorderElement >+ */ >+ private AbstractBorderElement mergeSolid(SolidAndDoubleBorderElement sde) { >+ AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0); >+ for (int i = 0; i < 4; i++) { >+ if (sde.getData(i) != 0) { >+ e.setData(i, sde.getData(i)); >+ } else { >+ e.setData(i, data[i]); >+ } >+ } >+ return e; >+ } >+ >+ /** >+ * Merges with e. >+ * @param e instance of AbstractBorderElement >+ * @return instance of AbstractBorderElement >+ */ >+ public AbstractBorderElement merge(AbstractBorderElement e) { >+ AbstractBorderElement abe = this; >+ if (e instanceof SolidAndDoubleBorderElement) { >+ abe = mergeSolid((SolidAndDoubleBorderElement) e); >+ } else if (e instanceof DottedBorderElement) { >+ abe = e; >+ } else if (e instanceof DashedBorderElement) { >+ abe = e.merge(this); >+ } >+ return abe; >+ } >+ >+ /** >+ * Maps to char. >+ * @return resulting mapping char >+ */ >+ private char map2Char() { >+ int key = 0; >+ key += data[UP] * UP3; >+ key += data[LEFT] * LEFT3; >+ key += data[DOWN] * DOWN3; >+ key += data[RIGHT] * RIGHT3; >+ return map[key]; >+ } >+ >+ /** >+ * Modifies data to nearest normal internal representation. >+ */ >+ private void modifyData() { >+ int c1 = 0; >+ int c2 = 0; >+ for (int i = 0; i < 4; i++) { >+ c1 += (data[i] == 1) ? 1: 0; >+ c2 += (data[i] == 2) ? 1: 0; >+ } >+ int m = c1 > c2 ? 1 : 0; >+ int[] p = {0, m, 2*(1 - m)}; >+ for (int i = 0; i < 4; i++) { >+ data[i] = p[data[i]]; >+ } >+ } >+ >+ public char convert2Char() { >+ char ch = map2Char(); >+ if (ch == UNDEFINED) { >+ modifyData(); >+ ch = map2Char(); >+ } >+ return ch; >+ } >+} >Index: src/java/org/apache/fop/render/txt/border/BorderManager.java >=================================================================== >--- src/java/org/apache/fop/render/txt/border/BorderManager.java (revision 0) >+++ src/java/org/apache/fop/render/txt/border/BorderManager.java (revision 0) >@@ -0,0 +1,162 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt.border; >+ >+import org.apache.fop.fo.Constants; >+import org.apache.fop.render.txt.TXTState; >+ >+/** >+ * This keeps all information about borders for current processed page. >+ */ >+public class BorderManager { >+ >+ /** Matrix for storing information about one border element. */ >+ private AbstractBorderElement[][] borderInfo; >+ >+ /** Width of current processed border. */ >+ private int width; >+ >+ /** Height of current processed border. */ >+ private int height; >+ >+ /** x-coordinate of upper left point of current processed border. */ >+ private int startX; >+ >+ /** y-coordinate of upper left point of current processed border. */ >+ private int startY; >+ >+ /** Stores TXTState for transforming border elements. */ >+ private TXTState state; >+ >+ /** >+ * Constructs BorderManger, using <code>pageWidth</code> and >+ * <code>pageHeight</code> for creating <code>borderInfo</code>. >+ * >+ * @param pageWidth page width >+ * @param pageHeight page height >+ * @param state TXTState >+ */ >+ public BorderManager(int pageWidth, int pageHeight, TXTState state) { >+ this.state = state; >+ borderInfo = new AbstractBorderElement[pageHeight][pageWidth]; >+ } >+ >+ /** >+ * Adds border element to <code>borderInfo</code>. >+ * >+ * @param x x-coordinate >+ * @param y y-coordinate >+ * @param style border-style >+ * @param type border element type, binary representation of wich gives >+ * information about availability or absence of corresponding side. >+ */ >+ public void addBorderElement(int x, int y, int style, int type) { >+ AbstractBorderElement be = null; >+ >+ if (style == Constants.EN_SOLID || style == Constants.EN_DOUBLE) { >+ be = new SolidAndDoubleBorderElement(style, type); >+ } else if (style == Constants.EN_DOTTED) { >+ be = new DottedBorderElement(); >+ } else if (style == Constants.EN_DASHED) { >+ be = new DashedBorderElement(type); >+ } else { >+ return; >+ } >+ be.transformElement(state); >+ >+ if (borderInfo[y][x] != null) { >+ borderInfo[y][x] = borderInfo[y][x].merge(be); >+ } else { >+ borderInfo[y][x] = be; >+ } >+ } >+ >+ /** >+ * @param x x-coordinate >+ * @param y y-coordinate >+ * @return if border element at point (x,y) is available, returns instance >+ * of Character, created on char, given by corresponding border element, >+ * otherwise returns null. >+ */ >+ public Character getCharacter(int x, int y) { >+ Character c = null; >+ if (borderInfo[y][x] != null) { >+ c = new Character(borderInfo[y][x].convert2Char()); >+ } >+ return c; >+ } >+ >+ /** >+ * @return width of current processed border. >+ */ >+ public int getWidth() { >+ return width; >+ } >+ >+ /** >+ * Sets width of current processed border. >+ * @param width width of border >+ */ >+ public void setWidth(int width) { >+ this.width = width; >+ } >+ >+ /** >+ * @return height of current processed border. >+ */ >+ public int getHeight() { >+ return height; >+ } >+ >+ /** >+ * Sets height of current processed border. >+ * @param height height of border >+ */ >+ public void setHeight(int height) { >+ this.height = height; >+ } >+ >+ /** >+ * @return x-coordinate of upper left point of current processed border. >+ */ >+ public int getStartX() { >+ return startX; >+ } >+ >+ /** >+ * Sets x-coordinate of upper left point of current processed border. >+ * @param startX x-coordinate of upper left border's point. >+ */ >+ public void setStartX(int startX) { >+ this.startX = startX; >+ } >+ >+ /** >+ * @return y-coordinate of upper left point of current processed border. >+ */ >+ public int getStartY() { >+ return startY; >+ } >+ >+ /** >+ * Sets y-coordinate of upper left point of current processed border. >+ * @param startY y-coordinate of upper left border's point. >+ */ >+ public void setStartY(int startY) { >+ this.startY = startY; >+ } >+} >Index: src/java/org/apache/fop/render/txt/border/AbstractBorderElement.java >=================================================================== >--- src/java/org/apache/fop/render/txt/border/AbstractBorderElement.java (revision 0) >+++ src/java/org/apache/fop/render/txt/border/AbstractBorderElement.java (revision 0) >@@ -0,0 +1,119 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt.border; >+ >+import java.awt.Point; >+import java.util.Arrays; >+ >+import org.apache.fop.area.CTM; >+import org.apache.fop.fo.Constants; >+import org.apache.fop.render.txt.TXTState; >+ >+/** >+ * This class keeps information about abstract border element, i. e. specifies >+ * border element for one text position. >+ */ >+public abstract class AbstractBorderElement implements Constants { >+ >+ public static final int UP = 0; >+ >+ public static final int RIGHT = 1; >+ >+ public static final int DOWN = 2; >+ >+ public static final int LEFT = 3; >+ >+ /** >+ * I-th element of this array specify, if there line from center of symbol >+ * to corresponding side (UP, RIGHT, DOWN, LEFT). >+ */ >+ protected int[] data = { 0, 0, 0, 0 }; >+ >+ public AbstractBorderElement() { >+ } >+ >+ /** >+ * Constructs a newly allocated <code>AbstractBorderElement</code> object. >+ * Fills <code>data</code> using binary representation of <code>type<code>. >+ * >+ * @param type binary representation of type gives <code>data</code> >+ */ >+ public AbstractBorderElement(int type) { >+ for (int i = 0; i < 4; i++) { >+ data[i] = (type >> i) & 1; >+ } >+ } >+ >+ /** >+ * @return value of side's element of <code>data</code> >+ */ >+ public int getData(int side) { >+ return data[side]; >+ } >+ >+ /** >+ * Sets value for <code>data[side]</code>. >+ */ >+ public void setData(int side, int value) { >+ data[side] = value; >+ } >+ >+ /** >+ * Transform border element in according with <code>state</code> >+ * @param state instance of TXTState >+ */ >+ public void transformElement(TXTState state) { >+ // here we'll get CTM^-1 without shift >+ double da[] = state.getResultCTM().toArray(); >+ CTM ctm = new CTM(da[0], -da[1], -da[2], da[3], 0, 0); >+ >+ Point[] pa = new Point[4]; >+ pa[0] = new Point(0, data[UP]); >+ pa[1] = new Point(data[RIGHT], 0); >+ pa[2] = new Point(0, -data[DOWN]); >+ pa[3] = new Point(-data[LEFT], 0); >+ >+ Arrays.fill(data, 0); >+ for (int i = 0; i < 4; i++) { >+ Point p = state.transformPoint(pa[i], ctm); >+ >+ int length = (int) p.distance(0, 0); >+ if (p.x == 0 && p.y > 0) { >+ data[UP] = length; >+ } else if (p.x == 0 && p.y < 0) { >+ data[DOWN] = length; >+ } else if (p.x > 0 && p.y == 0) { >+ data[RIGHT] = length; >+ } else if (p.x < 0 && p.y == 0) { >+ data[LEFT] = length; >+ } >+ } >+ } >+ >+ /** >+ * Merges with <code>e</code>. >+ * @param e instance of AbstractBorderElement >+ * @return instance of AbstractBorderElement >+ */ >+ public abstract AbstractBorderElement merge(AbstractBorderElement e); >+ >+ /** >+ * Convert internal representation of border element to char. >+ * @return corresponding char >+ */ >+ public abstract char convert2Char(); >+} >Index: src/java/org/apache/fop/render/txt/border/DottedBorderElement.java >=================================================================== >--- src/java/org/apache/fop/render/txt/border/DottedBorderElement.java (revision 0) >+++ src/java/org/apache/fop/render/txt/border/DottedBorderElement.java (revision 0) >@@ -0,0 +1,33 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt.border; >+ >+/** >+ * This class is responsible for managing of dotted border elements. >+ */ >+public class DottedBorderElement extends AbstractBorderElement { >+ >+ public static final char MIDDLE_DOT = '\u00B7'; >+ >+ public AbstractBorderElement merge(AbstractBorderElement e) { >+ return this; >+ } >+ >+ public char convert2Char() { >+ return MIDDLE_DOT; >+ } >+} >Index: src/java/org/apache/fop/render/txt/Helper.java >=================================================================== >--- src/java/org/apache/fop/render/txt/Helper.java (revision 0) >+++ src/java/org/apache/fop/render/txt/Helper.java (revision 0) >@@ -0,0 +1,60 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt; >+ >+public class Helper { >+ >+ /** >+ * @return nearest integer to <code>x</code>, divisible by >+ * <code>quantum</code>. >+ */ >+ public static int round(int x, int quantum) { >+ int ceil = ceil(x, quantum); >+ int floor = floor(x, quantum); >+ return (ceil - x < x - floor) ? ceil : floor; >+ } >+ >+ /** >+ * @return minimal possible integer, greater or equal than <code>x</code>, >+ * divisible by <code>quantum</code> >+ */ >+ public static int ceil(int x, int quantum) { >+ int dx = (x < 0) || (x % quantum == 0) ? 0 : 1; >+ return (x / quantum + dx) * quantum; >+ } >+ >+ /** >+ * @return maximum possible integer, less or equal than >+ * <code>oldValue</code>, divisible by <code>quantum</code> >+ */ >+ public static int floor(int x, int quantum) { >+ int dx = (x > 0) || (x % quantum == 0) ? 0 : -1; >+ return (x / quantum + dx) * quantum; >+ } >+ >+ public static int roundPosition(int x, int quantum) { >+ return round(x, quantum) / quantum; >+ } >+ >+ public static int ceilPosition(int x, int quantum) { >+ return ceil(x, quantum) / quantum; >+ } >+ >+ public static int floorPosition(int x, int quantum) { >+ return floor(x, quantum) / quantum; >+ } >+} >Index: src/java/org/apache/fop/render/txt/TXTHandler.java >=================================================================== >--- src/java/org/apache/fop/render/txt/TXTHandler.java (revision 0) >+++ src/java/org/apache/fop/render/txt/TXTHandler.java (revision 0) >@@ -0,0 +1,550 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt; >+ >+import java.io.OutputStream; >+import java.util.Arrays; >+import java.util.Iterator; >+import java.util.List; >+ >+import org.apache.fop.apps.FOPException; >+import org.apache.fop.apps.FOUserAgent; >+import org.apache.fop.area.AreaTreeHandler; >+import org.apache.fop.datatypes.CompoundDatatype; >+import org.apache.fop.datatypes.Length; >+import org.apache.fop.datatypes.PercentBaseContext; >+import org.apache.fop.fo.Constants; >+import org.apache.fop.fo.FONode; >+import org.apache.fop.fo.FOText; >+import org.apache.fop.fo.expr.NumericProperty; >+import org.apache.fop.fo.flow.Block; >+import org.apache.fop.fo.flow.BlockContainer; >+import org.apache.fop.fo.flow.ExternalGraphic; >+import org.apache.fop.fo.flow.Inline; >+import org.apache.fop.fo.flow.ListBlock; >+import org.apache.fop.fo.flow.ListItem; >+import org.apache.fop.fo.flow.Table; >+import org.apache.fop.fo.flow.TableCell; >+import org.apache.fop.fo.flow.TableColumn; >+import org.apache.fop.fo.pagination.PageSequence; >+import org.apache.fop.fo.properties.CommonAbsolutePosition; >+import org.apache.fop.fo.properties.CommonBorderPaddingBackground; >+import org.apache.fop.fo.properties.CommonFont; >+import org.apache.fop.fo.properties.CommonMarginBlock; >+import org.apache.fop.fo.properties.FixedLength; >+import org.apache.fop.fo.properties.Property; >+import org.apache.fop.fo.properties.SpaceProperty; >+import org.apache.fop.layoutmgr.BlockLayoutManager; >+ >+/** >+ * Handler for formatting objects in case of rendering to txt. >+ * >+ * This handler gets page-sequence, modifies formatting objects and return them >+ * to superclass. So areas are generated from modified FO. Idea of modifying is >+ * to quantize FO properties, making them divisible by width of char or height >+ * of char. >+ */ >+public class TXTHandler extends AreaTreeHandler { >+ >+ /** Percent base context. Needed for line-height. */ >+ private static final PercentBaseContext CONTEXT = >+ new BlockLayoutManager(new Block(null)); >+ >+ /** Modified font size in millipoints. */ >+ private static final int MODIFIED_FONT_SIZE = 10000; >+ >+ /** Quantum for each side (BEFORE, AFTER, START, END). */ >+ private final int[] quantum = { TXTRenderer.CHAR_HEIGHT, >+ TXTRenderer.CHAR_HEIGHT, TXTRenderer.CHAR_WIDTH, >+ TXTRenderer.CHAR_WIDTH }; >+ >+ /** Keeps overpatching for each side. */ >+ private int[] overPatching = new int[4]; >+ >+ /** >+ * Keeps last overpatching for each side. Needed for selective modifying of >+ * start-indent and end-indent. >+ */ >+ private int[] lastOverPatching = new int[4]; >+ >+ public TXTHandler(FOUserAgent userAgent, OutputStream stream) >+ throws FOPException { >+ super(userAgent, Constants.RENDER_TXT, stream); >+ } >+ >+ /** >+ * Sets a component <code>CP_LENGTH</code> of <code>cd</code> to >+ * <code>value</code>. >+ */ >+ private static void setLength(CompoundDatatype cd, int value) { >+ cd.setComponent(Constants.CP_LENGTH, new FixedLength(value), true); >+ } >+ >+ /** >+ * Sets components <code>CP_MINIMUM, CP_OPTIMUM, CP_MAXIMUM</code> of >+ * <code>cd</code> to <code>p</code>. >+ * >+ * @param cd instance of CompoundDatatype for modifying. >+ * @param p property for setting. >+ */ >+ private static void setMinOptMax(CompoundDatatype cd, Property p) { >+ cd.setComponent(Constants.CP_MINIMUM, p, true); >+ cd.setComponent(Constants.CP_OPTIMUM, p, true); >+ cd.setComponent(Constants.CP_MAXIMUM, p, true); >+ } >+ >+ /** >+ * Modifies border of side. If there is no border of given side, does >+ * nothing, otherwise sets border-width to half of char width or char height >+ * depending on side. <p> >+ * Difference between values of new border-width and old border-width is >+ * saved in <code>lastOverPatching</code>. >+ * >+ * @param side side to modify. >+ * @param bpb instance of CommonBorderPaddingBackground for modifying. >+ */ >+ private void modifyBorder(int side, CommonBorderPaddingBackground bpb) { >+ CommonBorderPaddingBackground.BorderInfo bi = bpb.getBorderInfo(side); >+ >+ if (bi != null) { >+ int width = bpb.getBorderWidth(side, false); >+ setLength(bi.getWidth(), quantum[side] / 2); >+ lastOverPatching[side] += bpb.getBorderWidth(side, false) - width; >+ } >+ } >+ >+ /** >+ * Modifies padding of side. First rounds padding to nearest integer, >+ * divisible by char width or char height depending on side. If border of >+ * given side is available, modifies padding in such a way, so sum of border >+ * width and padding will be divisible by char width or char height, >+ * depending on side. <p> >+ * Difference between values of new padding and old padding is saved >+ * in <code>lastOverPatching</code>. >+ * >+ * @param side side to modify. >+ * @param bpb instance of CommonBorderPaddingBackground for modifying. >+ */ >+ private void modifyPadding(int side, CommonBorderPaddingBackground bpb) { >+ int oldPadding = bpb.getPadding(side, false, null); >+ int newPadding = Helper.round(oldPadding, quantum[side]); >+ if (bpb.getBorderInfo(side) != null) { >+ newPadding = Math.max(newPadding, quantum[side]) >+ - bpb.getBorderWidth(side, false); >+ } >+ >+ setLength(bpb.getPaddingLengthProperty(side), newPadding); >+ lastOverPatching[side] += newPadding - oldPadding; >+ } >+ >+ /** >+ * Modifies borders and paddings of <code>bpb</code>. >+ * >+ * @param bpb instance of CommonBorderPaddingBackground for modifying. >+ */ >+ private void modifyBPB(CommonBorderPaddingBackground bpb) { >+ modifyBorder(CommonBorderPaddingBackground.BEFORE, bpb); >+ modifyBorder(CommonBorderPaddingBackground.AFTER, bpb); >+ modifyBorder(CommonBorderPaddingBackground.START, bpb); >+ modifyBorder(CommonBorderPaddingBackground.END, bpb); >+ >+ modifyPadding(CommonBorderPaddingBackground.BEFORE, bpb); >+ modifyPadding(CommonBorderPaddingBackground.AFTER, bpb); >+ modifyPadding(CommonBorderPaddingBackground.START, bpb); >+ modifyPadding(CommonBorderPaddingBackground.END, bpb); >+ } >+ >+ /** >+ * Rounds optimum value of <code>space</code> to nearest integer, >+ * divisible by <code>quantum</code>. >+ * >+ * @param space instance of SpaceProperty. >+ * @param quantum integer. >+ */ >+ private void modifySpace(SpaceProperty space, int quantum) { >+ int value = space.getOptimum(null).getLength().getValue(); >+ setMinOptMax(space, new FixedLength(Helper.round(value, quantum))); >+ } >+ >+ /** >+ * @param length instance of Length. >+ * @param quantum integer. >+ * @return instance of Length, having value nearest to value of >+ * <code>length</code>, and divisible by <code>quantum</code>. >+ */ >+ private Length roundLength(Length length, int quantum) { >+ int x = Helper.round(length.getValue(), quantum); >+ return new FixedLength(x); >+ } >+ >+ /** >+ * @param length instance of Length. >+ * @param quantum integer. >+ * @return instance of Length, having minimal value, greater value of >+ * <code>length</code>, and divisible by <code>quantum</code>. >+ */ >+ private Length ceilLength(Length length, int quantum) { >+ int x = Helper.ceil(length.getValue(), quantum); >+ return new FixedLength(x); >+ } >+ >+ /** >+ * Modifies indent for given side. Summarizes value of indent and modifing >+ * error (i.e. overPatching). Rounds result to nearest integer, divisible by >+ * quantum. >+ * >+ * @param indent Length to modify. >+ * @param side an integer, representing side. >+ * @return modified Length. >+ */ >+ private Length modifyIndent(Length indent, int side) { >+ if (indent instanceof NumericProperty) { >+ overPatching[side] += lastOverPatching[side]; >+ } >+ int newValue = indent.getValue() + overPatching[side]; >+ newValue = Helper.round(newValue, quantum[side]); >+ return new FixedLength(newValue); >+ } >+ >+ /** >+ * Modifies Common Margin Properties-Block: >+ * <ul> >+ * <li>margin-top, margin-left, margin-bottom, margin-right >+ * <li>start-indent, end-indent >+ * <li>space-before, space-after. >+ * </ul> >+ * >+ * @param cmb instance of CommonMarginBlock to modify. >+ */ >+ private void modifyCommonMarginBlock(CommonMarginBlock cmb) { >+ cmb.marginTop = roundLength(cmb.marginTop, TXTRenderer.CHAR_HEIGHT); >+ cmb.marginBottom = roundLength(cmb.marginBottom, >+ TXTRenderer.CHAR_HEIGHT); >+ cmb.marginLeft = roundLength(cmb.marginLeft, TXTRenderer.CHAR_WIDTH); >+ cmb.marginRight = roundLength(cmb.marginRight, TXTRenderer.CHAR_WIDTH); >+ >+ modifySpace(cmb.spaceBefore, TXTRenderer.CHAR_HEIGHT); >+ modifySpace(cmb.spaceAfter, TXTRenderer.CHAR_HEIGHT); >+ >+ cmb.startIndent = modifyIndent(cmb.startIndent, >+ CommonBorderPaddingBackground.START); >+ cmb.endIndent = modifyIndent(cmb.endIndent, >+ CommonBorderPaddingBackground.END); >+ } >+ >+ /** >+ * Modifies fo:table attributes: >+ * <ul> >+ * <li>Common Margin Properties Block >+ * <li>Common Border, Padding, and Background Properties >+ * <li>columns. >+ * </ul> >+ * >+ * @param table Table to modify. >+ */ >+ private void modifyTable(Table table) { >+ CommonMarginBlock cmb = table.getCommonMarginBlock(); >+ if (table.getBorderCollapse() == Constants.EN_COLLAPSE) { >+ // If border-collapse == "collapse", add space-after in order to >+ // impove interaction with other FO. >+ int value = cmb.spaceAfter.getOptimum(null).getLength().getValue(); >+ value += TXTRenderer.CHAR_HEIGHT; >+ setMinOptMax(cmb.spaceAfter, new FixedLength(value)); >+ } >+ modifyCommonMarginBlock(cmb); >+ >+ modifyBPB(table.getCommonBorderPaddingBackground()); >+ >+ // modify all table-columns >+ List columnList = table.getColumns(); >+ Iterator iter = columnList.iterator(); >+ while (iter.hasNext()) { >+ modifyTableColumn((TableColumn) iter.next()); >+ } >+ } >+ >+ /** >+ * Modifies fo:table-column attributes: >+ * <ul> >+ * <li>width. >+ * </ul> >+ * >+ * @param column TableColumn to modify. >+ */ >+ private void modifyTableColumn(TableColumn column) { >+ column.setColumnWidth(ceilLength(column.getColumnWidth(), >+ TXTRenderer.CHAR_WIDTH)); >+ } >+ >+ /** >+ * Modifies padding of fo:table-cell. >+ * >+ * @param side side. >+ * @param bpb instance of CommonBorderPaddingBackground to modify. >+ */ >+ private void modifyCellPadding(int side, CommonBorderPaddingBackground bpb) { >+ if (bpb.getBorderInfo(side) == null) { >+ int oldPadding = bpb.getPadding(side, false, null); >+ int newPadding = oldPadding + quantum[side] / 2; >+ setLength(bpb.getPaddingLengthProperty(side), newPadding); >+ } >+ } >+ >+ /** >+ * Modifies table-cell properties: >+ * <ul> >+ * <li>Common Border, Padding, and Background Properties. >+ * </ul> >+ * >+ * @param c TableCell to modify. >+ */ >+ private void modifyTableCell(TableCell c) { >+ CommonBorderPaddingBackground bpb = c >+ .getCommonBorderPaddingBackground(); >+ modifyBPB(bpb); >+ modifyCellPadding(CommonBorderPaddingBackground.BEFORE, bpb); >+ modifyCellPadding(CommonBorderPaddingBackground.AFTER, bpb); >+ modifyCellPadding(CommonBorderPaddingBackground.START, bpb); >+ modifyCellPadding(CommonBorderPaddingBackground.END, bpb); >+ } >+ >+ /** >+ * Modifies Common Absolute Position Properties: >+ * <ul> >+ * <li>left >+ * <li>top. >+ * </ul> >+ * >+ * @param cap CommonAbsolutePosition to modify. >+ */ >+ private void modifyCommonAbsolutePosition(CommonAbsolutePosition cap) { >+ if (cap.absolutePosition == Constants.EN_ABSOLUTE) { >+ cap.left = roundLength(cap.left, TXTRenderer.CHAR_WIDTH); >+ cap.top = roundLength(cap.top, TXTRenderer.CHAR_HEIGHT); >+ } >+ } >+ >+ /** >+ * Modifies line-height property. Sets a value of line-height to max(char >+ * height; lowest integer, divisible by char height). >+ * >+ * @param lineHeight SpaceProperty to modify. >+ */ >+ private void modifyLineHeight(SpaceProperty lineHeight) { >+ Property p = lineHeight.getOptimum(null); >+ int value = p.getLength().getValue(CONTEXT); >+ >+ int height = TXTRenderer.CHAR_HEIGHT; >+ int newValue = Math.max(Helper.floor(value, height), height); >+ setMinOptMax(lineHeight, new FixedLength(newValue)); >+ } >+ >+ /** >+ * Modifies Common Font Properties: >+ * <ul> >+ * <li>font-family = Courier; >+ * <li>font-size = MODIFIED_FONT_SIZE; >+ * <li>font-stretch = EN_NORMAL; >+ * <li>font-weight = EN_NORMAL. >+ * </ul> >+ * >+ * @param cf the font to modify. >+ */ >+ private void modifyCommonFont(CommonFont cf) { >+ if (cf != null) { >+ cf.fontFamily = "Courier"; >+ cf.fontSize = new FixedLength(MODIFIED_FONT_SIZE); >+ cf.fontStretch = Constants.EN_NORMAL; >+ cf.fontWeight = Constants.EN_NORMAL; >+ } >+ } >+ >+ /** >+ * Modifies fo:block: >+ * <ul> >+ * <li>Common Border, Padding, and Background Properties >+ * <li>Common Margin Properties-Block >+ * <li>Common Font Properties >+ * <li>line-height. >+ * </ul> >+ * >+ * @param block Block to modify. >+ */ >+ private void modifyBlock(Block block) { >+ modifyBPB(block.getCommonBorderPaddingBackground()); >+ modifyCommonMarginBlock(block.getCommonMarginBlock()); >+ modifyCommonFont(block.getCommonFont()); >+ modifyLineHeight(block.getLineHeight()); >+ } >+ >+ /** >+ * Modifies fo:block-container: >+ * <ul> >+ * <li>Common Border, Padding, and Background Properties >+ * <li>Common Margin Properties-Block >+ * <li>Common Absolute Position Properties. >+ * </ul> >+ * >+ * @param bc BlockContainer to modify. >+ */ >+ private void modifyBlockContainer(BlockContainer bc) { >+ modifyBPB(bc.getCommonBorderPaddingBackground()); >+ modifyCommonMarginBlock(bc.getCommonMarginBlock()); >+ modifyCommonAbsolutePosition(bc.getCommonAbsolutePosition()); >+ } >+ >+ /** >+ * Modifies fo:inline: >+ * <ul> >+ * <li>Common Font Properties >+ * </ul> >+ * >+ * @param inline Inline to modify. >+ */ >+ private void modifyInline(Inline inline) { >+ modifyCommonFont(inline.getCommonFont()); >+ } >+ >+ /** >+ * Modifies FOText: >+ * <ul> >+ * <li>Common Font Properties >+ * </ul> >+ * >+ * @param text FOText to modify. >+ */ >+ private void modifyFOText(FOText text) { >+ modifyCommonFont(text.getCommonFont()); >+ } >+ >+ /** >+ * Modifies fo:external-graphic: >+ * <ul> >+ * <li>Common Border, Padding, and Background Properties >+ * <li>line-height. >+ * </ul> >+ * >+ * @param eg ExternalGraphic to modify. >+ */ >+ private void modifyExternalGraphic(ExternalGraphic eg) { >+ modifyBPB(eg.getCommonBorderPaddingBackground()); >+ modifyLineHeight(eg.getLineHeight()); >+ } >+ >+ /** >+ * Modifies fo:list-block: >+ * <ul> >+ * <li>Common Border, Padding, and Background Properties >+ * <li>Common Margin Properties-Block. >+ * </ul> >+ * >+ * @param lb ListBlock to modify. >+ */ >+ private void modifyListBlock(ListBlock lb) { >+ modifyBPB(lb.getCommonBorderPaddingBackground()); >+ modifyCommonMarginBlock(lb.getCommonMarginBlock()); >+ } >+ >+ /** >+ * Modifies fo:list-item: >+ * <ul> >+ * <li>Common Border, Padding, and Background Properties >+ * <li>Common Margin Properties-Block. >+ * </ul> >+ * <p> >+ * Make refinement for fo:list-item-label and fo:list-item-body. >+ * >+ * @param li ListItem to modify. >+ */ >+ private void modifyListItem(ListItem li) { >+ modifyBPB(li.getCommonBorderPaddingBackground()); >+ modifyCommonMarginBlock(li.getCommonMarginBlock()); >+ refinement(li.getLabel()); >+ refinement(li.getBody()); >+ } >+ >+ /** >+ * Does refinement for particular node. Modifies node's properties and >+ * refines its children recursively. >+ * >+ * @param node the node to refine. >+ */ >+ private void refinement(FONode node) { >+ int[] saveOverPatching = (int[]) overPatching.clone(); >+ Arrays.fill(lastOverPatching, 0); >+ >+ if (node instanceof Block) { >+ modifyBlock((Block) node); >+ } else if (node instanceof BlockContainer) { >+ modifyBlockContainer((BlockContainer) node); >+ } else if (node instanceof Inline) { >+ modifyInline((Inline) node); >+ } else if (node instanceof FOText) { >+ modifyFOText((FOText) node); >+ } else if (node instanceof Table) { >+ modifyTable((Table) node); >+ Arrays.fill(overPatching, 0); >+ } else if (node instanceof TableCell) { >+ modifyTableCell((TableCell) node); >+ } else if (node instanceof ExternalGraphic) { >+ modifyExternalGraphic((ExternalGraphic) node); >+ } else if (node instanceof ListBlock) { >+ modifyListBlock((ListBlock) node); >+ } else if (node instanceof ListItem) { >+ modifyListItem((ListItem) node); >+ } >+ >+ Iterator it = node.getChildNodes(); >+ if (it != null) { >+ while (it.hasNext()) { >+ refinement((FONode) it.next()); >+ } >+ } >+ overPatching = saveOverPatching; >+ } >+ >+ /** >+ * Run refinement for: >+ * <ul> >+ * <li>mainflow (xsl-region-body) >+ * <li>staticflow (xsl-region-before, xsl-region-after, xsl-region-start, >+ * xsl-region-end). >+ * </ul> >+ * >+ * @param pageSequence PageSequence to refine. >+ */ >+ public void endPageSequence(PageSequence pageSequence) { >+ Arrays.fill(overPatching, 0); >+ >+ refinement(pageSequence.getMainFlow()); >+ >+ if (pageSequence.getStaticContent("xsl-region-before") != null) { >+ refinement(pageSequence.getStaticContent("xsl-region-before")); >+ } >+ if (pageSequence.getStaticContent("xsl-region-after") != null) { >+ refinement(pageSequence.getStaticContent("xsl-region-after")); >+ } >+ if (pageSequence.getStaticContent("xsl-region-start") != null) { >+ refinement(pageSequence.getStaticContent("xsl-region-start")); >+ } >+ if (pageSequence.getStaticContent("xsl-region-end") != null) { >+ refinement(pageSequence.getStaticContent("xsl-region-end")); >+ } >+ >+ super.endPageSequence(pageSequence); >+ } >+} >Index: src/java/org/apache/fop/render/txt/TXTRenderer.java >=================================================================== >--- src/java/org/apache/fop/render/txt/TXTRenderer.java (revision 328623) >+++ src/java/org/apache/fop/render/txt/TXTRenderer.java (working copy) >@@ -18,122 +18,449 @@ > > package org.apache.fop.render.txt; > >-// FOP >-import org.apache.fop.render.PrintRenderer; >-import org.apache.fop.render.pcl.PCLStream; >+import java.awt.Point; >+import java.awt.geom.Rectangle2D; >+import java.io.IOException; >+import java.io.OutputStream; >+import java.util.List; > >+import org.apache.fop.apps.FOPException; >+import org.apache.fop.area.Area; >+import org.apache.fop.area.CTM; >+import org.apache.fop.area.PageViewport; >+import org.apache.fop.area.inline.Image; >+import org.apache.fop.area.inline.TextArea; >+import org.apache.fop.datatypes.ColorType; >+import org.apache.fop.render.AbstractPathOrientedRenderer; >+import org.apache.fop.render.txt.border.AbstractBorderElement; >+import org.apache.fop.render.txt.border.BorderManager; >+ > /** >- * Renderer that renders areas to plain text >- * >- * Created by Arthur E Welch III while at M&I EastPoint Technology >- * Modified by Mark Lillywhite mark-fop@inomial.com to use the new >- * Renderer interface. >+ * Renderer that renders areas to plain text. >+ * >+ * @author Art Welch >+ * @author <a href="mailto:mark-fop@inomial.com">Mark Lillywhite</a> (to use >+ * the new Renderer interface) > */ >-public class TXTRenderer extends PrintRenderer { >+public class TXTRenderer extends AbstractPathOrientedRenderer { >+ >+ private static final char LIGHT_SHADE = '\u2591'; >+ >+ private static final char MEDIUM_SHADE = '\u2592'; >+ >+ private static final char DARK_SHADE = '\u2593'; > >- /** The MIME type for PostScript */ >- public static final String MIME_TYPE = "text/plain"; >+ private static final char FULL_BLOCK = '\u2588'; > >+ public static final char IMAGE_CHAR = '#'; >+ >+ /**The stream for output */ >+ private OutputStream outputStream; >+ >+ /** The current stream to add Text commands to. */ >+ private TXTStream currentStream; >+ >+ /** Buffer for text. */ >+ private StringBuffer charData[]; >+ >+ /** Buffer for background and images. */ >+ private StringBuffer decoData[]; >+ >+ /** Height of one symbol in Courier font size of 10pt. */ >+ public static final int CHAR_HEIGHT = 7860; >+ >+ /** Width of one symbol in Courier font size of 10pt. */ >+ public static final int CHAR_WIDTH = 6000; >+ >+ /** Current processing page width. */ >+ private int pageWidth; >+ >+ /** Current processing page height. */ >+ private int pageHeight; >+ >+ /** >+ * Every line except the last line on a page (which will end with >+ * pageEnding) will be terminated with this string. >+ */ >+ public String lineEnding = "\r\n"; >+ >+ /** Every page except the last one will end with this string. */ >+ public String pageEnding = "\f"; >+ >+ /** Equals true, if current page is first. */ >+ private boolean firstPage = false; >+ >+ /** Manager for storing border's information. */ >+ private BorderManager bm; >+ >+ /** Char for current filling. */ >+ private char fillChar; >+ >+ /** Saves current coordinate transformation. */ >+ private TXTState currentState = new TXTState(); >+ >+ public TXTRenderer() { >+ } >+ > /** >- * the current stream to add Text commands to >+ * Indicates if point (x, y) lay inside currentPage. >+ * >+ * @param x x coordinate >+ * @param y y coordinate >+ * @return <b>true</b> if point lay inside page > */ >- private PCLStream currentStream; >+ public boolean isLayInside(int x, int y) { >+ return (x >= 0) && (x < pageWidth) && (y >= 0) && (y < pageHeight); >+ } > >- private int pageHeight = 7920; >+ /** >+ * Add char to text buffer. >+ * >+ * @param x x coordinate >+ * @param y y coordinate >+ * @param ch char to add >+ */ >+ protected void addChar(int x, int y, char ch, boolean ischar) { >+ Point point = currentState.transformPoint(x, y); >+ putChar(point.x, point.y, ch, ischar); >+ } > >- // These variables control the virtual paggination functionality. >- private int curdiv = 0; >- private int divisions = -1; >- private int paperheight = -1; // Paper height in decipoints? >- private int orientation = -1; // -1=default/unknown, 0=portrait, 1=landscape. >- private int topmargin = -1; // Top margin in decipoints? >- private int leftmargin = -1; // Left margin in decipoints? >- private int fullmargin = 0; >- private final boolean debug = false; >+ /** >+ * Add char to text or background buffer. >+ * >+ * @param x x coordinate >+ * @param y x coordinate >+ * @param ch char to add >+ * @param ischar indicates if it char or background >+ */ >+ protected void putChar(int x, int y, char ch, boolean ischar) { >+ if (isLayInside(x, y)) { >+ StringBuffer sb = ischar ? charData[y] : decoData[y]; >+ while (sb.length() <= x) { >+ sb.append(' '); >+ } >+ sb.setCharAt(x, ch); >+ } >+ } > >- // Variables for rendering text. >- private StringBuffer charData[]; >- private StringBuffer decoData[]; >- private float textCPI = 16.67f; >- private float textLPI = 8; >- private int maxX = (int)(8.5f * textCPI + 1); >- private int maxY = (int)(11f * textLPI + 1); >- private float xFactor; >- private float yFactor; >- /** >- * Every line except the last line on a page (which will end with >- * pageEnding) will be terminated with this string. >+ /** >+ * Adds string to text buffer (<code>charData</code>). <p> >+ * Chars of string map in turn. >+ * >+ * @param row x coordinate >+ * @param col y coordinate >+ * @param s string to add > */ >- private String lineEnding = "\r\n"; >- /** >- * Every page except the last one will end with this string. >+ protected void addString(int row, int col, String s) { >+ for (int l = 0; l < s.length(); l++) { >+ addChar(col + l, row, s.charAt(l), true); >+ } >+ } >+ >+ /** >+ * Render TextArea to Text. >+ * >+ * @param area inline area to render >+ */ >+ protected void renderText(TextArea area) { >+ int col = Helper.ceilPosition(this.currentIPPosition, CHAR_WIDTH); >+ int row = Helper.ceilPosition(this.currentBPPosition, CHAR_HEIGHT); >+ >+ String s = area.getTextArea(); >+ >+ addString(row, col, s); >+ >+ super.renderText(area); >+ } >+ >+ /** >+ * Render page into Text. >+ * >+ * @param page - page to render >+ */ >+ public void renderPage(PageViewport page) throws IOException, FOPException { >+ if (firstPage) { >+ firstPage = false; >+ } else { >+ currentStream.add(pageEnding); >+ } >+ >+ Rectangle2D bounds = page.getViewArea(); >+ double width = bounds.getWidth(); >+ double height = bounds.getHeight(); >+ >+ pageWidth = Helper.ceilPosition((int) width, CHAR_WIDTH); >+ pageHeight = Helper.ceilPosition((int) height, CHAR_HEIGHT); >+ >+ // init buffers >+ charData = new StringBuffer[pageHeight]; >+ decoData = new StringBuffer[pageHeight]; >+ for (int i = 0; i < pageHeight; i++) { >+ charData[i] = new StringBuffer(); >+ decoData[i] = new StringBuffer(); >+ } >+ >+ bm = new BorderManager(pageWidth, pageHeight, currentState); >+ >+ super.renderPage(page); >+ >+ flushBorderToBuffer(); >+ flushBuffer(); >+ } >+ >+ /** >+ * Projects current page borders (i.e.<code>bm</code>) to buffer for >+ * background and images (i.e.<code>decoData</code>). > */ >- private String pageEnding = "\f"; >+ private void flushBorderToBuffer() { >+ for (int x = 0; x < pageWidth; x++) { >+ for (int y = 0; y < pageHeight; y++) { >+ Character c = bm.getCharacter(x, y); >+ if (c != null) { >+ putChar(x, y, c.charValue(), false); >+ } >+ } >+ } >+ } >+ > /** >- * If true then graphics/decorations will not be rendered - text only. >+ * Write out the buffer to output stream. > */ >- private boolean suppressGraphics = false; >- private boolean firstPage = false; >+ private void flushBuffer() { >+ for (int row = 0; row < pageHeight; row++) { >+ StringBuffer cr = charData[row]; >+ StringBuffer dr = decoData[row]; >+ StringBuffer outr = null; > >- private void addStr(int row, int col, String str, boolean ischar) { >- if (debug) { >- log.debug("TXTRenderer.addStr(" + row + ", " + col >- + ", \"" + str + "\", " + ischar + ")"); >- } >- if (suppressGraphics && !ischar) { >- return; >- } >- StringBuffer sb; >- if (row < 0) { >- row = 0; >- } >- if (ischar) { >- sb = charData[row]; >- } else { >- sb = decoData[row]; >- } >- if (sb == null) { >- sb = new StringBuffer(); >- } >- if ((col + str.length()) > maxX) { >- col = maxX - str.length(); >- } >- if (col < 0) { >- col = 0; >- if (str.length() > maxX) { >- str = str.substring(0, maxX); >- } >- } >- // Pad to col >- for (int countr = sb.length(); countr < col; countr++) { >- sb.append(' '); >- } >- if (debug) { >- log.debug("TXTRenderer.addStr() sb.length()=" >- + sb.length()); >- } >- for (int countr = col; countr < (col + str.length()); countr++) { >- if (countr >= sb.length()) { >- sb.append(str.charAt(countr - col)); >- } else { >- if (debug) { >- log.debug("TXTRenderer.addStr() sb.length()=" >- + sb.length() + " countr=" + countr); >- } >- sb.setCharAt(countr, str.charAt(countr - col)); >- } >- } >+ if (cr != null && dr == null) >+ outr = cr; >+ else if (dr != null && cr == null) >+ outr = dr; >+ else if (cr != null && dr != null) { >+ int len = dr.length(); >+ if (cr.length() > len) >+ len = cr.length(); >+ outr = new StringBuffer(); >+ for (int countr = 0; countr < len; countr++) { >+ if (countr < cr.length() && cr.charAt(countr) != ' ') >+ outr.append(cr.charAt(countr)); >+ else if (countr < dr.length()) >+ outr.append(dr.charAt(countr)); >+ else >+ outr.append(' '); >+ } >+ } > >- if (ischar) { >- charData[row] = sb; >- } else { >- decoData[row] = sb; >- } >- } >+ if (outr != null) { >+ currentStream.add(outr.toString()); >+ } >+ if (row < pageHeight) { >+ currentStream.add(lineEnding); >+ } >+ } >+ } > >- /** @see org.apache.fop.render.AbstractRenderer */ >- public String getMimeType() { >- return MIME_TYPE; >+ public void startRenderer(OutputStream outputStream) throws IOException { >+ log.info("Rendering areas to TEXT."); >+ this.outputStream = outputStream; >+ currentStream = new TXTStream(outputStream); >+ firstPage = true; >+ } >+ >+ public void stopRenderer() throws IOException { >+ log.info("writing out TEXT"); >+ outputStream.flush(); >+ super.stopRenderer(); >+ } >+ >+ /** Does nothing. */ >+ protected void restoreStateStackAfterBreakOut(List breakOutList) { >+ } >+ >+ /** Does nothing. */ >+ protected List breakOutOfStateStack() { >+ return null; >+ } >+ >+ /** Does nothing. */ >+ protected void saveGraphicsState() { >+ } >+ >+ /** Does nothing. */ >+ protected void restoreGraphicsState() { >+ } >+ >+ /** Does nothing. */ >+ protected void beginTextObject() { >+ } >+ >+ /** Does nothing. */ >+ protected void endTextObject() { >+ } >+ >+ /** Does nothing. */ >+ protected void clip() { >+ } >+ >+ /** Does nothing. */ >+ protected void clipRect(float x, float y, float width, float height) { >+ } >+ >+ /** Does nothing. */ >+ protected void moveTo(float x, float y) { >+ } >+ >+ /** Does nothing. */ >+ protected void lineTo(float x, float y) { >+ } >+ >+ /** Does nothing. */ >+ protected void closePath() { >+ } >+ >+ /** >+ * Fills rectangle startX, startY, width, height with char >+ * <code>fillChar</code>. >+ * >+ * @param startX x-coordinate of upper left point >+ * @param startY y-coordinate of upper left point >+ * @param width width of rectangle >+ * @param height height of rectangle >+ * @param fillChar filling char >+ */ >+ private void fillRect(int startX, int startY, int width, int height, >+ char fillChar) { >+ for (int x = startX; x < startX + width; x++) { >+ for (int y = startY; y < startY + height; y++) { >+ addChar(x, y, fillChar, false); >+ } >+ } >+ } >+ >+ protected void fillRect(float x, float y, float width, float height) { >+ fillRect(bm.getStartX(), bm.getStartY(), bm.getWidth(), bm.getHeight(), >+ fillChar); >+ } >+ >+ protected void updateColor(ColorType col, boolean fill) { >+ if (col == null) { >+ return; >+ } >+ // fillShade evaluation was taken from fop-0.20.5 >+ double fillShade = 0.3f * col.getRed() + >+ 0.59f * col.getGreen() + >+ 0.11f * col.getBlue(); >+ fillShade = 1 - fillShade; >+ >+ if (fillShade > 0.8f) { >+ fillChar = FULL_BLOCK; >+ } else if (fillShade > 0.6f) { >+ fillChar = DARK_SHADE; >+ } else if (fillShade > 0.4f) { >+ fillChar = MEDIUM_SHADE; >+ } else if (fillShade > 0.2f) { >+ fillChar = LIGHT_SHADE; >+ } else { >+ fillChar = ' '; >+ } >+ } >+ >+ /** Does nothing. */ >+ protected void drawImage(String url, Rectangle2D pos) { >+ } >+ >+ public void renderImage(Image image, Rectangle2D pos) { >+ int x1 = Helper.ceilPosition(currentIPPosition, CHAR_WIDTH); >+ int y1 = Helper.ceilPosition(currentBPPosition, CHAR_HEIGHT); >+ int width = Helper.ceilPosition((int) pos.getWidth(), CHAR_WIDTH); >+ int height = Helper.ceilPosition((int) pos.getHeight(), CHAR_HEIGHT); >+ >+ fillRect(x1, y1, width, height, IMAGE_CHAR); > } > >+ protected int toMilli(float x) { >+ return Math.round(x * 1000f); >+ } >+ >+ /** >+ * Adds one element of border. >+ * >+ * @param x x coordinate >+ * @param y y coordinate >+ * @param style >+ * @param type >+ */ >+ private void addBitOfBorder(int x, int y, int style, int type) { >+ Point point = currentState.transformPoint(x, y); >+ if (isLayInside(point.x, point.y)) { >+ bm.addBorderElement(point.x, point.y, style, type); >+ } >+ } >+ >+ protected void drawBorderLine(float x1, float y1, float x2, float y2, >+ boolean horz, boolean startOrBefore, int style, ColorType col) { >+ >+ int borderHeight = bm.getHeight(); >+ int borderWidth = bm.getWidth(); >+ int borderStartX = bm.getStartX(); >+ int borderStartY = bm.getStartY(); >+ >+ int x, y; >+ if (horz && startOrBefore) { // BEFORE >+ x = borderStartX; >+ y = borderStartY; >+ } else if (horz && !startOrBefore) { // AFTER >+ x = borderStartX; >+ y = borderStartY + borderHeight - 1; >+ } else if (!horz && startOrBefore) { // START >+ x = borderStartX; >+ y = borderStartY; >+ } else { // END >+ x = borderStartX + borderWidth - 1; >+ y = borderStartY; >+ } >+ >+ int dx, dy, length, startType, endType; >+ if (horz) { >+ length = borderWidth; >+ dx = 1; >+ dy = 0; >+ startType = 1 << AbstractBorderElement.RIGHT; >+ endType = 1 << AbstractBorderElement.LEFT; >+ } else { >+ length = borderHeight; >+ dx = 0; >+ dy = 1; >+ startType = 1 << AbstractBorderElement.DOWN; >+ endType = 1 << AbstractBorderElement.UP; >+ } >+ >+ addBitOfBorder(x, y, style, startType); >+ for (int i = 0; i < length - 2; i++) { >+ x += dx; >+ y += dy; >+ addBitOfBorder(x, y, style, startType + endType); >+ } >+ x += dx; >+ y += dy; >+ addBitOfBorder(x, y, style, endType); >+ } >+ >+ protected void drawBackAndBorders(Area area, float startx, float starty, >+ float width, float height) { >+ bm.setWidth(Helper.ceilPosition(toMilli(width), CHAR_WIDTH)); >+ bm.setHeight(Helper.ceilPosition(toMilli(height), CHAR_HEIGHT)); >+ bm.setStartX(Helper.ceilPosition(toMilli(startx), CHAR_WIDTH)); >+ bm.setStartY(Helper.ceilPosition(toMilli(starty), CHAR_HEIGHT)); >+ >+ super.drawBackAndBorders(area, startx, starty, width, height); >+ } >+ >+ protected void startVParea(CTM ctm) { >+ currentState.push(ctm); >+ } >+ >+ protected void endVParea() { >+ currentState.pop(); >+ } > } >Index: src/java/org/apache/fop/render/txt/TXTState.java >=================================================================== >--- src/java/org/apache/fop/render/txt/TXTState.java (revision 0) >+++ src/java/org/apache/fop/render/txt/TXTState.java (revision 0) >@@ -0,0 +1,130 @@ >+/* >+ * Copyright 2005 The Apache Software Foundation. >+ * >+ * Licensed 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.fop.render.txt; >+ >+import java.awt.Point; >+import java.awt.geom.Rectangle2D; >+import java.util.Iterator; >+import java.util.LinkedList; >+ >+import org.apache.fop.area.CTM; >+ >+/** >+ * This keeps information about the current state when writing to txt, i.e. >+ * manages coordinate transformation matrices for getting absolute coordinates. >+ */ >+public class TXTState { >+ >+ /** Keeps all coordinate transformation matrices during rendering. */ >+ private LinkedList stackCTM = new LinkedList(); >+ >+ /** >+ * Current result coordinate transformation matrix. It's product of >+ * all matrices in order, saved in <code>stackCTM</code>. >+ */ >+ private CTM resultCTM = new CTM(); >+ >+ public TXTState() { >+ } >+ >+ /** >+ * Updates result coordinate transformation matrix >+ * (i.e. <code>resultCTM</code>), multipliing it by given matrix. >+ * >+ * @param ctm CTM >+ */ >+ private void updateResultCTM(CTM ctm) { >+ resultCTM = resultCTM.multiply(ctm); >+ } >+ >+ /** >+ * Recalculate current result coordinate transformation matrix. >+ */ >+ private void calcResultCTM() { >+ resultCTM = new CTM(); >+ for (Iterator i = stackCTM.iterator(); i.hasNext(); ) { >+ updateResultCTM((CTM) i.next()); >+ } >+ } >+ >+ /** >+ * Push the current coordinate transformation matrix onto the stack and >+ * reevaluate <code>resultCTM</code>. >+ */ >+ public void push(CTM ctm) { >+ stackCTM.addLast(ctm); >+ updateResultCTM(ctm); >+ } >+ >+ /** >+ * Pop the coordinate transformation matrix from the stack and reevaluate >+ * <code>resultCTM</code>. >+ */ >+ public void pop() { >+ stackCTM.removeLast(); >+ calcResultCTM(); >+ } >+ >+ /** >+ * Modifies coordinate transformation matrix in such a way, so >+ * x-shift and y-shift will be transformed in text positions. >+ * >+ * @param ctm CTM to modify >+ * @return instance of CTM >+ */ >+ public CTM refineCTM(CTM ctm) { >+ double da[] = ctm.toArray(); >+ // refine x-shift >+ da[4] = Helper.roundPosition((int) da[4], TXTRenderer.CHAR_WIDTH); >+ // refine y-shift >+ da[5] = Helper.roundPosition((int) da[5], TXTRenderer.CHAR_HEIGHT); >+ >+ return new CTM(da[0], da[1], da[2], da[3], da[4], da[5]); >+ } >+ >+ /** >+ * Transforms <code>point</code> using <code>ctm</code>. >+ * >+ * @param p Point >+ * @param ctm CTM >+ * @return transformed Point >+ */ >+ public Point transformPoint(Point p, CTM ctm) { >+ Rectangle2D r = new Rectangle2D.Double(p.x, p.y, 0, 0); >+ CTM nctm = refineCTM(ctm); >+ r = nctm.transform(r); >+ return new Point((int) r.getX(), (int) r.getY()); >+ } >+ >+ /** >+ * Transforms point (x, y) using <code>resultCTM</code>. >+ * >+ * @param x x-coordinate >+ * @param y y-coordinate >+ * @return transformed Point >+ */ >+ public Point transformPoint(int x, int y) { >+ return transformPoint(new Point(x, y), resultCTM); >+ } >+ >+ /** >+ * @return current result coordinate transformation matrix >+ */ >+ public CTM getResultCTM() { >+ return resultCTM; >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 37253
: 16812 |
16923