Search code examples
c++flashdirect2d

Flash "CurveTo" and "LineTo" in Shapes


I'm working in trying to display some old SWF files with Direct2D.

I found swfmill which, for a simple SWF (found here) that displays a "W"

enter image description here

produces XML code, part of which is this one:

          <ShapeSetup x="-214" y="470" fillStyle1="1"/>
          <LineTo x="-20" y="0"/>
          <CurveTo x1="-35" y1="-74" x2="-45" y2="-109"/>
          <CurveTo x1="-46" y1="-109" x2="-109" y2="-244"/>
          <CurveTo x1="-110" y1="-244" x2="-32" y2="-50"/>
          <CurveTo x1="-33" y1="-50" x2="-27" y2="-18"/>
          <CurveTo x1="-27" y1="-19" x2="-21" y2="-3"/>
          <CurveTo x1="-21" y1="-1" x2="0" y2="-9"/>
          <CurveTo x1="0" y1="-10" x2="53" y2="0"/>
          <LineTo x="304" y="0"/>
          <CurveTo x1="43" y1="0" x2="0" y2="10"/>
          <CurveTo x1="0" y1="10" x2="-24" y2="0"/>
          <CurveTo x1="-100" y1="6" x2="0" y2="70"/>
          <CurveTo x1="0" y1="16" x2="8" y2="27"/>
          <CurveTo x1="8" y1="27" x2="100" y2="229"/>
          <CurveTo x1="99" y1="229" x2="59" y2="120"/>
          <CurveTo x1="22" y1="-56" x2="73" y2="-216"/>
          <CurveTo x1="72" y1="-215" x2="14" y2="-56"/>
          <CurveTo x1="-53" y1="-131" x2="-24" y2="-21"/>
          <CurveTo x1="-24" y1="-22" x2="-41" y2="-7"/>
          <CurveTo x1="-29" y1="-1" x2="0" y2="-9"/>
          <CurveTo x1="0" y1="-10" x2="52" y2="0"/>
          <LineTo x="305" y="0"/>
          <CurveTo x1="28" y1="0" x2="7" y2="2"/>
          <CurveTo x1="8" y1="2" x2="0" y2="6"/>
          <CurveTo x1="0" y1="6" x2="-40" y2="4"/>
          <CurveTo x1="-84" y1="13" x2="0" y2="68"/>
          <CurveTo x1="0" y1="106" x2="234" y2="531"/>
          <CurveTo x1="46" y1="-116" x2="44" y2="-123"/>
          <LineTo x="80" y="-220"/>
          <CurveTo x1="35" y1="-97" x2="4" y2="-25"/>
          <CurveTo x1="5" y1="-25" x2="0" y2="-21"/>
          <CurveTo x1="0" y1="-89" x2="-85" y2="-2"/>
          <CurveTo x1="-19" y1="0" x2="0" y2="-10"/>
          <CurveTo x1="0" y1="-6" x2="6" y2="-2"/>
          <CurveTo x1="6" y1="-2" x2="28" y2="0"/>
          <LineTo x="165" y="0"/>
          <CurveTo x1="74" y1="0" x2="10" y2="2"/>
          <CurveTo x1="11" y1="1" x2="0" y2="9"/>
          <CurveTo x1="0" y1="8" x2="-16" y2="0"/>
          <CurveTo x1="-74" y1="6" x2="-43" y2="83"/>
          <CurveTo x1="-42" y1="83" x2="-154" y2="449"/>
          <CurveTo x1="-81" y1="235" x2="-27" y2="64"/>
          <LineTo x="-21" y="0"/>
          <CurveTo x1="-58" y1="-160" x2="-55" y2="-132"/>
          <CurveTo x1="-54" y1="-132" x2="-100" y2="-257"/>
          <LineTo x="-229" y="681"/>
          <ShapeSetup/>

I'm not sure how to interpret this shape.

What I've tried:
I tried with a ID2D1PathGeometry and BeginFigure (for the ShapeSetup),

  • AddLine (for each LineTo),
  • AddQuadraticBezier (for each CurveTo) but the result is this:

enter image description here

I realized that I must combine some geometries but I'm not sure how. A spec I found here says:

FillStyle0 and FillStyle1
The Adobe Flash authoring tool supports two fill styles per edge, one for each side of the edge: FillStyle0 and FillStyle1.

For shapes that don’t self-intersect or overlap, FillStyle0 should be used.

For overlapping shapes the situation is more complex. For example, if a shape consists of two overlapping squares, and only FillStyle0 is defined,

Flash Player renders a ‘hole’ where the paths overlap. This area can be filled using FillStyle1. In this situation, the rule is that for any directed vector, FillStyle0 is the color to the left of the vector, and FillStyle1 is the color to the right of the vector

Is there anyone that understands how that shape should be drawn?


Solution

  • Probably, coordinates are all relative. So you need to calculate positions incrementally.

    For example,

    <ShapeSetup x="-214" y="470" fillStyle1="1"/>
    <LineTo x="-20" y="0"/>
    <CurveTo x1="-35" y1="-74" x2="-45" y2="-109"/>
    :
    

    are to be translated to

    pSink->BeginFigure(D2D1::Point2F(-214, 470), D2D1_FIGURE_BEGIN_FILLED);
    
    pSink->AddLine(D2D1::Point2F(-234, 470)); // -214, 470 + (-20, 0)
    
    D2D1_QUADRATIC_BEZIER_SEGMENT seg = {
        D2D1::Point2F(-269, 396), // -234, 470 + (-35,-74)
        D2D1::Point2F(-314, 287)  // -269, 396 + (-45,-109)
    };
    pSink->AddQuadraticBezier(&seg);
    :
    

    Appendix

    Testing it in XAML or SVG path-data form,

    M -214,470 
    l -20, 0 
    q -35,-74 -80,-183 
    q -46,-109 -155,-353 
    q -110,-244 -142,-294 
    q -33,-50 -60,-68 
    q -27,-19 -48,-22 
    q -21,-1 -21,-10 
    q 0,-10 53,-10 
    l 304, 0 
    q 43,0 43,10 
    q 0,10 -24,10 
    q -100,6 -100,76 
    q 0,16 8,43 
    q 8,27 108,256 
    q 99,229 158,349 
    q 22,-56 95,-272 
    q 72,-215 86,-271 
    q -53,-131 -77,-152 
    q -24,-22 -65,-29 
    q -29,-1 -29,-10 
    q 0,-10 52,-10 
    l 305, 0 
    q 28,0 35,2 
    q 8,2 8,8 
    q 0,6 -40,10 
    q -84,13 -84,81 
    q 0,106 234,637 
    q 46,-116 90,-239 
    l 80, -220 
    q 35,-97 39,-122 
    q 5,-25 5,-46 
    q 0,-89 -85,-91 
    q -19,0 -19,-10 
    q 0,-6 6,-8 
    q 6,-2 34,-2 
    l 165, 0 
    q 74,0 84,2 
    q 11,1 11,10 
    q 0,8 -16,8 
    q -74,6 -117,89 
    q -42,83 -196,532 
    q -81,235 -108,299 
    l -21, 0 
    q -58,-160 -113,-292 
    q -54,-132 -154,-389 
    l -229, 681 
    Z
    

    surely got W.

    Conversion from Flash path to XAML/SVG path