Archive for the ‘Flash’ Category

Font detection with Javascript and Flash

Thursday, June 26th, 2008

I was playing around with jquery and I wanted to see if it was possible to generate a cheat sheet of all the fonts on your system. Its also a good run through of how to load a SWF with a callback.

View a demo (Though, its possible it might not work)

The steps I used to generate this are:

  • Load SWF
  • Javascript calls to Actionscript fonts() method via ExternalInterface
  • Get the list of system fonts in Flash via Font.enumerateFonts(true)
  • Curse Flash for giving you a list of font names, where half of them are garbage.
  • For each font name, in javascript, create a test which adds a DOM element temporarily with a fallback font family set. For example, font-family: 'Apple Garamond Pro', 'Times New Roman';, where Times New Roman is your fallback.
  • Then check the actual width (via offsetWidth). If it does not match the offsetWidth of the fallback font, then we know it rendered ok. (The original idea is from http://www.lalit.org/lab/javascript-css-font-detect)

The only caveat is, if the actual font width and the fallback font width do match, then you would have a false negative. So its not bulletproof.

The actionscript to enumerate the fonts and call back out is pretty simple:

Expose the method in the constructor using ExternalInterface:

FontList.as

I used swfobject to load the SWF. Also be sure to enable allowScriptAccess.

The javascript to test the fonts is at: font-detect.js

You can use it by including:

In the end, I don’t think this is useful in practice, but I thought I would share anyway. Its on github too.

Updated: Now uses call straight to actionscript, doesn’t marshall JSON first so its much faster, and other refactoring.

Memory usage during file upload in AIR

Saturday, March 29th, 2008

Uploading files in AIR is a little bit problematic these days.

Here is the code:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" showStatusBar="false" 
  initialize="onInitialize(event)">  
 
  <mx:Script>
    <![CDATA[
 
      import com.rwnage.s3.service.S3PostOptions;
      import flash.events.Event;
 
      public function onInitialize(event:Event):void {
        var accessKey:String = "0RXZ3R7Y034PA8VGNWR2";
        var bucketName:String = "rwnage_test";
        var objectName:String = "test_file";
        var contentType:String = "application/octet-stream";
        var secretAccessKey:String = "[PUT YOUR SECRET ACCESS KEY HERE]";      
 
        var postOptions:S3PostOptions = new S3PostOptions(bucketName, objectName, accessKey, 
          { contentType: contentType });
 
        var policy:String = postOptions.getPolicy();
        var signature:String = postOptions.getSignature(secretAccessKey, policy);
 
        html.htmlText = '<html><body> \
          <form name="upload" action="http://' + bucketName + '.s3.amazonaws.com/" method="post" enctype="multipart/form-data"> \
            Key to upload: <input type="input" name="key" value="' + objectName + '" /><br /> \
            Content-Type: <input type="input" name="Content-Type" value="' + contentType + '" /><br /> \
            <input type="hidden" name="AWSAccessKeyId" value="' + accessKey + '" /> \
            <input type="hidden" name="Policy" value="' + policy + '" /> \
            <input type="hidden" name="Signature" value="' + signature + '" /> \
            File: <input type="file" name="file" /> <br /> \
            <!-- The elements after this will be ignored --> \
            <input type="submit" name="submit" value="Upload to Amazon S3" /> \
          </form></body></html>';                                                     
      }
 
    ]]>
  </mx:Script>
 
  <mx:HTML id="html" width="100%" height="100%" paddingLeft="20" paddingTop="20"/>
 
</mx:WindowedApplication>

No I don’t normally use mx:script tags, its a test case.

Eventually it malloc fails and crashes. This issue is Mac only and also occurs during a FileReference (or File) upload.

Actionscript splat (argument unpacking)

Thursday, February 14th, 2008

In actionscript there is no splat operator or argument unpacking.

In the case where you want to proxy calls to vararg methods you have to use the Function#apply() method.

var array:Array = [];
var stuffToAdd:Array = [ 1, 2, 3, 4 ];
 
array.push.apply(array, stuffToAdd);

It would be nice to have a splat/unpack operator:

array.push(*stuffToAdd);
// Or
array.push(... stuffToAdd);

The ecma mailing list discussed this use of super.apply(this, arguments). And specifically regarding argument unpacking in AS3:

We dropped this from AS3 for lack of evidence for its need.

I think any language with (... args) to Array needs the Array to (... args) if not for anything other than completeness. Does anyone know if this is planned for ES4 at least?

Socket output progress in AIR

Thursday, January 17th, 2008

Currently when using the flash.net.Socket api, there is no way to
determine that buffered data has been written to the socket. (The flush method is non-blocking and applies only to the actionscript socket buffer).

This is a follow-up to a previous post.

This issue does not arise when using the new File api (and writing to
files), since an event has been included in
flash.filesystem.FileStream: OutputProgressEvent.OUTPUT_PROGRESS

If this (or a similar) event could be added to the Socket api, it
would allow us to:

  • Send large amounts of data on a socket (without causing large memory
    usage as data buffers in memory).
  • Measure the current progress of data being sent on the socket.

We came upon this limitation from using our AS3 http client library, and trying to send large
files as part of a multipart upload. However this issue would arise
when sending any significant amounts of data on a socket. For example, an FTP or bittorrent client would be impossible.

This issue has been discussed in other places, but is probably more
pressing now with the AIR releases.

Update: Vote on this bug (FP-6)

Flush

Thursday, December 27th, 2007

So I decided to try to overcome the Leopard File.upload() bug by rolling my own http client: as3httpclientlib which even supports https with the TLS (Socket) support from as3crypto (which is great). The HTTP protocol is pretty simple and I figured it would be a good way to learn the internals and look smart reading ancient RFC’s. All you need is a Socket class and nice, flash api has one at flash.net.Socket

I got everything major working like GET, PUT and POST with multipart/form-data and reading chunked encoding and all that stuff. Not too hard since there are open source http libraries for every major language. I looked at ruby Net::HTTP (stole some regex’s) and Apache Httpclient (stole your multipart boundary).

I got to the point where I was testing uploading larger files, like in:

var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://mybucket.s3.amazonaws.com/big.mp3");
var testFile:File = new File("app:/test/assets/big.mp3");
client.upload(uri, testFile);

It turns out that when you call _socket.flush() (in HttpSocket) it doesn’t actually block, which you might expect. After thinking on it, this isn’t totally shocking since the whole threading model behind actionscript, you don’t really ever block (like there is no such thing as a modal dialog in flash). The problem is without blocking or an event to notify of a flush, the socket just gets filled with the request body all at once (all 800MB’s or whatever file size).

It turns out other people ran into this as well. If you look at (FlexFTP) source, the UploadInv.as file, you will see block of code commented out and replaced by a setInterval(.. , 300). Nice. I guess that upload is capped at ~12kb/sec.

Any of the links in the comments off this blog post are useful too.

If you look at FileStream object you will see it has an outputProgressEvent so that would be useful, you know, if Socket had that too.

I don’t know how you get around this issue, other than trying to guess how fast the socket can transmit and try to stay under that. So now I’m not sure what to do, other than abandon it and come back to it when its fixed, which hopefully will be soon. Thankfully, I can go back to ruby and maybe play with some RubyCocoa or Shoes framework.

Update: Feel free to chime in at Adobe Air Forum or Feature Request/Bug Report Form