1 50 51 package org.openlaszlo.iv.flash.commands; 52 53 import java.io.*; 54 import java.awt.geom.*; 55 import java.lang.reflect.*; 56 57 import org.openlaszlo.iv.flash.parser.*; 58 import org.openlaszlo.iv.flash.api.*; 59 import org.openlaszlo.iv.flash.api.action.*; 60 import org.openlaszlo.iv.flash.api.shape.*; 61 import org.openlaszlo.iv.flash.api.text.*; 62 import org.openlaszlo.iv.flash.util.*; 63 64 import org.openlaszlo.iv.flash.cache.*; 65 import org.openlaszlo.iv.flash.context.Context; 66 import org.openlaszlo.iv.flash.context.ContextFactory; 67 68 71 72 public class GenericCommand extends FlashObject { 73 74 public static final int TYPE_MOVIE = 0x01; 75 public static final int TYPE_BUTTON = 0x02; 76 public static final int TYPE_GRAPHICS = 0x04; 77 public static final int TYPE_GLOBAL = 0x08; 78 79 private int type; 80 private int depth; 81 private int flags; 82 private int frameNum; 83 84 private IVVector names = new IVVector(); 85 private IVVector values = new IVVector(); 86 private Instance instance; 87 88 89 private boolean isComponent = false; 90 91 private static final String MACROMEDIACLASS = "com.macromedia.generator.commands."; 92 private static final String MXCOMPONENT_CMDNAME = "JGeneratorCommand"; 93 94 public GenericCommand() {} 95 96 public void doCommand( FlashFile file, Context context, Script parent, int frame ) 97 throws IVException 98 { 99 } 100 101 106 public void setIsComponent(boolean isComponent) { 107 this.isComponent = isComponent; 108 } 109 110 115 public boolean isComponent() { 116 return isComponent; 117 } 118 119 public boolean isGlobal() { 120 return (type&TYPE_GLOBAL) != 0; 121 } 122 123 128 public String getCommandName() { 129 String name = getClass().getName(); 130 int idx = name.lastIndexOf('.'); 131 return name.substring(idx+1); 132 } 133 134 139 public Instance getInstance() { 140 return instance; 141 } 142 143 public void setInstance( Instance instance ) { 144 this.instance = instance; 145 } 146 147 169 public Instance getCommandInstance( FlashFile file, Context context, Script parent, int frameNum ) throws IVException { 170 Instance inst = null; 171 if( isComponent() ) { 172 String instancename = getParameter(context, "instancename"); 173 if( instancename != null ) { 174 instancename = instancename.trim(); 175 if( instancename.length() != 0 ) { 176 Script main = file.getMainScript(); 177 inst = main.findInstance(instancename); 178 } 179 } 180 if( inst == null ) { 181 183 IVVector defs = new IVVector(); 184 IVVector instances = new IVVector(); 185 186 Timeline timeline = parent.getTimeline(); 187 int maxFrameNum = Math.min(timeline.getFrameCount(), frameNum+1); 188 for( int i=0; i<maxFrameNum; i++ ) { 189 Frame frame = timeline.getFrameAt(i); 190 for( int k=0; k<frame.size(); k++ ) { 191 FlashObject fo = frame.getFlashObjectAt(k); 192 if( fo instanceof Instance ) { 193 Instance myInst = (Instance) fo; 194 int layer = myInst.depth; 195 FlashDef def = myInst.def; 196 if( def != null ) { 197 defs.setElementAt(def, layer); 198 } 199 instances.setElementAt(myInst, layer); 200 } else if( fo instanceof RemoveObject ) { 201 RemoveObject ro = (RemoveObject) fo; 202 int layer = ro.depth; 203 defs.setElementAt(null, layer); 204 instances.setElementAt(null, layer); 205 } 206 } 207 } 208 209 Point2D ptCmd = new Point2D.Double(-1024, -1024); 210 instance.matrix.transform(ptCmd, ptCmd); 211 212 int myDepth = instance.depth; for( int i=myDepth; --i>=0; ) { 214 Instance myInst = (Instance) instances.elementAt(i); 215 if( myInst == null ) continue; 216 FlashDef def = (FlashDef) defs.elementAt(i); 217 if( def == null || !(def instanceof Script) ) continue; Rectangle2D bounds = def.getBounds(); 219 if( bounds != null && myInst.matrix != null ) { 220 bounds = GeomHelper.calcBounds(myInst.matrix, bounds); 221 } 222 if( bounds == null ) continue; 223 if( bounds.contains(ptCmd) ) { 224 inst = myInst; 225 break; 226 } 227 } 228 } 229 } else { 230 inst = instance; 231 } 232 233 if( inst == null ) { 234 throw new IVException(Resource.CMDINSTNOTFOUND, new Object [] {getCommandName()}); 235 } else { 236 inst.setCommand(this); 237 } 238 239 return inst; 240 } 241 242 public IVVector getParameterNames() { 243 return names; 244 } 245 246 public void setParameter( String name, String value ) { 247 for( int i=0; i<names.size(); i++ ) { 248 String n = (String ) names.elementAt(i); 249 if( n.equals(name) ) { 250 values.setElementAt(value, i); 251 return; 252 } 253 } 254 addParameter(name, value); 255 } 256 257 public void addParameter( String name, String value ) { 258 names.addElement( name ); 259 values.addElement( value ); 260 } 261 262 public String getParameter( String name ) { 263 for( int i=0; i<names.size(); i++ ) { 264 String n = (String ) names.elementAt(i); 265 if( n.equals(name) ) 266 { 267 String value = (String ) values.elementAt(i); 268 if ( value == null || value.trim().length() == 0 ) 269 return null; 270 else 271 return value; 272 } 273 } 274 return null; 275 } 276 277 public String getParameter( String name, String defaultValue ) { 278 String res = getParameter( name ); 279 if( res != null ) return res; 280 return defaultValue; 281 } 282 283 public boolean getBoolParameter( String name ) { 284 return Util.toBool( getParameter( name ), false ); 285 } 286 287 public boolean getBoolParameter( String name, boolean def ) { 288 return Util.toBool( getParameter( name ), def ); 289 } 290 291 public String getParameter( Context context, String name, String def ) { 292 return context.apply( getParameter( name, def ) ); 293 } 294 295 public String getParameter( Context context, String name ) { 296 return context.apply( getParameter( name ) ); 297 } 298 299 public boolean getBoolParameter( Context context, String name, boolean def ) { 300 String v = context.apply( getParameter( name ) ); 301 return Util.toBool( v, def ); 302 } 303 304 public AlphaColor getColorParameter( Context context, String name, AlphaColor def ) { 305 String v = context.apply( getParameter( name ) ); 306 return Util.toColor( v, def ); 307 } 308 309 public int getIntParameter( Context context, String name, int def ) { 310 String v = context.apply( getParameter( name ) ); 311 return Util.toInt( v, def ); 312 } 313 314 public double getDoubleParameter( Context context, String name, double def ) { 315 String v = context.apply( getParameter( name ) ); 316 return Util.toDouble( v, def ); 317 } 318 319 protected int findColumn( String columnName, String [][] data ) { 320 for( int i=0; i<data[0].length; i++ ) { 321 String name = data[0][i]; 322 if( name.equalsIgnoreCase(columnName) ) return i; 323 } 324 return -1; 325 } 326 327 protected boolean isDefault( String s ) { 328 return Util.isDefault(s); 329 } 330 331 337 protected Shape getMask( Rectangle2D r ) { 338 Shape s = new Shape(); 339 s.setFillStyle0( FillStyle.newSolid( AlphaColor.white ) ); 340 s.setFillStyle1( 0 ); 341 s.setLineStyle( new LineStyle(1, AlphaColor.white) ); 342 s.drawRectangle(r); 343 s.setBounds(r); 344 return s; 345 } 346 347 363 protected void addMask( Script script, int frameNum, Instance inst, int width, int height ) { 364 addMask(script, frameNum, inst, GeomHelper.newRectangle(0, 0, width, height)); 365 } 366 367 protected void addMask( Script script, int frameNum, Instance inst, Rectangle2D maskRect ) { 368 int maskLayer = inst.depth; 370 script.reserveLayers(maskLayer, 1); 371 int instLayer = maskLayer+1; 372 Frame frame = script.getFrameAt(frameNum); 374 Instance maskInst = frame.addInstance( getMask(maskRect), maskLayer, 375 (AffineTransform) (inst.matrix!=null?inst.matrix.clone(): null), null); 376 maskInst.clip = instLayer; 377 378 int cnt = script.getFrameCount(); 380 main: 381 for( int i=frameNum+1; i<cnt; i++ ) { 382 Frame f = script.getFrameAt(i); 383 int fsz = f.size(); 384 for( int j=0; j<fsz; j++ ) { 385 FlashObject o = (FlashObject) f.getFlashObjectAt(j); 386 if( o instanceof Instance ) { 387 Instance inst1 = (Instance) o; 388 if( inst1.depth == instLayer && inst1.isMove && inst1.def != inst.def && inst1.def != null ) { 389 f.addFlashObject(new RemoveObject(maskLayer)); 391 break main; 392 } 393 } else if( o instanceof RemoveObject ) { 394 RemoveObject ro = (RemoveObject) o; 395 if( ro.depth == instLayer ) { 396 f.addFlashObject(new RemoveObject(maskLayer)); 398 break main; 399 } 400 } 401 } 402 } 403 } 404 405 protected Font getFont( FlashFile file, String fontName ) { 406 FlashFile defFile = file.getDefaultSymbolFile(); 407 if( defFile != null ) { 408 return defFile.getFont( fontName ); 409 } 410 return null; 411 } 412 413 424 protected LazyText newSimpleText( String txt, Font font, int height, AlphaColor color ) { 425 LazyText text = new LazyText(true); 426 427 TextStyleChangeRecord tsr = new TextStyleChangeRecord(font, height, color); 428 tsr.setX(0); 429 tsr.setY(font.ascent); 430 text.addTextStyleChangeRecord(tsr); 431 432 TextRecord tr = new TextRecord(txt.length()); 433 int l = txt.length(); 434 int x = 0; 435 for( int i=0; i<l; i++ ) { 436 char ch = txt.charAt(i); 437 int idx = font.getIndex(ch); 438 if( idx == -1 ) idx = 0; 439 int adv = font.getAdvanceValue(idx); 440 if( i < l-1 ) { 441 char ch_next = txt.charAt(i+1); 442 int kern = font.getKerning(ch, ch_next); 443 adv += kern; 444 } 445 tr.add(ch, idx, adv); 446 x += adv; 447 } 448 449 text.setBounds(GeomHelper.newRectangle(0, 0, x, font.ascent+font.descent)); 450 451 return text; 452 } 453 454 protected Text newText( FlashFile file, String msg, Font font, int size, AlphaColor color, Rectangle2D rect ) { 455 Text text = Text.newText(); 456 TextItem item = new TextItem( msg, font, size, color ); 457 text.addTextItem( item ); 458 text.setBounds( rect ); 459 return text; 460 } 461 462 protected Text newText( FlashFile file, String msg, Font font, int size, AlphaColor color, int width, int height ) { 463 return newText( file, msg, font, size, color, GeomHelper.newRectangle(0,0,width,height) ); 464 } 465 466 protected Text newText( FlashFile file, String msg, String fontName, int size, AlphaColor color, Rectangle2D rect ) { 467 Font font = getFont( file, fontName ); 468 if( font == null ) return null; 469 return newText( file, msg, font, size, color, rect ); 470 } 471 472 protected void processFlashDef( Instance inst, FlashFile file, Context context ) throws IVException { 473 if( inst.def != null ) { 474 inst.def.process(file, context); 475 } 476 } 477 478 protected Context makeContext( Context context, String [][] data, int row ) 479 throws IVException 480 { 481 return ContextFactory.createContext( context, data, row ); 482 } 483 484 public void setDepth( int depth ) { 485 this.depth = depth; 486 } 487 488 public void setFlags( int flags ) { 489 this.flags = flags; 490 } 491 492 public void setFrameNum( int frameNum ) { 493 this.frameNum = frameNum; 494 } 495 496 public int getDepth() { 497 return depth; 498 } 499 500 public int getFlags() { 501 return flags; 502 } 503 504 public int getFrameNum() { 505 return frameNum; 506 } 507 508 521 public void setType( int type ) { 522 this.type = type; 523 } 524 525 538 public int getType() { 539 return type; 540 } 541 542 public void printContent( PrintStream out, String indent ) { 543 out.println( indent+"Generator Command: "+getClass().getName() ); 544 out.println( indent+" Parameters: " ); 545 for( int i=0; i<values.size(); i++ ) { 546 String name = (String ) names.elementAt(i); 547 String value = (String ) values.elementAt(i); 548 out.println( indent+" "+name+"='"+value+"'" ); 549 } 550 } 551 552 public void write( FlashOutput fob ) { 553 int tagpos = fob.getPos(); 554 fob.skip(6); 556 fob.writeByte(type); 557 fob.writeByte(0); 558 fob.writeWord(depth); 559 560 if( (type&TYPE_GRAPHICS) != 0 ) { 561 fob.writeWord(flags); 562 fob.writeWord(frameNum); 563 } 564 565 StringBuffer sb = new StringBuffer (100); 566 sb.append(getClass().getName()); 567 568 for( int i=0; i<names.size(); i++ ) { 570 String n = (String ) names.elementAt(i); 571 String v = (String ) values.elementAt(i); 572 sb.append(' '); 573 sb.append(n); 574 sb.append("=\""); 575 if( v != null ) { 576 for( int j=0; j<v.length(); j++ ) { 577 char ch = v.charAt(j); 578 switch(ch) { 579 case '\n': 580 sb.append("/n/r"); 581 break; 582 case '"': 583 sb.append("\\\""); 584 break; 585 default: 586 sb.append(ch); 587 break; 588 } 589 } 590 } 591 sb.append('"'); 592 } 593 594 fob.writeStringZ(sb.toString()); 595 596 fob.writeLongTagAt(getTag(), fob.getPos()-tagpos-6, tagpos); 597 } 598 599 public static GenericCommand parse( Parser p ) { 600 int type = p.getUByte(); 605 606 p.getUByte(); 608 int depth = p.getUWord(); 609 int flags = 0; 610 int frameNum = 0; 611 if( (type&TYPE_GRAPHICS) != 0 ) { flags = p.getUWord(); 616 frameNum = p.getUWord(); 617 } 618 619 String command = p.getString(); 620 int clen = command.length(); 621 int idx = command.indexOf(' '); 622 String className; 623 if( idx == -1 ) { 624 className = command; 625 idx = clen; 626 } else { 627 className = command.substring(0,idx); 628 } 629 630 if( className.startsWith(MACROMEDIACLASS) ) { 631 className = "org.openlaszlo.iv.flash.commands."+ 632 className.substring(MACROMEDIACLASS.length()); 633 } 634 Class cmdClazz = CommandCache.getCommandClass(className); 635 if( cmdClazz == null ) { 636 Log.logRB( Resource.CMDNOTFOUND, new Object [] {className} ); 637 return null; 638 } 639 GenericCommand cmd = null; 640 try { 641 cmd = (GenericCommand) cmdClazz.newInstance(); 642 } catch( Exception e ) { 643 Log.logRB(Resource.CMDNOTCREATED, new Object [] {className}, e); 644 return null; 645 } 646 647 cmd.setType(type); 648 cmd.setDepth(depth); 649 cmd.setFlags(flags); 650 cmd.setFrameNum(frameNum); 651 652 657 StringBuffer sb = new StringBuffer (); 658 for( ; idx+1<clen; ) { 659 int startName = idx+1; 660 int endName = command.indexOf('=', startName); 661 String name = command.substring(startName, endName); 662 idx = endName+1; 663 sb.setLength(0); 664 boolean quotes = false; 665 ValueLoop: 666 while( idx < clen ) { 667 char ch = command.charAt(idx); 668 switch( ch ) { 669 case '\\': 670 sb.append( command.charAt(idx+1) ); 671 idx += 2; 672 break; 673 case '/': 674 if( clen-idx >= 4 && command.charAt(idx+2)=='/' && 675 ( (command.charAt(idx+1)=='n' && command.charAt(idx+3)=='r' ) || 676 (command.charAt(idx+1)=='r' && command.charAt(idx+3)=='n' ) 677 ) 678 ) { 679 sb.append('\n'); 680 idx += 4; 681 } else { 682 sb.append(ch); 683 idx++; 684 } 685 break; 686 case '"': 687 quotes = !quotes; 688 idx++; 689 break; 690 case ' ': 691 if( !quotes ) break ValueLoop; 692 default: 693 sb.append(ch); 694 idx++; 695 break; 696 } 697 } 698 String value = new String (sb); 699 cmd.addParameter( name, value ); 700 } 701 702 return cmd; 703 } 704 705 712 public static GenericCommand checkAndParseMX( Instance instance ) { 713 if( instance.actions == null ) return null; 714 715 IVVector acts = instance.actions.getActions(); 716 717 GenericCommand cmd = null; 718 719 for( int i = 0; i < acts.size(); i++ ) { 721 ClipAction action = (ClipAction) acts.elementAt(i); 722 723 if( action.getFlags() == ClipAction.MXCOMPONENT ) { 724 725 Program prog = action.getProgram(); 726 727 FlashBuffer body = prog.body(); 728 body.setPos(0); 729 boolean firstAction = true; 730 String [] strings = null; 731 732 String name = null; 733 String value = null; 734 735 mainLoop: 737 for (;;) { 738 int offset = body.getPos(); 739 int code = body.getUByte(); 740 boolean hasLength = (code&0x80) != 0; 741 int length = hasLength? body.getUWord(): 0; 742 int nextPos = body.getPos()+length; 743 744 switch( code ) { 745 case Actions.None: 746 body.setPos(nextPos); 747 break mainLoop; 748 case Actions.PushData: { 749 for( int l=length; l>0; ) { 750 int type = body.getUByte(); 751 l--; 752 switch( type ) { 753 case 0: 754 String ss = body.getString(); 755 if (name == null) 756 name = ss; 757 else 758 value = ss; 759 l-=ss.length()+1; 760 break; 761 case 1: 762 value = new Float (Float.intBitsToFloat(body.getUDWord())).toString(); 763 l-=4; 764 break; 765 case 2: 766 case 3: 767 break; 768 case 4: 769 l--; 770 break; 771 case 5: 772 value = new Boolean ( body.getUByte()!=0 ).toString(); 773 l--; 774 break; 775 case 6: 776 long dbits = ( ((long)body.getUDWord())<<32 ) | (((long)body.getUDWord())&0xffffffffL); 777 value = new Double (Double.longBitsToDouble(dbits)).toString(); 778 l-=8; 779 break; 780 case 7: 781 value = new Integer (body.getUDWord()).toString(); 782 l-=4; 783 break; 784 case 8: 785 int index = body.getUByte(); 786 if ( strings != null && index < strings.length ) { 787 if (name == null) 788 name = strings[index]; 789 else 790 value = strings[index]; 791 } 792 l--; 793 break; 794 } 795 } 796 if( firstAction && !MXCOMPONENT_CMDNAME.equals(name) ) 799 break mainLoop; 800 break; 801 } 802 case Actions.ConstantPool: { 803 int num = body.getUWord(); 804 strings = new String [num]; 805 for( int j=0; j<num; j++ ) { 806 strings[j] = body.getString(); 807 } 808 if( firstAction && !MXCOMPONENT_CMDNAME.equals(strings[0]) ) 811 break mainLoop; 812 break; 813 } 814 case Actions.SetVariable: 815 if( MXCOMPONENT_CMDNAME.equals(name) ) { 816 String className = "org.openlaszlo.iv.flash.commands." + value + "Command"; 818 819 Class cmdClazz = CommandCache.getCommandClass(className); 820 if( cmdClazz == null ) { 821 Log.logRB( Resource.CMDNOTFOUND, new Object [] {className} ); 822 return null; 823 } 824 825 try { 827 cmd = (GenericCommand) cmdClazz.newInstance(); 828 } catch( Exception e ) { 829 Log.logRB(Resource.CMDNOTCREATED, new Object [] {className}, e); 830 return null; 831 } 832 833 cmd.setDepth(instance.depth); 834 cmd.setType(cmd.isGlobal()?TYPE_GLOBAL:TYPE_MOVIE); 835 cmd.setIsComponent(true); 837 838 Script script = new Script(1); 840 instance.def = script; 841 instance.matrix.translate(1024,1024); 843 844 instance.setCommand(cmd); 846 cmd.setInstance(instance); 847 848 } else { 849 if( cmd != null ) 850 cmd.setParameter(name, value); 851 else 852 break mainLoop; 853 } 854 name = null; 855 break; 856 default: 857 break mainLoop; 859 } 860 firstAction = false; 861 } 862 } 863 864 if( cmd != null ) { 865 acts.removeElementAt(i); 867 instance.actions.setMask( instance.actions.getMask()&~ClipAction.MXCOMPONENT ); 868 break; } 870 } 871 872 if( acts.size() == 0 ) instance.actions = null; 873 874 return cmd; 875 } 876 877 public int getTag() { 878 return Tag.TEMPLATECOMMAND; 879 } 880 881 protected FlashItem copyInto( FlashItem item, ScriptCopier copier ) { 882 super.copyInto( item, copier ); 883 ((GenericCommand)item).type = type; 884 ((GenericCommand)item).depth = depth; 885 ((GenericCommand)item).flags = flags; 886 ((GenericCommand)item).frameNum = frameNum; 887 ((GenericCommand)item).instance = instance; 888 ((GenericCommand)item).isComponent = isComponent; 889 ((GenericCommand)item).names = new IVVector(names); 890 ((GenericCommand)item).values = new IVVector(values); 891 return item; 892 } 893 894 public FlashItem getCopy( ScriptCopier copier ) { 895 try { 896 Constructor c = getClass().getConstructor( new Class [] {} ); 897 GenericCommand o = (GenericCommand) c.newInstance( new Object [] {} ); 898 return copyInto( o, copier ); 899 } catch( Exception e ) { 900 Log.log(e); 901 return null; 902 } 903 904 } 905 906 } 907 | Popular Tags |