Search Box

Meta

Archive for July, 2010

With the upcoming release of Transform SWF 3.0 on Sept 15th it was time to move all the existing Cookbook examples over to use the new code. The process was surprisingly easy, though a little tedious, so that bodes well for anyone upgrading any existing applications.

The major changes in Version 3.0 were essentially structural and general cleanup rather than “semantic”. There is still a one-to-one mapping from the data structures in the Flash File Format Specification to classes in Transform. The classes are still essentially Java Beans that know how to encoded and decode themselves so the new version will be familiar, if not quite identical. Some of the changes, major and minor which affect porting existing code include:

Shorter class names. The “FS” prefix (a hangover from the original Objective-C code written a very long time ago) is gone and tedious to use names such as SetBackgroundColor, FSPlaceObject2 and FSRemoveObject2 now become the slimmer and fleeter: Background, Place2 and Remove2 respectively.

Fewer constructors for classes with optional fields. Instead of having constructors for every combination of optional fields, with FSPlaceObject2 being the canonical, bloated and easy to misuse example, now the classes are their own Builders. Typically there is one constructor and the set methods return the object allowing several calls to be chained together. For example, creating a ShapeStyle used to be:new ShapeStyle(1, 1, 0, 0, 0) now it is the much more readable but slightly verbose: new ShapeStyle().setLineStyle(1).setFillStyle(1).setMove(0, 0)

Movie objects used to maintain a counter used for generating unique identifiers for definitions. This is no longer the case and applications have to maintain the counter themselves. This means that calls such as: DefineMovieClip clip = new DefineMovieClip(movie.newIdentifier(), new ArrayList()); are now replaced by: int uid = 1;
...
DefineMovieClip clip = new DefineMovieClip(uid++, new ArrayList());

Integer constants are replaced by enums, e.g. the codes representing compound events for movie clip event handlers are now replaced by the Event enum and multiple events are represented with EnumSets.

Immutable classes make for fast copying of the parent object, so all actions and basic data types such as bounding boxes, coordinate and colour transforms are now immutable. Constructing immutable objects with multiple values, e.g. the Push NewFunction[2] actions and all Filters now employ special Builder classes:Push.Builder builder = new Push.Builder();
builder.add(integer).add(string);
actions.add(builder.build());

New Factories and Service Providers. The utilities classes that were used to generates the objects representing images, sounds and text were refactored to follow the Service Provider pattern. This was the biggest structural change, though the impact on existing code is relatively minor. For example creating the definition for an image was: FSImageConstructor imageGenerator = new FSImageConstructor(imageFile);
FSDefineObject image = imageGenerator.defineImage(movie.newIdentifier()); In the new version this becomes:final ImageFactory factory = new ImageFactory();
factory.read(new File(imageFile));
final ImageTag image = factory.defineImage(uid++);

Movie is now strictly a container. The fields such as version, signature, frameSize and frameRate are now part of the new MovieHeader class. This change was designed to make it easier for people to write their own decoders and to be consistent with other meta-data objects such as MovieMetaData and MovieAttributes since it was not practical to move everything into Movie. For example: FSMovie movie = new FSMovie();
movie.setFrameRate(1.0f);
movie.setFrameSize(new FSBounds(-4000, -4000, 4000, 4000)); Now becomes: Movie movie = new Movie();
MovieHeader header = new MovieHeader();
header.setFrameRate(1.0f);
header.setFrameSize(new Bounds(-4000, -4000, 4000, 4000));
movie.add(header);

There was one gotcha that took a little time to figure out (though not long). I ported Translate SWF to use classes in the new version of Transform rather rely on private copies intended to make the library independent of Transform. Now that actions are immutable:List<Object>values = push.getValues(); returned a copy of the array of values rather than a reference, so:List<Object>values = push.getValues();
values.add(literal); has no effect. However once I had figured out / remembered what the problem was the change was trivial:List<Object>values = push.getValues();
values.add(literal);
actions.set(index, new Push(values));

Not all the change required to port an existing codebase are listed. The best guide would be to perform a diff between the new Cookbook examples when they are released, with the current version for Transform 2.3. That should give a good overview of what needs changing, at least for relatively simple applications.

After spending some time wrestling with Ming, I got it to build on Windows Vista using the MinGW GCC tool chain, though with some caveats, see the issues section below. Here are the steps I went through:

Add c:\MSYS\bin, c:\MinGW\bin, in that order, to the PATH environment variable.

Open a windows shell, change directory to where you unzipped the ming files and run the following command: bash then at the prompt, run: ./configure --disable-freetype this will configure to build the libraries with c++ bindings.

Now edit the file, libtool, in the ming root directory. On line 686 in the function func_extract_an_archive () change: if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then to: if ($AR t "$f_ex_an_ar_oldlib" | sort | sort >/dev/null 2>&1); then Yes, this is subverting the build process and the step will be brittle but all the script is doing is comparing the names of the object files with those stored in the archive. The -uc option is for strict order checking of the file names and there is no obvious reason (at least in the limited time I spent looking) why it does not work.

Now compile and install the libraries: make install The libraries and header files will be installed in C:\msys\1.0\local

Issues:

In step 9, support for FreeType was disabled. This means that you will not be able to generate any font definitions from OpenType files. This is a nuisance since that limits the fonts you can use to ones already in Ming’s FDB format. However has FDB files for the Open Source Bitstream Vera fonts so you can get starting albeit with limited typography. I have not tries these fonts so there may be issues if the format changed – it is filed under Really Old Stuff.

The second major issue is another nuisance. The ming library is built without zlib. When the configure script runs it fails to find the compress2 function used by Ming even though the library was available in msys (downloaded and compiled specifically). That means that Ming cannot generate compressed Flash files. This is not too important, but obviously lacking in any code destined for serious use.

Next Steps:

Get zlib to be recognised by the configure script.

Add FreeType so OpenType fonts can be loaded.

Get the build working with the other language wrappers: python, php and perl.

I will post updates as soon as they are available. I also plan on posting the libraries and ported versions of the Cookbook examples over the next few weeks.

Getting the latest Java version of Transform SWF out of the door has been an enormous amount of work. Most of the problems were a direct result of reading Joshua Bloch’s “Effective Java” more than a few times – a remarkably good book, discovering PMD and Software Craftsmanship – yes I know this is 2010 and not 2001. Also starting a family and having a day-job did not help either.

So with new versions of Transform and Translate scheduled for release on Sept 15th I started thinking about the C++ versions of the libraries which, although quite useful, have been languishing untouched for quite some time now. Initially I was quite looking forward to getting them freshened up and getting the code to the point where I could say that it was rather nice, or at least it didn’t suck as much. But then, well, I started thinking about what that would take. Getting the code updated to support Flash 10 was not really the hard part – after all at the lowest level, C++ and Java syntax are not that different, especially when reading and writing bytes with streams, so the new Java code could easily be moved over to the C++ version. The harder part was cross-platform support. There are simply too many platform variations to be able to support it effectively. CMake does a good job of reducing the effort by making cross-platform builds easy, but the real issue is answering the “I can’t get it to work” requests. Limiting the set to compiler X on platform Y is too restrictive and does not solve the problem since there are still X * Y * Z versions to deal with.

So the C++ code is going to be retired – permanently this time. Instead if you need a library for generating Flash files with C and C++ bindings then take a look at Ming. After a dormant period, activity on the project is picking up again. They have support for Flash 8. Platform support is good, though building on Windows is kind of hairy (more on that later). I tried porting some examples from the Cookbook to Ming and the API is quite effective. The basic concepts and actions to generate a Flash file are the same and re-writing the simpler examples such as, BasicShapes, did not take long – the hardest (time-consuming) part was changing ints to doubles.

So over the next few weeks I am going to port the rest of the Cookbook to see, overall, how easy it is to use Ming. I’ll also post the code and ming libraries since there seems to be some demand for windows binaries and not a lot of success at creating them.