1 50 51 package org.openlaszlo.iv.flash.api.text; 52 53 import java.io.*; 54 import java.util.*; 55 import java.awt.geom.*; 56 57 import org.openlaszlo.iv.flash.parser.*; 58 import org.openlaszlo.iv.flash.util.*; 59 import org.openlaszlo.iv.flash.api.*; 60 import org.openlaszlo.iv.flash.context.*; 61 62 70 public final class LazyText extends FlashDef implements TextBlock { 71 72 public static final int HAS_FONT = 0x08; 73 public static final int HAS_COLOR = 0x04; 74 public static final int HAS_YOFFSET = 0x02; 75 public static final int HAS_XOFFSET = 0x01; 76 77 public boolean withAlpha; public Rectangle2D bounds; public AffineTransform matrix; public IVVector records = new IVVector(); private Text text; 83 public LazyText() {} 84 85 public LazyText( boolean withAlpha ) { 86 this.withAlpha = withAlpha; 87 } 88 89 public Rectangle2D getBounds() { 90 if( text != null ) return text.getBounds(); 91 return bounds; 92 } 93 94 public void setBounds( Rectangle2D bounds ) { 95 this.bounds = bounds; 96 } 97 98 103 public IVVector getAllTextRecords1() { 104 if( text != null ) return text.getAllTextRecords(); 105 return records; 106 } 107 108 113 public void setAllTextRecords( IVVector records ) { 114 this.records = records; 115 } 116 117 122 public void addTextRecord( TextRecord record ) { 123 records.addElement(record); 124 } 125 126 131 public void addTextStyleChangeRecord( TextStyleChangeRecord record ) { 132 records.addElement(record); 133 } 134 135 public void setMatrix( AffineTransform matrix ) { 136 this.matrix = matrix; 137 } 138 139 public AffineTransform getMatrix() { 140 if( text != null ) return text.getMatrix(); 141 return matrix; 142 } 143 144 public int getTag() { 145 if( withAlpha ) return Tag.DEFINETEXT2; 146 return Tag.DEFINETEXT; 147 } 148 149 public static LazyText parse( Parser p, boolean withAlpha ) { 150 LazyText text = new LazyText( withAlpha ); 151 text._parse( p ); 152 return text; 153 } 154 155 public void _parse( Parser p ) { 156 setID( p.getUWord() ); 158 bounds = p.getRect(); 160 matrix = p.getMatrix(); 161 162 int nGlyphBits = p.getUByte(); 164 int nAdvanceBits = p.getUByte(); 165 166 boolean is_swt = p.getFile().isTemplate(); 167 boolean is_const = true; 168 170 Font curFont = null; 172 boolean isData = false; 173 for(;;) { 174 int flags = p.getUByte(); 175 if( flags == 0 ) { 176 break; 177 } 178 if( isData || (flags&0x80) == 0 ) { 181 TextRecord tr = new TextRecord( flags ); records.addElement(tr); 183 p.initBits(); 185 for( int i=0; i<flags; i++ ) { 186 int idx = p.getBits(nGlyphBits); 188 int adv = p.getSBits(nAdvanceBits); 189 char ch = (char) curFont.codeTable[idx]; tr.add(ch, idx, adv); 192 } 193 if( !is_swt && is_const ) { 194 for( int i=0; i<flags; i++ ) { 195 if( tr.getChar(i) == '{' && (i+1>=flags || tr.getChar(i+1)!='{') ) { 196 is_const = false; 197 break; 198 } 199 } 200 } 201 } else { 203 TextStyleChangeRecord ts = new TextStyleChangeRecord(); 205 records.addElement(ts); 206 if( (flags&HAS_FONT) != 0 ) { 207 curFont = ((FontDef)p.getDef(p.getUWord())).getFont(); 209 ts.setFont( curFont ); 210 } 211 if( (flags&HAS_COLOR) != 0 ) { 212 ts.setColor( Color.parse(p, withAlpha) ); 214 } 215 if( (flags&HAS_XOFFSET) != 0 ) { 216 ts.setX( p.getWord() ); 217 } 218 if( (flags&HAS_YOFFSET) != 0 ) { 219 ts.setY( p.getWord() ); 220 } 221 if( (flags&HAS_FONT) != 0 ) { 222 ts.setHeight( p.getUWord() ); 223 } 224 } 226 isData = !isData; 227 } 228 setConstant(is_const); 229 } 230 231 public void write( FlashOutput fob ) { 232 if( text != null ) { 233 text.write(fob, this); 234 } else { 235 int start = fob.getPos(); fob.skip( 6 ); fob.writeDefID( this ); 238 fob.write(bounds); 239 fob.write(matrix); 240 241 int maxIdx = Integer.MIN_VALUE; 243 int maxAdv = Integer.MIN_VALUE; 244 Font lastFont = null; 245 for( int i=0; i<records.size(); i++ ) { 246 Object o = records.elementAt(i); 247 if( o instanceof TextStyleChangeRecord ) { 248 Font f = ((TextStyleChangeRecord)o).getFont(); 249 if( f != null ) lastFont = f; 250 } else { 251 TextRecord tr = (TextRecord) o; 252 int idx = tr.getMaxIndex(); 253 int adv = tr.getMaxAdvance(); 254 if( idx > maxIdx ) maxIdx = idx; 255 if( adv > maxAdv ) maxAdv = adv; 256 } 257 258 } 259 int nGlyphBits = Util.getMinBitsU(maxIdx); 260 int nAdvanceBits = Util.getMinBitsS(maxAdv); 261 262 fob.writeByte(nGlyphBits); 263 fob.writeByte(nAdvanceBits); 264 265 fob.setUserData( new int[] {nGlyphBits, nAdvanceBits} ); 266 records.write( fob ); 267 268 fob.writeByte(0); 269 270 int size = fob.getPos()-start-6; fob.writeLongTagAt( getTag(), size, start ); 272 } 273 } 274 275 public void printContent( PrintStream out, String indent ) { 276 out.println( indent+"LazyText: id="+getID() ); 277 out.println( indent+" "+bounds ); 278 out.println( indent+" "+matrix ); 279 records.printContent( out, indent+" " ); 280 } 281 282 289 public void layout() { 290 if( text != null ) text.layout(); 291 } 292 293 300 public IVVector getTextRecords( Font font ) { 301 if( text != null ) return text.getTextRecords(font); 302 IVVector trs = new IVVector(); 303 Font lastFont = null; 304 for( int k=0; k<records.size(); k++ ) { 305 Object o = records.elementAt(k); 306 if( o instanceof TextStyleChangeRecord ) { 307 Font f = ((TextStyleChangeRecord)o).getFont(); 308 if( f != null ) lastFont = f; 309 } else { 310 if( lastFont == font ) trs.addElement(o); 311 } 312 } 313 return trs; 314 } 315 316 325 public void changeFont( Font old_font, Font new_font ) { 326 if( text != null ) { 327 text.changeFont(old_font, new_font); 328 } else { 329 FontDef.changeRecordsFont(records, old_font, new_font); 330 } 331 } 332 333 335 public void collectDeps( DepsCollector dc ) { 336 if( text != null ) { 337 text.collectDeps(dc); 338 } else { 339 for( int i=0; i<records.size(); i++ ) { 340 FlashItem t = (FlashItem) records.elementAt(i); 341 if( t instanceof TextStyleChangeRecord ) { 342 TextStyleChangeRecord ts = (TextStyleChangeRecord) t; 343 if( ts.getFont() != null ) dc.addDep(ts.getFont()); 344 } 345 } 346 } 347 } 348 349 public void collectFonts( FontsCollector fc ) { 350 if( text != null ) { 351 text.collectFonts(fc); 352 } else { 353 for( int i=0; i<records.size(); i++ ) { 354 FlashItem t = (FlashItem) records.elementAt(i); 355 if( t instanceof TextStyleChangeRecord ) { 356 TextStyleChangeRecord ts = (TextStyleChangeRecord) t; 357 if( ts.getFont() != null ) fc.addFont( ts.getFont(), this ); 358 } 359 } 360 } 361 } 362 363 369 public Text createText() { 370 Font font = null; 371 Color color = null; 372 int lastX = -1, lastY = 0; 373 int height = 0; 374 int last_rem = 0; char end_ch = '\0'; 377 int max_ascent = 0; 378 int max_descent = 0; 379 int first_not_updated = 0; 380 381 boolean newItem = false; 382 IVVector items = new IVVector(); 383 TextItem curItem = null; 384 for( int i=0; i<records.size(); ) { 385 Object o = records.elementAt(i++); 386 if( !(o instanceof TextStyleChangeRecord) ) return null; 387 TextStyleChangeRecord tsr = (TextStyleChangeRecord) o; 388 o = records.elementAt(i++); 389 if( !(o instanceof TextRecord) ) return null; 390 TextRecord tr = (TextRecord) o; 391 String str = new String (tr.getText(), 0, tr.getSize()); 392 393 int first_word_size = 0; 396 int k = 0; 397 int max_adv = 0; 398 for(; k<tr.getSize(); k++) if( tr.getChar(k) != ' ' ) break; 399 for(; k<tr.getSize(); k++) { 400 if( tr.getChar(k) == ' ' ) break; 401 int adv = tr.getAdvance(k); 402 if( adv > max_adv ) max_adv = adv; 403 first_word_size += adv; 404 } 405 first_word_size += max_adv-1; 406 408 newItem = false; 409 if( tsr.getFont() != null ) { 411 font = tsr.getFont(); 412 height = tsr.getHeight(); 413 newItem = true; 414 } 415 416 if( tsr.getColor() != null ) { 417 color = tsr.getColor(); 418 if( !(color instanceof AlphaColor) ) { 419 color = new AlphaColor(color.getRGB()); 420 ((AlphaColor)color).setAlpha(255); 421 } 422 newItem = true; 423 } 424 426 if( newItem ) { 427 if( curItem != null ) items.addElement(curItem); 428 curItem = new TextItem("", font, height, color); 429 } 430 431 int newX = tsr.getX(); 433 int newY = tsr.getY(); 434 boolean x_changed = newX == Integer.MAX_VALUE? false: newX != lastX; 435 boolean y_changed = newY == Integer.MAX_VALUE? false: newY != lastY; 436 439 459 460 if( x_changed && y_changed ) { 461 if( end_ch == ' ' && last_rem < first_word_size ) { 465 curItem.text += str; 467 } else { 468 curItem.text += "\n"+str; 470 } 471 } else if( y_changed ) { 475 if( i == 2 ) curItem.text += str; 478 else { 479 curItem.text += "\n"+str; 480 } 481 } else if( x_changed ) { 482 curItem.text += str; 484 } else { 485 curItem.text += str; 487 } 488 489 end_ch = str.length() == 0? '\0': str.charAt(str.length()-1); 490 if( x_changed ) lastX = newX; 492 for( int j=0; j<tr.getSize(); j++ ) { 493 lastX += tr.getAdvance(j); 494 } 495 last_rem = (int) bounds.getMaxX()-lastX; 496 if( y_changed ) lastY = newY; 497 } 498 499 if( curItem != null ) items.addElement(curItem); 500 501 Text text = new Text(withAlpha); 502 text.setBounds(bounds); 503 text.setGenBounds(bounds); 504 text.setMatrix(matrix); 505 text.setTextItems(items); 506 508 return text; 509 } 510 511 public void apply( Context context ) { 512 if( isConstant() ) return; 513 text = createText(); 514 if( text == null ) return; 515 text.apply(context); 516 } 518 519 protected boolean _isConstant() { 520 return true; 521 } 522 523 protected FlashItem copyInto( FlashItem item, ScriptCopier copier ) { 524 super.copyInto( item, copier ); 525 ((LazyText)item).withAlpha = withAlpha; 526 ((LazyText)item).bounds = (Rectangle2D) bounds.clone(); 527 ((LazyText)item).matrix = (AffineTransform) matrix.clone(); 528 ((LazyText)item).records = records.getCopy(copier); 529 ((LazyText)item).text = text==null? null: (Text) text.getCopy(copier); 530 return item; 531 } 532 533 public FlashItem getCopy( ScriptCopier copier ) { 534 return copyInto( new LazyText(), copier ); 535 } 536 } 537 | Popular Tags |