Starling 1.3: monospace bitmap font layout problem

by Naohiko.Ueno forked from Starling scaffald for wonderfl (diff: 70)
Starlingでタイマー表示をするときなど、等幅フォントを使いたいけど、BitmapFontにレイアウトの問題があってピクピク動いてしまう。

バグ登録しました。
https://github.com/PrimaryFeather/Starling-Framework/issues/289
♥0 | Line 203 | Modified 2013-02-23 09:10:32 | MIT License | (replaced)
play

Related images

ActionScript3 source code

/**
 * Copyright Naohiko.Ueno ( http://wonderfl.net/user/Naohiko.Ueno )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pf27
 */

// forked from Naohiko.Ueno's Starling scaffald for wonderfl
package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.system.Capabilities;
    import flash.ui.ContextMenu;
    
    import starling.core.Starling;
    
    [SWF(width="465", height="465", frameRate="60", backgroundColor="#222222")]
    public class Startup extends flash.display.Sprite
    {
        public function Startup()
        {
            // Wonderflのプレピュー用にキャプチャ撮りたいときだけ第1引数をtrueにする。
            // 第2引数はキャプチャを撮るまでの秒数。
            WonderflCaptureUtil.init(false, 10);
            
            var menu:ContextMenu = new ContextMenu();
            menu.hideBuiltInItems();
            contextMenu = menu;
            
            loaderInfo.addEventListener(Event.COMPLETE, loaderInfo_completeHandler);
        }
        
        private var _starling:Starling;
        
        private function loaderInfo_completeHandler(event:flash.events.Event):void
        {
            loaderInfo.removeEventListener(Event.COMPLETE, loaderInfo_completeHandler);
            
            Starling.multitouchEnabled = false; // useful on mobile devices
            Starling.handleLostContext = true; // deactivate on mobile devices (to save memory) 
            
            _starling = new Starling(Root, stage);
            _starling.simulateMultitouch = true;
            _starling.enableErrorChecking = Capabilities.isDebugger;
            _starling.showStats = true;
            _starling.start();
            
            // Wonderflのプレピュー用キャプチャを撮るときだけStarlingの画面をビットマップ化してstage最前面に追加する。
            if (WonderflCaptureUtil.captureEnabled)
            {
                _starling.juggler.delayCall(function():void
                {
                    WonderflCaptureUtil.createStarlingCaptureImage(_starling);
                }, WonderflCaptureUtil.captureDelay - 0.5);
            }
        }
    }
}

import flash.system.Capabilities;
import flash.utils.getTimer;

import starling.display.Sprite;
import starling.events.Event;
import starling.text.BitmapFont;
import starling.text.TextField;
import starling.utils.AssetManager;
import starling.utils.HAlign;
import starling.utils.VAlign;

class Root extends starling.display.Sprite
{    
    
    public function Root()
    {
        addEventListener(Event.ADDED_TO_STAGE, init);
    }
    
    private var _assets:AssetManager;
    private var _timerTextField:TextField;
    
    public function init():void
    {
        _assets = new AssetManager();
        
        _assets.verbose = Capabilities.isDebugger;
        _assets.enqueue(
            BITMAP_FONT_PNG_URL
        );
        
        _assets.loadQueue(function onProgress(ratio:Number):void
        {
            if (ratio == 1)
                addBitmapFont();
        });
    }
    
    private function addBitmapFont():void
    {
        TextField.registerBitmapFont(new BitmapFont(_assets.getTexture(BITMAP_FONT_PNG_NAME), BITMAP_FONT_XML));
        
        var textField:TextField = new TextField(stage.stageWidth, 64 * 3, "1234567890\n1234567890\n123456789.", "Courier", BitmapFont.NATIVE_SIZE, 0xFFFFFF);
        textField.hAlign = HAlign.RIGHT;
        textField.vAlign = VAlign.TOP;
        addChild(textField);
        
        _timerTextField = new TextField(stage.stageWidth, 64, "", "Courier", BitmapFont.NATIVE_SIZE, 0xFFFFFF);
        _timerTextField.y = 300;
        _timerTextField.hAlign = HAlign.RIGHT;
        addChild(_timerTextField);
        
        addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
    
    private function enterFrameHandler(event:Event, passedTime:Number):void
    {
        _timerTextField.text = (getTimer() / 100).toFixed();
    }
}

const BITMAP_FONT_PNG_URL:String = "http://assets.wonderfl.net/images/related_images/c/cb/cb6b/cb6bf7b5d68d73ac7f43ae194c8e136ed1f2017d";
const BITMAP_FONT_PNG_NAME:String = "cb6bf7b5d68d73ac7f43ae194c8e136ed1f2017d";
const BITMAP_FONT_XML:XML = 
    <font>
        <info face="Courier" size="64" bold="0" italic="0" chasrset="" unicode="0" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="2,2"/>
        <common lineHeight="64" base="48" scaleW="256" scaleH="128" pages="1" packed="0"/>
        <pages>
            <page id="0" file="CourierNumber.png"/>
        </pages>
        <chars count="12">
            <char id="32" x="126" y="53" width="0" height="0" xoffset="0" yoffset="48" xadvance="38" page="0" chnl="0" letter="space"/>
            <char id="46" x="104" y="53" width="20" height="19" xoffset="13" yoffset="29" xadvance="38" page="0" chnl="0" letter="."/>
            <char id="48" x="143" y="2" width="33" height="49" xoffset="6" yoffset="0" xadvance="38" page="0" chnl="0" letter="0"/>
            <char id="49" x="37" y="53" width="31" height="48" xoffset="8" yoffset="0" xadvance="38" page="0" chnl="0" letter="1"/>
            <char id="50" x="214" y="2" width="34" height="48" xoffset="5" yoffset="0" xadvance="38" page="0" chnl="0" letter="2"/>
            <char id="51" x="2" y="2" width="34" height="49" xoffset="6" yoffset="0" xadvance="38" page="0" chnl="0" letter="3"/>
            <char id="52" x="2" y="53" width="33" height="48" xoffset="6" yoffset="0" xadvance="38" page="0" chnl="0" letter="4"/>
            <char id="53" x="178" y="2" width="34" height="48" xoffset="5" yoffset="1" xadvance="38" page="0" chnl="0" letter="5"/>
            <char id="54" x="73" y="2" width="33" height="49" xoffset="6" yoffset="0" xadvance="38" page="0" chnl="0" letter="6"/>
            <char id="55" x="70" y="53" width="32" height="47" xoffset="6" yoffset="2" xadvance="38" page="0" chnl="0" letter="7"/>
            <char id="56" x="38" y="2" width="33" height="49" xoffset="6" yoffset="0" xadvance="38" page="0" chnl="0" letter="8"/>
            <char id="57" x="108" y="2" width="33" height="49" xoffset="6" yoffset="0" xadvance="38" page="0" chnl="0" letter="9"/>
        </chars>
    </font>;

////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  WonderflCaptureUtil
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.errors.IllegalOperationError;
import flash.events.MouseEvent;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.getDefinitionByName;

import starling.core.RenderSupport;
import starling.core.Starling;

class WonderflCaptureUtil
{
    // Wonderfl default setting @see http://wonderfl.net/help#help_capture
    private static var _capture:Boolean = true;
    private static var _captureDelay:Number = 3;
    
    private static var _inited:Boolean = false;
    private static var _wonderflClassChecked:Boolean = false;
    private static var _wonderflClass:Class;
    
    public static function get captureEnabled():Boolean
    {
        return wonderflClass ? _capture : false;
    }
    
    public static function get captureDelay():Number
    {
        return _captureDelay;
    }
    
    public static function get wonderflClass():Class
    {
        if (_wonderflClassChecked)
            return _wonderflClass;
        else
        {
            try
            {
                _wonderflClassChecked = true;
                _wonderflClass = getDefinitionByName("Wonderfl") as Class
                return _wonderflClass;
            }
            catch (e:Error) {}
        }
        
        return null;
    }
    
    public static function init(capture:Boolean=false, captureDelay:Number=3):void
    {
        if (_inited)
            throw new IllegalOperationError("WonderflCaptureUtil is already inited.");
        
        _inited = true;
        _capture = capture;
        _captureDelay = captureDelay;
        
        if (wonderflClass)
        {
            if (capture)
                wonderflClass["capture_delay"](captureDelay);
            else
                wonderflClass["disable_capture"]();
        }
    }
    
    public static function createStarlingCaptureImage(starlingInstance:Starling=null):void
    {
        if (starlingInstance == null)
            starlingInstance = Starling.current;
        
        if (starlingInstance == null)
            throw new IllegalOperationError("Starling instance is missing");
        if (starlingInstance.context == null)
            throw new IllegalOperationError("Contex3D is missing");
        
        var captchaData:BitmapData = new BitmapData(465, 465, false);
        
        var support:RenderSupport = new RenderSupport();
        RenderSupport.clear(starlingInstance.stage.color, 1.0);
        support.setOrthographicProjection(0, 0, captchaData.width, captchaData.height);
        starlingInstance.stage.render(support, 1.0);
        support.finishQuadBatch();
        
        starlingInstance.context.drawToBitmapData(captchaData);
        
        var textField:Object = new (getDefinitionByName("flash.text::TextField"));
        textField.defaultTextFormat = new TextFormat("Arial", 10, 0xFFFFFF);
        textField.text = "This is captured image for winderfl preview.";
        textField.autoSize = TextFieldAutoSize.CENTER;
        textField.x = 465 - textField.width - 4;
        textField.y = 465 - textField.height - 4;
        var sprite:Object = new (getDefinitionByName("flash.display::Sprite"));
        sprite.graphics.beginFill(0x000000, 0.5);
        sprite.graphics.drawRoundRect(textField.x - 2, textField.y - 2, textField.width + 2, textField.height + 2, 6);
        sprite["addChild"](textField);
        captchaData["draw"](sprite);
        
        var captcha:Bitmap = new Bitmap(captchaData);
        starlingInstance.nativeStage.addChild(captcha);
        starlingInstance.nativeStage.addEventListener(MouseEvent.CLICK, nativeStage_clickHandler);
        
        function nativeStage_clickHandler(event:MouseEvent):void
        {
            starlingInstance.nativeStage.removeEventListener(MouseEvent.CLICK, nativeStage_clickHandler);
            starlingInstance.nativeStage.removeChild(captcha);
            captchaData.dispose();
        }
    }
}

Forked