xref: /trunk/main/xmerge/java/pexcel/src/main/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java (revision e44970e361d561c4fb365c9f2d78a4d8a70d0e0d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
25 
26 import java.io.OutputStream;
27 import java.io.InputStream;
28 import java.io.IOException;
29 import java.awt.Color;
30 
31 import org.openoffice.xmerge.util.Debug;
32 import org.openoffice.xmerge.util.EndianConverter;
33 import org.openoffice.xmerge.util.ColourConverter;
34 import org.openoffice.xmerge.converter.xml.sxc.Format;
35 import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
36 
37 /**
38  * Represents a BIFF Record describing extended formatting information
39  *
40  */
41 public class ExtendedFormat implements BIFFRecord,
42 org.openoffice.xmerge.converter.xml.OfficeConstants {
43 
44     private byte[] ixfnt        = new byte[2];  // Index to Font Record
45     private byte[] ixnf         = new byte[2];
46     private byte[] fattributes  = new byte[4];
47     private byte[] fBaseAttr    = new byte[2];  // base attribute flags
48     private byte[] fTextAttr    = new byte[2];  // text attribute flags
49     private byte[] icvFore      = new byte[2];  // Background colour of the cell
50     private byte[] icvFill      = new byte[2];
51     private byte bRight;                        // Right border Style
52     private byte bTop;                          // Top border style
53     private byte bLeft;                         // Left border style
54     private byte bBottom;                       // Bottom border style
55     private byte backstyle;
56     private byte borderstyle;
57 
58     public static final int TOP_BORDER      = 0x01;
59     public static final int LEFT_BORDER     = 0x02;
60     public static final int BOTTOM_BORDER   = 0x04;
61     public static final int RIGHT_BORDER    = 0x08;
62 
63     // Horizontal Alignment Styles
64     public static final int NORMAL_ALIGN    = 0x00;
65     public static final int LEFT_ALIGN      = 0x01;
66     public static final int CENTER_ALIGN    = 0x02;
67     public static final int RIGHT_ALIGN     = 0x03;
68 
69     // Vertical Alignment Styles
70     public static final int TOP_ALIGN       = 0x10;
71     public static final int MIDDLE_ALIGN    = 0x20;
72     public static final int BOTTOM_ALIGN    = 0x30;
73 
74     public static final int WORD_WRAP       = 0x08;
75 
76     /**
77      * Constructs an <code>ExtendedFormat</code> from the
78      * <code>InputStream</code>
79      *
80      * @param   is <code>InputStream</code> to read from
81      */
ExtendedFormat(InputStream is)82     public ExtendedFormat(InputStream is) throws IOException {
83         read(is);
84     }
85 
86     /**
87      * Constructs a pocket Excel Document using defualt values and sets the
88      * font index using the specified attribute
89      *
90      * @param   ixfnt   index of the font this format should use
91      */
ExtendedFormat(int ixfnt, Format fmt)92     public ExtendedFormat(int ixfnt, Format fmt) {
93 
94         this.ixfnt          = EndianConverter.writeShort((short)ixfnt);
95         String category = fmt.getCategory();
96         if(category.equalsIgnoreCase(CELLTYPE_CURRENCY)) {
97             this.ixnf           = EndianConverter.writeShort((short) 0);
98         } else if(category.equalsIgnoreCase(CELLTYPE_DATE)) {
99             this.ixnf           = EndianConverter.writeShort((short) 0x12);
100         } else if(category.equalsIgnoreCase(CELLTYPE_TIME)) {
101             this.ixnf           = EndianConverter.writeShort((short) 0x1E);
102         } else {
103             this.ixnf           = EndianConverter.writeShort((short) 0);
104         }
105         this.fattributes    = new byte[] {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
106         this.fBaseAttr      = new byte[] {(byte)0x02,(byte)0x00};
107 
108         this.fTextAttr      = new byte[] {(byte)0x00, (byte)0x00};
109 
110         int align = fmt.getAlign();
111 
112         // Horizontal alignment
113         if(align==Format.CENTER_ALIGN) {
114             fTextAttr[0] |= CENTER_ALIGN;
115         } else if(align==Format.LEFT_ALIGN) {
116             fTextAttr[0] |= LEFT_ALIGN;
117         } else if(align==Format.RIGHT_ALIGN) {
118             fTextAttr[0] |= RIGHT_ALIGN;
119         } else {
120             fTextAttr[0] |= NORMAL_ALIGN;
121         }
122 
123         int vertAlign = fmt.getVertAlign();
124 
125         // Vertical alignment
126         if(vertAlign==Format.TOP_ALIGN) {
127             fTextAttr[0] |= TOP_ALIGN;
128         } else if(vertAlign==Format.BOTTOM_ALIGN) {
129             fTextAttr[0] |= BOTTOM_ALIGN;
130         } else if(vertAlign==Format.MIDDLE_ALIGN) {
131             fTextAttr[0] |= MIDDLE_ALIGN;
132         } else {
133             fTextAttr[0] |= BOTTOM_ALIGN;
134         }
135 
136         if(fmt.getAttribute(Format.WORD_WRAP)) {
137             fTextAttr[0] |= WORD_WRAP;
138         }
139 
140         if(fmt.getAttribute(Format.LEFT_BORDER)) {
141             fTextAttr[1] |= LEFT_BORDER;
142         }
143         if(fmt.getAttribute(Format.RIGHT_BORDER)) {
144             fTextAttr[1] |= RIGHT_BORDER;
145         }
146         if(fmt.getAttribute(Format.TOP_BORDER)) {
147             fTextAttr[1] |= TOP_BORDER;
148         }
149         if(fmt.getAttribute(Format.BOTTOM_BORDER)) {
150             fTextAttr[1] |= BOTTOM_BORDER;
151         }
152 
153         Color background = fmt.getBackground();
154         if( background != null ) {
155             ColourConverter cc = new ColourConverter(PocketExcelConstants.cLookup);
156             icvFill = EndianConverter.writeShort(cc.convertFromRGB(background));
157         } else {
158             icvFill     = new byte[] {(byte)0xFF,(byte)0x00};
159         }
160 
161         icvFore     = new byte[] {(byte)0xFF,(byte)0x00};
162 
163         bRight      = (byte) 0xFF;
164         bTop        = (byte) 0xFF;
165         bLeft       = (byte) 0xFF;
166         bBottom     = (byte) 0xFF;
167         backstyle   = (byte) 0x00;
168         borderstyle = (byte) 0x00;
169 
170     }
171 
172     /**
173      * Get the font index this format uses
174      *
175      * @return the font index
176      */
getFontIndex()177     public int getFontIndex() {
178         return EndianConverter.readShort(ixfnt);
179     }
180 
181     /**
182      * Get the font index this format uses
183      *
184      * @return the font index
185      */
getFormatIndex()186     public int getFormatIndex() {
187         return EndianConverter.readShort(ixnf);
188     }
189 
190     /**
191      * Get the font index this format uses
192      *
193      * @return the font index
194      */
getTextAttr()195     public int getTextAttr() {
196         return EndianConverter.readShort(fTextAttr);
197     }
198 
199     /**
200      * Get the background color this format uses
201      *
202      * @return the background color
203      */
getBackground()204     public Color getBackground() {
205         short rgb = EndianConverter.readShort(icvFill);
206         Color c = null;
207         if(rgb!=0xFF) {
208             ColourConverter cc = new ColourConverter(PocketExcelConstants.cLookup);
209             c = cc.convertToRGB(rgb);
210         }
211         return c;
212     }
213 
214     /**
215      * Get the Vertical alignment for this Format
216      *
217      * @return the alignment
218      */
getVertAlign()219     public int getVertAlign() {
220 
221         int mask = MIDDLE_ALIGN | BOTTOM_ALIGN | TOP_ALIGN;
222         int masked = fTextAttr[0] & mask;
223 
224         if(masked == MIDDLE_ALIGN)
225             return Format.MIDDLE_ALIGN;
226 
227         if(masked == BOTTOM_ALIGN)
228             return Format.BOTTOM_ALIGN;
229 
230         if(masked == TOP_ALIGN)
231             return Format.TOP_ALIGN;
232 
233         return Format.BOTTOM_ALIGN;
234     }
235 
236     /**
237      * Get the alignment for this Format
238      *
239      * @return the alignment
240      */
getAlign()241     public int getAlign() {
242 
243         int mask = LEFT_ALIGN | CENTER_ALIGN | RIGHT_ALIGN;
244         int masked = fTextAttr[0] & mask;
245 
246         if(masked == MIDDLE_ALIGN)
247             return Format.LEFT_ALIGN;
248 
249         if(masked == CENTER_ALIGN)
250             return Format.CENTER_ALIGN;
251 
252         if(masked == RIGHT_ALIGN)
253             return Format.RIGHT_ALIGN;
254 
255         return Format.LEFT_ALIGN;
256     }
257 
258     /**
259      * Is the word wrap set
260      *
261      * @return true if it is selected
262      */
isWordWrap()263     public boolean isWordWrap() {
264         return (!((fTextAttr[0] & WORD_WRAP) == 0));
265     }
266     /**
267      * Get the border style
268      *
269      * @param side the side to test
270      * @return true if it is selected
271      */
isBorder(int side)272     public boolean isBorder(int side) {
273         return (!((fTextAttr[1] & side) == 0));
274     }
275 
276     /**
277      * Compare two ExtendedFormat to see if the font index is the same
278      *
279      * @param rhs the ExtendedFormat to be used in the comaprison
280      * @return boolean if the two are the same otherwise false
281      */
compareTo(ExtendedFormat rhs)282     public boolean compareTo(ExtendedFormat rhs) {
283 
284         if(EndianConverter.readShort(icvFill) !=
285         EndianConverter.readShort(rhs.icvFill))
286             return false;
287 
288         if(this.getTextAttr() != rhs.getTextAttr())
289             return false;
290 
291         if(this.getVertAlign() != rhs.getVertAlign())
292             return false;
293 
294         if(this.getAlign() != rhs.getAlign())
295             return false;
296 
297         if (this.getFontIndex() != rhs.getFontIndex())
298             return false;
299 
300         if (this.getFormatIndex() != rhs.getFormatIndex())
301             return false;
302 
303         return true;
304     }
305 
306     /**
307      * Get the hex code for this particular <code>BIFFRecord</code>
308      *
309      * @return the hex code for <code>ExtendedFormat</code>
310      */
getBiffType()311     public short getBiffType() {
312         return PocketExcelConstants.EXTENDED_FORMAT;
313     }
314 
315     /**
316      * Reads the extended format from the <code>Inputstream</code>
317      *
318      * @param   input the <code>Inputstream</code>to read
319      * @return  toal number of bytes read
320      */
read(InputStream input)321     public int read(InputStream input) throws IOException {
322 
323         int numOfBytesRead  = input.read(ixfnt);
324         numOfBytesRead  += input.read(ixnf);
325         numOfBytesRead  += input.read(fattributes);
326         numOfBytesRead  += input.read(fBaseAttr);
327         numOfBytesRead  += input.read(fTextAttr);
328         numOfBytesRead  += input.read(icvFore);
329         numOfBytesRead  += input.read(icvFill);
330         bRight      = (byte) input.read();
331         bTop        = (byte) input.read();
332         bLeft       = (byte) input.read();
333         bBottom     = (byte) input.read();
334         backstyle   = (byte) input.read();
335         borderstyle = (byte) input.read();
336         numOfBytesRead += 6;
337 
338         Debug.log(Debug.TRACE,"\tixfnt : "+ EndianConverter.readShort(ixfnt) +
339                             " ixnf : " + EndianConverter.readShort(ixnf) +
340                             " fattributes : " + EndianConverter.readInt(fattributes) +
341                             " fBaseAttr : " + EndianConverter.readShort(fBaseAttr) +
342                             "\n\tfTextAttr : " + EndianConverter.readShort(fTextAttr) +
343                             " icvFore : " + EndianConverter.readShort(icvFore) +
344                             " icvFill : " + EndianConverter.readShort(icvFill) +
345                             " bRight : " + bRight +
346                             "\n\tbTop : " + bTop +
347                             " bLeft : " + bLeft +
348                             " bBottom : " + bBottom +
349                             " backstyle : " + backstyle +
350                             " borderstyle : " + borderstyle);
351         return numOfBytesRead;
352     }
353 
354     /**
355      * Writes the ExtendedFormat to the <code>Outputstream</code>
356      *
357      * @param   output the <code>Outputstream</code>to write to
358      */
write(OutputStream output)359     public void write(OutputStream output) throws IOException {
360 
361         output.write(getBiffType());
362         output.write(ixfnt);
363         output.write(ixnf);
364         output.write(fattributes);
365         output.write(fBaseAttr);
366         output.write(fTextAttr);
367         output.write(icvFore);
368         output.write(icvFill);
369         output.write(bRight);
370         output.write(bTop);
371         output.write(bLeft);
372         output.write(bBottom);
373         output.write(backstyle);
374         output.write(borderstyle);
375 
376         Debug.log(Debug.TRACE,"Writing ExtendedFormat record");
377 
378     }
379 
380 }
381