<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>w3blog</title>
	<atom:link href="http://wahlers.com.br/claus/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://wahlers.com.br/claus/blog</link>
	<description>Claus Wahlers on Application Development, Web Standards and what not</description>
	<lastBuildDate>Thu, 11 Feb 2010 09:27:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Realtime MP3 Decoding in Actionscript 3</title>
		<link>http://wahlers.com.br/claus/blog/realtime-mp3-decoding-in-actionscript-3/</link>
		<comments>http://wahlers.com.br/claus/blog/realtime-mp3-decoding-in-actionscript-3/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 09:27:49 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[AS3]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/?p=144</guid>
		<description><![CDATA[So did you ever try to play Shoutcast streams in Flash? Did you run into memory leaks? Did the playback sound pitched or otherwise screwed? Fear no more. Let me introduce you to <a href="http://github.com/claus/as3icy">as3icy</a>.]]></description>
			<content:encoded><![CDATA[<p>So did you ever try to play Shoutcast streams in Flash? Did you run into memory leaks? Did the playback sound pitched or otherwise screwed? Fear no more. Let me introduce you to <a href="http://github.com/claus/as3icy">as3icy</a>.</p>
<p><a href="http://github.com/claus/as3icy">as3icy</a> is a drop-in replacement for the Flash Player&#8217;s Sound object that can reliably play Shoutcast, Icecast and Limewire MP3 streams. And it extracts metadata info from the stream in real time. It also reliably plays VBR MP3.</p>
<p>DISCLAIMER IN CAPITAL LETTERS. This is experimental code. I basically threw this code together in two 24 hour coding sessions. Also, i know as much about sound engineering as i know about pottery &#8211; i blind-ported a big chunk of Java code (the excellent <a href="http://www.javazoom.net/javalayer/javalayer.html">JLayer MP3</a> decoder, originally ported from C if i&#8217;m not mistaken) to Actionscript 3 without really knowing what i was doing. So expect a few WTF moments when reading through the code, and do not expect everything to work perfectly just yet.</p>
<p><strong>Some known issues</strong></p>
<ul>
<li><span style="color: red;">IT IS SLOW AND STRESSES YOUR CPU</span>. Depending on the encoding, i get around 20-50% load on my 2.4GHz Core 2 Duo (Vista), which is way too much. On my MacBook Air 2.16 GHz: full load and playback chokes, which is unacceptable. There is plenty of room for optimization though, the code is currently not optimized at all. It&#8217;s probably worth taking a look at Apparat, or Alchemy in general for more performant alternatives to decode MP3..</li>
<li>Only Layer III is supported (Layer I and II decoders not ported yet).</li>
<li>Only 44100Hz playback is supported (up/down-sampling to 44100Hz not implemented yet).</li>
<li>Only stereo modes are supported (mono not implemented yet).</li>
<li>The stream parser seems to be with problems yet, sometimes it happens that it runs out of sync for some reason.</li>
</ul>
<p>Also, Adobe AIR is recommended to play Shoutcast streams, for two reasons: The meta data interval is passed back to the client via HTTP response headers, which are not available in the plugin version of the Flash Player, and as soon as you put the thing online you need the streaming server to host a crossdomain.xml file. If you happen to have access to the streaming server, you can of course solve these issues by hardcoding the meta data interval and have the streaming server serve an appropriate crossdomain.xml, or by using a proxy script of some sort. Also, this only applies to playing Shoutcast streams. You can play static MP3 files (for example VBR MP3s) using as3swf in the plugin version of the Flash Player without any problem (security restrictions still apply of course).</p>
<p><strong>A simple example: Shoutcast stream playback</strong></p>
<pre><code>package
{
  import com.codeazur.as3icy.ICYSound;
  import com.codeazur.as3icy.events.ICYMetaDataEvent;

  import flash.display.Sprite;
  import flash.events.HTTPStatusEvent;
  import flash.net.URLRequest;
  import flash.net.URLRequestHeader;

  public class SimpleShoutcastPlayer extends Sprite
  {
    protected static const URL:String = "http://72.233.14.70/hype";

    protected var icySound:ICYSound;

    public function SimpleShoutcastPlayer()
    {
      var req:URLRequest = new URLRequest(URL);
      req.requestHeaders = [ new URLRequestHeader("Icy-Metadata", "1") ];
      icySound = new ICYSound();
      icySound.addEventListener(ICYMetaDataEvent.METADATA, metaDataHandler);
      icySound.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, httpResponseStatusHandler);
      icySound.load(req);
      icySound.play();
    }

    protected function httpResponseStatusHandler(e:HTTPStatusEvent):void {
      // The HTTP_RESPONSE_STATUS event is fired when the stream is opened and starting to load.
      var s:String = "Connected!";
      if (icySound.icyName.length > 0) { s += "\rName: " + icySound.icyName; }
      if (icySound.icyDescription.length > 0) { s += "\rDescription: " + icySound.icyDescription; }
      if (icySound.icyUrl.length > 0) { s += "\rURL: " + icySound.icyUrl; }
      if (icySound.icyServer.length > 0) { s += "\rServer: " + icySound.icyServer; }
      if (icySound.icyMetaInterval > 0) { s += "\rMeta Interval: " + icySound.icyMetaInterval; }
      trace(s);
    }

    protected function metaDataHandler(e:ICYMetaDataEvent):void {
      // The METADATA event is fired when new metadata is available.
      if (e.metaData.length > 0) {
        trace("Now playing: " + e.metaData.slice(13, -2));
      }
    }
  }
}</code></pre>
<p>This code (Adobe AIR required) plays the <a href="http://hypem.com/#/radio/live">Hype Machine live radio stream</a>, and traces out general information about the station, as well as the names of currently playing songs.</p>
<p>Note that we set a custom request header, <code>Icy-Metadata: 1</code>. This tells the server to periodically send meta data with the stream. Under the hood, as3icy transparently extracts this meta data from the stream in real time and passes it to the application via the ICYMetaDataEvent. This event won&#8217;t be fired when the request header above is not sent.</p>
<p>The trace output should look something like this:</p>
<pre><code>Connected!
Name: Hype Radio
Description: Radio powered by music blogs
URL: http://hypem.com/radio/
Server: Icecast 2.3.1
Meta Interval: 16000
Now playing: Collider - Time Concerns
Now playing: Rogue Wave - Birds (Neil Young cover)
Now playing: The Big Pink – Dominos
[..]</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/realtime-mp3-decoding-in-actionscript-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SWFtrospection</title>
		<link>http://wahlers.com.br/claus/blog/swftrospection/</link>
		<comments>http://wahlers.com.br/claus/blog/swftrospection/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 21:58:10 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[AS3]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[SWF]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/?p=151</guid>
		<description><![CDATA[Open Flash CS4, create new AS3 FLA, add as3swf.swc and paste this on frame 1:
import com.codeazur.as3swf.SWF;
var swf:SWF = new SWF(root.loaderInfo.bytes);
trace(swf);
Trace output:
[SWF]
  Header:
    Version: 10
    FileLength: 149405
    FileLengthCompressed: 149405
    FrameSize: (550,400)
    FrameRate: 24
    FrameCount: 1
  Tags:
 [...]]]></description>
			<content:encoded><![CDATA[<p>Open Flash CS4, create new AS3 FLA, add <a href="http://github.com/claus/as3swf/blob/master/lib/as3swf.swc">as3swf.swc</a> and paste this on frame 1:</p>
<pre><code>import com.codeazur.as3swf.SWF;
var swf:SWF = new SWF(root.loaderInfo.bytes);
trace(swf);</code></pre>
<p>Trace output:</p>
<pre><code>[SWF]
  Header:
    Version: 10
    FileLength: 149405
    FileLengthCompressed: 149405
    FrameSize: (550,400)
    FrameRate: 24
    FrameCount: 1
  Tags:
    [69:FileAttributes] AS3: true, HasMetadata: false,
      UseDirectBlit: false, UseGPU: false, UseNetwork: false
    [09:SetBackgroundColor] Color: #FFFFFF
    [86:DefineSceneAndFrameLabelData]
      Scenes:
        [0] Frame: 0, Name: Scene 1
    [82:DoABC] Lazy: true, Length: 149219
    [76:SymbolClass]
      Symbols:
        [0] TagID: 0, Name: Untitled_fla.MainTimeline
    [01:ShowFrame]
    [00:End]</code></pre>
<p>Excercise: Draw something on stage, and run the code again.</p>
<p>Want more? Drop by my session <a href="http://www.fitc.ca/events/presentations/presentation.cfm?event=101&#038;presentation_id=1078">Hacking SWF</a> at <a href="http://www.fitc.ca/events/about/?event=101">FITC Amsterdam</a> (Feb 22th, 16:00).</p>
<p>[Edit] <a href="http://twitter.com/jimcheng">Jim Cheng</a> deserves credits. He was the one who whispered &#8220;root.loaderInfo.bytes&#8221; into my virtual ear on IM.</p>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/swftrospection/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>The Boteco São Bento Incident &#8211; Or: Fuck Free Speech!</title>
		<link>http://wahlers.com.br/claus/blog/the-boteco-sao-bento-incident/</link>
		<comments>http://wahlers.com.br/claus/blog/the-boteco-sao-bento-incident/#comments</comments>
		<pubDate>Thu, 01 Oct 2009 01:01:19 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/?p=141</guid>
		<description><![CDATA[This pisses me off to no end, so i decided to blog it.
So there is this blog called Resenha Em 6 where the author posts random reviews of movies, CDs, DVDs, books, shows, bars, restaurants and TV shows, in six lines of text or less.
Recently, he reviewed the hipster bar Boteco São Bento (warning, ugly [...]]]></description>
			<content:encoded><![CDATA[<p>This pisses me off to no end, so i decided to blog it.</p>
<p>So there is this blog called <a href="http://resenhaem6.blogspot.com/">Resenha Em 6</a> where the author posts random reviews of movies, CDs, DVDs, books, shows, bars, restaurants and TV shows, in six lines of text or less.</p>
<p>Recently, he reviewed the hipster bar <a href="http://www.botecosaobento.com.br/">Boteco São Bento</a> (warning, ugly Flash site) in São Paulo. Let&#8217;s just say it was a rather devastating review.</p>
<p>Soon people who appeared to be running/owning that bar posted threatening comments, &#8220;asking&#8221; to remove the review (they later claimed it wasn&#8217;t them.. YEAH RIGHT). The rest is history, the blog post went viral big time (Twitter and such) and drew A LOT of comments (many of them confirming that the bar is shitty).</p>
<p>Next, the unthinkable happened. The bar owners got their lawyers to send the blogger a takedown notice, ordering him to remove the post and all comments, and he (very unfortunately) complied to prevent further legal action.</p>
<p>This is outrageous.</p>
<p>I&#8217;ll never set foot into the bars Boteco São Bento (and Dona Flor in Moema, same owner) again. Ever. Dona Flor is two blocks from my house, and i actually used to go there from time to time. No more. Fuckers.</p>
<p>Sue me, please. Looking forward.</p>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/the-boteco-sao-bento-incident/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Back when Twitter was called FlashCoders</title>
		<link>http://wahlers.com.br/claus/blog/back-when-twitter-was-called-flashcoders/</link>
		<comments>http://wahlers.com.br/claus/blog/back-when-twitter-was-called-flashcoders/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 01:56:17 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/?p=136</guid>
		<description><![CDATA[Back when Twitter was called FlashCoders, there was a ragtag bunch of rebels who refused to bow to the Empire.
The Rebel Alliance had mastered the ancient art of wielding the __proto__, an elegant weapon for a more civilized age. Its sharp underscores could slice through any object. So cleanly, in fact, that members could be [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Back when Twitter was called FlashCoders, there was a ragtag bunch of rebels who refused to bow to the Empire.</p>
<p>The Rebel Alliance had mastered the ancient art of wielding the __proto__, an elegant weapon for a more civilized age. Its sharp underscores could slice through any object. So cleanly, in fact, that members could be attached to new objects and stay alive.</p>
<p>The Empire loved to twist the Prototype in unnatural ways. But the Alliance refused to turn to the Dark Side.</p>
<p>&#8220;A Jedi&#8217;s strength flows from the Prototype,&#8221; said Obiyang. He was the wise mentor of the Alliance, preserving the Old Ways in his quantum archives. Obiyang was the first to achieve MovieClip fusion by plunging his __proto__ deep into the Prototype.</p>
<p>Count Moockoo was a double agent. He maintained a cozy relationship with the Empire whilst feeding information to the Rebels.</p>
<p>Skypenner developed an unhealthy obsession with parenting issues. He challenged Jabba Grossman to a duel in the Beta quadrant, brandishing an ECMA-262 spec-tronator. But Grossman laughed at Skypenner and returned to eating frogs.</p></blockquote>
<p>(by Robert Penner on the <a href="http://groups.google.com/group/grumpy-old-flashers">Grumpy Old Flashers</a> mailinglist)</p>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/back-when-twitter-was-called-flashcoders/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hacking SWF &#8211; Everything You Never Wanted To Know About Shapes In Flash</title>
		<link>http://wahlers.com.br/claus/blog/hacking-swf-1-shapes-in-flash/</link>
		<comments>http://wahlers.com.br/claus/blog/hacking-swf-1-shapes-in-flash/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 22:33:04 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/?p=107</guid>
		<description><![CDATA[I have been inbetween projects the last weeks and thought i could do something productive while i&#8217;m idle, so i created as3swf, a low level Actionscript 3 library to parse, create, modify and publish SWF files.
At the same time i experimented with iPhone development, as we at côdeazur have some commercial iPhone work lined up. Part of [...]]]></description>
			<content:encoded><![CDATA[<p>I have been inbetween projects the last weeks and thought i could do something productive while i&#8217;m idle, so i created <a href="http://github.com/claus/as3swf/tree/master">as3swf</a>, a low level Actionscript 3 library to parse, create, modify and publish SWF files.</p>
<p>At the same time i experimented with iPhone development, as we at <a href="http://codeazur.com.br/lab/">côdeazur</a> have some commercial iPhone work lined up. Part of those experiments involved Core Graphics/Quartz programming, and the old grumpy Flash developer in me immediately thought it would be cool if i could reuse Flash vector art in my iPhone applications. More details on that here: <a href="http://wiki.github.com/claus/as3swf/shape-export-to-objective-c">Shape Export to Objective-C</a>.</p>
<p>With <a href="http://github.com/claus/as3swf/tree/master">as3swf</a> (which parses SWF shapes down to the bone) i already had a powerful weapon in my hands. I&#8217;d &#8220;just&#8221; had to extend it to generate Objective-C source code from a SWF shape. SWF shape records translate almost directly to AS3 drawing API calls (so i thought), and thus also to the similar Quartz Core Graphics API calls. I couldn&#8217;t have been more wrong.</p>
<p>So, for the record, SWF shape records <em>kinda</em> translate to AS3 drawing API calls, but not <em>really</em> &#8211; there are quite a few nuts to crack along the way. It is not as easy as it initially sounds, and little of this is officially documented or explained in Adobe&#8217;s SWF10 specification (or anywhere else for that matter), so i thought i document my findings here.</p>
<p>One blog post was brought to my attention, that helped me understand how the Flash Player actually draws shapes: Mike Swanson&#8217;s &#8220;<a href="http://blogs.msdn.com/mswanson/archive/2006/02/27/539749.aspx">Converting Flash Shapes to WPF</a>&#8221; (ironically, Mike is Technical Evangelist at Microsoft). A very good read, i learned much of the stuff i&#8217;m going to explain here through that post.</p>
<h3 style="font-size: 1.17em;">SWF Shapes</h3>
<p>I don&#8217;t want to go into much detail about the SWF10 file format in general here, it is sufficiently well documented by Adobe. However, an introduction to Flash shapes and how they are stored in SWF seems appropriate.</p>
<p>Shapes are represented in SWF by DefineShape tags. Let&#8217;s jump right into practice and draw a simple shape on stage  in the Flash IDE.</p>
<p>Create a new FLA. Select the Rectangle tool, choose a 10px red stroke and a solid gray fill, and draw a rectangle:</p>
<p><img style="border: 0px initial initial;" title="Rectangle" src="http://codeazur.com.br/stuff/shapes/shape_rectangle.png" alt="" width="140" height="140" /></p>
<p>Publish the SWF, load it into a ByteArray, have as3swf parse it, and dump the results to the console (<a href="http://wiki.github.com/claus/as3swf">example code here</a>). The output should contain a DefineShape4 tag that looks something like this:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">[83:DefineShape4] ID: 1
  FillStyles:
    [1] [SWFFillStyle] Type: 0 (solid), Color: 666666
  LineStyles:
    [1] [SWFLineStyle2] Width: 200, Color: ff0000
  ShapeRecords:
    [SWFShapeRecordStyleChange] MoveTo: 400,400, FillStyle1: 1, LineStyle: 1
    [SWFShapeRecordStraightEdge] Horizontal: 2000
    [SWFShapeRecordStraightEdge] Vertical: 2000
    [SWFShapeRecordStraightEdge] Horizontal: -2000
    [SWFShapeRecordStraightEdge] Vertical: -2000
    [SWFShapeRecordEnd]</pre>
<p>DefineShape contains a set of initial style definitions (in this case that&#8217;s the dark gray solid fill  and the 10px red stroke), followed by a set of shape records describing the geometry of the shape. Note that all coordinates are measured in &#8220;Twips&#8221; (a 20th of a pixel) so you have to divide all of them by 20 to get to the pixel coordinates.</p>
<p>Shape records can come in four flavors:</p>
<p><em>StyleChange </em>records can have more than one purpose. They move the drawing cursor to a new position (equivalent to moveTo in the drawing API), set line and fill styles for following edges (equivalent to beginFill and lineStyle in the drawing API), and define new line and fill styles where needed.</p>
<p><em>StraightEdge </em>and <em>CurvedEdge </em>records define the actual edges of the shape (equivalent to lineTo and curveTo in the drawing API).</p>
<p>The <em>End </em>record is always the last shape record, it simply tells the Flash Player that the shape ends there.</p>
<p>Simple stuff you might think. I haven&#8217;t told you about FillStyle0 and FillStyle1 yet, though.</p>
<h3 style="font-size: 1.17em;">FillStyle0 and FillStyle1</h3>
<p>This is where things get twisted. Edges in SWF shapes can have <em>two</em> different fills.</p>
<p>Create a new FLA, select the Rectangle tool, choose a 10px red stroke and <em>no</em> fill, and draw two rectangles, the second one completely enclosed by the first one. Then use the Paint Bucket tool to fill the donut part with solid dark gray:</p>
<p><img style="border: 0px initial initial;" src="http://codeazur.com.br/stuff/shapes/shape_rectangle_2.png" alt="" width="140" height="140" /></p>
<p>The as3swf dump of the resulting SWF contains the following DefineShape tag:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">[83:DefineShape4] ID: 1
  FillStyles:
    [1] [SWFFillStyle] Type: 0 (solid), Color: 666666
  LineStyles:
    [1] [SWFLineStyle2] Width: 200, Color: ff0000
  ShapeRecords:
    [SWFShapeRecordStyleChange] MoveTo: 1800,1800, FillStyle0: 1, LineStyle: 1
    [SWFShapeRecordStraightEdge] Horizontal: -800
    [SWFShapeRecordStraightEdge] Vertical: -800
    [SWFShapeRecordStraightEdge] Horizontal: 800
    [SWFShapeRecordStraightEdge] Vertical: 800
    [SWFShapeRecordStyleChange] MoveTo: 2400,400, FillStyle0: 0, FillStyle1: 1
    [SWFShapeRecordStraightEdge] Vertical: 2000
    [SWFShapeRecordStraightEdge] Horizontal: -2000
    [SWFShapeRecordStraightEdge] Vertical: -2000
    [SWFShapeRecordStraightEdge] Horizontal: 2000
    [SWFShapeRecordEnd]</pre>
<p>The shape records define the inner rectangle first, then the outer rectangle.</p>
<p>It is important to note that in this example, <em>both </em>rectangles are &#8220;drawn&#8221; <em>clockwise</em>. The shape starts with the inner rectangle&#8217;s bottom right corner, then moves 40px left, 40px up, 40px right, and 40px down, back to the origin. It then moves to the right top corner of the outer rectangle, moves 100px down, 100px left, 100px up, and 100px right, back to the outer rectangle&#8217;s origin.</p>
<p>The interesting parts of this shape structure are the two StyleChange records and the FillStyle information they contain: FillStyle0 and FillStyle1 are 1-based indices into the array of FillStyles, defining the fills of the following (sub-)shapes. <strong>FillStyle0 defines the fill to the left side of an edge, FillStyle1 defines the fill to the right side of an edge.</strong></p>
<p>Lets look at the first StyleChange record. It defines the style properties of the inner rectangle. FillStyle0 is set to 1 (our solid dark gray fill), FillStyle1 is missing and thus defaults to 0 (no fill). As the rectangle edges draw clockwise, FillStyle0 defines the fill <em>on the outside</em> of the rectangle. FillStyle1 defines the <em>inside </em>fill, which in our case is transparent.</p>
<p>Moving on to the second StyleChange record. It defines the style properties for the outer rectangle. FillStyle0 is reset to 0 (no fill), FillStyle1 is set to 1 (solid dark gray fill). The rectangle edges again draw clockwise, so FillStyle0 defines the outside fill (transparent), and FillStyle1 the inside fill (dark gray).</p>
<p>Now let&#8217;s add some more juice and look at a third, slightly more complex example.</p>
<p>Create a new FLA, select the Rectangle tool, choose a 10px red stroke and <em>no </em>fill, and draw two intersecting rectangles. Then use the Paint Bucket tool to fill each of the resulting three closed areas with a different color. I chose light gray, dark gray and black for this example:</p>
<p><img style="border: 0px initial initial;" src="http://codeazur.com.br/stuff/shapes/shape_rectangle_3.png" alt="" width="190" height="190" /></p>
<p>Note how the intersecting edges are split in two.<strong> Fills and edges <em>never </em>overlap in individual SWF shapes. Ever</strong>.</p>
<p>The resulting SWF shape dump looks like this:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">[83:DefineShape4] ID: 1
   FillStyles:
     [1] [SWFFillStyle] Type: 0 (solid), Color: 666666
     [2] [SWFFillStyle] Type: 0 (solid), Color: 999999
     [3] [SWFFillStyle] Type: 0 (solid), Color: 000000
   LineStyles:
     [1] [SWFLineStyle2] Width: 200, Color: ff0000
   ShapeRecords:
     [SWFShapeRecordStyleChange] MoveTo: 2400,1400, FillStyle1: 3, LineStyle: 1
     [SWFShapeRecordStraightEdge] Horizontal: 1000
     [SWFShapeRecordStraightEdge] Vertical: 2000
     [SWFShapeRecordStraightEdge] Horizontal: -2000
     [SWFShapeRecordStraightEdge] Vertical: -1000
     [SWFShapeRecordStyleChange] FillStyle1: 2
     [SWFShapeRecordStraightEdge] Horizontal: -1000
     [SWFShapeRecordStraightEdge] Vertical: -2000
     [SWFShapeRecordStraightEdge] Horizontal: 2000
     [SWFShapeRecordStraightEdge] Vertical: 1000
     [SWFShapeRecordStyleChange] FillStyle0: 3, FillStyle1: 1
     [SWFShapeRecordStraightEdge] Vertical: 1000
     [SWFShapeRecordStraightEdge] Horizontal: -1000
     [SWFShapeRecordStyleChange] FillStyle0: 2
     [SWFShapeRecordStraightEdge] Vertical: -1000
     [SWFShapeRecordStraightEdge] Horizontal: 1000
     [SWFShapeRecordEnd]</pre>
<p>The first noteable difference to the previous two example are the FillStyle definitions. We use three different fills for this shape, so three FillStyles are defined in the header.</p>
<p>The first two sets of shape records define the outer edges of our shape (all edges are again drawn clockwise in this example). The first four edge records define the outer edges of the black shape (FillStyle1 is set to 3, referencing black for the inner fill), the following four edge records define the outer edges of the light gray shape (FillStyle1 is set to 2, referencing light gray for the inner fill).</p>
<p>The last two sets of edges are the interesting ones. They define the inner edges of our shape (the intersection area), whose fill is dark gray. And sure enough, FillStyle1 is set to 1, referencing the dark gray FillStyle for the inner fill. What&#8217;s different here is that FillStyle0 is also set, first to 3 (black), then to 2 (light gray), defining the outer fills for those edges (remember, we&#8217;re drawing clockwise, and FillStyle0 defines the fill to the left of the edge).</p>
<p>To recap: fills and edges in SWF shapes never intersect, and edges can have two fill styles. With these little tricks, SWF shapes save some file size, as each edge is only defined once.</p>
<p>The drawback is that raw SWF shapes need some tweaking in order to be redrawn using Actionscript and the Drawing API, which doesn&#8217;t support those concepts. Luckily, i did all the heavy lifting for you already in as3swf. The TagDefineShape class features a export() method, which dissects the shape in question and outputs code that is compatible with the AS3 Drawing API and Apple&#8217;s Quartz framework.</p>
<h3 style="font-size: 1.17em;">Draw fills first</h3>
<p>Fills and strokes need to be drawn separately (fills first, strokes last). We focus on fills for now.</p>
<p>Let&#8217;s look at the third example again. In order to redraw that shape using the AS3 Drawing API, we need to draw three closed paths with three different fills. Now how do we get from the rather compressed SWF shape format to shapes that can be drawn using AS3?</p>
<p>Mike Swanson explains that in his blog post &#8220;<a href="http://blogs.msdn.com/mswanson/archive/2006/02/27/539749.aspx">Converting Flash Shapes to WPF</a>&#8221; quite well.</p>
<p>We look at the FillStyle indices of each StyleChange record. If <em>FillStyle1 </em>is set to anything other than 0, we add the following edge records <em>as is</em> to our new edge list, along with the FillStyle info referenced by FillStyle1. If <em>FillStyle0 </em>is set to anything other than 0, we add the following edge records to the list <em>in reversed order</em>, along with the FillStyle info referenced by FillStyle0. </p>
<p>This way, if both FillStyle0 and FillStyle1 are set in a StyleChange record, we end up adding the edges that are following <em>twice</em>, once for each of the two fills. In our example, we end up with 16 edges instead of the 12 that are defined in the SWF.</p>
<p>All that&#8217;s left is sorting the edges by FillStyle, i.e.first draw edges with black fill, then draw edges with light gray fill, and finally draw edges with dark gray fill. Voilá, we got fill!</p>
<h3 style="font-size: 1.17em;">Draw strokes last</h3>
<p>Last but not least we have to draw the strokes. This really got me puzzled for a while. To draw strokes in the correct order, we need to know how the Flash Player draws them internally, otherwise we might end up getting artefacts at end points.</p>
<p>Of course this is not documented anywhere, so we need to investigate. A very good start is the Flash IDE (i am using CS4 btw. Your mileage may vary if you use CS3 or older versions of the IDE). Create a new FLA, and draw some lines:</p>
<p><img class="alignnone" src="http://codeazur.com.br/stuff/shapes/shape_lines.png" alt="" width="430" height="140" /></p>
<p>Select the Line tool, choose a 10px red stroke, and draw a horizontal line.</p>
<p>Then, choose a 20px blue stroke, and draw a vertical line that intersects the red line. Note how the blue line is drawn <em>on top</em> of the red line, as we would expect.</p>
<p>Now choose the 10px red stroke again, and draw a horizontal line that intersects the blue line. At first everything seems right, the second red line appears on top of the blue line, as we would expect. Until you deselect the lines by clicking somewhere on stage, that is. The red line moves below the blue line. WTF?</p>
<p>So let&#8217;s publish the SWF and take a look inside:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">[83:DefineShape4] ID: 1
   LineStyles:
     [1] [SWFLineStyle2] Width: 200, Color: ff0000
     [2] [SWFLineStyle2] Width: 400, Color: 0000ff
   Shapes:
     [SWFShapeRecordStyleChange] MoveTo: 1000,1000, LineStyle: 2
     [SWFShapeRecordStraightEdge] Vertical: 800
     [SWFShapeRecordStyleChange] LineStyle: 1
     [SWFShapeRecordStraightEdge] Horizontal: 1400
     [SWFShapeRecordStyleChange] MoveTo: 400,1800
     [SWFShapeRecordStraightEdge] Horizontal: 600
     [SWFShapeRecordStyleChange] LineStyle: 2
     [SWFShapeRecordStraightEdge] Vertical: 600
     [SWFShapeRecordStyleChange] MoveTo: 1000,400
     [SWFShapeRecordStraightEdge] Vertical: 600
     [SWFShapeRecordStyleChange] LineStyle: 1
     [SWFShapeRecordStraightEdge] Horizontal: 1400
     [SWFShapeRecordStyleChange] MoveTo: 400,1000
     [SWFShapeRecordStraightEdge] Horizontal: 600
     [SWFShapeRecordEnd]</pre>
<p>Examining the shape records, we find that the order of edges is totally messed up. There is no way to find out what is drawn first from the order of the edges in a SWF. Apparently, the Flash Player uses some other way of sorting stroked edges before it draws them.</p>
<p>The Flash IDE gave us a clue though. Lines with the same LineStyle seem to be drawn on the same layer. This is confirmed by the order of LineStyles in the SWF: the first LineStyle is the 10px red stroke (drawn first, thus appearing below everything else), the second LineStyle is the 20px blue stroke (drawn last, thus appearing in front). This suggests that <strong>stroked edges are sorted by LineStyle index</strong>.</p>
<p>Sure enough, this seems to be the case. We thus need to sort edges by LineStyle index and draw them in that order.</p>
<h3 style="font-size: 1.17em;">BAZINGA!</h3>
<p>We now have knowledge about all the theory to redraw SWF shapes in AS3, Objective-C or any other language/platform, and as3swf provides us with the implementation. </p>
<p>Go create!</p>
<p>I&#8217;ll leave you with the Drawing API code for the fancy côdeazur logo, generated directly from SWF:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">// Fills:
graphics.beginFill(0x000000);
graphics.moveTo(132.200000, 38.200000);
graphics.curveTo(146.150000, 44.950000, 156.050000, 56.950000);
graphics.curveTo(146.450000, 70.000000, 143.150000, 85.600000);
graphics.curveTo(138.200000, 73.000000, 127.100000, 65.200000);
graphics.curveTo(115.550000, 57.250000, 101.600000, 57.250000);
graphics.curveTo(83.150000, 57.250000, 70.100000, 70.300000);
graphics.curveTo(57.050000, 83.350000, 57.050000, 101.800000);
graphics.curveTo(57.050000, 120.250000, 70.100000, 133.300000);
graphics.curveTo(83.150000, 146.350000, 101.600000, 146.350000);
graphics.curveTo(115.550000, 146.350000, 127.100000, 138.400000);
graphics.curveTo(138.200000, 130.600000, 143.150000, 118.000000);
graphics.curveTo(146.450000, 133.600000, 156.050000, 146.650000);
graphics.curveTo(146.150000, 158.650000, 132.200000, 165.400000);
graphics.curveTo(117.800000, 172.300000, 101.600000, 172.300000);
graphics.curveTo(72.350000, 172.300000, 51.800000, 151.750000);
graphics.curveTo(31.100000, 131.050000, 31.100000, 101.800000);
graphics.curveTo(31.100000, 72.550000, 51.800000, 52.000000);
graphics.curveTo(72.350000, 31.300000, 101.600000, 31.300000);
graphics.curveTo(117.800000, 31.300000, 132.200000, 38.200000);
graphics.beginFill(0x86b9e1);
graphics.moveTo(128.750000, 74.650000);
graphics.curveTo(140.000000, 85.900000, 140.000000, 101.800000);
graphics.curveTo(140.000000, 117.850000, 128.750000, 128.950000);
graphics.curveTo(117.650000, 140.200000, 101.600000, 140.200000);
graphics.curveTo(85.550000, 140.200000, 74.300000, 128.950000);
graphics.curveTo(63.050000, 117.700000, 63.050000, 101.800000);
graphics.curveTo(63.050000, 85.900000, 74.300000, 74.650000);
graphics.curveTo(85.550000, 63.400000, 101.600000, 63.400000);
graphics.curveTo(117.650000, 63.400000, 128.750000, 74.650000);
graphics.moveTo(118.700000, 84.700000);
graphics.curveTo(111.650000, 77.500000, 101.600000, 77.500000);
graphics.curveTo(91.550000, 77.500000, 84.500000, 84.700000);
graphics.curveTo(77.300000, 91.750000, 77.300000, 101.800000);
graphics.curveTo(77.300000, 111.850000, 84.500000, 118.900000);
graphics.curveTo(91.550000, 126.100000, 101.600000, 126.100000);
graphics.curveTo(111.650000, 126.100000, 118.700000, 118.900000);
graphics.curveTo(125.900000, 111.850000, 125.900000, 101.800000);
graphics.curveTo(125.900000, 91.750000, 118.700000, 84.700000);
graphics.beginFill(0x000000);
graphics.moveTo(288.800000, 101.500000);
graphics.lineTo(288.800000, 172.600000);
graphics.lineTo(262.550000, 172.600000);
graphics.lineTo(262.700000, 101.650000);
graphics.curveTo(262.550000, 83.200000, 249.500000, 70.150000);
graphics.curveTo(236.450000, 57.100000, 218.000000, 57.100000);
graphics.curveTo(199.550000, 57.100000, 186.500000, 70.300000);
graphics.curveTo(173.300000, 83.350000, 173.300000, 101.800000);
graphics.curveTo(173.300000, 120.250000, 186.350000, 133.300000);
graphics.curveTo(199.400000, 146.350000, 217.850000, 146.500000);
graphics.lineTo(256.850000, 146.500000);
graphics.lineTo(256.850000, 172.600000);
graphics.lineTo(217.700000, 172.600000);
graphics.curveTo(188.450000, 172.450000, 167.900000, 151.750000);
graphics.curveTo(147.200000, 131.050000, 147.200000, 101.800000);
graphics.curveTo(147.200000, 72.400000, 167.900000, 51.700000);
graphics.curveTo(188.600000, 31.000000, 218.000000, 31.000000);
graphics.curveTo(247.250000, 31.000000, 267.950000, 51.700000);
graphics.curveTo(288.650000, 72.400000, 288.800000, 101.500000);
graphics.beginFill(0x86b9e1);
graphics.moveTo(242.600000, 101.950000);
graphics.lineTo(242.600000, 101.650000);
graphics.curveTo(242.450000, 91.450000, 235.250000, 84.400000);
graphics.curveTo(228.050000, 77.200000, 218.000000, 77.200000);
graphics.curveTo(207.950000, 77.200000, 200.600000, 84.400000);
graphics.curveTo(193.400000, 91.750000, 193.400000, 101.800000);
graphics.curveTo(193.400000, 111.850000, 200.600000, 119.050000);
graphics.curveTo(207.650000, 126.250000, 217.850000, 126.400000);
graphics.lineTo(242.450000, 126.400000);
graphics.lineTo(242.450000, 102.550000);
graphics.lineTo(242.600000, 101.950000);
graphics.moveTo(218.000000, 62.950000);
graphics.curveTo(234.050000, 62.950000, 245.450000, 74.200000);
graphics.curveTo(256.850000, 85.600000, 256.850000, 101.650000);
graphics.lineTo(256.850000, 140.650000);
graphics.lineTo(217.850000, 140.650000);
graphics.curveTo(201.800000, 140.650000, 190.400000, 129.250000);
graphics.curveTo(179.150000, 117.850000, 179.150000, 101.800000);
graphics.curveTo(179.150000, 85.750000, 190.550000, 74.350000);
graphics.curveTo(201.950000, 62.950000, 218.000000, 62.950000);
graphics.endFill();</pre>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/hacking-swf-1-shapes-in-flash/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Undocumented SWF Tags written by MXMLC</title>
		<link>http://wahlers.com.br/claus/blog/undocumented-swf-tags-written-by-mxmlc/</link>
		<comments>http://wahlers.com.br/claus/blog/undocumented-swf-tags-written-by-mxmlc/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 20:45:51 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[AS3]]></category>
		<category><![CDATA[SWF]]></category>
		<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/?p=89</guid>
		<description><![CDATA[While testing my AS3 SWF library as3swf yesterday, i found that MXMLC (the compiler that comes with the Flex SDKs)  writes undocumented SWF tags to the SWFs it produces.
I was able to identify two so far:
ProductInfo (Tag ID 41)
The ProductInfo tag contains infos about the tool used to generate the SWF, as well as the [...]]]></description>
			<content:encoded><![CDATA[<p>While testing my AS3 SWF library <a href="http://github.com/claus/as3swf/tree/master">as3swf</a> yesterday, i found that MXMLC (the compiler that comes with the Flex SDKs)  writes undocumented SWF tags to the SWFs it produces.</p>
<p>I was able to identify two so far:</p>
<p><strong>ProductInfo</strong> (Tag ID 41)</p>
<p>The ProductInfo tag contains <em>infos about the tool used to generate the SWF</em>, as well as the <em>date and time the SWF was compiled</em>. It also contains info about the &#8220;Edition&#8221; of the software used (see below), and although this seems to be always set to &#8220;None&#8221; in Flex Builder 3 and Flash Builder 4, it potentially could become a privacy issue, especially being an undocumented feature (you better know about this tag just in case you accidentally publish commercial work with your non commercial Flash Builder license).</p>
<ul>
<li>ProductID (UI32)<br />
0: Unknown<br />
1: Macromedia Flex for J2EE<br />
2: Macromedia Flex for .NET<br />
3: Adobe Flex</li>
<li>Edition (UI32)<br />
0: Developer Edition<br />
1: Full Commercial Edition<br />
2: Non Commercial Edition<br />
3: Educational Edition<br />
4: Not For Resale (NFR) Edition<br />
5: Trial Edition<br />
6: None</li>
<li>MajorVersion (UI8)</li>
<li>MinorVersion (UI8)</li>
<li>BuildLow (UI32)</li>
<li>BuildHigh (UI32)</li>
<li>CompilationDate (UI64)<br />
Milliseconds since 1.1.1970</li>
</ul>
<p>Examples:</p>
<p>Flex 4.0 &#8211; [41:ProductInfo] ProductID: 3, Edition: 6, Version: 4.0.0.7791, CompileDate: Fri Aug 21 05:18:21 GMT-0300 2009</p>
<p>Flex 3.2 &#8211; [41:ProductInfo] ProductID: 3, Edition: 6, Version: 3.2.0.3958, CompileDate: Fri Aug 21 05:23:22 GMT-0300 2009</p>
<p><strong>DebugID</strong> (Tag ID 63)</p>
<p>This tag is written to SWFs that are enabled for debugging. It contains a 16 byte UUID.</p>
<ul>
<li>UUID (UI8[16])</li>
</ul>
<p>Example:</p>
<p>[63:DebugID] UUID: b8f36d6a-c735-a340-daa7-44730af92505</p>
<p><strong>Reference</strong></p>
<p>Flex SDK:</p>
<ul>
<li><a href="http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/swfutils/src/java/flash/swf/TagValues.java">TagValues.java</a></li>
<li><a href="http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/swfutils/src/java/flash/swf/tags/ProductInfo.java">ProductInfo.java</a></li>
<li><a href="http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/swfutils/src/java/flash/swf/tags/DebugID.java">DebugID.java</a></li>
</ul>
<p>Community:</p>
<ul>
<address><span style="line-height: 33px; font-size: 21px; color: #3e3e3e;"> </span></address>
</ul>
<ul>
<li>Igor Costa: <a href="http://www.igorcosta.org/?p=220">Reading the compilation date of SWF with the magic of ByteArray</a></li>
<li>Judah Frangipane: <a href="http://www.judahfrangipane.com/blog/?p=252">Cache busting your Flex SWF and the SWF Compilation Date</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/undocumented-swf-tags-written-by-mxmlc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>AUPEO!</title>
		<link>http://wahlers.com.br/claus/blog/aupeo/</link>
		<comments>http://wahlers.com.br/claus/blog/aupeo/#comments</comments>
		<pubDate>Mon, 19 Nov 2007 13:39:01 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/aupeo/</guid>
		<description><![CDATA[In case you were wondering what i have been working on in the last few months (and what will keep me busy in the coming months).. AUPEO! is a brand new platform that combines music and community &#8211; online, offline, on the road, on the web, on your desktop, on your devices.
I can&#8217;t tell too [...]]]></description>
			<content:encoded><![CDATA[<p>In case you were wondering what i have been working on in the last few months (and what will keep me busy in the coming months).. <a title="AUPEO! - We love music!" href="http://aupeo.com/">AUPEO!</a> is a brand new platform that combines music and community &#8211; online, offline, on the road, on the web, on your desktop, on your devices.</p>
<p>I can&#8217;t tell too much just yet but i think it&#8217;s safe to say that it&#8217;s going to seriously rock the tardis. It will feature an open REST API for your integration pleasures, it will come with a super sweet <a title="Adobe AIR" href="http://en.wikipedia.org/wiki/Adobe_AIR">AIR</a> application that i am sure you will love (not only because it will be 100% open sourced), and the site (handcrafted in Rails and designed by one of the coolest design houses in the universe) is definately going to please your eyes <em>and</em> ears.</p>
<p>Be one of the first to play with it, <a title="AUPEO! - We love music!" href="http://aupeo.com/">sign up</a> for the closed beta today!</p>
<p><a title="AUPEO! - We love music!" href="http://aupeo.com/"><img title="AUPEO!" src="http://wahlers.com.br/claus/blog/wp-images/aupeo-logo.png" alt="AUPEO!" width="284" height="136" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/aupeo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Custom Installer For Adobe AIR Applications</title>
		<link>http://wahlers.com.br/claus/blog/custom-installer-for-adobe-air-applications/</link>
		<comments>http://wahlers.com.br/claus/blog/custom-installer-for-adobe-air-applications/#comments</comments>
		<pubDate>Sat, 20 Oct 2007 07:47:28 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[AS3]]></category>
		<category><![CDATA[Air]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex 2]]></category>
		<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/custom-installer-for-adobe-air-applications/</guid>
		<description><![CDATA[I need a custom installer for an AIR application i&#8217;m currently developing. That&#8217;s because my AIR app needs additional functionality that the AIR runtime doesn&#8217;t provide (specifically: detecting USB storage devices, act as a TCP socket server, talk to Last.fm scrobbler plugins). For that purpose i wrote a local RPC socket server gateway in C [...]]]></description>
			<content:encoded><![CDATA[<p>I need a custom installer for an AIR application i&#8217;m currently developing. That&#8217;s because my AIR app needs additional functionality that the AIR runtime doesn&#8217;t provide (specifically: detecting USB storage devices, act as a TCP socket server, talk to Last.fm scrobbler plugins). For that purpose i wrote a local RPC socket server gateway in C (one for Mac OS X and one for Windows) which always runs once the user logs in to her OS. The AIR application can then call methods on that local gateway, or receive events.</p>
<p>The problem is that the user needs to install the RPC server before she installs the actual AIR application. The install process should be seamless (one installer installs RPC server, AIR runtime if needed, and the application itself in one go)  and the installer should be as small as possible. Currently there is no info available from Adobe on how to write custom installers that automatically download/install the AIR runtime if needed (is there?).</p>
<p>Artemis is another project aiming at extending AIR using a local socket server, but it seems that the project has been shut down because of the reasons stated above.</p>
<p>So i have been pulling out my hair lately on how to solve that problem.</p>
<p>I think i found a feasible solution. I am not sure because i haven&#8217;t tested all this, but i wanted to throw it online for discussion. The drawback is that the user needs to install your application with a OS native custom installer.</p>
<p>First you write standard installers for both Mac OS X and Windows, that install the local socket server either as a service/daemon or as an agent so that the server always starts at system launch or user login. Nothing special here yet.</p>
<p>The trick would be to write a simple SWHX application that basically implements the code included with the AIR Installer badge. That helper application can then be included with the installer, which executes it after the local socket server has been installed.</p>
<p>As i said i haven&#8217;t tested this yet (will do soonish), but this should work, no?</p>
<p>The question remains why i don&#8217;t just use SWHX for the main app and screw AIR alltogether.</p>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/custom-installer-for-adobe-air-applications/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adoro Problemas</title>
		<link>http://wahlers.com.br/claus/blog/adoro-problemas/</link>
		<comments>http://wahlers.com.br/claus/blog/adoro-problemas/#comments</comments>
		<pubDate>Tue, 09 Oct 2007 07:32:23 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/adoro-problemas/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><img src="http://wahlers.com.br/claus/blog/wp-content/uploads/2007/10/adoroproblemas.jpg" alt="Adoro Problemas" /></p>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/adoro-problemas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FZip Alpha Release: Create And Modify ZIP Archives</title>
		<link>http://wahlers.com.br/claus/blog/fzip-alpha-release-create-and-modify-zip-archives/</link>
		<comments>http://wahlers.com.br/claus/blog/fzip-alpha-release-create-and-modify-zip-archives/#comments</comments>
		<pubDate>Mon, 08 Oct 2007 20:08:25 +0000</pubDate>
		<dc:creator>Claus Wahlers</dc:creator>
				<category><![CDATA[AS3]]></category>
		<category><![CDATA[Air]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex 2]]></category>
		<category><![CDATA[WebDev]]></category>

		<guid isPermaLink="false">http://wahlers.com.br/claus/blog/fzip-alpha-release-create-and-modify-zip-archives/</guid>
		<description><![CDATA[FZip has been around for some time now, and people seem to like it. However one feature has been asked for repeatedly: In addition to reading ZIP archive, people want to be able to create new (and modify existing) archives.
So i finally sat down this weekend and added that.
The code is not tested very well [...]]]></description>
			<content:encoded><![CDATA[<p>FZip has been around for some time now, and people seem to like it. However one feature has been asked for repeatedly: In addition to reading ZIP archive, people want to be able to create new (and modify existing) archives.</p>
<p>So i finally sat down this weekend and added that.</p>
<p>The code is not tested very well (it works for me but may not work for you)  and has no ASDocs yet, so i release it as an alpha version, with the hope of massive bug feedback.. :)</p>
<p>Download: <a href="http://codeazur.com.br/lab/fzip/download/fzip_1_0_52_alpha.zip" style="text-decoration: line-through" title="FZip 1.0.52 Alpha">fzip_1_0_52_alpha.zip</a> <a href="http://codeazur.com.br/lab/fzip/download/fzip.zip" title="FZip">fzip.zip</a></p>
<p>New methods in class FZip:</p>
<ul>
<li>addFile(name:String, date:Date, content:ByteArray)</li>
<li>addFileAt(index:uint, name:String, date:Date, content:ByteArray)</li>
<li>removeFileAt(index:uint)</li>
<li>serialize(stream:IDataOutput)</li>
</ul>
<p>Sample code:</p>
<pre style="margin-left: 20px"><code><span style="color: #808080; font-style: italic">// Create file contents</span>
<span style="color: #000000; font-weight: bold">var</span> ba:ByteArray = <span style="color: #000000; font-weight: bold">new</span> ByteArray<span style="color: #66cc66">(</span><span style="color: #66cc66">)</span>;
ba.<span style="color: #006600">writeUTFBytes</span><span style="color: #66cc66">(</span><span style="color: #ff0000">"Hello World!"</span><span style="color: #66cc66">)</span>;
<span style="color: #808080; font-style: italic">// Create ZIP archive and add file</span>
<span style="color: #000000; font-weight: bold">var</span> zip:FZip = <span style="color: #000000; font-weight: bold">new</span> FZip<span style="color: #66cc66">(</span><span style="color: #66cc66">)</span>;
zip.<span style="color: #006600">addFile</span><span style="color: #66cc66">(</span><span style="color: #ff0000">"hello.txt"</span>, <span style="color: #000000; font-weight: bold">null</span>, ba<span style="color: #66cc66">)</span>;
<span style="color: #808080; font-style: italic">// Serialize ZIP into a new file</span>
<span style="color: #808080; font-style: italic">// (we use the Adobe AIR specific class FileStream here,</span>
<span style="color: #808080; font-style: italic">// but you can as well use ByteArray </span></code><code><span style="color: #808080; font-style: italic">or anything that</span></code><code><span style="color: #808080; font-style: italic"></span>
<span style="color: #808080; font-style: italic">// implements IDataOutput)</span>
<span style="color: #000000; font-weight: bold">var</span> file:File = File.<span style="color: #006600">applicationStorageDirectory</span>;
file = file.<span style="color: #006600">resolvePath</span><span style="color: #66cc66">(</span><span style="color: #ff0000">"hello.zip"</span><span style="color: #66cc66">)</span>;
<span style="color: #000000; font-weight: bold">var</span> stream:FileStream = <span style="color: #000000; font-weight: bold">new</span> FileStream<span style="color: #66cc66">(</span><span style="color: #66cc66">)</span>;
stream.<span style="color: #006600">open</span><span style="color: #66cc66">(</span>file, FileMode.<span style="color: #006600">WRITE</span><span style="color: #66cc66">)</span>;
zip.<span style="color: #006600">serialize</span><span style="color: #66cc66">(</span>stream<span style="color: #66cc66">)</span>;
stream.<span style="color: #0066cc">close</span><span style="color: #66cc66">(</span><span style="color: #66cc66">)</span>;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://wahlers.com.br/claus/blog/fzip-alpha-release-create-and-modify-zip-archives/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
	</channel>
</rss>
