views:

77

answers:

2

Wow, my first post on Stack Overflow. Have I "arrived"?

Okay, this is an oddball. I'm trying to determine whether there might be some programmatic way to introspect the classes within a linked SWC at runtime.

To give a little more background (maybe there's a completely different way to go about doing this), I'm considering a general framework for Font Embedding. Currently, to embed fonts (using a linked SWC, not the [embed] metatag), you need to embed the font in your SWC using the Flash IDE, and then you need to hard-code a reference to the library asset's Class in your code (possibly being created by someone else, using a different IDE - FlashDevelop for instance).

Now, if it were possible at runtime to introspect the SWC and iterate through the classes it exposes, one could theoretically instantiate/register these fonts programatically without having to know (at compile time) what those fonts might be.

Hence the question: does anyone know of any way to access the SWC as an entity at runtime and introspect its exposed Classes?


As an aside, the rationale for this sort of thing is a simple desire for clean separation of design and application logic responsibilities. It's easy for a Designer to embed the font and author and SWC, and also edit a corresponding external CSS file. It's much more dangerous to count on them to update the hard references to the classes in code, or count on the client not changing their mind about the font usage after the job has been compiled and released.

A: 

You should look at FLexSpy (fxspy) http://code.google.com/p/fxspy/

There are some others out there that will be helpful, too:

KapInspect: http://lab.kapit.fr/display/kapinspect/Kap+Inspect

DeMonster DeBugger: http://demonsterdebugger.com/

Chad Udell
Thanks for the response. Unfortunately, these are all external programs that run on the compiled (and presumably executing) object code. I'm looking for a (possibly native) method to introspect an SWC at runtime, by the same codebase that the SWC has been compiled into.
Tom Auger
+1  A: 

You could load the file in as a binary (or use the bytes property of the stage's LoaderInfo if it's the main file), look through the 'tags' for the ABC data, parse it, and look for the data you need. It is a hassle though.

There are such things as font tags. DefineFont2 (tag type 48) which contains a FontID and a FontName, DefineFontName (tag type 88) which also contains FontID and FontName. Maybe that's the data you need. If it is, then it can be insanely quick to look through even the largest of files.

You can read through the .swf file format specification here: http://www.adobe.com/devnet/swf.html

Joony
Yes, as it turns out, this is probably the only solution until Adobe supports some kind of getDefninitions() method. A couple of guys have already done this, though AFAICT they don't go so far as to filter by type. http://www.bytearray.org/?p=175 (SWFExplorer), http://etcs.ru/pre/ClassExplorer/ (ClassExplorer), and then the oddball http://etcs.ru/pre/FontLoaderDemo/srcview/ (FontLoader) which looks for Fonts embedded within textFields in an SWF and then creates a Class for that font using a byteArray.
Tom Auger
I've also got a hold of the SWF tech specs as well as the AVM2 spec, and I was able to get as far as determining the tag type. But I'll be honest, even after poring over the code of SWFExplorer and ClassExplorer, I can't really figure out enough to modify or create a parser that can filter out based on tag type.
Tom Auger
Well, if you can determine the tag type then you're halfway there. The process is something like this. Read tag type, if it's not the one you're looking for then you read the length (check the tag types in the swf spec. for the difference in reading long and short tag length) which is the length of the current tag. Skip that number of bytes and start over. If it is the tag you're looking for then you use the swf spec. and read through the bytes until you get the information you need.
Joony
Things to know: UI8 = byte (readUnsignedByte()), UI16 = short (readUnsignedShort()), UI32 = Int (readUnsignedInt()), UI8[FontNameLen] is a UTF-8 string which is slightly different to a normal ByteArray UTF-8 string as the length prefix is a byte, not a short, so using readUTF() doesn't work, use readUTFBytes(length) instead.
Joony
Also, some code might be handy, and I'm sure we can work through it.
Joony