Shapes Contents.................................................................................................................................................. 1
Shapes......................................................................................................................................................................... 1
Shape Overview..................................................................................................................................................... 2
An Example Shape................................................................................................................................................. 3
Fill Styles............................................................................................................................................................... 4
Line Styles............................................................................................................................................................. 4
Shape structures..................................................................................................................................................... 5
Shape Records........................................................................................................................................................ 6
End Shape Record.................................................................................................................................................. 6
Style Change Record.............................................................................................................................................. 6
FillStyle0 and FillStyle1........................................................................................................................................ 7
Edge Records.......................................................................................................................................................... 8
Straight Edge Record.............................................................................................................................................. 8
Curved Edge Record............................................................................................................................................... 9
Converting between Quadratic and Cubic Bezier curves..................................................................................... 10
DefineShape......................................................................................................................................................... 10
DefineShape2....................................................................................................................................................... 10
DefineShape3....................................................................................................................................................... 11
SDK Examples....................................................................................................................................................... 11
The SWF shape architecture is designed to be compact, flexible and rendered very quickly to the display. It is similar to most vector formats in that shapes are defined by a list of edges called a path. A path may be closed – where the start and end of the path meet to close the figure, or open – where the path forms an open-ended stroke. A path may contain a mixture of straight edges, curved edges, and ‘pen up and move’ commands. The latter allows multiple disconnected figures to be described by a single shape structure. (see MoveTo flag)
A fill style defines the appearance of an area enclosed by a path. Fill styles supported by SWF include a color, a gradient, or a bitmapped image.
A line style defines the appearance of the outline of a path. The line style may be a stroke of any thickness and color.
Most vector formats only allow one fill and line style per path. SWF extends this concept by allowing each edge to have its own line and fill style. This can have unpredictable results when fill styles change in the middle of a path.
Flash also supports two fill styles per edge, one for each side of the edge:
FillStyle0 and FillStyle1. FillStyle0
should always be used first and then FillStyle1 if the shape is filled on both
sides of the edge.
A shape is comprised of the following elements:
·
CharacterId — A
16-bit value that uniquely identifies this shape as a ‘character’ in the
dictionary. The CharacterId can be
referred to in control tags such as PlaceObject. Characters can be re-used and combined with other characters to
make more complex shapes.
· Bounding box — The rectangle that completely encloses the shape.
· Fill style array — A list of all the fill styles used in a shape.
· Line style array — A list of all the line styles used in a shape.
·
Shape-record array — A
list of shape-records. Shape-records
can define straight or curved edges, style changes, or move the drawing
position.
Note: Line and fill styles are defined once only, and may be used
(and re-used) by any of the edges in the shape.
This example appears to be a collection of shapes, but it can be described with a single DefineShape tag.
The red circle, red square and green rounded-rectangle are closed paths. The curved line is an open path. The red square consists of all straight edges, the red circle consists of all curved edges, while the rounded rectangle has curved edges interspersed with straight edges.
There are two fill styles; solid green and solid red, and two line styles; 1-pixel black, and 2-pixel black. The red circle and red square share the same fill and line styles. The rounded rectangle and curved line share the same line style.
Here’s how to describe this example with SWF:
· First, the fill styles are defined with a FILLSTYLEARRAY. The two unique fill styles are solid red and solid green.
· This is followed by a LINESTYLEARRAY that includes the two unique line styles; 1-pixel black, and 2-pixel black .
· This is followed by an array of SHAPERECORDs.
All shape records share a similar structure but can have varied
meaning. A shape-record can define
straight or curved edge, a style change, or it can move the current drawing position.
Now we define the curved line:
· The first shape-record selects the 2-pixel wide line style, and moves the drawing position to the top of the curved line by setting the MoveTo flag.
· The next shape-record is a curved edge, which ends to the bottom of the line. The path is not closed.
Now we define the red square:
· The next shape-record selects the 1-pixel line style and the red fill style. It also moves the drawing position to the top-left corner of the red rectangle.
· The following four shape-records are straight edges. The last edge must end at the top-left corner. Flash requires that closed figures be joined explicitly. That is, the first and last points must be co-incident.
Now we define the red circle:
· The next shape-record does not change any style settings, but moves the drawing position to the top of the red circle.
· The following eight shape-records are curved edges that define the circle. Again, the path must finish where it started.
Now we define the green rounded-rectangle:
· The next shape-record selects the 2-pixel wide line style, and the green fill. It also moves the drawing position to the top-left of the rounded-rectangle.
· The following twelve shape-records are a mixture of straight shape-records (the sides) interspersed with curved shape-records (the rounded corners). The path finishes where it began.
SWF supports three basic types of fills for a shape.
· Solid fill — A simple RGBA color that fills a portion of a shape. An alpha value of 255 means a completely opaque fill. An alpha value of zero means a completely transparent fill. Any alpha between 0 and 255 will be partially transparent.
· Gradient Fill — A gradient fill can be either a linear or a radial gradient. See Gradients for an in depth description of how gradients are defined.
· Bitmap fill — Bitmap fills refer to a bitmap characterId. There are two styles: clipped and tiled. A clipped bitmap fill repeats the color on the edge of a bitmap if the fill extends beyond the edge of the bitmap. A tiled fill repeats the bitmap if the fill extends beyond the edge of the bitmap.
A fill style array enumerates a number of fill styles. The format of a fill style array is described in the following table:
(See class FFillStyleArray in the Flash File Format SDK)
FILLSTYLEARRAY |
||
Field |
Type |
Comment |
FillStyleCount |
count = UI8 |
Count of fill styles |
FillStyleCountExtended |
If count = 0xFF count =
UI16 |
Extended count of fill
styles. Supported only for Shape2 and Shape3. |
FillStyles |
FILLSTYLE[count] |
Array of fill styles |
The format of a fill style value within the file is described in the following table:
(See class FFillStyle in the Flash File Format SDK)
FILLSTYLE |
|
|
Field |
Type |
Comment |
FillStyleType |
type = UI8 |
Type of fill style |
Color |
If type = 0x00 RGBA (if
Shape3); RGB (if Shape1 or Shape2) |
Solid fill color with
transparency information |
GradientMatrix |
If type = 0x10 or 0x12 MATRIX |
Matrix for gradient fill |
Gradient |
If type = 0x10 or 0x12 GRADIENT |
Gradient fill |
BitmapId |
If type = 0x40 or 0x41 UI16 |
ID of bitmap character for
fill |
BitmapMatrix |
If type = 0x40 or 0x41 MATRIX |
Matrix for bitmap fill |
A line style array enumerates a number of line styles. The format of a line style array is described in the following table:
(See class FLineStyleArray in the Flash File Format SDK)
LINESTYLEARRAY |
|
|
Field |
Type |
Comment |
LineStyleCount |
count = UI8 |
Count of line styles |
LineStyleCountExtended |
If count = 0xFF count =
UI16 |
Extended count of line
styles |
LineStyles |
LINESTYLE[count] |
Array of line styles |
A line style represents a width and color of a line. The format of a line style value within the file is described in the following table:
(See class FLineStyle in the Flash File Format SDK)
LINESTYLE |
||
Field |
Type |
Comment |
Width |
UI16 |
Width of line in twips |
Color |
Color value including alpha
channel information for Shape3s |
Notes:
1. All lines in SWF have rounded joins and end-caps. Different join styles and end styles can be simulated with a very narrow shape that looks identical to the desired stroke.
2. SWF has no native support for dashed or dotted line styles. A dashed line can be simulated by breaking up the path into a series of short lines.
The SHAPE structure defines a shape without a fill style or line style information. SHAPE is used by the DefineFont tag, to define character glyphs.
(See class FShape in the Flash File Format SDK)
SHAPE |
|
|
Field |
Type |
Comment |
NumFillBits |
NfillBits = UB[4] |
Number of fill index bits |
NumLineBits |
NlineBits = UB[4] |
Number of line index bits |
ShapeRecords |
SHAPERECORD[one or more] |
Shape records - see below |
The SHAPEWITHSTYLE structure extends the SHAPE structure by including fill style and line style information. SHAPEWITHSTYLE is used by the DefineShape tag.
(See class FShapeWStyle in the Flash File Format SDK)
SHAPEWITHSTYLE |
||
Field |
Type |
Comment |
FillStyles |
Array of fill styles |
|
LineStyles |
Array of line styles |
|
NumFillBits |
NfillBits = UB[4] |
Number of fill index bits |
NumLineBits |
NlineBits = UB[4] |
Number of line index bits |
ShapeRecords |
SHAPERECORD[one
or more] |
Shape records - see below |
Note: The LINESTYLELARRAY and FILLSTYLEARRAY begin at index 1, not index 0.
This diagram illustrates the SHAPEWITHSTYLE structure.
First, the Fill styles and Line styles are defined. These are defined once only and are referred to by array index.
The blue area represents the array of shape-records.
The first shape-record selects a fill from the fill style array, and moves the drawing position to the start of the shape. This is followed by a series of edge records that define the shape.
The next record changes the fill style, and the subsequent edge-records are filled using this new style.
This tag is a completely autonomous object. The style change records only refer to fill and line styles that have been defined in this tag.
There are four types of shape-record:
1. End shape record.
2. Style change record.
3. Straight edge record.
4. Curved edge record.
All shape-records begin with a TypeFlag. If the TypeFlag is zero, the shape-record is a non-edge record, and a further five bits of flag information follow.
The end shape record simply indicates the end of the shape-record array. It is a non-edge record with all five flags equal to zero.
(See class FShapeRecEnd in the Flash File Format SDK)
ENDSHAPERECORD |
||
Field |
Type |
Comment |
TypeFlag |
UB[1] = 0 |
Non-edge record flag |
EndOfShape |
UB[5] = 0 |
End of shape flag |
The style change record is also a non-edge record. It can be used to:
· Select a fill or line style for drawing
· Move the current drawing position (without drawing)
· Replace the current fill and line style arrays with a new set of styles
Because fill and line styles often change at the start of a new path, it is useful to perform more than one action in a single record. For example, say a DefineShape tag defines a red circle and a blue square. After the circle is closed, it is necessary to move the drawing position, and replace the red fill with the blue fill. The style change record can achieve this with a single shape-record.
(See class FShapeRecChange in the Flash File Format SDK)
STYLECHANGERECORD |
||
Field |
Type |
Comment |
TypeFlag |
UB[1] = 0 |
Non-edge record flag |
StateNewStyles |
NewStyles = UB[1] |
New styles flag. Used by
DefineShape2 and DefineShape3 only. |
StateLineStyle |
LineStyle = UB[1] |
Line style change flag |
StateFillStyle1 |
FillStyle1 = UB[1] |
Fill style 1 change flag |
StateFillStyle0 |
FillStyle0 = UB[1] |
Fill style 0 change flag |
MoveTo
= UB[1] |
Move
to flag |
|
MoveBits |
If moveTo nMoveBits = UB[5] |
Move bit count |
MoveDeltaX |
If moveTo SB[nMoveBits] |
Delta X value |
MoveDeltaY |
If moveTo SB[nMoveBits] |
Delta Y value |
FillStyle0 |
If fillStyle0 UB[nFillBits] |
Fill 0 Style |
FillStyle1 |
If fillStyle1 UB[nFillBits] |
Fill 1 Style |
LineStyle |
If lineStyle UB[nLineBits] |
Line Style |
FillStyles |
If newStyles FILLSTYLEARRAY |
Array of new fill styles |
LineStyles |
If newStyles LINESTYLEARRAY |
Array of new line styles |
NumFillBits |
If newStyles NfillBits = UB[4] |
Number of fill index bits
for new styles |
NumLineBits |
If newStyles NlineBits = UB[4] |
Number of line index bits for
new styles |
In the first shape record MoveDeltaX and MoveDeltaY are relative to the shape origin. In subsequent shape-records, MoveDeltaX and MoveDeltaY are relative to the current drawing position.
The style arrays begin at index 1, not index 0. FillStyle = 1 refers to the first style in the fill style array, FillStyle = 2 refers to the second style in the fill style array, and so on. A fill style index of zero means the path is not filled, and a line style index of zero means the path has no stroke. Initially the fill and line style indices are set to zero – no fill or stroke.
Flash supports two fill styles per edge, one
for each side of the edge: FillStyle0 and FillStyle1. For most shapes (those which don’t self-intersect or overlap)
FillStyle0 should be used. For
overlapping shapes the situation is more complex.
For example, if a shape
consisted of two overlapping squares, and only FillStyle0 is defined, the Flash
player will render 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. (See diagram below)
Note: FillStyle0 and FillStyle1 should not be confused with FILLSTYLEARRAY indices. FillStyle0 and FillStyle1 are variables that contain indices into the FILLSTYLEARRAY.
Edge-records have a TypeFlag of 1. There are two types of edge records; straight and curved. The StraightFlag determines the type.
The straight-edge record stores the edge as an X-Y delta. The delta is added to the current drawing position, and this becomes the new drawing position. The edge is rendered between the old and new drawing positions.
Straight-edge records support three types of line:
1. General lines.
2. Horizontal lines.
3. Vertical lines.
General lines store both X & Y deltas, the horizontal and vertical lines store only the X delta and Y delta respectively.
(See class FShapeRecEdgeStraight in the Flash File Format SDK)
STRAIGHTEDGERECORD |
||
Field |
Type |
Comment |
TypeFlag |
UB[1] = 1 |
This is an edge record |
StraightFlag |
UB[1] = 1 |
Straight edge – always 1 |
NumBits |
NBits = UB[4] +
2 |
|
GeneralLineFlag |
LineFlag = UB[1] |
General Line equals 1 Vert/Horz Line equals 0 |
DeltaX |
If lineFlag = 1
SB[nBits] |
X delta |
DeltaY |
If lineFlag = 1
SB[nBits] |
Y delta |
VertLineFlag |
If lineFlag = 0 vertFlag = SB[1] |
Vertical Line equals 1 Horizontal Line equals 0 |
DeltaX |
If vertFlag = 0
SB[nBits] |
X delta |
DeltaY |
If vertFlag = 1
SB[nBits] |
Y delta |
SWF differs from most vector
file formats by using Quadratic Bezier curves rather than Cubic Bezier
curves. PostScript uses Cubic Beziers,
as do most drawing applications, such as Illustrator, FreeHand and Corel
Draw. SWF uses Quadratic Bezier curves
because they can be stored more compactly, and can be rendered more
efficiently.
Below is a diagram of a Quadratic Bezier curve and a Cubic Bezier curve.
A Quadratic Bezier curve has 3 points. Two on-curve anchor points, and one off-curve control point.
A Cubic Bezier curve has 4 points. Two on-curve anchor points, and two off-curve control points.
The curved-edge record stores the edge as two X-Y deltas. The three points that define the Quadratic Bezier are calculated like this:
· The first anchor point is the current drawing position.
· The control point is the current drawing position + ControlDelta.
· The last anchor point is the current drawing position + ControlDelta + AnchorDelta.
The last anchor point becomes the current drawing position.
(See class FShapeRecEdgeCurved in the Flash File Format SDK)
CURVEDEDGERECORD |
||
Field |
Type |
Comment |
TypeFlag |
UB[1] = 1 |
This is an edge record |
StraightFlag |
UB[1] = 0 |
Curved edge - always 0 |
NumBits |
nBits = UB[4] +
2 |
|
ControlDeltaX |
SB[nBits] |
X control point change |
ControlDeltaY |
SB[nBits] |
Y control point change |
AnchorDeltaX |
SB[nBits] |
X anchor point change |
AnchorDeltaY |
SB[nBits] |
Y anchor point
change |
A Quadratic Bezier curve can be represented exactly by a Cubic Bezier curve, since you are going from a 2nd order curve to a 3rd order curve. The conversion is fairly straightforward.
For a discussion of how to convert Quadratic Bezier curves to Cubic Bezier curves see: http://www.icce.rug.nl/erikjan/bluefuzz/beziers/beziers/node2.html
A Cubic Bezier curve can be only be approximated with a Quadratic Bezier curve, since you are going from a 3rd order curve to a 2nd order curve. This involves recursive subdivision of the curve, until the cubic curve and the quadratic equivalent are matched within some arbitrary tolerance.
For a discussion of how to approximate Cubic Bezier curves
with Quadratic Bezier curves see: http://www.research.microsoft.com/~hollasch/cgindex/curves/cbez-quadspline.html
http://fonts.apple.com/TTRefMan/RM08/appendixE.html
The DefineShape tag defines a shape for later use by control tags such as PlaceObject. The ShapeId uniquely identifies this shape as ‘character’ in the Dictionary. The ShapeBounds field is the rectangle that completely encloses the shape. The SHAPEWITHSTYLE structure includes all the paths, fill styles and line styles that make up the shape.
(See class FDTDefineShape in the Flash File Format SDK)
DefineShape |
|
|
Field |
Type |
Comment |
Header |
RECORDHEADER |
Tag ID = 2 |
ShapeId |
UI16 |
ID for this character |
ShapeBounds |
Bounds of the shape |
|
Shapes |
Shape information |
Extends the capabilities of DefineShape with the ability to support more than 255 styles in the style list and multiple style lists in a single shape. (SWF 2.0)
(See class FDTDefineShape2 in the Flash File Format SDK)
DefineShape2 |
||
Field |
Type |
Comment |
Header |
RECORDHEADER |
Tag ID = 22 |
ShapeId |
UI16 |
ID for this character |
ShapeBounds |
Bounds of the shape |
|
Shapes |
Shape information |
Extends the capabilities of DefineShape2 by extending all of the RGB color fields to support RGBA with alpha transparency. (SWF 3.0)
(See class FDTDefineShape3 in the Flash File Format SDK)
DefineShape3 |
||
Field |
Type |
Comment |
Header |
RECORDHEADER |
Tag ID = 32 |
ShapeId |
UI16 |
ID for this character |
ShapeBounds |
Bounds of the shape |
|
Shapes |
Shape information |
The SDK contains C++ examples that demonstrate how to create shapes in SWF.
The low-level examples are:
· FExampleRectangle.cpp creates a rectangle from straight edge records.
· FExampleCircle.cpp creates a circle from curved edge records.
· FExampleOval.cpp creates an oval (or ellipse) from curved edge records.
The high-level examples are:
· HFExampleRectangle.cpp creates three rectangles by specifying the origin and size of each rectangle.
· HFExampleCircle.cpp creates two circles by specifying center and radius.
· HFExampleOval.cpp creates an oval by specifying the bounding-box of the oval.