******************** Update: ********************
There’s now a google project for this: code.google.com/p/swfvector. I’m going to be updating this so there might be some changes to the how the whole thing works.
I had a lot of positive feedback for my last project that lets you extract font glyphs out of a swf and write text using the flash drawing API or one of the popular 3D engines.
Now, this update fixes a couple of bugs and also adds support for any vector shape on the stage or the library.
Demo:
The syntax is very similar to the the old DynamicText class. The main difference is that for Text, you need to define a fill type and for vectors, the fill type is ignored because vector shapes have their own fill types.
for Vector Shapes
1 2 3 4 | // extract shape from swf VectorShapes.extractFromLibrary(_loader.data, ["woman", "snowman"], VectorShapes.METHOD_CONTINUOUS_POINTS); // draw shape VectorShapes.draw(graphics, "woman"); |
for Vector Text
1 2 3 4 5 | // extract font data from swf VectorText.extractFont(root.loaderInfo.bytes); // draw text graphics.beginFill(0x0000); VectorText.write(graphics, "_Arial", 16, 16, 0, "Hello World", 10, 10); |
IMPORTANT
There are two methods to parse and draw vectors. METHOD_CONTINUOUS_POINTS & METHOD_REGULAR.
METHOD_CONTINUOUS_POINTS (the default method) parses shapes while trying to keep the points continuous. This is the best way but it does not support flat shapes (more on that later)
METHOD_REGULAR parses the data as it is saved in the swf. This supports all vector shapes but is slower in both parsing and rendering.
For best performance and to get data that is easier to work with. Use METHOD_CONTINUOUS_POINTS , but your vector shapes must not be flat. What do I mean by flat? Flat is when you collapse everything into one layer in flash and keep hitting CTRL+B until all groups are killed and everything is merged. The flash then saves this in a very compact way which makes it difficult to break out (more on that later), Anyway, this flatten shape takes a lot more passes to render and it also create a data set that is not that friendly to work with.
The best way to create your vector data is to have each individual shape grouped so that they don’t cut into each other. In the included source, the snowman symbol is the right way and the circles symbol is the wrong way.
ok. more,
This is straight out of the SWF file specs:
“Most vector formats allow only one fill and line style per path. The SWF file format 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.”
This is why i have two methods to parse the data. METHOD_CONTINUOUS_POINTS actually does it wrong, because it ignores the two fill style per edge thing. two fills per edges is never used if the shapes don’t intersect. So even though METHOD_CONTINUOUS_POINTS is wrong, it is the preferred and default method.
Another thing worth mentioning is that the flash drawing API DOES NOT support two fill per edge. instead flash saves the shapes as triangles with one common point, I’m using 0,0. It then draws these triangles erasing it’s 0,0 tail by drawing over it again. that’s the short version anyway, the whole version is a lot more complicated and i’m too lazy to go into it.
Source code: code.google.com/p/swfvector
Tags: ActionScript, ByteArray, PV3D

Wow!
Have been looking for ever since I started to mess with as graphics…!
A question:
Replacing the test example fonts to a normal text font works fine (for example replacing the Font1.as systemFont from “Verdana” to “Times New Roman”).
When replacing the font name with some graphic bullet font, for example “Wingdings” or “Webdings”, the output is blank.
Any clue?
Keep up the good work! / Jonas
Jonas,
The best way to embed a font is to use the Flash IDE, I added an example called TestLoadFonts in the test package.
The flash IDE font transcoder supports more font types than the Flex SDK. I only used the Flex SDK for the samples because it was something i could do fast, but I normally use the flash IDE to embed the fonts. This would be the best method.
1. create dynamic text fields on the timeline and embed the font ranges via the properties panel
2. export as a swf
3. create a class that extends flash.text.Font like this
package ogilvy.website.fonts {
import flash.text.Font;
[Embed(fontName="DIN-Bold", source="../../../../lib/fontsForFlexSDK.swf", mimeType="application/x-shockwave-flash")]
public class DINBold extends Font {
public function DINBold() {
}
}
}
4. The in your flash project, you can use Font.registerFont(DINBold); to embed your fonts
Ok, I see.. Thanks!
Just wonder why Adobe are bullying us like this?
Regards!
J
Hi there,
Impressive work!
I’m trying to use the parser tu draw vector text letter by letter (so I can play at a letter level instead of having a block), but I can’t find a way to get it properly, I miss the spaces and widths/heights of each letter, is there a way to get it back from the parsed font? quite something like it was done in Five3D with a dictionary or something?
Bests.
G.
VectorText.getFontDefinition(“FONT NAME”).advances
will return an object containing the “widths” of characters. (it’s actually more than the width, it’s the width + padding before the next character.
for example
var charWidth:Number = VectorText.getFontDefinition(“Arial”).advances["A"];
will get the the width for the character “A”
That’s what I figured after posting my question and messing with the classes ^_^
thank you!
G.
If its possible to read the fonts in flash.text.Font; I think it will be more flexible if it can read the fonts by Font.enumerateFonts()[i]
Hey,
On the googlecode site it is appearently not possible to get the source code or download the project. Is this an error or did you not get around to uploading it yet?
Rasmus,
you need an svn client to download the source code. you can find the repository url in the “Source” tab.
I was playing around with this code and works nicely, but did come across a bug.
In ShapeRecord.as line 83 should be this
_hasStateNewStyle = _tagType == TagTypes.DEFINE_SHAPE2
|| _tagType == TagTypes.DEFINE_SHAPE3
|| _tagType == TagTypes.DEFINE_SHAPE4;
I had a couple of objects which were Shape4 Type and were not showing up correctly. This fixed sorted it.
But nice code.
Phil,
I made the change to the code. thanks
This is an excellent work! Congratulations!
I was wondering if you could help me with one thing: I see the library does not yet handle line shapes – I got it working all right with filled shapes, but it just seems to be ignoring line drawings.
I’ve been fiddling around with the code and downloaded the swf specification from Adobe, but it would be great if you could point me in the right direction to get it working for shapes with no fills as well.
I guess it shouldn’t be too difficult, since the drawing commands should be the same in both cases, but now the ShapeRecord for that sort of library items seems to be empty.
Thanks a lot.
Leonardo,
Drawing lines has to be done on a separate pass. I decided not to implement it because it was too slow.
Basically you need to create a new array of points (during parsing) and push only those that contain stroke information. Then sort the array to make sure they are in the right order.
Have you considered updating this library for Flash 10?
Doing the actual VectorText.write() takes about as much time as the flash player takes to do the actual rendering.
I’m guessing that if you used the Flash 10 GraphicsPath object for storing the ShapeRecord, instead of the list of Edge classes, it will be much more efficient to transform it during write().
This is because the ShapeRecord has only two vectors — the command and data. The command has the drawTo, curveTo, and moveTo information. This never gets transformed. The data contains a continuous list of x,y co-ordinates, in a Vector.. It is an easy job to iterate over the whole data vector with a scale and offset (and rotation if need be).
Doing this would also greatly reduce the number of objects within the ShapeRecord. The Arial ASCII glyphs that I checked did not use any Fill objects. Therefore the ShapeRecord could consist of only two fields — the bounds, and GraphicsPath for most cases. Only in strange cases would there be an interleaved array of FillStyle and GraphicsPath.
What do you think?
Hello. This is awesome and I’m already using it. But what about line breaks ? Would be even more awesome if we could just send a parameter when “writing” for a desired width. like “200″, and before reaching that width it would start drawing characters in a line below. This would imply also setting line spacing I guess. If this is possible, I probably won’t use TextFields again.
And I support speedGuy’s idea
abrandao,
thank you. you can already use line breaks but there’s no word wrap, which is what you’re after.
Hi
Excellent work!!!
I’m using VectorText.getFontDefinition to get letter size, but what units is the size in please?
VectorText.getFontDefinition(“_Arial”).advances.["A"] is giving me 683 (not pixels i’m guessing).
Also if you VectorText.write ‘Hello World’ at font size 100, how do you get the width in pixels of a letter written at font size 100.
Thx
Took a look at your classes and I see in VectorText you have:
static private const EM_SIZE:Number = 1024;
var scale:Number = 1.0 / (EM_SIZE / size);
Where size is font size.
So I multiply getFontDefinition .ascent, .decent, .leading, advances etc by scale and I can derive from this character size in pixels.
Are my thoughts correct or is there another way to derive character size in pixels?
Anthony,
I wrote this so long ago, I truly don’t remember
– I must be doing some fuzzy logic because if you look at the swf specification.
http://www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf
pg. 172 talks about EM Square (1024×1024)
pg. 173 talks about kerning & advance values
you can see that the width is the advance and the start of the next character should be advance + kerning. I just woke up, so what I did there it’s not making all that much sense, maybe it’ll come back to me after a cup of coffee or something… or you can put 1 & 1 together with the above info
Cool thanks for your quick response (pre-coffee = wow!)
I will take a look at the PDF, it seems to contain more than enough info.
I have checked out polygonal & degrafa libs also. I’m surprised that adobe don’t provide the ability to convert fonts to vectors so we can manipulate them in detail.
My aim at the moment is to accurately render a text sentence along an interactive cubic bezier and add a gradient fill.
I have all this working in Flash Builder 4 but I don’t like the way I have to use TextField objects with bitmaps to obtain results. It’s a bit of a mine field with all the adobe text objects TextFields, Labels, RichText etc.
Hence; I’m looking into these great vector libs to help. Can’t be sure I’m heading down the right path yet though, but Wu is looking promising!
Hi
I’m trying using the current VectorShapes, with Away3d (3.6 FP10), but i can’t see my shape in 3D.
What is the graphic where i must draw the shape ? In the geometry.graphics of an AbstractPrimitive ? or in a Mesh ?
Here a little part of my code :
private function loadShapes():void {
var shapeLoader:URLLoader = new URLLoader();
shapeLoader.dataFormat = URLLoaderDataFormat.BINARY;
shapeLoader.addEventListener(Event.COMPLETE, onShapesLoadedHandler);
shapeLoader.load(new URLRequest(“externalshapes.swf”));
}
private function onShapesLoadedHandler(e:Event):void {
var shapeLoader:URLLoader = e.target as URLLoader;
var shapeBytes:ByteArray = shapeLoader.data as ByteArray;
VectorShapes.extractFromLibrary(shapeBytes, ["c26", "c27", "c28"]);
initObjects();
}
private function initObjects():void {
var plane:AbstractPrimitive = new AbstractPrimitive();
VectorShapes.draw(plane.geometry.graphics, “c26″);
view.scene.addChild(plane);
view.render();
}
Really thank for your job and for your help
One easy way to test is to draw your shape on a regular flash display object to make sure that it was parsed correctly.
var o:Shape = new Shape();
addChild(o);
VectorShapes.draw(o.graphics, “c26″);
you can also see how Li is doing it in away3d http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/loaders/Swf.as
Any possible way you can do some italic, bold, italic and bold with this? It would be great if you could email me some starting point.
Thanks! Great work!
Hey friend can i publish some paragraph of your article on my little blog of university.I have to publish a good articles out there and i really think your post Fits best into it.I will be grateful to give you an source link as well.I have two blogs one my own and the other which is my college blog.I will publish some part in the university blog.Hope you do not mind.
Support Chinese fonts?