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