Finding character positions in ActionScript 2

Also known as:

  • finding the position of a character in a dynamic textfield with embedded fonts using actionscript 2

One of current projects involves some texteffects and I am loath to do anything on the timeline that can be done quicker by code. So my basic idea was (keeping the designer in me happy):

Doing the design stuff at design time on stage:

  • put a dynamic textfield on stage
  • apply a font, fontsize, color, anti-aliasing
  • apply effects such as dropshadow, glow etc to make it look good

Doing the animate stuff at runtime through code:

  • break apart the stage textfield into little textfields that I could animate

At this point I was already thinking about converting the stage textfields to bitmaps but found I was thinking about optimising things too early, so back to KISS, basic principles first.

Read more

JSFL FLfile.listFolder archive bit bug

Today I ran into a nasty ‘feature’ of FLfile.listFolder in Flash 8 on Windows XP.

FLfile.listFolder doesn’t list files that don’t have the archive flag enabled.

Workaround: none except enabling the archive flag for all files you are searching for.

Flash 8 hitArea quirks

Also known as:

  • dynamically drawn hitarea bug
  • filter applied hitarea bug
  • hitarea no longer works
  • hitarea stops working

I recently noticed two weird bugs while handling hitArea’s in Flash (I say bug you might say feature).

Situation 1:

  • you have a clip on the timeline, let’s call it dialog
  • you have a large hitarea below the dialog, let’s call it largeHitArea
  • you have connected the hitarea to the dialog: dialog.hitArea = largeHitArea
  • you have set the onPress of the dialog to anything but null

Everything works fine up to this point, the large hitarea makes the dialog act as a modal dialog, since you cannot trigger any mouse events below it.

Read more

Consuming webservices in Flash 8

During a partial refactoring process of the Behrloo client system, one of the items on my list was the backend webservice result processing. Without going into a lot of detail how these services are wrapped, it suffices to say that somewhere in the application a couple of webservices are being initialized and utilized through the macromedia webservice classes.

You might be familiar with them, they come in several flavours, for example the WebServiceConnector and the Webservice class. Personally I don’t like to use the WebServiceConnector, mostly since the Webservice class is simple enough to use and tends to give you more control over what is happening.

Basic example

As a simple example of using this Webservice class, paste the following code onto the first frame of the timeline in a new fla document (on a sidenote, REAL applications are not written on a timeline, but for example purposes/quick proof of concepts, this will do just fine):

Read more

Non selectable transparent textfield with embedded font

Some of the V2 Flash Components are less than intuitive now and then. While working on the new trophy tour for Heineken we had to create an application with a transparent textarea with non selectable non editable text using a non standard (embedded) font with Spanish characters.

Oh and the text had to be rendered smoothy using advanced anti-aliasing.

This leaves you with different options. Although I was tempted to simply use a standard textfield, this should be easy to implement using a TextArea component as well, right? As a reference for our own and your convenience, here is a step by step approach.
Read more

Some notes on inheritance in ActionScript 2

When implementing super and subclasses, Flash will call the superclass’ constructor automatically unless you call it yourself.
Imagine you have the following code:

class Super { 
   public function Super () {
       trace ("super called");
   }
}

class Sub extends Super { 
}

var myObject:Object = new Sub();

Read more

Inverting the alpha of a bitmap image in ActionScript 2

A piece of code and a demo says more than a thousand words :). This code demonstrates inversion of an alpha channel in Flash8/AS2.


/**
 * This example demonstrates inverting an alpha channel on an image.
 * Since Flash premultiplies the alpha, we need to keep two separate images: one with the color data, and 
 * one with the alpha data.  It demonstrates splitting the alpha from an image, inverting and proves 
 * premultiplying the alpha destroys color information.
 *
 * @author J.C. Wichman / Objectpainters.com
 */

import flash.geom.Rectangle;
import flash.geom.Point;
import flash.display.BitmapData;
import flash.filters.ColorMatrixFilter;

//set up some default params for the images
var width:Number = 100;
var height:Number = 100;
var fillColor:Number = 0x000000;

/**
 * Simple function that checks how many bitmaps have already been shown on stage and
 * bases the location for the next one on that information. Never use code like this
 * out of context, since its bad programming practice:).
 */
function showBitmap (pBitmap:BitmapData, title:String) {
	var imageCount:Number = this.getNextHighestDepth();
	var row:Number = Math.floor (imageCount/3);
	var columns:Number = imageCount%3;

	var newClip:MovieClip = this.createEmptyMovieClip("image"+imageCount, imageCount);
	newClip.attachBitmap(pBitmap, 0);
	newClip.createTextField("title", 1, 0, 110, 10,10);
	var textClip:TextField = newClip["title"];
	textClip.autoSize = true;
	textClip.text = "Image "+imageCount+":\n"+title;
	var tf:TextFormat = new TextFormat();
	tf.font = "Arial";
	tf.align ="center";
	textClip.setTextFormat(tf);
	
	newClip._x = (columns * 150)+10;
	newClip._y = (row * 170)+10;
}


//setting up demo rgb image, this is an image without alpha. 
//Since flash uses premultiplied alpha, adding an alpha channel will ruin the image for
//further use when we want to invert the alpha channel, so we keep colours separate from alpha
//(omg pink shirts!)
var colorImage:BitmapData = new BitmapData(width, height, false, fillColor);
for (var x = 0; x < width; x++) {
	for (var y = 0; y < height; y++) {
		//fiddle with the pixel data to show a dark gradient
		colorImage.setPixel( x,y, x<<16|y<<8|x+y);
	}
}
showBitmap (colorImage, "Colour w/o alpha");

//now we create a demo alpha bitmap. All color info is non existent, only
//alpha data is set. When x<y the alpha value is near opaque, otherwise its near transparent.
//we only use 0xAF and 0x10 instead of 0xFF and 0x00 to show partial alpha values are inverted ok as well
var demoAlpha:BitmapData = new BitmapData(width, height, true, fillColor);
for (var x = 0; x < width; x++) {
	for (var y = 0; y < height; y++) {
		demoAlpha.setPixel32( x,y, (x<y?0xAF:0x10)<<24);
	}
}
showBitmap (demoAlpha, "Alpha only");

//now imagine you didnt have a separate alpha bitmap to start with, but a starting image with alpha
//which you needed to extract first:
var alphaSplit:BitmapData = new BitmapData(width, height, true, fillColor);
//copy the alpha channel of one image to another image
alphaSplit.copyChannel(demoAlpha, new Rectangle(0,0, width, height), new Point(0,0), 8,8);
showBitmap (alphaSplit, "Alpha channel copy\n (same as previous)");

//now we are going to invert the alpha. This can be done on a pixel by pixel basis, but this might just
//be faster, you'd have to test it
var alphaInvert:BitmapData = alphaSplit.clone();
var matrix:Array = new Array();
matrix = matrix.concat([1, 0, 0, 0, 0]); // red
matrix = matrix.concat([0, 1, 0, 0, 0]); // green
matrix = matrix.concat([0, 0, 1, 0, 0]); // blue
matrix = matrix.concat([0, 0, 0, -1, 0xff]); // alpha, negate the alpha and add 255
alphaInvert.applyFilter(alphaInvert, alphaInvert.rectangle, new Point(0, 0), new ColorMatrixFilter (matrix));
showBitmap (alphaInvert, "Inversion of \nalpha channel");

//now the real action, we combine our original color pixels with the inverted alpha channel
var comboImage:BitmapData = new BitmapData(width, height, true, fillColor);
comboImage.copyPixels(colorImage, colorImage.rectangle, new Point(0,0), alphaInvert, new Point(0,0));  
showBitmap (comboImage, "Colours + \ninverted alpha");

//now to prove premultiplied alpha destroys color information:
var colorImgWithAlpha:BitmapData = new BitmapData(width, height, true, fillColor);
for (var x = 0; x < width; x++) {
	for (var y = 0; y < height; y++) {
		//fiddle with the pixel data to show a dark gradient
		colorImgWithAlpha.setPixel32( x,y, (x<y?0xfe:0x01)<<24|x<<16|y<<8|x+y);
	}
}
colorImgWithAlpha.applyFilter(colorImgWithAlpha, colorImgWithAlpha.rectangle, new Point(0, 0), new ColorMatrixFilter (matrix));
showBitmap (colorImgWithAlpha, "Colour with\n premultiplied \n inverted alpha");

Casting to Array in ActionScript 2

Imagine you have:
var my2dArray:Array = new Array();

my2dArray.push ([1,2,3,4,5]);
my2dArray.push ([6,7,8,9,0]);

And now you want to access and cast an element of myArray to an array:

var firstArray:Array = Array (my2dArray[0]);
trace (firstArray.length);

Right?
Read more

Wrapping function calls in ActionScript 2

Also known as:

  • debugging function calls
  • displaying the name of a called function
  • tracing function calls director like

Today I finally got to try something I had been wanting to try for a long time: wrapping function calls in a nice way.

I had been playing around with function pointers etc, which was ok in itself, but I was forced to create the messy pointer bit each time over again. So I implemented a FunctionWrapper class.

Say we have a class Test, with a method testMethod.

Now we want to execute some code before calling testMethod and after calling testMethod. “Well write another function to do so”, you might say. Of course that is one option, but assume we are looking for another way to do so (I’ll discuss some scenario’s in a minute).
Read more

Local Flash Content and SSL

We are in the process of migrating one of our largest eLearning systems to SSL and Active Directory. Some of the Learning Objects within this system are pretty complex and I’ve implemented a mechanism which allows you to test them standalone.

However during the migration to SSL these objects stopped working when run locally, from the IDE or from FlashDevelop.

I tried to wrap my head around why this was happening, since I’ve been doing less and less with serverside content and certificates these past few years.

Luckily I found this URL which described the problem quite accurate.

Http:// content cannot always access https:// content it seems, but the invalid security certificate was the biggest issue for us.

Our system admin Roy Olthof quickly jumped in, installed a valid certificate and tadaaaaa. Local content could access https content again. Note that we were accessing https content on our own test server, which didnt have a certificate installed.

In addition the Flash content kept giving me the mixed content (secure and unsecure) warning. After changing all the http://’s in the macromedia/adobe codebases (contained within the object and embed tags) this disappeared as well.