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 descibing 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