In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

MaxRectsBinPack + Compact

< Cheating with initial box sizes to avoid interstitial spaces. >
+ benchmarking of the different packing methods
/**
 * Copyright FLASHMAFIA ( http://wonderfl.net/user/FLASHMAFIA )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/5l6A
 */

package {
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.utils.getTimer;

    [SWF(width = '465', height = '465')]
    public class BinPack extends Sprite//
    {
        private const NUM_BOXES : uint = 700;
        private const METHOD_NAME : Vector.<String> = Vector.<String>(['BSSF', 'BLSF', 'BAF', 'BL', 'CP']);
        /* */
        private var pack : MaxRectsBinPack = new MaxRectsBinPack();
        private var dtf : DOSTxT = new DOSTxT(465, 32, 0x282624, 0xA8A6A4);
        private var msg : Vector.<String> = new Vector.<String>(3, true);
        private var boxes : Vector.<Node> = new Vector.<Node>(NUM_BOXES, true);
        private var curMethod : int = (5 * Math.random()) >> 0;
        private var fcnt : int;

        public function BinPack() {
            /* */

            stage.stageFocusRect = tabChildren = tabEnabled = mouseChildren = mouseEnabled = false;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.LOW;
            stage.frameRate = 16;
            opaqueBackground = 0x0;

            /* */

            var i : int = boxes.length;
            while (i-- != 0) {
                var w : int = (1 << (3 + ((3 * Math.random()) >> 0)));
                var h : int = (1 << (3 + ((3 * Math.random()) >> 0)));
                boxes[i] = new Node(0, 0, w, h);
            }

            var bm : Bitmap = new Bitmap(dtf);
            bm.opaqueBackground = 0x0;
            addChild(bm);

            stage.addEventListener(Event.ENTER_FRAME, oef);
        }

        private function oef(e : Event) : void//
        {
            fcnt++;

            if ((fcnt & 63) == 1) {
                graphics.clear();
                graphics.beginFill(0x181410);
                graphics.drawRect(0, dtf.height, 465, 465);
                graphics.endFill();
            }

            if ((fcnt & 63) == 3) {
                if (++curMethod > 4) curMethod = 0;

                pack.reset(465, 465 - dtf.height, false);

                /* process */

                var startTime : int = getTimer();

                for each (var box : Node in boxes) {
                    var node : Node = pack.insert(box.width, box.height, curMethod);
                    if ((node.width == 0) || (node.height == 0)) break;
                }

                var elapsed : int = getTimer() - startTime;

                /* draw */

                var len : uint = pack.usedRectangles.length;
                var i : uint = len;
                while (i-- != 0) {
                    node = pack.usedRectangles[i];

                    var lum : uint = 0x60 + (0x80 * (i / len));
                    var c : uint = ((lum + 2) << 16) | ((lum) << 8) | (lum - 2);

                    graphics.lineStyle(0, c, 1.0, false, 'none', 'none');

                    lum ^= 0xFF;
                    c = ((lum + 2) << 16) | ((lum) << 8) | (lum - 2);

                    graphics.beginFill(c);
                    graphics.drawRect(node.x + 1, node.y + 1 + dtf.height, node.width - 2, node.height - 2);
                }

                /* info */

                msg[0] = 'METHOD  | ' + METHOD_NAME[curMethod];
                msg[1] = 'PACKED  | ' + pack.usedRectangles.length + '/' + NUM_BOXES + ' | ' + (pack.usedRectangles.length / NUM_BOXES * 100).toPrecision(4) + '%';
                msg[2] = 'ELAPSED | ' + elapsed + 'ms';
                dtf.write(msg);
            }
        }
    }
}

import flash.display.BitmapData;


internal class MaxRectsBinPack {
    /* Best Short Side Fit: Positions the Rectangle against the short side of a free Rectangle into which it fits the best. */
    private const BSSF : int = 0;
    /* Best Long Side Fit: Positions the Rectangle against the long side of a free Rectangle into which it fits the best. */
    private const BLSF : int = 1;
    /* Best Area Fit: Positions the Rectangle into the smallest free Rectangle into which it fits. */
    private const BAF : int = 2;
    /* Bottom Left Rule: Does the Tetris placement. */
    private const BL : int = 3;
    /* Contact Point Rule: Choose the placement where the Rectangle touches other Rectangles as much as possible. */
    private const CP : int = 4;
    /* */
    public var usedRectangles : Vector.<Node> = new Vector.<Node>();
    /* */
    private var binWidth : int = 0;
    private var binHeight : int = 0;
    private var allowRotations : Boolean = false;
    private var freeRectangles : Vector.<Node> = new Vector.<Node>();
    private var bestShortSideFit : int;
    private var bestLongSideFit : int;

    public function reset(width : int, height : int, rotations : Boolean) : void {
        binWidth = width;
        binHeight = height;
        allowRotations = rotations;
        usedRectangles.length = 0;
        freeRectangles.length = 0;
        freeRectangles.push(new Node(0, 0, width, height));
    }

    public function insert(width : int, height : int, method : int) : Node {
        var node : Node = new Node();

        switch(method) {
            case BSSF:
                node = insertBSSF(width, height);
                break;
            case BL:
                node = insertBL(width, height);
                break;
            case CP:
                node = insertCP(width, height);
                break;
            case BLSF:
                node = insertBLSF(width, height);
                break;
            case BAF:
                node = insertBAF(width, height);
                break;
        }

        if ((node.width == 0) || (node.height == 0)) return node;

        var len : int = freeRectangles.length;
        for (var i : int = 0; i < len; i++) {
            if (splitFreeNode(freeRectangles[i], node)) {
                freeRectangles.splice(i, 1);
                --i;
                --len;
            }
        }

        /* pruneFreeList(); */

        prune:
        for (i = 0; i < freeRectangles.length; i++) {
            for (var j : int = i + 1; j < freeRectangles.length; j++) {
                var a : Node = freeRectangles[i];
                var b : Node = freeRectangles[j];

                if (isContainedIn(a, b)) {
                    freeRectangles.splice(i, 1);
                    break prune;
                } else if (isContainedIn(b, a)) {
                    freeRectangles.splice(j, 1);
                }
            }
        }

        usedRectangles.push(node);

        return node;
    }

    private function isContainedIn(a : Node, b : Node) : Boolean {
        return (a.x >= b.x) && (a.y >= b.y) && ((a.x + a.width) <= (b.x + b.width)) && ((a.y + a.height) <= (b.y + b.height));
    }

    private function insertBL(width : int, height : int) : Node {
        var bestNode : Node = new Node();
        var bestX : int;
        var bestY : int = int.MAX_VALUE;
        var rect : Node;
        var topSideY : int;

        for (var i : int = 0; i < freeRectangles.length; i++) {
            rect = freeRectangles[i];
            /* Try to place the Node in upright (non-flipped) orientation. */

            if (rect.width >= width && rect.height >= height) {
                topSideY = rect.y + height;

                if (topSideY < bestY || (topSideY == bestY && rect.x < bestX)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = width;
                    bestNode.height = height;
                    bestY = topSideY;
                    bestX = rect.x;
                }
            }
            if (allowRotations && rect.width >= height && rect.height >= width) {
                topSideY = rect.y + width;

                if (topSideY < bestY || (topSideY == bestY && rect.x < bestX)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = height;
                    bestNode.height = width;
                    bestY = topSideY;
                    bestX = rect.x;
                }
            }
        }
        return bestNode;
    }

    private function insertBSSF(width : int, height : int) : Node {
        var bestNode : Node = new Node();

        bestShortSideFit = int.MAX_VALUE;
        var rect : Node;
        var leftoverHoriz : int;
        var leftoverVert : int;
        var shortSideFit : int;
        var longSideFit : int;

        for (var i : int = 0; i < freeRectangles.length; i++) {
            rect = freeRectangles[i];
            /* Try to place the Node in upright (non-flipped) orientation. */

            if (rect.width >= width && rect.height >= height) {
                leftoverHoriz = Math.abs(rect.width - width);
                leftoverVert = Math.abs(rect.height - height);
                shortSideFit = Math.min(leftoverHoriz, leftoverVert);
                longSideFit = Math.max(leftoverHoriz, leftoverVert);

                if (shortSideFit < bestShortSideFit || (shortSideFit == bestShortSideFit && longSideFit < bestLongSideFit)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = width;
                    bestNode.height = height;
                    bestShortSideFit = shortSideFit;
                    bestLongSideFit = longSideFit;
                }
            }
            var flippedLeftoverHoriz : int;
            var flippedLeftoverVert : int;
            var flippedShortSideFit : int;
            var flippedLongSideFit : int;
            if (allowRotations && rect.width >= height && rect.height >= width) {
                flippedLeftoverHoriz = Math.abs(rect.width - height);
                flippedLeftoverVert = Math.abs(rect.height - width);
                flippedShortSideFit = Math.min(flippedLeftoverHoriz, flippedLeftoverVert);
                flippedLongSideFit = Math.max(flippedLeftoverHoriz, flippedLeftoverVert);

                if (flippedShortSideFit < bestShortSideFit || (flippedShortSideFit == bestShortSideFit && flippedLongSideFit < bestLongSideFit)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = height;
                    bestNode.height = width;
                    bestShortSideFit = flippedShortSideFit;
                    bestLongSideFit = flippedLongSideFit;
                }
            }
        }

        return bestNode;
    }

    private function  insertBLSF(width : int, height : int) : Node {
        var bestNode : Node = new Node();
        var bestLongSideFit : int = int.MAX_VALUE;
        var rect : Node;
        var leftoverHoriz : int;
        var leftoverVert : int;
        var shortSideFit : int;
        var longSideFit : int;

        for (var i : int = 0; i < freeRectangles.length; i++) {
            rect = freeRectangles[i];

            /* Try to place the Node in upright (non-flipped) orientation. */

            if (rect.width >= width && rect.height >= height) {
                leftoverHoriz = Math.abs(rect.width - width);
                leftoverVert = Math.abs(rect.height - height);
                shortSideFit = Math.min(leftoverHoriz, leftoverVert);
                longSideFit = Math.max(leftoverHoriz, leftoverVert);

                if (longSideFit < bestLongSideFit || (longSideFit == bestLongSideFit && shortSideFit < bestShortSideFit)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = width;
                    bestNode.height = height;
                    bestShortSideFit = shortSideFit;
                    bestLongSideFit = longSideFit;
                }
            }

            if (allowRotations && rect.width >= height && rect.height >= width) {
                leftoverHoriz = Math.abs(rect.width - height);
                leftoverVert = Math.abs(rect.height - width);
                shortSideFit = Math.min(leftoverHoriz, leftoverVert);
                longSideFit = Math.max(leftoverHoriz, leftoverVert);

                if (longSideFit < bestLongSideFit || (longSideFit == bestLongSideFit && shortSideFit < bestShortSideFit)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = height;
                    bestNode.height = width;
                    bestShortSideFit = shortSideFit;
                    bestLongSideFit = longSideFit;
                }
            }
        }
        return bestNode;
    }

    private function insertBAF(width : int, height : int) : Node {
        var bestNode : Node = new Node();
        var bestAreaFit : int = int.MAX_VALUE;
        var rect : Node;
        var leftoverHoriz : int;
        var leftoverVert : int;
        var shortSideFit : int;
        var areaFit : int;

        for (var i : int = 0; i < freeRectangles.length; i++) {
            rect = freeRectangles[i];
            areaFit = rect.width * rect.height - width * height;

            /* Try to place the Node in upright (non-flipped) orientation. */
            if (rect.width >= width && rect.height >= height) {
                leftoverHoriz = Math.abs(rect.width - width);
                leftoverVert = Math.abs(rect.height - height);
                shortSideFit = Math.min(leftoverHoriz, leftoverVert);

                if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = width;
                    bestNode.height = height;
                    bestShortSideFit = shortSideFit;
                    bestAreaFit = areaFit;
                }
            }

            if (allowRotations && rect.width >= height && rect.height >= width) {
                leftoverHoriz = Math.abs(rect.width - height);
                leftoverVert = Math.abs(rect.height - width);
                shortSideFit = Math.min(leftoverHoriz, leftoverVert);

                if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit)) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = height;
                    bestNode.height = width;
                    bestShortSideFit = shortSideFit;
                    bestAreaFit = areaFit;
                }
            }
        }
        return bestNode;
    }

    /* Returns 0 if the two intervals i1 and i2 are disjoint, or the length of their overlap otherwise. */
    private function commonIntervalLength(i1start : int, i1end : int, i2start : int, i2end : int) : int {
        if (i1end < i2start || i2end < i1start) return 0;
        return Math.min(i1end, i2end) - Math.max(i1start, i2start);
    }

    private function contactPointScoreNode(x : int, y : int, width : int, height : int) : int {
        var score : int = 0;

        if (x == 0 || x + width == binWidth) score += height;
        if (y == 0 || y + height == binHeight) score += width;

        var rect : Node;
        for (var i : int = 0; i < usedRectangles.length; i++) {
            rect = usedRectangles[i];
            if (rect.x == x + width || rect.x + rect.width == x)
                score += commonIntervalLength(rect.y, rect.y + rect.height, y, y + height);
            if (rect.y == y + height || rect.y + rect.height == y)
                score += commonIntervalLength(rect.x, rect.x + rect.width, x, x + width);
        }
        return score;
    }

    private function insertCP(width : int, height : int) : Node {
        var bestNode : Node = new Node();
        var bestContactScore : int = -1;
        var rect : Node;
        var score : int;

        for (var i : int = 0; i < freeRectangles.length; i++) {
            rect = freeRectangles[i];

            /* Try to place the Node in upright (non-flipped) orientation. */

            if (rect.width >= width && rect.height >= height) {
                score = contactPointScoreNode(rect.x, rect.y, width, height);

                if (score > bestContactScore) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = width;
                    bestNode.height = height;
                    bestContactScore = score;
                }
            }
            if (allowRotations && rect.width >= height && rect.height >= width) {
                score = contactPointScoreNode(rect.x, rect.y, height, width);

                if (score > bestContactScore) {
                    bestNode.x = rect.x;
                    bestNode.y = rect.y;
                    bestNode.width = height;
                    bestNode.height = width;
                    bestContactScore = score;
                }
            }
        }
        return bestNode;
    }

    private function splitFreeNode(freeNode : Node, usedNode : Node) : Boolean {
        /* Test with SAT if the Rectangles even intersect. */
        if (usedNode.x >= freeNode.x + freeNode.width || usedNode.x + usedNode.width <= freeNode.x || usedNode.y >= freeNode.y + freeNode.height || usedNode.y + usedNode.height <= freeNode.y) {
            return false;
        }

        var newNode : Node;
        if (usedNode.x < freeNode.x + freeNode.width && usedNode.x + usedNode.width > freeNode.x) {
            /* New node at the top side of the used node. */
            if (usedNode.y > freeNode.y && usedNode.y < freeNode.y + freeNode.height) {
                newNode = freeNode.clone();
                newNode.height = usedNode.y - newNode.y;
                freeRectangles.push(newNode);
            }

            /* New node at the bottom side of the used node. */
            if (usedNode.y + usedNode.height < freeNode.y + freeNode.height) {
                newNode = freeNode.clone();
                newNode.y = usedNode.y + usedNode.height;
                newNode.height = freeNode.y + freeNode.height - (usedNode.y + usedNode.height);
                freeRectangles.push(newNode);
            }
        }

        if (usedNode.y < freeNode.y + freeNode.height && usedNode.y + usedNode.height > freeNode.y) {
            /* New node at the left side of the used node. */
            if (usedNode.x > freeNode.x && usedNode.x < freeNode.x + freeNode.width) {
                newNode = freeNode.clone();
                newNode.width = usedNode.x - newNode.x;
                freeRectangles.push(newNode);
            }

            /* New node at the right side of the used node. */
            if (usedNode.x + usedNode.width < freeNode.x + freeNode.width) {
                newNode = freeNode.clone();
                newNode.x = usedNode.x + usedNode.width;
                newNode.width = freeNode.x + freeNode.width - (usedNode.x + usedNode.width);
                freeRectangles.push(newNode);
            }
        }

        return true;
    }
}

internal class Node {
    public var x : int;
    public var y : int;
    public var width : int;
    public var height : int;

    function Node(x : int = 0, y : int = 0, width : int = 0, height : int = 0) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public function clone() : Node {
        return new Node(x, y, width, height);
    }
}

internal class DOSTxT extends BitmapData {
    private var fmap : Vector.<int>;
    private var c0 : uint;
    private var c1 : uint;
    private var buff : Vector.<uint>;

    function DOSTxT(width : int, height : int, c0 : int, c1 : int) : void {
        this.c0 = c0;
        this.c1 = c1;

        super(width, height, false, c0);
        buff = new Vector.<uint>(width * height, true);

        fmap = Vector.<int>([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, 0x7E, 0xFF, 0x00, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, 0x7F, 0x00, 0x00, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00, 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00, 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00, 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00, 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00, 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00, 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00, 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00, 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00, 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00, 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00, 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00, 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00, 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00]);
        fmap.fixed = true;
    }

    public function write(txt : Vector.<String>) : void {
        var id : uint = buff.length;
        while (id-- != 0) buff[id] = c0;
        var w : uint = width;
        var py : uint = txt.length;

        while (py-- != 0) {
            var line : String = txt[py];
            var y0 : uint = (py >> 1) + (py << 3);

            var px : uint = line.length;
            while (px-- != 0) {
                var x0 : uint = (px >> 1) + (px << 3);
                id = line.charCodeAt(px) << 3;

                var fy : uint = 8;
                while (fy-- != 0) {
                    var ybits : int = fmap[id + fy];

                    var fx : int = 8;
                    while (fx-- != 0) {
                        if (((ybits << fx) & 0x80) == 0x80) {
                            buff[(x0 + fx) + ((y0 + fy) * w)] = c1;
                        }
                    }
                }
            }
        }

        setVector(rect, buff);
    }
}