1 50 51 package org.openlaszlo.iv.flash.api.shape; 52 53 import java.io.PrintStream ; 54 import java.awt.geom.*; 55 import java.util.*; 56 57 import org.openlaszlo.iv.flash.parser.*; 58 import org.openlaszlo.iv.flash.util.*; 59 import org.openlaszlo.iv.flash.api.*; 60 61 102 public final class Shape extends FlashDef { 103 104 private StyleBlock style_block; 105 private Rectangle2D bounds; private int tagcode; 108 111 public Shape() { 112 this( Tag.DEFINESHAPE3 ); 113 newStyleBlock(); 114 } 115 116 121 public ShapeStyles getShapeStyles() { 122 return style_block.shapeStyles; 123 } 124 125 130 public ShapeRecords getShapeRecords() { 131 return style_block.shapeRecords; 132 } 133 134 142 public int addFillStyle( FillStyle fillStyle ) { 143 return getShapeStyles().addFillStyle( fillStyle ); 144 } 145 146 154 public int addLineStyle( LineStyle lineStyle ) { 155 return getShapeStyles().addLineStyle( lineStyle ); 156 } 157 158 169 public int setFillStyle0( FillStyle fillStyle ) { 170 int fs = getShapeStyles().getFillStyleIndex( fillStyle ); 171 if( fs == -1 ) fs = addFillStyle( fillStyle ); 172 setFillStyle0( fs ); 173 return fs; 174 } 175 176 187 public int setFillStyle1( FillStyle fillStyle ) { 188 int fs = getShapeStyles().getFillStyleIndex( fillStyle ); 189 if( fs == -1 ) fs = addFillStyle( fillStyle ); 190 setFillStyle1( fs ); 191 return fs; 192 } 193 194 205 public int setLineStyle( LineStyle lineStyle ) { 206 int ls = getShapeStyles().getLineStyleIndex( lineStyle ); 207 if( ls == -1 ) ls = addLineStyle( lineStyle ); 208 setLineStyle( ls ); 209 return ls; 210 } 211 212 217 public void setFillStyle0( int fillStyle ) { 218 StyleChangeRecord sc = getStyleChange(); 219 sc.addFlags( StyleChangeRecord.FILLSTYLE0 ); 220 sc.setFillStyle0( fillStyle ); 221 } 222 223 228 public void setFillStyle1( int fillStyle ) { 229 StyleChangeRecord sc = getStyleChange(); 230 sc.addFlags( StyleChangeRecord.FILLSTYLE1 ); 231 sc.setFillStyle1( fillStyle ); 232 } 233 234 239 public void setLineStyle( int lineStyle ) { 240 StyleChangeRecord sc = getStyleChange(); 241 sc.addFlags( StyleChangeRecord.LINESTYLE ); 242 sc.setLineStyle( lineStyle ); 243 } 244 245 250 public int getLineStyleIndex() { 251 StyleChangeRecord sc = getStyleChange(); 252 return sc.getLineStyle(); 253 } 254 255 260 public LineStyle getLineStyle() { 261 int idx = getLineStyleIndex(); 262 return getShapeStyles().getLineStyle(idx); 263 } 264 265 270 public int getFillStyle0Index() { 271 StyleChangeRecord sc = getStyleChange(); 272 return sc.getFillStyle0(); 273 } 274 275 280 public FillStyle getFillStyle0() { 281 int idx = getFillStyle0Index(); 282 return getShapeStyles().getFillStyle(idx); 283 } 284 285 290 public int getFillStyle1Index() { 291 StyleChangeRecord sc = getStyleChange(); 292 return sc.getFillStyle1(); 293 } 294 295 300 public FillStyle getFillStyle1() { 301 int idx = getFillStyle1Index(); 302 return getShapeStyles().getFillStyle(idx); 303 } 304 305 313 public void newStyleBlock() { 314 StyleBlock sb = new StyleBlock(); 315 sb.prev = style_block; 316 317 if( style_block != null ) { 320 IVVector shape_records = style_block.shapeRecords.getShapeRecords(); 321 if( shape_records.size() > 0 ) { 322 Object o = shape_records.elementAt(shape_records.size()-1); 323 if( o instanceof StyleChangeRecord ) { 324 StyleChangeRecord sr = (StyleChangeRecord) o; 325 sr.addFlags(StyleChangeRecord.NEW_STYLES); 326 } else { 327 StyleChangeRecord sr = new StyleChangeRecord(); 328 sr.addFlags(StyleChangeRecord.NEW_STYLES); 329 shape_records.addElement(sr); 330 } 331 } 332 } 333 334 style_block = sb; 335 } 336 337 342 public static Shape newShape1() { 343 Shape shape = new Shape(Tag.DEFINESHAPE); 344 shape.newStyleBlock(); 345 return shape; 346 } 347 348 353 public static Shape newShape2() { 354 Shape shape = new Shape(Tag.DEFINESHAPE2); 355 shape.newStyleBlock(); 356 return shape; 357 } 358 359 364 public static Shape newShape3() { 365 Shape shape = new Shape(Tag.DEFINESHAPE3); 366 shape.newStyleBlock(); 367 return shape; 368 } 369 370 375 public static Shape newShape3( ShapeStyles styles, ShapeRecords records ) { 376 Shape shape = new Shape(Tag.DEFINESHAPE3); 377 shape.style_block = new StyleBlock(styles, records); 378 return shape; 379 } 380 381 386 public static Shape newEmptyShape1() { 387 Shape emptyShape = newShape1(); 388 emptyShape.setLineStyle( new LineStyle(1, new Color(0,0,0) ) ); 389 emptyShape.movePenTo(0,0); 390 emptyShape.setBounds( GeomHelper.newRectangle(0,0,0,0) ); 391 return emptyShape; 392 } 393 394 public int getTag() { 395 return tagcode; 396 } 397 398 public void collectDeps( DepsCollector dc ) { 399 StyleBlock sb = style_block; 400 while( sb != null ) { 401 sb.shapeStyles.collectDeps(dc); 402 sb = sb.prev; 403 } 404 } 405 406 protected StyleChangeRecord getStyleChange() { 407 return getShapeRecords().getStyleChange(); 408 } 409 410 416 public static Shape parse( Parser p ) { 417 418 int tagCode = p.getTagCode(); 419 Shape shape = new Shape( tagCode ); 420 shape.setID( p.getUWord() ); 421 shape.bounds = p.getRect(); 422 423 boolean withAlpha = shape.isWithAlpha(); 424 425 ShapeStyles shape_styles = ShapeStyles.parse(p, withAlpha); 427 428 IVVector shape_records = new IVVector(); 429 430 int nBits = p.getUByte(); 432 int nFillBits = (nBits&0xf0)>>4; 433 int nLineBits = nBits&0x0f; 434 p.initBits(); 435 for(;;) { 436 if( p.getBool() ) { if( p.getBool() ) { int nb = p.getBits(4)+2; 439 if( p.getBool() ) { int deltaX = p.getSBits(nb); 441 int deltaY = p.getSBits(nb); 442 shape_records.addElement( StrightEdgeRecord.newLine(deltaX, deltaY) ); 443 } else if( p.getBool() ) { int deltaY = p.getSBits(nb); 445 shape_records.addElement( StrightEdgeRecord.newVLine(deltaY) ); 446 } else { int deltaX = p.getSBits(nb); 448 shape_records.addElement( StrightEdgeRecord.newHLine(deltaX) ); 449 } 450 } else { int nb = p.getBits(4)+2; 452 int cx = p.getSBits(nb); 453 int cy = p.getSBits(nb); 454 int ax = p.getSBits(nb); 455 int ay = p.getSBits(nb); 456 shape_records.addElement( new CurvedEdgeRecord(cx, cy, ax, ay) ); 457 } 458 } else { int flags = p.getBits(5); 460 if( flags == 0 ) break; StyleChangeRecord scr = new StyleChangeRecord(); 462 scr.setFlags( flags ); 463 464 if( (flags & StyleChangeRecord.MOVETO) != 0 ) { 465 int nMoveBits = p.getBits(5); 466 scr.setDeltaX( p.getSBits(nMoveBits) ); 467 scr.setDeltaY( p.getSBits(nMoveBits) ); 468 } 469 470 if( (flags & StyleChangeRecord.FILLSTYLE0) != 0 ) { 471 scr.setFillStyle0( p.getBits(nFillBits) ); 472 } 473 474 if( (flags & StyleChangeRecord.FILLSTYLE1) != 0 ) { 475 scr.setFillStyle1( p.getBits(nFillBits) ); 476 } 477 478 if( (flags & StyleChangeRecord.LINESTYLE) != 0 ) { 479 scr.setLineStyle( p.getBits(nLineBits) ); 480 } 481 482 if( (flags & StyleChangeRecord.NEW_STYLES) != 0 ) { 483 484 shape_records.addElement(scr); 486 487 491 StyleBlock new_style_block = new StyleBlock(shape_styles, shape_records); 492 new_style_block.prev = shape.style_block; 493 shape.style_block = new_style_block; 494 495 shape_styles = ShapeStyles.parse(p, withAlpha); 497 shape_records = new IVVector(); 499 500 nBits = p.getUByte(); 502 nFillBits = (nBits&0xf0)>>4; 503 nLineBits = nBits&0x0f; 504 p.initBits(); 505 506 } else { 507 shape_records.addElement(scr); 508 } 509 510 if( (flags&0x80) != 0 ) { 511 break; 512 } 513 } 514 } 515 516 StyleBlock new_style_block = new StyleBlock(shape_styles, shape_records); 518 new_style_block.prev = shape.style_block; 519 shape.style_block = new_style_block; 520 521 return shape; 522 } 523 524 public boolean isWithAlpha() { 525 return getTag() == Tag.DEFINESHAPE3; 526 } 527 528 535 private static class StyleBlock { 536 537 StyleBlock prev; 538 ShapeStyles shapeStyles; ShapeRecords shapeRecords; 541 StyleBlock() { 542 this.shapeStyles = new ShapeStyles(); 543 this.shapeRecords = new ShapeRecords(); 544 } 545 546 StyleBlock( ShapeStyles styles, IVVector records ) { 547 this(styles, new ShapeRecords(records)); 548 } 549 550 StyleBlock( ShapeStyles styles, ShapeRecords records ) { 551 this.shapeStyles = styles; 552 this.shapeRecords = records; 553 } 554 555 private void write_block( FlashOutput fob ) { 556 if( prev != null ) { 557 prev.write_block(fob); 558 fob.flushBits(); 559 } 560 561 shapeStyles.write(fob); 562 563 int nFillBits = shapeStyles.calcNFillBits(); 564 int nLineBits = shapeStyles.calcNLineBits(); 565 fob.writeByte( (nFillBits<<4) | nLineBits ); 566 shapeRecords.write(fob, nFillBits, nLineBits); 567 } 568 569 public void write( FlashOutput fob ) { 570 write_block(fob); 571 fob.writeBits(0, 6); 572 fob.flushBits(); 573 } 574 575 public void printContent( PrintStream out, String indent ) { 576 if( prev != null ) { 577 prev.printContent(out, indent ); 578 out.println( indent+" new styleblock:" ); 579 } 580 shapeStyles.printContent(out, indent+" " ); 581 shapeRecords.printContent(out, indent+" " ); 582 } 583 584 public StyleBlock getCopy( ScriptCopier copier ) { 585 StyleBlock my_prev = null; 586 if( prev != null ) { 587 my_prev = prev.getCopy(copier); 588 } 589 StyleBlock my_block = new StyleBlock( 590 (ShapeStyles) shapeStyles.getCopy(copier), 591 (ShapeRecords) shapeRecords.getCopy(copier) 592 ); 593 my_block.prev = my_prev; 594 return my_block; 595 } 596 } 597 598 public void write( FlashOutput main ) { 599 FlashOutput fob = new FlashOutput(main,100); 600 601 fob.setUserData(this); 603 fob.write( bounds ); 604 605 style_block.write(fob); 606 607 main.writeTag( getTag(), 2+fob.getSize() ); 608 main.writeDefID( this ); 609 main.writeFOB( fob ); 610 } 611 612 public void printContent( PrintStream out, String indent ) { 613 out.println( indent+"Shape("+Tag.tagNames[getTag()]+"): id="+getID()+", name='"+getName()+"'" ); 614 out.println( indent+" "+bounds ); 615 style_block.printContent(out, indent); 616 } 617 618 public boolean isConstant() { 619 return true; 620 } 621 622 627 public Rectangle2D getBounds() { 628 return bounds; 629 } 630 631 636 public void setBounds( Rectangle2D bounds ) { 637 this.bounds = bounds; 638 } 639 640 644 public void setBounds( int x, int y, int width, int height ) { 645 setBounds( GeomHelper.newRectangle(x,y,width,height) ); 646 } 647 648 protected FlashItem copyInto( FlashItem item, ScriptCopier copier ) { 649 super.copyInto( item, copier ); 650 ((Shape)item).bounds = (Rectangle2D) bounds.clone(); 651 ((Shape)item).style_block = (StyleBlock) style_block.getCopy(copier); 652 ((Shape)item).tagcode = tagcode; 653 return item; 654 } 655 656 public FlashItem getCopy( ScriptCopier copier ) { 657 return copyInto( new Shape(), copier ); 658 } 659 660 private Shape( int tagcode ) { 661 this.tagcode = tagcode; 662 } 663 664 665 666 667 668 677 public void drawCurveTo( int cx, int cy, int ax, int ay ) { 678 getShapeRecords().drawCurveTo(cx, cy, ax, ay); 679 } 680 681 692 public void drawCurve( int ax1, int ay1, int cx, int cy, int ax2, int ay2 ) { 693 getShapeRecords().drawCurve(ax1, ay1, cx, cy, ax2, ay2); 694 } 695 696 704 public void drawCurve( Point2D anchor1, Point2D control, Point2D anchor2 ) { 705 getShapeRecords().drawCurve(anchor1, control, anchor2); 706 } 707 708 715 public void drawLineTo( int x, int y ) { 716 getShapeRecords().drawLineTo(x, y); 717 } 718 719 725 public void drawLineTo( Point2D p1 ) { 726 getShapeRecords().drawLineTo(p1); 727 } 728 729 739 public void drawLine( int x1, int y1, int x2, int y2 ) { 740 getShapeRecords().drawLine(x1, y1, x2, y2); 741 } 742 743 751 public void drawLine( Point2D p0, Point2D p1 ) { 752 getShapeRecords().drawLine(p0, p1); 753 } 754 755 765 public void drawRectangle( int x, int y, int width, int height ) { 766 getShapeRecords().drawRectangle(x, y, width, height); 767 } 768 769 776 public void drawRectangle( Rectangle2D r ) { 777 getShapeRecords().drawRectangle(r); 778 } 779 780 787 public void movePenTo( int x, int y ) { 788 getShapeRecords().movePenTo(x, y); 789 } 790 791 797 public void movePenTo( Point2D p ) { 798 getShapeRecords().movePenTo(p); 799 } 800 801 808 public void drawAWTShape( java.awt.Shape shape ) { 809 getShapeRecords().drawAWTShape(shape); 810 } 811 812 819 public void drawAWTShape( java.awt.Shape shape, AffineTransform matrix ) { 820 getShapeRecords().drawAWTShape(shape, matrix); 821 } 822 823 830 public void drawAWTPathIterator( java.awt.geom.PathIterator pi ) { 831 getShapeRecords().drawAWTPathIterator(pi); 832 } 833 834 839 public Point2D getCurrentPos() { 840 return getShapeRecords().getCurrentPos(); 841 } 842 843 848 public Point2D getFirstPos() { 849 return getShapeRecords().getFirstPos(); 850 } 851 852 853 854 855 856 862 863 private static class Painter { 864 java.awt.Graphics2D g2; 865 GeneralPath gp_line; 866 GeneralPath gp_fill; 867 java.awt.Paint [] lstyle_paints; 868 java.awt.Stroke [] lstyle_strokes; 869 java.awt.Paint [] fstyle_paints; 870 ShapeStyles ss; 871 int line_idx; 872 int fill_idx; 873 874 Painter( java.awt.Graphics2D g2, GeneralPath gp_fill, GeneralPath gp_line, ShapeStyles ss ) { 875 this.g2 = g2; 876 this.ss = ss; 877 this.gp_line = gp_line; 878 this.gp_fill = gp_fill; 879 880 line_idx = -1; 881 fill_idx = -1; 882 lstyle_paints = new java.awt.Paint [ss.lineStyles.size()]; 883 lstyle_strokes = new java.awt.Stroke [ss.lineStyles.size()]; 884 fstyle_paints = new java.awt.Paint [ss.fillStyles.size()]; 885 } 886 887 void paint_line() { 888 if( line_idx >= 0 && gp_line != null ) { 889 java.awt.Paint paint = lstyle_paints[line_idx]; 890 java.awt.Stroke stroke = lstyle_strokes[line_idx]; 891 if( paint == null ) { 892 LineStyle lstyle = ss.getLineStyle(line_idx); 893 894 int width = lstyle.getWidth(); 895 stroke = new java.awt.BasicStroke (width); paint = lstyle.getColor().getAWTColor(); 898 899 lstyle_paints[line_idx] = paint; 900 lstyle_strokes[line_idx] = stroke; 901 } 902 903 g2.setPaint(paint); 904 g2.setStroke(stroke); 905 906 g2.draw(gp_line); 907 gp_line.reset(); 908 } 909 } 910 911 void paint_fill() { 912 if( fill_idx >= 0 && gp_fill != null ) { 913 java.awt.Paint paint = fstyle_paints[fill_idx]; 914 if( paint == null ) { 915 FillStyle fstyle = ss.getFillStyle(fill_idx); 916 917 switch( fstyle.getType() ) { 918 case FillStyle.SOLID: { 919 paint = fstyle.getColor().getAWTColor(); 920 break; 921 } 922 case FillStyle.LINEAR_GRADIENT: { 923 Gradient grad = fstyle.getGraduent(); 924 paint = grad.getColors()[0].getAWTColor(); 925 break; 926 } 927 } 928 fstyle_paints[fill_idx] = paint; 929 } 930 931 if( paint != null ) g2.setPaint(paint); 932 933 g2.fill(gp_fill); 934 gp_fill.reset(); 935 } 936 } 937 938 } 939 940 945 public void draw( java.awt.Graphics2D g2 ) { 946 IVVector blocks = new IVVector(); 947 948 StyleBlock sb = style_block; 949 while( sb.prev != null ) { 950 blocks.addElement(sb); 951 sb = sb.prev; 952 } 953 blocks.addElement(sb); 954 955 float x = 0f; 956 float y = 0f; 957 958 GeneralPath gp_line = null; 959 GeneralPath gp_fill = null; 960 for( int blk=blocks.size(); --blk>=0; ) { 961 sb = (StyleBlock) blocks.elementAt(blk); 962 ShapeRecords shaperecords = sb.shapeRecords; 963 964 boolean isFills = sb.shapeStyles.fillStyles.size()>0; 965 boolean isLines = sb.shapeStyles.lineStyles.size()>0; 966 967 if( isFills && gp_fill == null ) gp_fill = new GeneralPath(GeneralPath.WIND_EVEN_ODD); 968 if( isLines && gp_line == null ) gp_line = new GeneralPath(GeneralPath.WIND_EVEN_ODD); 969 970 Painter painter = new Painter(g2, gp_fill, gp_line, sb.shapeStyles); 971 972 IVVector records = shaperecords.getShapeRecords(); 973 boolean isGpEmpty = true; 974 for( int r=0; r<records.size(); r++ ) { 975 Object o = records.elementAt(r); 976 if( o instanceof StyleChangeRecord ) { 977 StyleChangeRecord sr = (StyleChangeRecord) o; 978 int f = sr.getFlags(); 979 980 boolean isGpEmpty1 = isGpEmpty; 981 982 if( (f&(StyleChangeRecord.FILLSTYLE1|StyleChangeRecord.FILLSTYLE0)) != 0 ) { 983 if( !isGpEmpty ) painter.paint_fill(); 984 int idx = sr.getFillStyle0()-1; 985 if( idx < 0 ) idx = sr.getFillStyle1()-1; 986 painter.fill_idx = idx; 987 isGpEmpty1 = true; 988 } 989 990 if( (f&StyleChangeRecord.LINESTYLE) != 0 ) { 991 if( !isGpEmpty ) painter.paint_line(); 992 painter.line_idx = sr.getLineStyle()-1; 993 isGpEmpty1 = true; 994 } 995 isGpEmpty = isGpEmpty1; 996 997 if( (f&StyleChangeRecord.MOVETO) != 0 ) { 998 x = sr.getDeltaX(); 999 y = sr.getDeltaY(); 1000 } 1001 1002 if( isFills ) gp_fill.moveTo(x, y); 1003 if( isLines ) gp_line.moveTo(x, y); 1004 1005 } else if( o instanceof StrightEdgeRecord ) { 1006 StrightEdgeRecord se = (StrightEdgeRecord) o; 1007 x += se.getDeltaX(); 1008 y += se.getDeltaY(); 1009 if( isFills ) gp_fill.lineTo(x, y); 1010 if( isLines ) gp_line.lineTo(x, y); 1011 isGpEmpty = false; 1012 } else { 1013 CurvedEdgeRecord ce = (CurvedEdgeRecord) o; 1014 float xx = x+ce.getControlDeltaX(); 1015 float yy = y+ce.getControlDeltaY(); 1016 x = xx+ce.getAnchorDeltaX(); 1017 y = yy+ce.getAnchorDeltaY(); 1018 if( isFills ) gp_fill.quadTo(xx, yy, x, y); 1019 if( isLines ) gp_line.quadTo(xx, yy, x, y); 1020 isGpEmpty = false; 1021 } 1022 } 1023 if( !isGpEmpty ) { 1024 painter.paint_fill(); 1025 painter.paint_line(); 1026 } 1027 } 1028 } 1029} 1030 | Popular Tags |