View | Details | Raw Unified | Return to bug 37253
Collapse All | Expand All

(-)src/java/org/apache/fop/fo/flow/TableColumn.java (+9 lines)
Lines 30-35 Link Here
30
import org.apache.fop.fo.ValidationException;
30
import org.apache.fop.fo.ValidationException;
31
import org.apache.fop.fo.expr.PropertyException;
31
import org.apache.fop.fo.expr.PropertyException;
32
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
32
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
33
import org.apache.fop.fo.properties.FixedLength;
33
34
34
/**
35
/**
35
 * Class modelling the fo:table-column object.
36
 * Class modelling the fo:table-column object.
Lines 176-180 Link Here
176
        sb.append(" column-width=").append(getColumnWidth());
177
        sb.append(" column-width=").append(getColumnWidth());
177
        return sb.toString();
178
        return sb.toString();
178
    }
179
    }
180
181
    /**
182
     * Sets a column width.
183
     * @param length
184
     */
185
    public void setColumnWidth(Length columnWidth) {
186
        this.columnWidth = columnWidth;
187
    }
179
}
188
}
180
189
(-)src/java/org/apache/fop/render/RendererFactory.java (+3 lines)
Lines 33-38 Link Here
33
import org.apache.fop.fo.FOEventHandler;
33
import org.apache.fop.fo.FOEventHandler;
34
import org.apache.fop.render.mif.MIFHandler;
34
import org.apache.fop.render.mif.MIFHandler;
35
import org.apache.fop.render.rtf.RTFHandler;
35
import org.apache.fop.render.rtf.RTFHandler;
36
import org.apache.fop.render.txt.TXTHandler;
36
37
37
/**
38
/**
38
 * Factory for FOEventHandlers and Renderers.
39
 * Factory for FOEventHandlers and Renderers.
Lines 132-137 Link Here
132
                return new MIFHandler(userAgent, out);
133
                return new MIFHandler(userAgent, out);
133
            } else if (renderType == Constants.RENDER_RTF) {
134
            } else if (renderType == Constants.RENDER_RTF) {
134
                return new RTFHandler(userAgent, out);
135
                return new RTFHandler(userAgent, out);
136
            } else if (renderType == Constants.RENDER_TXT) {
137
                 return new TXTHandler(userAgent, out);
135
            } else {
138
            } else {
136
                if (renderType < Constants.RENDER_MIN_CONST 
139
                if (renderType < Constants.RENDER_MIN_CONST 
137
                    || renderType > Constants.RENDER_MAX_CONST) {
140
                    || renderType > Constants.RENDER_MAX_CONST) {
(-)src/java/org/apache/fop/render/txt/border/DashedBorderElement.java (+141 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt.border;
20
21
import java.util.Arrays;
22
23
/**
24
 * This class is responsible for managing of dashed border elements.
25
 */
26
public class DashedBorderElement extends AbstractBorderElement {
27
    
28
    private static final char DASH_HORIZONTAL = '-';
29
30
    private static final char DASH_VERTICAL = '|';
31
    
32
    private static final char UNDEFINED = '?';
33
    
34
    private static final int UP2 = 1;
35
    
36
    private static final int RIGHT2 = 2;
37
    
38
    private static final int DOWN2 = 4;
39
    
40
    private static final int LEFT2 = 8;
41
    
42
    private static char[] map = new char[20];
43
    
44
    static {
45
        Arrays.fill(map, UNDEFINED);
46
        map[0] = ' ';
47
        map[UP2] = DASH_VERTICAL;
48
        map[DOWN2] = DASH_VERTICAL;
49
        map[UP2 + DOWN2] = DASH_VERTICAL;
50
        
51
        map[LEFT2] = DASH_HORIZONTAL;
52
        map[RIGHT2] = DASH_HORIZONTAL;
53
        map[LEFT2 + RIGHT2] = DASH_HORIZONTAL;
54
    }
55
    
56
    /**
57
     * Constructs a newly allocated <code>DashedBorderElement</code> object.
58
     * Fills <code>data</code> using superclass constructor.
59
     * 
60
     * @param type binary representation of type gives <code>data</code>
61
     */
62
    public DashedBorderElement(int type) {
63
        super(type);
64
    }
65
66
    /**
67
     * Merges dashed border element with instance of solid and double border
68
     * element, returns instance of <code>SolidAndDoubleBorderElement</code>. 
69
     * 
70
     * @param sdb instance of <code>SolidAndDoubleBorderElement</code> to merge
71
     * @return merged border element
72
     */
73
    private AbstractBorderElement mergeSolid(SolidAndDoubleBorderElement sdb) {
74
        AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0);
75
        for (int i = 0; i < 4; i++) {
76
            e.setData(i, Math.max(data[i], sdb.getData(i)));
77
        }
78
        return e;        
79
    }
80
81
    /**
82
     * Merges dashed border element with dashed border element and returns 
83
     * instance of <code>DashedBorderElement</code>. 
84
     * 
85
     * @param dbe instance of <code>DashedBorderElement</code> to merge
86
     * @return merged border element
87
     */
88
    private AbstractBorderElement mergeDashed(DashedBorderElement dbe) {
89
        for (int i = 0; i < 4; i++) {
90
            data[i] = Math.max(data[i], dbe.getData(i));
91
        }
92
        return this;
93
    }
94
    
95
    /**
96
     * Converts dashed border element to 
97
     * <code>SolidAndDoubleBorderElement</code>.
98
     * 
99
     * @return converted instance of <code>SolidAndDoubleBorderElement</code>
100
     */
101
    private AbstractBorderElement toSolidAndDouble() {
102
        AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0);
103
        for (int i = 0; i < 4; i++) {
104
            e.setData(i, data[i]);
105
        }
106
        return e;        
107
    }
108
109
    /**
110
     * Merges with border element.
111
     * @param e instance of AbstractBorderElement
112
     * @return instance of AbstractBorderElement
113
     */
114
    public AbstractBorderElement merge(AbstractBorderElement e) {
115
        AbstractBorderElement abe = this;
116
        if (e instanceof SolidAndDoubleBorderElement) {
117
            abe = mergeSolid((SolidAndDoubleBorderElement) e);
118
        } else if (e instanceof DashedBorderElement) {
119
            abe = mergeDashed((DashedBorderElement) e);
120
        } else {
121
            abe = e;
122
        }
123
        return abe;
124
    }
125
126
    /** 
127
     * @see org.apache.fop.render.txt.border.AbstractBorderElement#convert2Char()
128
     */
129
    public char convert2Char() {
130
        int key = 0;
131
        key += data[UP] * UP2;
132
        key += data[DOWN] * DOWN2;
133
        key += data[LEFT] * LEFT2;
134
        key += data[RIGHT] * RIGHT2;
135
        char ch = map[key];
136
        if (ch == UNDEFINED) {
137
            ch = toSolidAndDouble().convert2Char();
138
        }
139
        return ch;
140
    }
141
}
(-)src/java/org/apache/fop/render/txt/border/SolidAndDoubleBorderElement.java (+276 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt.border;
20
21
import java.util.Arrays;
22
23
/**
24
 * This class is responsible for solid and double border elements managing.
25
 */
26
public class SolidAndDoubleBorderElement extends AbstractBorderElement {
27
28
    private static final char LIGHT_HORIZONTAL = '\u2500';
29
30
    private static final char LIGHT_VERTICAL = '\u2502';
31
32
    private static final char LIGHT_DOWN_AND_RIGHT = '\u250C';
33
34
    private static final char LIGHT_DOWN_AND_LEFT = '\u2510';
35
36
    private static final char LIGHT_UP_AND_RIGHT = '\u2514';
37
38
    private static final char LIGHT_UP_AND_LEFT = '\u2518';
39
40
    private static final char LIGHT_VERTICAL_AND_RIGHT = '\u251C';
41
42
    private static final char LIGHT_VERTICAL_AND_LEFT = '\u2524';
43
44
    private static final char LIGHT_DOWN_AND_HORIZONTAL = '\u252C';
45
46
    private static final char LIGHT_UP_AND_HORIZONTAL = '\u2534';
47
48
    private static final char LIGHT_VERTICAL_AND_HORIZONTAL = '\u253C';
49
    
50
    private static final char DOUBLE_HORIZONTAL = '\u2550';
51
52
    private static final char DOUBLE_VERTICAL = '\u2551';
53
    
54
    private static final char DOUBLE_DOWN_AND_RIGHT = '\u2554';    
55
56
    private static final char DOUBLE_DOWN_AND_LEFT = '\u2557';
57
58
    private static final char DOUBLE_UP_AND_RIGHT = '\u255A';
59
60
    private static final char DOUBLE_UP_AND_LEFT = '\u255D';
61
    
62
    private static final char DOUBLE_VERTICAL_AND_RIGHT = '\u2560';
63
    
64
    private static final char DOUBLE_VERTICAL_AND_LEFT = '\u2563';
65
    
66
    private static final char DOUBLE_DOWN_AND_HORIZONTAL = '\u2566';
67
    
68
    private static final char DOUBLE_UP_AND_HORIZONTAL = '\u2569';
69
    
70
    private static final char DOUBLE_VERTICAL_AND_HORIZONTAL = '\u256C';
71
    
72
    private static final char DOWN_SINGLE_AND_RIGHT_DOUBLE = '\u2552';
73
    
74
    private static final char DOWN_DOUBLE_AND_RIGHT_SINGLE = '\u2553';
75
76
    private static final char DOWN_SINGLE_AND_LEFT_DOUBLE = '\u2555';
77
78
    private static final char DOWN_DOUBLE_AND_LEFT_SINGLE = '\u2556';
79
    
80
    private static final char UP_SINGLE_AND_RIGHT_DOUBLE = '\u2558';
81
    
82
    private static final char UP_DOUBLE_AND_RIGHT_SINGLE = '\u2559';
83
    
84
    private static final char UP_SINGLE_AND_LEFT_DOUBLE = '\u255B';
85
    
86
    private static final char UP_DOUBLE_AND_LEFT_SINGLE = '\u255C';
87
    
88
    private static final char VERTICAL_SINGLE_AND_RIGHT_DOUBLE = '\u255E';
89
    
90
    private static final char VERTICAL_DOUBLE_AND_RIGHT_SINGLE = '\u255F';
91
    
92
    private static final char VERTICAL_SINGLE_AND_LEFT_DOUBLE = '\u2561';
93
    
94
    private static final char VERTICAL_DOUBLE_AND_LEFT_SINGLE = '\u2562';
95
    
96
    private static final char DOWN_SINGLE_AND_HORIZONTAL_DOUBLE = '\u2564';
97
    
98
    private static final char DOWN_DOUBLE_AND_HORIZONTAL_SINGLE = '\u2565';
99
    
100
    private static final char UP_SINGLE_AND_HORIZONTAL_DOUBLE = '\u2567';
101
    
102
    private static final char UP_DOUBLE_AND_HORIZONTAL_SINGLE = '\u2568';
103
    
104
    private static final char VERTICAL_SINGLE_AND_HORIZONTAL_DOUBLE = '\u256A';
105
    
106
    private static final char VERTICAL_DOUBLE_AND_HORIZONTAL_SINGLE = '\u256B';
107
    
108
    private static final char UNDEFINED = '?';
109
    
110
    private static final int UP3 = 1;
111
112
    private static final int DOWN3 = 3;
113
114
    private static final int LEFT3 = 9;
115
116
    private static final int RIGHT3 = 27;
117
118
    private static final char[] MAP = new char[100];
119
120
    static {
121
        Arrays.fill(MAP, UNDEFINED);
122
        MAP[0] = ' ';
123
        MAP[UP3] = LIGHT_VERTICAL;
124
        MAP[DOWN3] = LIGHT_VERTICAL;
125
        MAP[RIGHT3] = LIGHT_HORIZONTAL;
126
        MAP[LEFT3] = LIGHT_HORIZONTAL;
127
        MAP[UP3 + DOWN3] = LIGHT_VERTICAL;
128
        MAP[LEFT3 + RIGHT3] = LIGHT_HORIZONTAL;
129
        MAP[UP3 + LEFT3] = LIGHT_UP_AND_LEFT;
130
        MAP[LEFT3 + DOWN3] = LIGHT_DOWN_AND_LEFT;
131
        MAP[DOWN3 + RIGHT3] = LIGHT_DOWN_AND_RIGHT;
132
        MAP[UP3 + RIGHT3] = LIGHT_UP_AND_RIGHT;
133
        MAP[UP3 + DOWN3 + RIGHT3] = LIGHT_VERTICAL_AND_RIGHT;
134
        MAP[UP3 + LEFT3 + DOWN3] = LIGHT_VERTICAL_AND_LEFT;
135
        MAP[LEFT3 + DOWN3 + RIGHT3] = LIGHT_DOWN_AND_HORIZONTAL;
136
        MAP[UP3 + LEFT3 + RIGHT3] = LIGHT_UP_AND_HORIZONTAL;
137
        MAP[UP3 + LEFT3 + DOWN3 + RIGHT3] = LIGHT_VERTICAL_AND_HORIZONTAL;
138
        //DOUBLE
139
        MAP[2 * UP3] = DOUBLE_VERTICAL;
140
        MAP[2 * DOWN3] = DOUBLE_VERTICAL;
141
        MAP[2 * RIGHT3] = DOUBLE_HORIZONTAL;
142
        MAP[2 * LEFT3] = DOUBLE_HORIZONTAL;
143
        MAP[2 * UP3 + 2 * DOWN3] = DOUBLE_VERTICAL;
144
        MAP[2 * LEFT3 + 2 * RIGHT3] = DOUBLE_HORIZONTAL;
145
        MAP[2 * UP3 + 2 * LEFT3] = DOUBLE_UP_AND_LEFT;
146
        MAP[2 * LEFT3 + 2 * DOWN3] = DOUBLE_DOWN_AND_LEFT;
147
        MAP[2 * DOWN3 + 2 * RIGHT3] = DOUBLE_DOWN_AND_RIGHT;
148
        MAP[2 * UP3 + 2 * RIGHT3] = DOUBLE_UP_AND_RIGHT;
149
        MAP[2 * UP3 + 2 * DOWN3 + 2 * RIGHT3] = DOUBLE_VERTICAL_AND_RIGHT;
150
        MAP[2 * UP3 + 2 * DOWN3 + 2 * LEFT3] = DOUBLE_VERTICAL_AND_LEFT;
151
        MAP[2 * DOWN3 + 2 * RIGHT3 + 2 * LEFT3] = DOUBLE_DOWN_AND_HORIZONTAL;
152
        MAP[2 * UP3 + 2 * RIGHT3 + 2 * LEFT3] = DOUBLE_UP_AND_HORIZONTAL;
153
        MAP[2 * UP3 + 2 * DOWN3 + 2 * RIGHT3 + 2 * LEFT3] = DOUBLE_VERTICAL_AND_HORIZONTAL;
154
        //DOUBLE&SINGLE
155
        MAP[DOWN3 + 2 * RIGHT3] = DOWN_SINGLE_AND_RIGHT_DOUBLE;
156
        MAP[2 * DOWN3 + RIGHT3] = DOWN_DOUBLE_AND_RIGHT_SINGLE;
157
        MAP[DOWN3 + 2 * LEFT3] = DOWN_SINGLE_AND_LEFT_DOUBLE;
158
        MAP[2 * DOWN3 + LEFT3] = DOWN_DOUBLE_AND_LEFT_SINGLE;
159
        MAP[UP3 + 2 * RIGHT3] = UP_SINGLE_AND_RIGHT_DOUBLE;
160
        MAP[2 * UP3 + RIGHT3] = UP_DOUBLE_AND_RIGHT_SINGLE;
161
        MAP[UP3 + 2 * LEFT3] = UP_SINGLE_AND_LEFT_DOUBLE;
162
        MAP[2 * UP3 + LEFT3] = UP_DOUBLE_AND_LEFT_SINGLE;
163
        MAP[UP3 + DOWN3 + 2 * RIGHT3] = VERTICAL_SINGLE_AND_RIGHT_DOUBLE;
164
        MAP[2 * UP3 + 2 * DOWN3 + RIGHT3] = VERTICAL_DOUBLE_AND_RIGHT_SINGLE;
165
        MAP[UP3 + DOWN3 + 2 * LEFT3] = VERTICAL_SINGLE_AND_LEFT_DOUBLE;
166
        MAP[2 * UP3 + 2 * DOWN3 + LEFT3] = VERTICAL_DOUBLE_AND_LEFT_SINGLE;
167
        MAP[DOWN3 + 2 * LEFT3 + 2 * RIGHT3] = DOWN_SINGLE_AND_HORIZONTAL_DOUBLE;
168
        MAP[2 * DOWN3 + LEFT3 + RIGHT3] = DOWN_DOUBLE_AND_HORIZONTAL_SINGLE;
169
        MAP[UP3 + 2 * LEFT3 + 2 * RIGHT3] = UP_SINGLE_AND_HORIZONTAL_DOUBLE;
170
        MAP[2 * UP3 + LEFT3 + RIGHT3] = UP_DOUBLE_AND_HORIZONTAL_SINGLE;
171
        MAP[UP3 + DOWN3 + 2 * LEFT3 + 2 * RIGHT3] = VERTICAL_SINGLE_AND_HORIZONTAL_DOUBLE;
172
        MAP[2 * UP3 + 2 * DOWN3 + LEFT3 + RIGHT3] = VERTICAL_DOUBLE_AND_HORIZONTAL_SINGLE;
173
    }
174
175
    /**
176
     * Initializes a newly created <code>SolidAndDoubleBorderElement</code> 
177
     * object so that it represents an empty border element.
178
     */
179
    public SolidAndDoubleBorderElement() {
180
    }
181
182
    /**
183
     * Constructs a newly allocated <code>SolidAndDoubleBorderElement</code> 
184
     * object. Fills <code>data</code> using binary representation of 
185
     * <code>type</code>. If border style is EN_DOUBLE, multiplies 
186
     * <code>data[side]</code> by 2 for every side to distinguish EN_SOLID and 
187
     * EN_DOUBLE.
188
     * 
189
     * @param style integer, representing border style.
190
     * @param type binary representation of type gives <code>data</code>
191
     */
192
    public SolidAndDoubleBorderElement(int style, int type) {
193
        super(type);
194
        if (style == EN_DOUBLE) {
195
            for (int i = 0; i < 4; i++) {
196
                data[i] *= 2;
197
            }
198
        }
199
    }
200
    
201
    /**
202
     * Merges with <code>sde</code>.
203
     * @param sde instance of SolidAndDoubleBorderElement
204
     * @return instance of AbstractBorderElement
205
     */
206
    public AbstractBorderElement mergeSolid(SolidAndDoubleBorderElement sde) {
207
        AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0);
208
        for (int i = 0; i < 4; i++) {
209
            if (sde.getData(i) != 0) {
210
                e.setData(i, sde.getData(i));
211
            } else {
212
                e.setData(i, data[i]);
213
            }
214
        }
215
        return e;
216
    }
217
218
    /**
219
     * Merges with e.
220
     * @param e instance of AbstractBorderElement
221
     * @return instance of AbstractBorderElement
222
     */
223
    public AbstractBorderElement merge(AbstractBorderElement e) {
224
        AbstractBorderElement abe = this;
225
        if (e instanceof SolidAndDoubleBorderElement) {
226
            abe = mergeSolid((SolidAndDoubleBorderElement) e);
227
        } else if (e instanceof DottedBorderElement) {
228
            abe = e;
229
        } else if (e instanceof DashedBorderElement) {
230
            abe = e.merge(this);
231
        }
232
        return abe;
233
    }
234
    
235
    /**
236
     * Maps to char.
237
     * @return resulting mapping char 
238
     */
239
    private char map2Char() {
240
        int key = 0;
241
        key += data[UP] * UP3;
242
        key += data[LEFT] * LEFT3;
243
        key += data[DOWN] * DOWN3;
244
        key += data[RIGHT] * RIGHT3;
245
        return MAP[key];
246
    }
247
248
    /**
249
     * Modifies data to nearest normal internal representation.
250
     */
251
    private void modifyData() {
252
        int c1 = 0;
253
        int c2 = 0;
254
        for (int i = 0; i < 4; i++) {
255
            c1 += (data[i] == 1) ? 1 : 0;
256
            c2 += (data[i] == 2) ? 1 : 0;
257
        }
258
        int m = c1 > c2 ? 1 : 0;
259
        int[] p = {0, m, 2 * (1 - m)};
260
        for (int i = 0; i < 4; i++) {
261
            data[i] = p[data[i]];
262
        }
263
    }
264
265
    /**
266
     * @see org.apache.fop.render.txt.border.AbstractBorderElement#convert2Char()
267
     */
268
    public char convert2Char() {
269
        char ch = map2Char();
270
        if (ch == UNDEFINED) {
271
            modifyData();
272
            ch = map2Char();
273
        }
274
        return ch;
275
    }
276
}
(-)src/java/org/apache/fop/render/txt/border/BorderManager.java (+164 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt.border;
20
21
import org.apache.fop.fo.Constants;
22
import org.apache.fop.render.txt.TXTState;
23
24
/**
25
 * This keeps all information about borders for current processed page.
26
 */
27
public class BorderManager {
28
29
    /** Matrix for storing information about one border element. */
30
    private AbstractBorderElement[][] borderInfo;
31
32
    /** Width of current processed border. */
33
    private int width;
34
    
35
    /** Height of current processed border. */
36
    private int height;
37
38
    /** x-coordinate of upper left point of current processed border. */
39
    private int startX;
40
41
    /** y-coordinate of upper left point of current processed border. */
42
    private int startY;
43
44
    /** Stores TXTState for transforming border elements. */
45
    private TXTState state;
46
47
    /**
48
     * Constructs BorderManger, using <code>pageWidth</code> and 
49
     * <code>pageHeight</code> for creating <code>borderInfo</code>.
50
     *  
51
     * @param pageWidth page width
52
     * @param pageHeight page height
53
     * @param state TXTState
54
     */
55
    public BorderManager(int pageWidth, int pageHeight, TXTState state) {
56
        this.state = state;
57
        borderInfo = new AbstractBorderElement[pageHeight][pageWidth];
58
    }
59
60
    /**
61
     * Adds border element to <code>borderInfo</code>.
62
     * 
63
     * @param x x-coordinate
64
     * @param y y-coordinate
65
     * @param style border-style
66
     * @param type border element type, binary representation of wich gives 
67
     *         information about availability or absence of corresponding side. 
68
     */
69
    public void addBorderElement(int x, int y, int style, int type) {
70
        AbstractBorderElement be = null;
71
72
        if (style == Constants.EN_SOLID || style == Constants.EN_DOUBLE) {
73
            be = new SolidAndDoubleBorderElement(style, type);
74
        } else if (style == Constants.EN_DOTTED) {
75
            be = new DottedBorderElement();
76
        } else if (style == Constants.EN_DASHED) {
77
            be = new DashedBorderElement(type);
78
        } else {
79
            return;
80
        }
81
        be.transformElement(state);
82
83
        if (borderInfo[y][x] != null) {
84
            borderInfo[y][x] = borderInfo[y][x].merge(be);
85
        } else {
86
            borderInfo[y][x] = be;
87
        }
88
    }
89
90
    /**
91
     * @param x x-coordinate
92
     * @param y y-coordinate
93
     * @return if border element at point (x,y) is available, returns instance 
94
     * of Character, created on char, given by corresponding border element, 
95
     * otherwise returns null. 
96
     */
97
    public Character getCharacter(int x, int y) {
98
        Character c = null;
99
        if (borderInfo[y][x] != null) {
100
            c = new Character(borderInfo[y][x].convert2Char());
101
        }
102
        return c;
103
    }
104
105
    /**
106
     * @return width of current processed border.
107
     */
108
    public int getWidth() {
109
        return width;
110
    }
111
    
112
    /**
113
     * Sets width of current processed border.
114
     * @param width width of border
115
     */
116
    public void setWidth(int width) {
117
        this.width = width;
118
    }
119
    
120
    /**
121
     * @return height of current processed border.
122
     */
123
    public int getHeight() {
124
        return height;
125
    }
126
127
    /**
128
     * Sets height of current processed border.
129
     * @param height height of border
130
     */
131
    public void setHeight(int height) {
132
        this.height = height;
133
    }
134
135
    /**
136
     * @return x-coordinate of upper left point of current processed border.
137
     */
138
    public int getStartX() {
139
        return startX;
140
    }
141
142
    /**
143
     * Sets x-coordinate of upper left point of current processed border.
144
     * @param startX x-coordinate of upper left border's point.
145
     */
146
    public void setStartX(int startX) {
147
        this.startX = startX;
148
    }
149
150
    /**
151
     * @return y-coordinate of upper left point of current processed border.
152
     */
153
    public int getStartY() {
154
        return startY;
155
    }
156
157
    /**
158
     * Sets y-coordinate of upper left point of current processed border.
159
     * @param startY y-coordinate of upper left border's point.
160
     */
161
    public void setStartY(int startY) {
162
        this.startY = startY;
163
    }
164
}
(-)src/java/org/apache/fop/render/txt/border/AbstractBorderElement.java (+148 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt.border;
20
21
import java.awt.Point;
22
import java.util.Arrays;
23
24
import org.apache.fop.area.CTM;
25
import org.apache.fop.fo.Constants;
26
import org.apache.fop.render.txt.TXTState;
27
28
/**
29
 * This class keeps information about abstract border element, i.e. specifies
30
 * border element for one text position.
31
 */
32
public abstract class AbstractBorderElement implements Constants {
33
34
    /**
35
     * Constant for a line segment, directing from a center of symbol up 
36
     * the the symbol boundary.
37
     */
38
    public static final int UP = 0;
39
40
    /**
41
     * Constant for a line segment, directing from a center of symbol right 
42
     * the the symbol boundary.
43
     */
44
    public static final int RIGHT = 1;
45
46
    /**
47
     * Constant for a line segment, directing from a center of symbol down 
48
     * the the symbol boundary.
49
     */
50
    public static final int DOWN = 2;
51
52
    /**
53
     * Constant for a line segment, directing from a center of symbol left 
54
     * the the symbol boundary.
55
     */
56
    public static final int LEFT = 3;
57
58
    /**
59
     * I-th element of this array specify, if there line from center of symbol
60
     * to corresponding side (UP, RIGHT, DOWN, LEFT).
61
     */
62
    protected int[] data = {0, 0, 0, 0};
63
64
    /**
65
     * Initializes a newly created <code>AbstractBorderElement</code> object 
66
     * so that it represents an empty border element.
67
     */
68
    public AbstractBorderElement() {
69
    }
70
71
    /**
72
     * Constructs a newly allocated <code>AbstractBorderElement</code> object.
73
     * Fills array <code>data</code> using binary representation of 
74
     * <code>type</code>.
75
     * 
76
     * @param type binary representation of type gives <code>data</code>
77
     */
78
    public AbstractBorderElement(int type) {
79
        for (int i = 0; i < 4; i++) {
80
            data[i] = (type >> i) & 1;
81
        }
82
    }
83
84
    /**
85
     * Returns value of side's element of <code>data</code>.
86
     * 
87
     * @param side integer, representing side
88
     * @return value of side's element
89
     */
90
    public int getData(int side) {
91
        return data[side];
92
    }
93
94
    /**
95
     * Sets a value for <code>data[side]</code>.
96
     * 
97
     * @param side integer, representing side
98
     * @param value a new value for <code>data[side]</code>
99
     */
100
    public void setData(int side, int value) {
101
        data[side] = value;
102
    }
103
104
    /**
105
     * Transform border element in according with <code>state</code>.
106
     * @param state instance of TXTState
107
     */
108
    public void transformElement(TXTState state) {
109
        // here we'll get CTM^-1 without shift
110
        double[] da = state.getResultCTM().toArray();
111
        CTM ctm = new CTM(da[0], -da[1], -da[2], da[3], 0, 0);
112
113
        Point[] pa = new Point[4];
114
        pa[0] = new Point(0, data[UP]);
115
        pa[1] = new Point(data[RIGHT], 0);
116
        pa[2] = new Point(0, -data[DOWN]);
117
        pa[3] = new Point(-data[LEFT], 0);
118
119
        Arrays.fill(data, 0);
120
        for (int i = 0; i < 4; i++) {
121
            Point p = state.transformPoint(pa[i], ctm);
122
123
            int length = (int) p.distance(0, 0);
124
            if (p.x == 0 && p.y > 0) {
125
                data[UP] = length;
126
            } else if (p.x == 0 && p.y < 0) {
127
                data[DOWN] = length;
128
            } else if (p.x > 0 && p.y == 0) {
129
                data[RIGHT] = length;
130
            } else if (p.x < 0 && p.y == 0) {
131
                data[LEFT] = length;
132
            }
133
        }
134
    }
135
136
    /**
137
     * Merges with border element.
138
     * @param e instance of AbstractBorderElement
139
     * @return instance of AbstractBorderElement
140
     */
141
    public abstract AbstractBorderElement merge(AbstractBorderElement e);
142
143
    /**
144
     * Convert internal representation of border element to char.
145
     * @return corresponding char
146
     */
147
    public abstract char convert2Char();
148
}
(-)src/java/org/apache/fop/render/txt/border/DottedBorderElement.java (+45 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt.border;
20
21
/**
22
 * This class is responsible for managing of dotted border elements.
23
 */
24
public class DottedBorderElement extends AbstractBorderElement {
25
    
26
    private static final char MIDDLE_DOT = '\u00B7';
27
28
    /**
29
     * Merges dotted border element with another border element. Here merging
30
     * is quite simple: returning <code>this</code> without any comparing.
31
     * 
32
     * @param e instance of AbstractBorderElement
33
     * @return instance of DottedBorderElement
34
     */
35
    public AbstractBorderElement merge(AbstractBorderElement e) {
36
        return this;
37
    }
38
39
    /**
40
     * @see org.apache.fop.render.txt.border.AbstractBorderElement#convert2Char()
41
     */
42
    public char convert2Char() {
43
        return MIDDLE_DOT;
44
    }
45
}
(-)src/java/org/apache/fop/render/txt/Helper.java (+117 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt;
20
21
/**
22
 * This class has a few convenient static methods for number quantization.
23
 */
24
public final class Helper {
25
26
    /**
27
     * Don't let anyone instantiate this class.
28
     */
29
    private Helper() { }
30
31
    /**
32
     * Returns nearest integer to <code>x</code>, divisible by 
33
     * <code>quantum</code>. 
34
     * 
35
     * @param x integer for quantization
36
     * @param quantum integer, representing quantization
37
     * @return computed nearest integer
38
     */
39
    public static int round(int x, int quantum) {
40
        int ceil = ceil(x, quantum);
41
        int floor = floor(x, quantum);
42
        return (ceil - x < x - floor) ? ceil : floor;
43
    }
44
45
    /**
46
     * Returns minimal possible integer, greater or equal than 
47
     * <code>x</code>, divisible by <code>quantum</code>.
48
     *         
49
     * @param x integer for quantization
50
     * @param quantum integer, representing quantization
51
     * @return computed nearest integer
52
     */
53
    public static int ceil(int x, int quantum) {
54
        int dx = (x < 0) || (x % quantum == 0) ? 0 : 1;
55
        return (x / quantum + dx) * quantum;
56
    }
57
58
    /**
59
     * Returns maximum possible integer, less or equal than
60
     * <code>oldValue</code>, divisible by <code>quantum</code>.
61
     * 
62
     * @param x integer for quantization
63
     * @param quantum integer, representing quantization
64
     * @return computed nearest integer
65
     */
66
    public static int floor(int x, int quantum) {
67
        int dx = (x > 0) || (x % quantum == 0) ? 0 : -1;
68
        return (x / quantum + dx) * quantum;
69
    }
70
71
    /**
72
     * Returns the closest integer to <code>x/y</code> fraction.
73
     * It's possible to consider this methos as a analog of Math.round(x/y), 
74
     * without having deal with non-integer.
75
     * 
76
     * @param x integer, fraction numerator
77
     * @param y  integer, fraction denominator
78
     * @return the value of the fraction rounded to the nearest
79
     * @see java.lang.Math#round(double)
80
     */
81
    public static int roundPosition(int x, int y) {
82
        return round(x, y) / y;
83
    }
84
85
    /**
86
     * Returns the smallest integer that is greater than or equal to the 
87
     * <code>x/y</code> fraction.
88
     * It's possible to consider this function as a analog of Math.ceil(x/y), 
89
     * without having deal with non-integer.
90
     * 
91
     * @param x integer, fraction numerator
92
     * @param y  integer, fraction denominator
93
     * @return the smallest integer that is greater than or equal to 
94
     *         <code>x/y</code> fraction
95
     * @see java.lang.Math#ceil(double)
96
     */
97
    public static int ceilPosition(int x, int y) {
98
        return ceil(x, y) / y;
99
    }
100
    
101
    
102
    /**
103
     * Returns the largest integer that is less than or equal to the
104
     * argument and is equal to <code>x/y</code> fraction.
105
     * It's possible to consider this function as a analog of Math.floor(x/y), 
106
     * without having deal with non-integer.
107
     * 
108
     * @param x integer, fraction numerator
109
     * @param y integer, fraction denominator
110
     * @return the largest integer that is less than or equal to 
111
     *            the argument and is equal to <code>x/y</code> fraction
112
     * @see java.lang.Math#ceil(double)
113
     */
114
    public static int floorPosition(int x, int y) {
115
        return floor(x, y) / y;
116
    }
117
}
(-)src/java/org/apache/fop/render/txt/TXTHandler.java (+570 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt;
20
21
import java.io.OutputStream;
22
import java.util.Arrays;
23
import java.util.Iterator;
24
import java.util.List;
25
26
import org.apache.fop.apps.FOPException;
27
import org.apache.fop.apps.FOUserAgent;
28
import org.apache.fop.area.AreaTreeHandler;
29
import org.apache.fop.datatypes.CompoundDatatype;
30
import org.apache.fop.datatypes.Length;
31
import org.apache.fop.datatypes.PercentBaseContext;
32
import org.apache.fop.fo.Constants;
33
import org.apache.fop.fo.FONode;
34
import org.apache.fop.fo.FOText;
35
import org.apache.fop.fo.expr.NumericProperty;
36
import org.apache.fop.fo.expr.RelativeNumericProperty;
37
import org.apache.fop.fo.flow.Block;
38
import org.apache.fop.fo.flow.BlockContainer;
39
import org.apache.fop.fo.flow.ExternalGraphic;
40
import org.apache.fop.fo.flow.Inline;
41
import org.apache.fop.fo.flow.ListBlock;
42
import org.apache.fop.fo.flow.ListItem;
43
import org.apache.fop.fo.flow.PageNumber;
44
import org.apache.fop.fo.flow.Table;
45
import org.apache.fop.fo.flow.TableCell;
46
import org.apache.fop.fo.flow.TableColumn;
47
import org.apache.fop.fo.pagination.PageSequence;
48
import org.apache.fop.fo.properties.CommonAbsolutePosition;
49
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
50
import org.apache.fop.fo.properties.CommonFont;
51
import org.apache.fop.fo.properties.CommonMarginBlock;
52
import org.apache.fop.fo.properties.FixedLength;
53
import org.apache.fop.fo.properties.Property;
54
import org.apache.fop.fo.properties.SpaceProperty;
55
import org.apache.fop.layoutmgr.BlockLayoutManager;
56
57
/**
58
 * Handler for formatting objects in case of rendering to txt.
59
 * 
60
 * This handler gets page-sequence, modifies formatting objects and return them
61
 * to superclass. So areas are generated from modified FO. Idea of modifying is
62
 * to quantize FO properties, making them divisible by width of char or height 
63
 * of char.
64
 */
65
public class TXTHandler extends AreaTreeHandler {
66
67
    /** Percent base context. Needed for line-height. */
68
    private static final PercentBaseContext CONTEXT 
69
        = new BlockLayoutManager(new Block(null));
70
71
    /** Modified font size in millipoints. */
72
    private static final int MODIFIED_FONT_SIZE = 10000;
73
74
    /** Quantum for each side (BEFORE, AFTER, START, END). */
75
    private final int[] quantum = {TXTRenderer.CHAR_HEIGHT,
76
            TXTRenderer.CHAR_HEIGHT, TXTRenderer.CHAR_WIDTH,
77
            TXTRenderer.CHAR_WIDTH};
78
79
    /** Keeps overpatching for each side. */
80
    private int[] overPatching = new int[4];
81
82
    /**
83
     * Keeps last overpatching for each side. Needed for selective modifying of
84
     * start-indent and end-indent.
85
     */
86
    private int[] lastOverPatching = new int[4];
87
88
    /**
89
     * Constructs a newly allocated <code>TXTHandler</code> object.
90
     * 
91
     * @param userAgent FOUserAgent
92
     * @param stream OutputStream
93
     * @throws FOPException if the RenderPagesModel cannot be created
94
     */
95
    public TXTHandler(FOUserAgent userAgent, OutputStream stream)
96
            throws FOPException {
97
        super(userAgent, Constants.RENDER_TXT, stream);
98
    }
99
100
    /**
101
     * Sets a component <code>CP_LENGTH</code> of <code>cd</code> to
102
     * <code>value</code>.
103
104
     * @param cd  CompoundDatatype
105
     * @param value  new integer value
106
     */
107
    private static void setLength(CompoundDatatype cd, int value) {
108
        cd.setComponent(Constants.CP_LENGTH, new FixedLength(value), true);
109
    }
110
111
    /**
112
     * Sets components <code>CP_MINIMUM, CP_OPTIMUM, CP_MAXIMUM</code> of
113
     * <code>cd</code> to <code>p</code>.
114
     * 
115
     * @param cd instance of CompoundDatatype for modifying.
116
     * @param p  property for setting.
117
     */
118
    private static void setMinOptMax(CompoundDatatype cd, Property p) {
119
        cd.setComponent(Constants.CP_MINIMUM, p, true);
120
        cd.setComponent(Constants.CP_OPTIMUM, p, true);
121
        cd.setComponent(Constants.CP_MAXIMUM, p, true);
122
    }
123
124
    /**
125
     * Modifies border of side. If there is no border of given side, does
126
     * nothing, otherwise sets border-width to half of char width or char height
127
     * depending on side. <p> 
128
     * Difference between values of new border-width and old border-width is 
129
     * saved in <code>lastOverPatching</code>.
130
     * 
131
     * @param side side to modify.
132
     * @param bpb instance of CommonBorderPaddingBackground for modifying.
133
     */
134
    private void modifyBorder(int side, CommonBorderPaddingBackground bpb) {
135
        CommonBorderPaddingBackground.BorderInfo bi = bpb.getBorderInfo(side);
136
137
        if (bi != null) {
138
            int width = bpb.getBorderWidth(side, false);
139
            setLength(bi.getWidth(), quantum[side] / 2);
140
            lastOverPatching[side] += bpb.getBorderWidth(side, false) - width;
141
        }
142
    }
143
144
    /**
145
     * Modifies padding of side. First rounds padding to nearest integer,
146
     * divisible by char width or char height depending on side. If border of
147
     * given side is available, modifies padding in such a way, so sum of border
148
     * width and padding will be divisible by char width or char height,
149
     * depending on side. <p>
150
     * Difference between values of new padding and old padding is saved 
151
     * in <code>lastOverPatching</code>.
152
     * 
153
     * @param side side to modify.
154
     * @param bpb instance of CommonBorderPaddingBackground for modifying.
155
     */
156
    private void modifyPadding(int side, CommonBorderPaddingBackground bpb) {
157
        int oldPadding = bpb.getPadding(side, false, null);
158
        int newPadding = Helper.round(oldPadding, quantum[side]);
159
        if (bpb.getBorderInfo(side) != null) {
160
            newPadding = Math.max(newPadding, quantum[side])
161
                    - bpb.getBorderWidth(side, false);
162
        }
163
164
        setLength(bpb.getPaddingLengthProperty(side), newPadding);
165
        lastOverPatching[side] += newPadding - oldPadding;
166
    }
167
168
    /**
169
     * Modifies borders and paddings of <code>bpb</code>.
170
     * 
171
     * @param bpb instance of CommonBorderPaddingBackground for modifying.
172
     */
173
    private void modifyBPB(CommonBorderPaddingBackground bpb) {
174
        modifyBorder(CommonBorderPaddingBackground.BEFORE, bpb);
175
        modifyBorder(CommonBorderPaddingBackground.AFTER, bpb);
176
        modifyBorder(CommonBorderPaddingBackground.START, bpb);
177
        modifyBorder(CommonBorderPaddingBackground.END, bpb);
178
179
        modifyPadding(CommonBorderPaddingBackground.BEFORE, bpb);
180
        modifyPadding(CommonBorderPaddingBackground.AFTER, bpb);
181
        modifyPadding(CommonBorderPaddingBackground.START, bpb);
182
        modifyPadding(CommonBorderPaddingBackground.END, bpb);
183
    }
184
185
    /**
186
     * Rounds optimum value of <code>space</code> to nearest integer,
187
     * divisible by <code>q</code>.
188
     * 
189
     * @param space instance of SpaceProperty.
190
     * @param q integer.
191
     */
192
    private void modifySpace(SpaceProperty space, int q) {
193
        int value = space.getOptimum(null).getLength().getValue();
194
        setMinOptMax(space, new FixedLength(Helper.round(value, q)));
195
    }
196
197
    /**
198
     * @param length instance of Length.
199
     * @param q integer.
200
     * @return instance of Length, having value nearest to value of
201
     *         <code>length</code>, and divisible by <code>q</code>.
202
     */
203
    private Length roundLength(Length length, int q) {
204
        int x = Helper.round(length.getValue(), q);
205
        return new FixedLength(x);
206
    }
207
208
    /**
209
     * @param length instance of Length.
210
     * @param q integer.
211
     * @return instance of Length, having minimal value, greater value of
212
     *         <code>length</code>, and divisible by <code>q</code>.
213
     */
214
    private Length ceilLength(Length length, int q) {
215
        int x = Helper.ceil(length.getValue(), q);
216
        return new FixedLength(x);
217
    }
218
219
    /**
220
     * Modifies indent for given side. Summarizes value of indent and modifing
221
     * error (i.e. overPatching). Rounds result to nearest integer, divisible by
222
     * quantum.
223
     * 
224
     * @param indent Length to modify.
225
     * @param side an integer, representing side.
226
     * @return modified Length.
227
     */
228
    private Length modifyIndent(Length indent, int side) {
229
        if (indent instanceof NumericProperty) {
230
            overPatching[side] += lastOverPatching[side];
231
        }
232
        int newValue = indent.getValue() + overPatching[side];
233
        newValue = Helper.round(newValue, quantum[side]);
234
        return new FixedLength(newValue);
235
    }
236
237
    /**
238
     * Modifies Common Margin Properties-Block:
239
     * <ul>
240
     * <li>margin-top, margin-left, margin-bottom, margin-right
241
     * <li>start-indent, end-indent
242
     * <li>space-before, space-after.
243
     * </ul>
244
     * 
245
     * @param cmb instance of CommonMarginBlock to modify.
246
     */
247
    private void modifyCommonMarginBlock(CommonMarginBlock cmb) {
248
        cmb.marginTop = roundLength(cmb.marginTop, TXTRenderer.CHAR_HEIGHT);
249
        cmb.marginBottom = roundLength(cmb.marginBottom,
250
                TXTRenderer.CHAR_HEIGHT);
251
        cmb.marginLeft = roundLength(cmb.marginLeft, TXTRenderer.CHAR_WIDTH);
252
        cmb.marginRight = roundLength(cmb.marginRight, TXTRenderer.CHAR_WIDTH);
253
254
        modifySpace(cmb.spaceBefore, TXTRenderer.CHAR_HEIGHT);
255
        modifySpace(cmb.spaceAfter, TXTRenderer.CHAR_HEIGHT);
256
257
        if (!(cmb.startIndent instanceof RelativeNumericProperty)) {
258
            cmb.startIndent = modifyIndent(cmb.startIndent,
259
                    CommonBorderPaddingBackground.START);
260
        }
261
        if (!(cmb.endIndent instanceof RelativeNumericProperty)) {
262
            cmb.endIndent = modifyIndent(cmb.endIndent,
263
                    CommonBorderPaddingBackground.END);
264
        }
265
    }
266
267
    /**
268
     * Modifies fo:table attributes:
269
     * <ul>
270
     * <li>Common Margin Properties Block
271
     * <li>Common Border, Padding, and Background Properties
272
     * <li>columns.
273
     * </ul>
274
     * 
275
     * @param table Table to modify.
276
     */
277
    private void modifyTable(Table table) {
278
        CommonMarginBlock cmb = table.getCommonMarginBlock();
279
        if (table.getBorderCollapse() == Constants.EN_COLLAPSE) {
280
            // If border-collapse == "collapse", add space-after in order to
281
            // impove interaction with other FO.
282
            int value = cmb.spaceAfter.getOptimum(null).getLength().getValue();
283
            value += TXTRenderer.CHAR_HEIGHT;
284
            setMinOptMax(cmb.spaceAfter, new FixedLength(value));
285
        }
286
        modifyCommonMarginBlock(cmb);
287
288
        modifyBPB(table.getCommonBorderPaddingBackground());
289
290
        // modify all table-columns
291
        List columnList = table.getColumns();
292
        Iterator iter = columnList.iterator();
293
        while (iter.hasNext()) {
294
            modifyTableColumn((TableColumn) iter.next());
295
        }
296
    }
297
298
    /**
299
     * Modifies fo:table-column attributes:
300
     * <ul>
301
     * <li>width.
302
     * </ul>
303
     * 
304
     * @param column TableColumn to modify.
305
     */
306
    private void modifyTableColumn(TableColumn column) {
307
        column.setColumnWidth(ceilLength(column.getColumnWidth(), 
308
                TXTRenderer.CHAR_WIDTH));
309
    }
310
311
    /**
312
     * Modifies padding of fo:table-cell.
313
     * 
314
     * @param side side.
315
     * @param bpb instance of CommonBorderPaddingBackground to modify.
316
     */
317
    private void modifyCellPadding(int side, CommonBorderPaddingBackground bpb) {
318
        if (bpb.getBorderInfo(side) == null) {
319
            int oldPadding = bpb.getPadding(side, false, null);
320
            int newPadding = oldPadding + quantum[side] / 2;
321
            setLength(bpb.getPaddingLengthProperty(side), newPadding);
322
        }
323
    }
324
325
    /**
326
     * Modifies table-cell properties:
327
     * <ul>
328
     * <li>Common Border, Padding, and Background Properties.
329
     * </ul>
330
     * 
331
     * @param c TableCell to modify.
332
     */
333
    private void modifyTableCell(TableCell c) {
334
        CommonBorderPaddingBackground bpb = c
335
                .getCommonBorderPaddingBackground();
336
        modifyBPB(bpb);
337
        modifyCellPadding(CommonBorderPaddingBackground.BEFORE, bpb);
338
        modifyCellPadding(CommonBorderPaddingBackground.AFTER, bpb);
339
        modifyCellPadding(CommonBorderPaddingBackground.START, bpb);
340
        modifyCellPadding(CommonBorderPaddingBackground.END, bpb);
341
    }
342
343
    /**
344
     * Modifies Common Absolute Position Properties:
345
     * <ul>
346
     * <li>left
347
     * <li>top.
348
     * </ul>
349
     * 
350
     * @param cap CommonAbsolutePosition to modify.
351
     */
352
    private void modifyCommonAbsolutePosition(CommonAbsolutePosition cap) {
353
        if (cap.absolutePosition == Constants.EN_ABSOLUTE) {
354
            cap.left = roundLength(cap.left, TXTRenderer.CHAR_WIDTH);
355
            cap.top = roundLength(cap.top, TXTRenderer.CHAR_HEIGHT);
356
        }
357
    }
358
359
    /**
360
     * Modifies line-height property. Sets a value of line-height to max(char
361
     * height; lowest integer, divisible by char height).
362
     * 
363
     * @param lineHeight SpaceProperty to modify.
364
     */
365
    private void modifyLineHeight(SpaceProperty lineHeight) {
366
        Property p = lineHeight.getOptimum(null);
367
        int value = p.getLength().getValue(CONTEXT);
368
369
        int height = TXTRenderer.CHAR_HEIGHT;
370
        int newValue = Math.max(Helper.floor(value, height), height);
371
        setMinOptMax(lineHeight, new FixedLength(newValue));
372
    }
373
374
    /**
375
     * Modifies Common Font Properties:
376
     * <ul>
377
     * <li>font-family = Courier;
378
     * <li>font-size = MODIFIED_FONT_SIZE;
379
     * <li>font-stretch = EN_NORMAL;
380
     * <li>font-weight = EN_NORMAL.
381
     * </ul>
382
     * 
383
     * @param cf the font to modify.
384
     */
385
    private void modifyCommonFont(CommonFont cf) {
386
        if (cf != null) {
387
            cf.fontFamily = "Courier";
388
            cf.fontSize = new FixedLength(MODIFIED_FONT_SIZE);
389
            cf.fontStretch = Constants.EN_NORMAL;
390
            cf.fontWeight = Constants.EN_NORMAL;
391
        }
392
    }
393
394
    /**
395
     * Modifies fo:block:
396
     * <ul>
397
     * <li>Common Border, Padding, and Background Properties
398
     * <li>Common Margin Properties-Block
399
     * <li>Common Font Properties
400
     * <li>line-height.
401
     * </ul>
402
     * 
403
     * @param block Block to modify.
404
     */
405
    private void modifyBlock(Block block) {
406
        modifyBPB(block.getCommonBorderPaddingBackground());
407
        modifyCommonMarginBlock(block.getCommonMarginBlock());
408
        modifyCommonFont(block.getCommonFont());
409
        modifyLineHeight(block.getLineHeight());
410
    }
411
412
    /**
413
     * Modifies fo:block-container:
414
     * <ul>
415
     * <li>Common Border, Padding, and Background Properties
416
     * <li>Common Margin Properties-Block
417
     * <li>Common Absolute Position Properties.
418
     * </ul>
419
     * 
420
     * @param bc BlockContainer to modify.
421
     */
422
    private void modifyBlockContainer(BlockContainer bc) {
423
        modifyBPB(bc.getCommonBorderPaddingBackground());
424
        modifyCommonMarginBlock(bc.getCommonMarginBlock());
425
        modifyCommonAbsolutePosition(bc.getCommonAbsolutePosition());
426
    }
427
428
    /**
429
     * Modifies fo:inline:
430
     * <ul>
431
     * <li>Common Font Properties
432
     * </ul>
433
     * 
434
     * @param inline Inline to modify.
435
     */
436
    private void modifyInline(Inline inline) {
437
        modifyCommonFont(inline.getCommonFont());
438
    }
439
440
    /**
441
     * Modifies FOText:
442
     * <ul>
443
     * <li>Common Font Properties
444
     * </ul>
445
     * 
446
     * @param text FOText to modify.
447
     */
448
    private void modifyFOText(FOText text) {
449
        modifyCommonFont(text.getCommonFont());
450
    }
451
452
    /**
453
     * Modifies fo:external-graphic:
454
     * <ul>
455
     * <li>Common Border, Padding, and Background Properties
456
     * <li>line-height.
457
     * </ul>
458
     * 
459
     * @param eg ExternalGraphic to modify.
460
     */
461
    private void modifyExternalGraphic(ExternalGraphic eg) {
462
        modifyBPB(eg.getCommonBorderPaddingBackground());
463
        modifyLineHeight(eg.getLineHeight());
464
    }
465
466
    /**
467
     * Modifies fo:list-block:
468
     * <ul>
469
     * <li>Common Border, Padding, and Background Properties
470
     * <li>Common Margin Properties-Block.
471
     * </ul>
472
     * 
473
     * @param lb ListBlock to modify.
474
     */
475
    private void modifyListBlock(ListBlock lb) {
476
        modifyBPB(lb.getCommonBorderPaddingBackground());
477
        modifyCommonMarginBlock(lb.getCommonMarginBlock());
478
    }
479
480
    /**
481
     * Modifies fo:list-item:
482
     * <ul>
483
     * <li>Common Border, Padding, and Background Properties
484
     * <li>Common Margin Properties-Block.
485
     * </ul>
486
     * <p>
487
     * Make refinement for fo:list-item-label and fo:list-item-body.
488
     * 
489
     * @param li ListItem to modify.
490
     */
491
    private void modifyListItem(ListItem li) {
492
        modifyBPB(li.getCommonBorderPaddingBackground());
493
        modifyCommonMarginBlock(li.getCommonMarginBlock());
494
        refinement(li.getLabel());
495
        refinement(li.getBody());
496
    }
497
    
498
    /**
499
     * Does refinement for particular node. Modifies node's properties and
500
     * refines its children recursively.
501
     * 
502
     * @param node the node to refine.
503
     */
504
    private void refinement(FONode node) {
505
        int[] saveOverPatching = (int[]) overPatching.clone();
506
        Arrays.fill(lastOverPatching, 0);
507
508
        if (node instanceof Block) {
509
            modifyBlock((Block) node);
510
        } else if (node instanceof BlockContainer) {
511
            modifyBlockContainer((BlockContainer) node);
512
        } else if (node instanceof Inline) {
513
            modifyInline((Inline) node);
514
        } else if (node instanceof FOText) {
515
            modifyFOText((FOText) node);
516
        } else if (node instanceof Table) {
517
            modifyTable((Table) node);
518
            Arrays.fill(overPatching, 0);
519
        } else if (node instanceof TableCell) {
520
            modifyTableCell((TableCell) node);
521
        } else if (node instanceof ExternalGraphic) {
522
            modifyExternalGraphic((ExternalGraphic) node);
523
        } else if (node instanceof ListBlock) {
524
            modifyListBlock((ListBlock) node);
525
        } else if (node instanceof ListItem) {
526
            modifyListItem((ListItem) node);
527
        } else if (node instanceof PageNumber) {
528
            modifyCommonFont(((PageNumber) node).getCommonFont());
529
        }
530
531
        Iterator it = node.getChildNodes();
532
        if (it != null) {
533
            while (it.hasNext()) {
534
                refinement((FONode) it.next());
535
            }
536
        }
537
        overPatching = saveOverPatching;
538
    }
539
540
    /**
541
     * Run refinement for:
542
     * <ul>
543
     * <li>mainflow (xsl-region-body)
544
     * <li>staticflow (xsl-region-before, xsl-region-after, xsl-region-start,
545
     * xsl-region-end).
546
     * </ul>
547
     * 
548
     * @param pageSequence PageSequence to refine.
549
     */
550
    public void endPageSequence(PageSequence pageSequence) {
551
        Arrays.fill(overPatching, 0);
552
553
        refinement(pageSequence.getMainFlow());
554
555
        if (pageSequence.getStaticContent("xsl-region-before") != null) {
556
            refinement(pageSequence.getStaticContent("xsl-region-before"));
557
        }
558
        if (pageSequence.getStaticContent("xsl-region-after") != null) {
559
            refinement(pageSequence.getStaticContent("xsl-region-after"));
560
        }
561
        if (pageSequence.getStaticContent("xsl-region-start") != null) {
562
            refinement(pageSequence.getStaticContent("xsl-region-start"));
563
        }
564
        if (pageSequence.getStaticContent("xsl-region-end") != null) {
565
            refinement(pageSequence.getStaticContent("xsl-region-end"));
566
        }
567
568
        super.endPageSequence(pageSequence);
569
    }
570
}
(-)src/java/org/apache/fop/render/txt/TXTRenderer.java (-85 / +493 lines)
Lines 18-139 Link Here
18
 
18
 
19
package org.apache.fop.render.txt;
19
package org.apache.fop.render.txt;
20
20
21
// FOP
21
import java.awt.Point;
22
import org.apache.fop.render.PrintRenderer;
22
import java.awt.geom.Rectangle2D;
23
import org.apache.fop.render.pcl.PCLStream;
23
import java.io.IOException;
24
import java.io.OutputStream;
25
import java.util.List;
24
26
27
import org.apache.fop.apps.FOPException;
28
import org.apache.fop.area.Area;
29
import org.apache.fop.area.CTM;
30
import org.apache.fop.area.PageViewport;
31
import org.apache.fop.area.inline.Image;
32
import org.apache.fop.area.inline.TextArea;
33
import org.apache.fop.datatypes.ColorType;
34
import org.apache.fop.render.AbstractPathOrientedRenderer;
35
import org.apache.fop.render.txt.border.AbstractBorderElement;
36
import org.apache.fop.render.txt.border.BorderManager;
37
25
/**
38
/**
26
 * Renderer that renders areas to plain text
39
 * Renderer that renders areas to plain text.
27
 *
40
 * 
28
 * Created by Arthur E Welch III while at M&I EastPoint Technology
41
 * @author Art Welch
29
 * Modified by Mark Lillywhite mark-fop@inomial.com to use the new
42
 * @author <a href="mailto:mark-fop@inomial.com">Mark Lillywhite</a> (to use
30
 * Renderer interface.
43
 *         the new Renderer interface)
31
 */
44
 */
32
public class TXTRenderer extends PrintRenderer {
45
public class TXTRenderer extends AbstractPathOrientedRenderer {
46
    
47
    private static final char LIGHT_SHADE = '\u2591';
48
    
49
    private static final char MEDIUM_SHADE = '\u2592';
50
    
51
    private static final char DARK_SHADE = '\u2593';
33
52
34
    /** The MIME type for PostScript */
53
    private static final char FULL_BLOCK = '\u2588';
35
    public static final String MIME_TYPE = "text/plain";
36
54
37
    /**
55
    private static final char IMAGE_CHAR = '#';
38
     * the current stream to add Text commands to
39
     */
40
    private PCLStream currentStream;
41
56
42
    private int pageHeight = 7920;
57
    /**The stream for output */
58
    private OutputStream outputStream;
43
59
44
    // These variables control the virtual paggination functionality.
60
    /** The current stream to add Text commands to. */
45
    private int curdiv = 0;
61
    private TXTStream currentStream;
46
    private int divisions = -1;
47
    private int paperheight = -1;    // Paper height in decipoints?
48
    private int orientation = -1;    // -1=default/unknown, 0=portrait, 1=landscape.
49
    private int topmargin = -1;      // Top margin in decipoints?
50
    private int leftmargin = -1;     // Left margin in decipoints?
51
    private int fullmargin = 0;
52
    private final boolean debug = false;
53
62
54
    // Variables for rendering text.
63
    /** Buffer for text. */
55
    private StringBuffer charData[];
64
    private StringBuffer[] charData;
56
    private StringBuffer decoData[];
65
57
    private float textCPI = 16.67f;
66
    /** Buffer for background and images. */
58
    private float textLPI = 8;
67
    private StringBuffer[] decoData;
59
    private int maxX = (int)(8.5f * textCPI + 1);
68
60
    private int maxY = (int)(11f * textLPI + 1);
69
    /** Height of one symbol in Courier font size of 10pt. */
61
    private float xFactor;
70
    public static final int CHAR_HEIGHT = 7860;
62
    private float yFactor;
71
63
    /** 
72
    /** Width of one symbol in Courier font size of 10pt. */
64
     * Every line except the last line on a page (which will end with 
73
    public static final int CHAR_WIDTH = 6000;
74
75
    /** Current processing page width. */
76
    private int pageWidth;
77
78
    /** Current processing page height. */
79
    private int pageHeight;
80
81
    /**
82
     * Every line except the last line on a page (which will end with
65
     * pageEnding) will be terminated with this string.
83
     * pageEnding) will be terminated with this string.
66
     */
84
     */
67
    private String lineEnding = "\r\n";
85
    private String lineEnding = "\r\n";
68
    /** 
86
69
     * Every page except the last one will end with this string.
87
    /** Every page except the last one will end with this string. */
70
     */
71
    private String pageEnding = "\f";
88
    private String pageEnding = "\f";
89
90
    /** Equals true, if current page is first. */
91
    private boolean firstPage = false;
92
93
    /** Manager for storing border's information. */
94
    private BorderManager bm;
95
    
96
    /** Char for current filling. */
97
    private char fillChar;
98
99
    /** Saves current coordinate transformation. */
100
    private TXTState currentState = new TXTState();
101
72
    /**
102
    /**
73
     * If true then graphics/decorations will not be rendered - text only.
103
     * Constructs a newly allocated <code>TXTRenderer</code> object.
74
     */
104
     */
75
    private boolean suppressGraphics = false;
105
    public TXTRenderer() {
76
    private boolean firstPage = false;
106
    }
77
107
78
    private void addStr(int row, int col, String str, boolean ischar) {
108
    /**
79
        if (debug) {
109
     * Indicates if point (x, y) lay inside currentPage.
80
            log.debug("TXTRenderer.addStr(" + row + ", " + col
110
     * 
81
                               + ", \"" + str + "\", " + ischar + ")");
111
     * @param x x coordinate
112
     * @param y y coordinate
113
     * @return <b>true</b> if point lay inside page
114
     */
115
    public boolean isLayInside(int x, int y) {
116
        return (x >= 0) && (x < pageWidth) && (y >= 0) && (y < pageHeight);
117
    }
118
119
    /**
120
     * Add char to text buffer.
121
     * 
122
     * @param x  x coordinate
123
     * @param y  y coordinate
124
     * @param ch  char to add
125
     * @param ischar boolean, repersenting is character adding to text buffer
126
     */
127
    protected void addChar(int x, int y, char ch, boolean ischar) {
128
        Point point = currentState.transformPoint(x, y);
129
        putChar(point.x, point.y, ch, ischar);
130
    }
131
132
    /**
133
     * Add char to text or background buffer.
134
     * 
135
     * @param x x coordinate
136
     * @param y x coordinate
137
     * @param ch char to add
138
     * @param ischar indicates if it char or background
139
     */
140
    protected void putChar(int x, int y, char ch, boolean ischar) {
141
        if (isLayInside(x, y)) {
142
            StringBuffer sb = ischar ? charData[y] : decoData[y];
143
            while (sb.length() <= x) {
144
                sb.append(' ');
145
            }
146
            sb.setCharAt(x, ch);
82
        }
147
        }
83
        if (suppressGraphics && !ischar) {
148
    }
84
            return;
149
150
    /**
151
     * Adds string to text buffer (<code>charData</code>). <p>
152
     * Chars of string map in turn.
153
     * 
154
     * @param row x coordinate
155
     * @param col y coordinate
156
     * @param s string to add
157
     */
158
    protected void addString(int row, int col, String s) {
159
        for (int l = 0; l < s.length(); l++) {
160
            addChar(col + l, row, s.charAt(l), true);
85
        }
161
        }
86
        StringBuffer sb;
162
    }
87
        if (row < 0) {
163
88
            row = 0;
164
    /**
89
        }
165
     * Render TextArea to Text.
90
        if (ischar) {
166
     * 
91
            sb = charData[row];
167
     * @param area  inline area to render
168
     */
169
    protected void renderText(TextArea area) {
170
        int col = Helper.ceilPosition(this.currentIPPosition, CHAR_WIDTH);
171
        int row = Helper.ceilPosition(this.currentBPPosition, CHAR_HEIGHT);
172
173
        String s = area.getText();
174
175
        addString(row, col, s);
176
177
        super.renderText(area);
178
    }
179
180
    /**
181
     * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
182
     */
183
    public void renderPage(PageViewport page) throws IOException, FOPException {
184
        if (firstPage) {
185
            firstPage = false;
92
        } else {
186
        } else {
93
            sb = decoData[row];
187
            currentStream.add(pageEnding);
94
        }
188
        }
95
        if (sb == null) {
189
96
            sb = new StringBuffer();
190
        Rectangle2D bounds = page.getViewArea();
191
        double width = bounds.getWidth();
192
        double height = bounds.getHeight();
193
194
        pageWidth = Helper.ceilPosition((int) width, CHAR_WIDTH);
195
        pageHeight = Helper.ceilPosition((int) height, CHAR_HEIGHT);
196
        
197
        // init buffers
198
        charData = new StringBuffer[pageHeight];
199
        decoData = new StringBuffer[pageHeight];
200
        for (int i = 0; i < pageHeight; i++) {
201
            charData[i] = new StringBuffer();
202
            decoData[i] = new StringBuffer();
97
        }
203
        }
98
        if ((col + str.length()) > maxX) {
204
99
            col = maxX - str.length();
205
        bm = new BorderManager(pageWidth, pageHeight, currentState);
206
207
        super.renderPage(page);
208
209
        flushBorderToBuffer();
210
        flushBuffer();
211
    }
212
213
    /**
214
     * Projects current page borders (i.e.<code>bm</code>) to buffer for 
215
     * background and images (i.e.<code>decoData</code>). 
216
     */
217
    private void flushBorderToBuffer() {
218
        for (int x = 0; x < pageWidth; x++) {
219
            for (int y = 0; y < pageHeight; y++) {
220
                Character c = bm.getCharacter(x, y);
221
                if (c != null) {
222
                    putChar(x, y, c.charValue(), false);
223
                }
224
            }
100
        }
225
        }
101
        if (col < 0) {
226
    }
102
            col = 0;
227
103
            if (str.length() > maxX) {
228
    /**
104
                str = str.substring(0, maxX);
229
     * Write out the buffer to output stream.
230
     */
231
    private void flushBuffer() {
232
        for (int row = 0; row < pageHeight; row++) {
233
            StringBuffer cr = charData[row];
234
            StringBuffer dr = decoData[row];
235
            StringBuffer outr = null;
236
237
            if (cr != null && dr == null) {
238
                outr = cr;
239
            } else if (dr != null && cr == null) {
240
                outr = dr;
241
            } else if (cr != null && dr != null) {
242
                int len = dr.length();
243
                if (cr.length() > len) {
244
                    len = cr.length();
245
                }
246
                outr = new StringBuffer();
247
                for (int countr = 0; countr < len; countr++) {
248
                    if (countr < cr.length() && cr.charAt(countr) != ' ') {
249
                        outr.append(cr.charAt(countr));
250
                    } else if (countr < dr.length()) {
251
                        outr.append(dr.charAt(countr));
252
                    } else {
253
                        outr.append(' ');
254
                    }
255
                }
105
            }
256
            }
257
258
            if (outr != null) {
259
                currentStream.add(outr.toString());
260
            }
261
            if (row < pageHeight) {
262
                currentStream.add(lineEnding);
263
            }
106
        }
264
        }
107
        // Pad to col
265
    }
108
        for (int countr = sb.length(); countr < col; countr++) {
266
109
            sb.append(' ');
267
    /**
268
     * @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream)
269
     */
270
    public void startRenderer(OutputStream os) throws IOException {
271
        log.info("Rendering areas to TEXT.");
272
        this.outputStream = os;
273
        currentStream = new TXTStream(os);
274
        firstPage = true;
275
    }
276
277
    /**
278
     * @see org.apache.fop.render.Renderer#stopRenderer()
279
     */
280
    public void stopRenderer() throws IOException {
281
        log.info("writing out TEXT");
282
        outputStream.flush();
283
        super.stopRenderer();
284
    }
285
286
    /**
287
     * Does nothing.
288
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
289
     */
290
    protected void restoreStateStackAfterBreakOut(List breakOutList) {
291
    }
292
293
    /**
294
     * Does nothing.
295
     * @return null
296
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
297
     */
298
    protected List breakOutOfStateStack() {
299
        return null;
300
    }
301
302
    /**
303
     * Does nothing.
304
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
305
     */
306
    protected void saveGraphicsState() {
307
    }
308
309
    /**
310
     * Does nothing.
311
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
312
     */
313
    protected void restoreGraphicsState() {
314
    }
315
316
    /**
317
     * Does nothing.
318
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
319
     */
320
    protected void beginTextObject() {
321
    }
322
323
    /**
324
     * Does nothing.
325
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
326
     */
327
    protected void endTextObject() {
328
    }
329
330
    /**
331
     * Does nothing.
332
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
333
     */
334
    protected void clip() {
335
    }
336
337
    /**
338
     * Does nothing.
339
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
340
     */
341
    protected void clipRect(float x, float y, float width, float height) {
342
    }
343
344
    /**
345
     * Does nothing. 
346
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
347
     */
348
    protected void moveTo(float x, float y) {
349
    }
350
351
    /**
352
     * Does nothing. 
353
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
354
     */
355
    protected void lineTo(float x, float y) {
356
    }
357
358
    /**
359
     * Does nothing.
360
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
361
     */
362
    protected void closePath() {
363
    }
364
365
    /**
366
     * Fills rectangle startX, startY, width, height with char 
367
     * <code>charToFill</code>.
368
     * 
369
     * @param startX x-coordinate of upper left point
370
     * @param startY y-coordinate of upper left point
371
     * @param width width of rectangle
372
     * @param height height of rectangle
373
     * @param charToFill filling char 
374
     */
375
    private void fillRect(int startX, int startY, int width, int height, 
376
            char charToFill) {
377
        for (int x = startX; x < startX + width; x++) {
378
            for (int y = startY; y < startY + height; y++) {
379
                addChar(x, y, charToFill, false);
380
            }
110
        }
381
        }
111
        if (debug) {
382
    }
112
            log.debug("TXTRenderer.addStr() sb.length()="
383
    
113
                               + sb.length());
384
    /**
385
     * Fills a rectangular area with the current filling char.
386
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
387
     */
388
    protected void fillRect(float x, float y, float width, float height) {
389
        fillRect(bm.getStartX(), bm.getStartY(), bm.getWidth(), bm.getHeight(),
390
                fillChar);
391
    }
392
    
393
    /**
394
     * Changes current filling char.
395
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
396
     */
397
    protected void updateColor(ColorType col, boolean fill) {
398
        if (col == null) {
399
            return;
114
        }
400
        }
115
        for (int countr = col; countr < (col + str.length()); countr++) {
401
        // fillShade evaluation was taken from fop-0.20.5 
116
            if (countr >= sb.length()) {
402
        double fillShade = 0.30f * col.getRed() 
117
                sb.append(str.charAt(countr - col));
403
                         + 0.59f * col.getGreen() 
118
            } else {
404
                         + 0.11f * col.getBlue();
119
                if (debug) {
405
        fillShade = 1 - fillShade;
120
                    log.debug("TXTRenderer.addStr() sb.length()="
406
        
121
                                       + sb.length() + " countr=" + countr);
407
        if (fillShade > 0.8f) {
122
                }
408
            fillChar = FULL_BLOCK;
123
                sb.setCharAt(countr, str.charAt(countr - col));
409
        } else if (fillShade > 0.6f) {
124
            }
410
            fillChar = DARK_SHADE;
411
        } else if (fillShade > 0.4f) {
412
            fillChar = MEDIUM_SHADE;
413
        } else if (fillShade > 0.2f) {
414
            fillChar = LIGHT_SHADE;
415
        } else {
416
            fillChar = ' ';
125
        }
417
        }
418
    }
126
419
127
        if (ischar) {
420
    /** 
128
            charData[row] = sb;
421
     * Does nothing. 
422
     * @param url  String
423
     * @param pos  Rectangle2D
424
     */
425
    protected void drawImage(String url, Rectangle2D pos) {
426
    }
427
    
428
    /**
429
     * Fills image rectangle with a <code>IMAGE_CHAR</code>.
430
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
431
     */
432
    public void renderImage(Image image, Rectangle2D pos) {
433
        int x1 = Helper.ceilPosition(currentIPPosition, CHAR_WIDTH);
434
        int y1 = Helper.ceilPosition(currentBPPosition, CHAR_HEIGHT);
435
        int width = Helper.ceilPosition((int) pos.getWidth(), CHAR_WIDTH);
436
        int height = Helper.ceilPosition((int) pos.getHeight(), CHAR_HEIGHT);
437
        
438
        fillRect(x1, y1, width, height, IMAGE_CHAR);
439
    }
440
441
    
442
    /**
443
     * Returns the closest integer to the multiplication of a number and 1000.
444
     * 
445
     * @param x  the value of the argument, multiplied by 
446
     *            1000 and rounded
447
     * @return the value of the argument multiplied by 
448
     *         1000 and rounded to the nearest integer
449
     */
450
    protected int toMilli(float x) {
451
        return Math.round(x * 1000f);
452
    }
453
454
    /**
455
     * Adds one element of border.
456
     * 
457
     * @param x  x coordinate
458
     * @param y  y coordinate
459
     * @param style  integer, representing border style
460
     * @param type  integer, representing border element type 
461
     */
462
    private void addBitOfBorder(int x, int y, int style, int type) {
463
        Point point = currentState.transformPoint(x, y);
464
        if (isLayInside(point.x, point.y)) {
465
            bm.addBorderElement(point.x, point.y, style, type);
466
        }
467
    }
468
469
    /**
470
     * @see org.apache.fop.render.AbstractPathOrientedRenderer
471
     */
472
    protected void drawBorderLine(float x1, float y1, float x2, float y2,
473
            boolean horz, boolean startOrBefore, int style, ColorType col) {
474
475
        int borderHeight = bm.getHeight();
476
        int borderWidth = bm.getWidth();
477
        int borderStartX = bm.getStartX();
478
        int borderStartY = bm.getStartY();
479
480
        int x, y;
481
        if (horz && startOrBefore) { // BEFORE
482
            x = borderStartX;
483
            y = borderStartY;
484
        } else if (horz && !startOrBefore) { // AFTER
485
            x = borderStartX;
486
            y = borderStartY + borderHeight - 1;
487
        } else if (!horz && startOrBefore) { // START
488
            x = borderStartX;
489
            y = borderStartY;
490
        } else { // END
491
            x = borderStartX + borderWidth - 1;
492
            y = borderStartY;
493
        }
494
495
        int dx, dy, length, startType, endType;
496
        if (horz) {
497
            length = borderWidth;
498
            dx = 1;
499
            dy = 0;
500
            startType = 1 << AbstractBorderElement.RIGHT;
501
            endType = 1 << AbstractBorderElement.LEFT;
129
        } else {
502
        } else {
130
            decoData[row] = sb;
503
            length = borderHeight;
504
            dx = 0;
505
            dy = 1;
506
            startType = 1 << AbstractBorderElement.DOWN;
507
            endType = 1 << AbstractBorderElement.UP;
131
        }
508
        }
509
510
        addBitOfBorder(x, y, style, startType);
511
        for (int i = 0; i < length - 2; i++) {
512
            x += dx;
513
            y += dy;
514
            addBitOfBorder(x, y, style, startType + endType);
515
        }
516
        x += dx;
517
        y += dy;
518
        addBitOfBorder(x, y, style, endType);
132
    }
519
    }
133
520
134
    /** @see org.apache.fop.render.AbstractRenderer */
521
    /**
135
    public String getMimeType() {
522
     * @see org.apache.fop.render.AbstractPathOrientedRenderer 
136
        return MIME_TYPE;
523
     */
524
    protected void drawBackAndBorders(Area area, float startx, float starty,
525
            float width, float height) {
526
        bm.setWidth(Helper.ceilPosition(toMilli(width), CHAR_WIDTH));
527
        bm.setHeight(Helper.ceilPosition(toMilli(height), CHAR_HEIGHT));
528
        bm.setStartX(Helper.ceilPosition(toMilli(startx), CHAR_WIDTH));
529
        bm.setStartY(Helper.ceilPosition(toMilli(starty), CHAR_HEIGHT));
530
531
        super.drawBackAndBorders(area, startx, starty, width, height);
137
    }
532
    }
138
533
534
    /**
535
     * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
536
     */
537
    protected void startVParea(CTM ctm) {
538
        currentState.push(ctm);
539
    }
540
541
    /**
542
     * @see org.apache.fop.render.AbstractRenderer#endVParea()
543
     */
544
    protected void endVParea() {
545
        currentState.pop();
546
    }
139
}
547
}
(-)src/java/org/apache/fop/render/txt/TXTState.java (+137 lines)
Line 0 Link Here
1
/*
2
 * Copyright 2005 The Apache Software Foundation.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* $Id$ */
18
19
package org.apache.fop.render.txt;
20
21
import java.awt.Point;
22
import java.awt.geom.Rectangle2D;
23
import java.util.Iterator;
24
import java.util.LinkedList;
25
26
import org.apache.fop.area.CTM;
27
28
/**
29
 * This keeps information about the current state when writing to txt, i.e. 
30
 * manages coordinate transformation matrices for getting absolute coordinates.
31
 */
32
public class TXTState {
33
34
    /** Keeps all coordinate transformation matrices during rendering. */
35
    private LinkedList stackCTM = new LinkedList();
36
37
    /**
38
     * Current result coordinate transformation matrix. It's product of 
39
     * all matrices in order, saved in <code>stackCTM</code>.
40
     */
41
    private CTM resultCTM = new CTM();
42
43
    /**
44
     * Constructs a newly allocated <code>TXTState</code> object.
45
     */
46
    public TXTState() {
47
    }
48
49
    /**
50
     * Updates result coordinate transformation matrix 
51
     * (i.e. <code>resultCTM</code>), multipliing it by given matrix.
52
     * 
53
     * @param ctm CTM
54
     */
55
    private void updateResultCTM(CTM ctm) {
56
        resultCTM = resultCTM.multiply(ctm);
57
    }
58
59
    /**
60
     * Recalculate current result coordinate transformation matrix.
61
     */
62
    private void calcResultCTM() {
63
        resultCTM = new CTM();
64
        for (Iterator i = stackCTM.iterator(); i.hasNext();) {
65
            updateResultCTM((CTM) i.next());
66
        }
67
    }
68
69
    /**
70
     * Push the current coordinate transformation matrix onto the stack and 
71
     * reevaluate <code>resultCTM</code>.
72
     * 
73
     * @param ctm  instance of CTM
74
     */
75
    public void push(CTM ctm) {
76
        stackCTM.addLast(ctm);
77
        updateResultCTM(ctm);
78
    }
79
80
    /**
81
     * Pop the coordinate transformation matrix from the stack and reevaluate
82
     * <code>resultCTM</code>.
83
     */
84
    public void pop() {
85
        stackCTM.removeLast();
86
        calcResultCTM();
87
    }
88
    
89
    /**
90
     * Modifies coordinate transformation matrix in such a way, so 
91
     * x-shift and y-shift will be transformed in text positions.
92
     * 
93
     * @param ctm CTM to modify
94
     * @return instance of CTM
95
     */
96
    public CTM refineCTM(CTM ctm) {
97
        double[] da = ctm.toArray();
98
        // refine x-shift
99
        da[4] = Helper.roundPosition((int) da[4], TXTRenderer.CHAR_WIDTH);
100
        // refine y-shift
101
        da[5] = Helper.roundPosition((int) da[5], TXTRenderer.CHAR_HEIGHT);
102
        
103
        return new CTM(da[0], da[1], da[2], da[3], da[4], da[5]);
104
    }
105
106
    /**
107
     * Transforms <code>point</code> using <code>ctm</code>.
108
     * 
109
     * @param p Point
110
     * @param ctm CTM
111
     * @return transformed Point
112
     */
113
    public Point transformPoint(Point p, CTM ctm) {
114
        Rectangle2D r = new Rectangle2D.Double(p.x, p.y, 0, 0);
115
        CTM nctm = refineCTM(ctm);
116
        r = nctm.transform(r);
117
        return new Point((int) r.getX(), (int) r.getY());
118
    }
119
120
    /**
121
     * Transforms point (x, y) using <code>resultCTM</code>.
122
     * 
123
     * @param x x-coordinate
124
     * @param y y-coordinate
125
     * @return transformed Point
126
     */
127
    public Point transformPoint(int x, int y) {
128
        return transformPoint(new Point(x, y), resultCTM);
129
    }
130
131
    /**
132
     * @return current result coordinate transformation matrix
133
     */
134
    public CTM getResultCTM() {
135
        return resultCTM;
136
    }
137
}
(-)src/java/org/apache/fop/render/txt/TXTStream.java (-1 / +1 lines)
Lines 47-53 Link Here
47
        }
47
        }
48
48
49
        try {
49
        try {
50
            byte buff[] = str.getBytes("UTF-8");
50
            byte[] buff = str.getBytes("UTF-8");
51
            out.write(buff);
51
            out.write(buff);
52
        } catch (IOException e) {
52
        } catch (IOException e) {
53
            throw new RuntimeException(e.toString());
53
            throw new RuntimeException(e.toString());

Return to bug 37253