1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /* $Id: SolidAndDoubleBorderElement.java 679326 2008-07-24 09:35:34Z vhennebert $ */
19 
20 package org.apache.fop.render.txt.border;
21 
22 import java.util.Arrays;
23 
24 /**
25  * This class is responsible for solid and double border elements managing.
26  */
27 public class SolidAndDoubleBorderElement extends AbstractBorderElement {
28 
29     private static final char LIGHT_HORIZONTAL = '\u2500';
30 
31     private static final char LIGHT_VERTICAL = '\u2502';
32 
33     private static final char LIGHT_DOWN_AND_RIGHT = '\u250C';
34 
35     private static final char LIGHT_DOWN_AND_LEFT = '\u2510';
36 
37     private static final char LIGHT_UP_AND_RIGHT = '\u2514';
38 
39     private static final char LIGHT_UP_AND_LEFT = '\u2518';
40 
41     private static final char LIGHT_VERTICAL_AND_RIGHT = '\u251C';
42 
43     private static final char LIGHT_VERTICAL_AND_LEFT = '\u2524';
44 
45     private static final char LIGHT_DOWN_AND_HORIZONTAL = '\u252C';
46 
47     private static final char LIGHT_UP_AND_HORIZONTAL = '\u2534';
48 
49     private static final char LIGHT_VERTICAL_AND_HORIZONTAL = '\u253C';
50 
51     private static final char DOUBLE_HORIZONTAL = '\u2550';
52 
53     private static final char DOUBLE_VERTICAL = '\u2551';
54 
55     private static final char DOUBLE_DOWN_AND_RIGHT = '\u2554';
56 
57     private static final char DOUBLE_DOWN_AND_LEFT = '\u2557';
58 
59     private static final char DOUBLE_UP_AND_RIGHT = '\u255A';
60 
61     private static final char DOUBLE_UP_AND_LEFT = '\u255D';
62 
63     private static final char DOUBLE_VERTICAL_AND_RIGHT = '\u2560';
64 
65     private static final char DOUBLE_VERTICAL_AND_LEFT = '\u2563';
66 
67     private static final char DOUBLE_DOWN_AND_HORIZONTAL = '\u2566';
68 
69     private static final char DOUBLE_UP_AND_HORIZONTAL = '\u2569';
70 
71     private static final char DOUBLE_VERTICAL_AND_HORIZONTAL = '\u256C';
72 
73     private static final char DOWN_SINGLE_AND_RIGHT_DOUBLE = '\u2552';
74 
75     private static final char DOWN_DOUBLE_AND_RIGHT_SINGLE = '\u2553';
76 
77     private static final char DOWN_SINGLE_AND_LEFT_DOUBLE = '\u2555';
78 
79     private static final char DOWN_DOUBLE_AND_LEFT_SINGLE = '\u2556';
80 
81     private static final char UP_SINGLE_AND_RIGHT_DOUBLE = '\u2558';
82 
83     private static final char UP_DOUBLE_AND_RIGHT_SINGLE = '\u2559';
84 
85     private static final char UP_SINGLE_AND_LEFT_DOUBLE = '\u255B';
86 
87     private static final char UP_DOUBLE_AND_LEFT_SINGLE = '\u255C';
88 
89     private static final char VERTICAL_SINGLE_AND_RIGHT_DOUBLE = '\u255E';
90 
91     private static final char VERTICAL_DOUBLE_AND_RIGHT_SINGLE = '\u255F';
92 
93     private static final char VERTICAL_SINGLE_AND_LEFT_DOUBLE = '\u2561';
94 
95     private static final char VERTICAL_DOUBLE_AND_LEFT_SINGLE = '\u2562';
96 
97     private static final char DOWN_SINGLE_AND_HORIZONTAL_DOUBLE = '\u2564';
98 
99     private static final char DOWN_DOUBLE_AND_HORIZONTAL_SINGLE = '\u2565';
100 
101     private static final char UP_SINGLE_AND_HORIZONTAL_DOUBLE = '\u2567';
102 
103     private static final char UP_DOUBLE_AND_HORIZONTAL_SINGLE = '\u2568';
104 
105     private static final char VERTICAL_SINGLE_AND_HORIZONTAL_DOUBLE = '\u256A';
106 
107     private static final char VERTICAL_DOUBLE_AND_HORIZONTAL_SINGLE = '\u256B';
108 
109     private static final char UNDEFINED = '?';
110 
111     private static final int UP3 = 1;
112 
113     private static final int DOWN3 = 3;
114 
115     private static final int LEFT3 = 9;
116 
117     private static final int RIGHT3 = 27;
118 
119     private static final char[] MAP = new char[100];
120 
121     static {
Arrays.fill(MAP, UNDEFINED)122         Arrays.fill(MAP, UNDEFINED);
123         MAP[0] = ' ';
124         MAP[UP3] = LIGHT_VERTICAL;
125         MAP[DOWN3] = LIGHT_VERTICAL;
126         MAP[RIGHT3] = LIGHT_HORIZONTAL;
127         MAP[LEFT3] = LIGHT_HORIZONTAL;
128         MAP[UP3 + DOWN3] = LIGHT_VERTICAL;
129         MAP[LEFT3 + RIGHT3] = LIGHT_HORIZONTAL;
130         MAP[UP3 + LEFT3] = LIGHT_UP_AND_LEFT;
131         MAP[LEFT3 + DOWN3] = LIGHT_DOWN_AND_LEFT;
132         MAP[DOWN3 + RIGHT3] = LIGHT_DOWN_AND_RIGHT;
133         MAP[UP3 + RIGHT3] = LIGHT_UP_AND_RIGHT;
134         MAP[UP3 + DOWN3 + RIGHT3] = LIGHT_VERTICAL_AND_RIGHT;
135         MAP[UP3 + LEFT3 + DOWN3] = LIGHT_VERTICAL_AND_LEFT;
136         MAP[LEFT3 + DOWN3 + RIGHT3] = LIGHT_DOWN_AND_HORIZONTAL;
137         MAP[UP3 + LEFT3 + RIGHT3] = LIGHT_UP_AND_HORIZONTAL;
138         MAP[UP3 + LEFT3 + DOWN3 + RIGHT3] = LIGHT_VERTICAL_AND_HORIZONTAL;
139         //DOUBLE
140         MAP[2 * UP3] = DOUBLE_VERTICAL;
141         MAP[2 * DOWN3] = DOUBLE_VERTICAL;
142         MAP[2 * RIGHT3] = DOUBLE_HORIZONTAL;
143         MAP[2 * LEFT3] = DOUBLE_HORIZONTAL;
144         MAP[2 * UP3 + 2 * DOWN3] = DOUBLE_VERTICAL;
145         MAP[2 * LEFT3 + 2 * RIGHT3] = DOUBLE_HORIZONTAL;
146         MAP[2 * UP3 + 2 * LEFT3] = DOUBLE_UP_AND_LEFT;
147         MAP[2 * LEFT3 + 2 * DOWN3] = DOUBLE_DOWN_AND_LEFT;
148         MAP[2 * DOWN3 + 2 * RIGHT3] = DOUBLE_DOWN_AND_RIGHT;
149         MAP[2 * UP3 + 2 * RIGHT3] = DOUBLE_UP_AND_RIGHT;
150         MAP[2 * UP3 + 2 * DOWN3 + 2 * RIGHT3] = DOUBLE_VERTICAL_AND_RIGHT;
151         MAP[2 * UP3 + 2 * DOWN3 + 2 * LEFT3] = DOUBLE_VERTICAL_AND_LEFT;
152         MAP[2 * DOWN3 + 2 * RIGHT3 + 2 * LEFT3] = DOUBLE_DOWN_AND_HORIZONTAL;
153         MAP[2 * UP3 + 2 * RIGHT3 + 2 * LEFT3] = DOUBLE_UP_AND_HORIZONTAL;
154         MAP[2 * UP3 + 2 * DOWN3 + 2 * RIGHT3 + 2 * LEFT3] = DOUBLE_VERTICAL_AND_HORIZONTAL;
155         //DOUBLE&SINGLE
156         MAP[DOWN3 + 2 * RIGHT3] = DOWN_SINGLE_AND_RIGHT_DOUBLE;
157         MAP[2 * DOWN3 + RIGHT3] = DOWN_DOUBLE_AND_RIGHT_SINGLE;
158         MAP[DOWN3 + 2 * LEFT3] = DOWN_SINGLE_AND_LEFT_DOUBLE;
159         MAP[2 * DOWN3 + LEFT3] = DOWN_DOUBLE_AND_LEFT_SINGLE;
160         MAP[UP3 + 2 * RIGHT3] = UP_SINGLE_AND_RIGHT_DOUBLE;
161         MAP[2 * UP3 + RIGHT3] = UP_DOUBLE_AND_RIGHT_SINGLE;
162         MAP[UP3 + 2 * LEFT3] = UP_SINGLE_AND_LEFT_DOUBLE;
163         MAP[2 * UP3 + LEFT3] = UP_DOUBLE_AND_LEFT_SINGLE;
164         MAP[UP3 + DOWN3 + 2 * RIGHT3] = VERTICAL_SINGLE_AND_RIGHT_DOUBLE;
165         MAP[2 * UP3 + 2 * DOWN3 + RIGHT3] = VERTICAL_DOUBLE_AND_RIGHT_SINGLE;
166         MAP[UP3 + DOWN3 + 2 * LEFT3] = VERTICAL_SINGLE_AND_LEFT_DOUBLE;
167         MAP[2 * UP3 + 2 * DOWN3 + LEFT3] = VERTICAL_DOUBLE_AND_LEFT_SINGLE;
168         MAP[DOWN3 + 2 * LEFT3 + 2 * RIGHT3] = DOWN_SINGLE_AND_HORIZONTAL_DOUBLE;
169         MAP[2 * DOWN3 + LEFT3 + RIGHT3] = DOWN_DOUBLE_AND_HORIZONTAL_SINGLE;
170         MAP[UP3 + 2 * LEFT3 + 2 * RIGHT3] = UP_SINGLE_AND_HORIZONTAL_DOUBLE;
171         MAP[2 * UP3 + LEFT3 + RIGHT3] = UP_DOUBLE_AND_HORIZONTAL_SINGLE;
172         MAP[UP3 + DOWN3 + 2 * LEFT3 + 2 * RIGHT3] = VERTICAL_SINGLE_AND_HORIZONTAL_DOUBLE;
173         MAP[2 * UP3 + 2 * DOWN3 + LEFT3 + RIGHT3] = VERTICAL_DOUBLE_AND_HORIZONTAL_SINGLE;
174     }
175 
176     /**
177      * Initializes a newly created <code>SolidAndDoubleBorderElement</code>
178      * object so that it represents an empty border element.
179      */
SolidAndDoubleBorderElement()180     public SolidAndDoubleBorderElement() {
181     }
182 
183     /**
184      * Constructs a newly allocated <code>SolidAndDoubleBorderElement</code>
185      * object. Fills <code>data</code> using binary representation of
186      * <code>type</code>. If border style is EN_DOUBLE, multiplies
187      * <code>data[side]</code> by 2 for every side to distinguish EN_SOLID and
188      * EN_DOUBLE.
189      *
190      * @param style integer, representing border style.
191      * @param type binary representation of type gives <code>data</code>
192      */
SolidAndDoubleBorderElement(int style, int type)193     public SolidAndDoubleBorderElement(int style, int type) {
194         super(type);
195         if (style == EN_DOUBLE) {
196             for (int i = 0; i < 4; i++) {
197                 data[i] *= 2;
198             }
199         }
200     }
201 
202     /**
203      * Merges with <code>sde</code>.
204      * @param sde instance of SolidAndDoubleBorderElement
205      * @return instance of AbstractBorderElement
206      */
mergeSolid(SolidAndDoubleBorderElement sde)207     public AbstractBorderElement mergeSolid(SolidAndDoubleBorderElement sde) {
208         AbstractBorderElement e = new SolidAndDoubleBorderElement(EN_SOLID, 0);
209         for (int i = 0; i < 4; i++) {
210             if (sde.getData(i) != 0) {
211                 e.setData(i, sde.getData(i));
212             } else {
213                 e.setData(i, data[i]);
214             }
215         }
216         return e;
217     }
218 
219     /**
220      * Merges with e.
221      * @param e instance of AbstractBorderElement
222      * @return instance of AbstractBorderElement
223      */
merge(AbstractBorderElement e)224     public AbstractBorderElement merge(AbstractBorderElement e) {
225         AbstractBorderElement abe = this;
226         if (e instanceof SolidAndDoubleBorderElement) {
227             abe = mergeSolid((SolidAndDoubleBorderElement) e);
228         } else if (e instanceof DottedBorderElement) {
229             abe = e;
230         } else if (e instanceof DashedBorderElement) {
231             abe = e.merge(this);
232         }
233         return abe;
234     }
235 
236     /**
237      * Maps to char.
238      * @return resulting mapping char
239      */
map2Char()240     private char map2Char() {
241         int key = 0;
242         key += data[UP] * UP3;
243         key += data[LEFT] * LEFT3;
244         key += data[DOWN] * DOWN3;
245         key += data[RIGHT] * RIGHT3;
246         return MAP[key];
247     }
248 
249     /**
250      * Modifies data to nearest normal internal representation.
251      */
modifyData()252     private void modifyData() {
253         int c1 = 0;
254         int c2 = 0;
255         for (int i = 0; i < 4; i++) {
256             c1 += (data[i] == 1) ? 1 : 0;
257             c2 += (data[i] == 2) ? 1 : 0;
258         }
259         int m = c1 > c2 ? 1 : 0;
260         int[] p = {0, m, 2 * (1 - m)};
261         for (int i = 0; i < 4; i++) {
262             data[i] = p[data[i]];
263         }
264     }
265 
266     /**
267      * {@inheritDoc}
268      */
convert2Char()269     public char convert2Char() {
270         char ch = map2Char();
271         if (ch == UNDEFINED) {
272             modifyData();
273             ch = map2Char();
274         }
275         return ch;
276     }
277 }
278