Apple blocks Adobe Flash CS5 iPhone Exporter

No Flash for Apple iPhone Fresh off the heels of the release of Flash Builder 4, Apple has announced it will be blocking any attempts by Adobe to create iPhone applications via a Flash CS5 iPhone compiler. Apple made this change following its iPhone 4 preview media event.

The new language in the iPhone SDK:

Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

In other words, one the shiniest, most powerful, most interesting new features of Flash CS5, namely the Packager for iPhone is dead exactly 4 days before the release of Adobe CS5. Adobe has acknowledged the issue.

Despite my previous article critical of Flash Builder 4, I am quite disappointed by this news. Since Flash has been banned from Apple portable devices since their inception, this could have been an excellent way to bring tens of thousands of applications to these devices without any of the risks Steve Jobs (pictured here) has publically chastised Flash for. It seems a like win-win compromise for everyone; Adobe gets Flash applications on the iPhone, and iPhone keeps free of any Adobe-made plug-ins since technically Apple is providing the run-time environment.

I would like to say the two companies will work it out, but the timing of the SDK change seems pointedly directed at Adobe. I guess it is safe to say Apple still holds a grudge.

Update Over the last few days there’s been numerous public fighting between the two companies. Now, sources close to the issue claim Adobe will file a suit against Apple. While I disagree with what Apple is doing, I agree with their ability to block Flash from their devices.

What a lot of Adobe fanatics tend to forget is that Flash is a proprietary platform, not an open web standard. It would be like a developer creating a specialized web plug-in and then demanding it be supported on a cell phone without the ability to modify/change the plug-in. In short, I’d only be on Adobe’s side if they made Flash an open standard that anyone can develop on. It’s ironic that Adobe is claiming foul on Apple’s proprietary platform when they make the only Flash/Flex compilers in the world (the only one anyone uses, to be precise).

Review of Flex/Flash Builder 4 – Defective By Design?

Adobe has released its new version of the Flex Builder, now renamed Flash Builder 4. This version is radically different from previous versions of Flex, introducing the new Spark architecture and theme support. While I’m pleased Adobe has finally added support for Eclipse 3.5, I’m disappointed with some of the new architecture changes that make doing simple things, such as skinning a button, now quite cumbersome.

1. Spark and Halo: Duplicate Code will be Flex’s downfall

The Spark framework introduces a new set of UI components that sit on top of mx, and in many cases, duplicate the logic. For example, you can now define an old Halo button <mx:button/> alongside a new Spark button <s:button/>, both within the same component. I predict this duplication of code will lead to confusing and muddled codebases. Some developers will use all Spark components, some will use all Halo components, and some will use an inconsistent mix of the two.

The idea of two different components with the same name existing within the same application worries me greatly. It would be like Sun releasing a new version of the String class in Java 8, and rather than updating the old String class you now had 2 distinct classes to choose from, both called String, with the package name determining which you use. Sometimes reinventing the wheel is a sign the developers were too lazy to merge their changes into the existing wheel.

2. Broken Migration Paths

When I attempted to migrate some of my Flex 3 applications into Flash Builder 4, I received a number of compiler errors. The first thing I needed to do was right click on the project and change the Theme to Halo (Flex 3-based theme), since it defaults to Spark. This fixed many, but not all, of the compiler issues. After fixing the remaining compiler issues by hand, I ran the application only to discover none of my buttons had text on them! I enabled “Use Flash Text Engine in MX components” which fixed some, but not all, of the button text, but there were still dozens, possibly hundreds, of UI issues that caused the application to look awful. Realizing migrating the entire application into a native Flex 4 application would take endless amount of hours, I reviewed the compiler options again and checked the “Use Flex 3 compatibility mode” option, which, again, fixed some, but not all, of all the issues. Even with Flex 3 compatibility mode enabled, the compiler still handled the following components differently than it had in Flex 3: drag/drop pop-up images, recognizing css text-align property on certain components, and adding padding on some components. With the compatibility mode enabled, the number of issues was drastically reduced to a few dozen issues, but this was at the cost of limiting the new features available in Flex 4.

3. Skinning a button: 5 lines of code now take 51 lines of code

Previously, skinning a button was just a matter of defining some images in a CSS file and telling the application to use this style. It was intuitive, quite similar to HTML/CSS so it was easy to pick up, and only took a few lines of code, such as the following:

.myButton{
	skin:Embed(source="/assets/menu.png");
	overSkin:Embed(source="/assets/menu_over.png"); 
	downSkin:Embed(source="/assets/menu_down.png");
}

Flex 4 now makes skinning extremely complicated. In order to accomplish the above example in Flex 4, you would need to define a custom skin class such as in the following example taken from here:

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2010/03/24/using-a-bitmap-image-skin-in-a-spark-button-control-in-flex-4/ -->
<s:SparkSkin name="ImageButtonSkin"
        xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
        minWidth="21" minHeight="21"
        alpha.disabled="0.5">
    <!-- states -->
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>
 
    <!-- host component -->
    <fx:Metadata>
        [HostComponent("spark.components.Button")]
    </fx:Metadata>
 
    <fx:Script fb:purpose="styling">
        <![CDATA[
            /* Define the skin elements that should not be colorized.
            For button, the graphics are colorized but the label is not. */
            static private const exclusions:Array = ["labelDisplay"];
 
            override public function get colorizeExclusions():Array {
                return exclusions;
            }
 
            override protected function initializationComplete():void {
                useChromeColor = true;
                super.initializationComplete();
            }
        ]]>
    </fx:Script>
 
    <s:BitmapImage source="@Embed('/assets/menu.png')"
            source.over="@Embed('/assets/menu_over.png')"
            source.down="@Embed('/assets/menu_down.png')"
            left="0" right="0" top="0" bottom="0" />
    <!-- layer 8: text -->
    <s:Label id="labelDisplay"
            textAlign="center"
            verticalAlign="middle"
            maxDisplayedLines="1"
            horizontalCenter="0" verticalCenter="1"
            left="10" right="10" top="2" bottom="2" />
 
</s:SparkSkin>

Talk about wasted space! I understand the power the new skin mechanism adds (you can now layer effects), but I personally don’t feel it’s worth it.

The future of Flex

Adobe has touted the power of Flash Builder 4, but as we have all seen in the past sometimes more powerful designs lead to failure. I think Adobe forgot the KISS principle, or perhaps they had one too many designers at the table instead of developers when they were creating the new architecture. While I liked the ease, power, and simple nature of Flex 3, I’m not convinced of the merits of Flash Builder 4 from a developer perspective. It seems like they made our job a lot more difficult and time consuming.

More articles to follow as I delve into the beast that is Flash Builder 4!

Solution to Flex Image Rotation and Flipping around Center

Today, I was trying to rotate and flip an image around its center point in Flex and the solutions I came across on the web didn’t seem to do the trick. For images that have been previously dragged/dropped, resized, rotated, or translated, the existing solutions are simply not sufficient. With that in mind, I’ve written a solution for rotating and flipping an image around its center that works perfectly in all situations.

The Code

Without further ado, here’s the solution:

private static function rotateImage(image:Image, degrees:Number):void {
	// Calculate rotation and offsets
	var radians:Number = degrees * (Math.PI / 180.0);
	var offsetWidth:Number = image.contentWidth/2.0;
	var offsetHeight:Number =  image.contentHeight/2.0;

	// Perform rotation
	var matrix:Matrix = new Matrix();
	matrix.translate(-offsetWidth, -offsetHeight);
	matrix.rotate(radians);
	matrix.translate(+offsetWidth, +offsetHeight);
	matrix.concat(image.transform.matrix);
	image.transform.matrix = matrix;	
}

Also, here’s a related function to perform a horizontal (left to right) flip of an image:

private static function flipImage(image:Image):void {
	// Calculate offset
	var offsetWidth:Number = image.contentWidth/2.0;
	var offsetHeight:Number =  image.contentHeight/2.0;

	// Perform horizontal flip
	var matrix:Matrix = new Matrix();
	matrix.translate(-offsetWidth, -offsetHeight);
	matrix.scale(-1, 1);  // change to matrix.scale(1,-1) for vertical flip
	matrix.translate(+offsetWidth, +offsetHeight);
	matrix.concat(image.transform.matrix);
	image.transform.matrix = matrix;
}

The Problem Explained

The problem, in a nutshell, is that Flex maintains the top left corner of the image for all transformation and ignores the center point. For example, just calling the rotate() method will produce rotations around the corner such as in this example. Many almost-solutions, see here and here, resolve this by first moving (translating) the image around its center by using the image’s vertical and horizontal midpoint.

A more complex issue arises, though, when the image is no longer positioned at its anchor, or in technical speak the image’s transformation tx/ty values are not 0. I found once you sufficiently drag/drop, rotate, or otherwise modify the image, all of the solutions tend to fall apart. In my situation, all the images were oriented with tx/ty referring to the anchor of the canvas, making these previous solutions difficult to rely upon.

The Solution Explained

After some fun manipulating matrices, I’ve written and tested a solution that will properly rotate an existing image around its center regardless of where it is positioned on the canvas or what transformations have been performed on it. It starts by applying rotation around the image’s center to the identity matrix. In this way, it simulates rotating the matrix around its midpoint translated position, but it is actually applied to the identity matrix. Once the rotational matrix has been calculated, the image is stuck at the top of the canvas. What we really need is a matrix that will take the rotational matrix we’ve just calculated and apply all the previous transformations to orient/rotate the image in the proper position. Well it so happens we have such a matrix, the image’s transformation matrix in fact! So, we apply the transformation matrix of the image to our calculated rotational matrix and voila! The result is our transformed image rotated by the specified amount around its center. We just set the image’s transformation matrix to this result and we are done.