TextField auto format error on HTML5?

Hi, I’m using a TextField object with the autosize property set to LEFT (as the text align). I’m getting some strange results while running it on HTML5 target. The width I get from the TextField after setting the text is smaller than the actual text, like the image below. There, I put a transparent overlay above the text with the width I get by reading the TextField width property for comparison. This is an embed font.

I also managed to retrieve the metrics for the line and the results are the same: the text width+margins give me the same results.

Am I doing something wrong? I need to get the object correct size after setting the text to apply some transformations.

Oh, and if I don’t use an embed font it works as expected, but this is not an option for me.

Can you show our code?

It is, in fact very simple:

// creating the text field
this._text = new TextField();
this._text.selectable = false;
this._format = new TextFormat();
this._format.align = TextFormatAlign.LEFT;
this._format.font = 'font name';
this._format.size = font size;
this._text.defaultTextFormat = this._format;
this._text.autoSize = TextFieldAutoSize.LEFT;
this._text.wordWrap = false;
this._text.multiline = false;
this._text.embedFonts = true;
this._text.cacheAsBitmap = true;
this.addChild(this._text);

// setting the text
var txt:String = 'My text here';
this._text.text = txt;

// getting text field size
trace (this._text.width);

My issue is that this._text.width is in fact lower than it should be (even considering it is being displayed correctly). On my picture above, the tranaparent box width is set to the value I get: it corresponds to the with I get from the below text.

I run example of our code and all works correctly.
My settings :
haxe 4.2.5
openfl 9.3.2
lime 8.1.1
My by You are using bad file of font or wrong type (svg or eot). (In may case it was *.ttf)
Send my your project on mail. [email protected]
(System Win 10, Chrome)

The font must be woff/woff2 since it is running on HTML5. On other targets (and without embed fonts) it works as expected.

I’m put *.ttf in Assets folder and haxe converted It to woff/eot/svg/ttf in bin.

I need to load the woff font at runtime on the browser, not while building. Probably the isso with the size comes from there.

O, sorry. So I need to see your code for loading fonts. Do you change CSS in runtime after load new font?

No, in fact I use this class to enable the user to upload the font at runtime:

package com.tilbuci.font;

/** OPENFL **/
import openfl.text.Font;
#if (js && html5)
	import js.Browser;
	import js.html.FontFace;
    import js.lib.ArrayBuffer;
    import js.lib.DataView;
#end

/** TILBUCI **/
import com.tilbuci.data.DataLoader;
import com.tilbuci.data.Global;

/**
    Embeds a font file at runtime.
    (many thanks to sanline for HTML5 font loading - https://github.com/scanline)
**/
class EmbedFont {

    /**
        loaded font name
    **/
    public var fname(get, null):String;
    private var _fname:String = '';
    private function get_fname():String { return (this._fname); }

    /**
        method to call after font load
    **/
    private var _ac:Dynamic;

    /**
        Constructor.
        @param  path    the path to the font (ttf, otf or woff2 file)
        @param  name    the font family name
        @param  ac  a method to call after font loading (receives two parameters: Bool and EmbedFont)
    **/
    public function new(path:String, name:String, ac:Dynamic = null) {
        // adjust path
        #if (js && html5)
            path = StringTools.replace(path, '.ttf', '.woff2');
            path = StringTools.replace(path, '.otf', '.woff2');
        #else
            path = StringTools.replace(path, '.woff2', '.ttf');
            path = StringTools.replace(path, '.woff', '.ttf');
        #end
        // load file
        this._fname = name;
        this._ac = ac;
        new DataLoader(true, path, 'GET', null, DataLoader.MODEBINARY, onLoad);
    }

    /**
        File loading ends.
        @param  ok  load successful?
        @param  ld  the loader reference
    **/
    private function onLoad(ok:Bool, ld:DataLoader):Void {
        if (ok) {
            // load the font file
            #if (js && html5)
                // browser
                var buffer:ArrayBuffer = new ArrayBuffer(ld.binary.length);
                var view:DataView = new DataView(buffer, 0, buffer.byteLength);
                for (i in 0...ld.binary.length) view.setUint8(i, ld.binary[i]);
                var face:FontFace = new FontFace(this._fname, buffer);
                Browser.document.fonts.add(face);
                face.load().then(function(_){
                    var future:lime.app.Future<Font> = Font.loadFromName(this._fname);
                    future.onComplete(function(font){
                        // warn listeners about load ok
                        Global.fonts.push(this._fname);
                        if (this._ac != null) this._ac(true, this);
                        this._ac = null;
                    });
                });
            #elseif air
                // no support for AIR dynamic font loading
                this._fname = '';
                if (this._ac = null) this._ac(false, this);
                this._ac = null;
            #else
                // binary font load
                var fnt:Font = Font.fromBytes(ld.binary);
                Font.registerFont(fnt);
                this._fname = fnt.fontName;
                // warn listeners about load ok
                Global.fonts.push(this._fname);
                if (this._ac != null) this._ac(true, this);
                this._ac = null;
            #end
        } else {
            // error loading the font file
            this._fname = '';
            if (this._ac = null) this._ac(false, this);
            this._ac = null;
        }
    }

}

/**
    Information about an embed font.
**/
typedef FontInfo = {
    var name:String;    // name
    var file:String;    // file
}

By measuring line metrics char by char when I set a text I realized that I get a slightly lower value for width that it should be, so when I add up all of them, the result gets worse for bigger lines.

Another thing I noticed is that if I try to draw the textfield into a bitmapdata, it won’t work as expected as blurred squares appear instead of the text itself. I was trying to use this as an alternate way to measure the line width.

About CSS. In head of index.html you can find:

<style>
	html,body { margin: 0; padding: 0; height: 100%; overflow: hidden; }
	#openfl-content { background: #000000; width: 100%; height: 100%; }
	@font-face {
		font-family: 'Bebas Neue Bold Regular';
		src: url('assets/BebasNeue.eot?#iefix') format('embedded-opentype'),
		url('assets/BebasNeue.woff') format('woff'),
		url('assets/BebasNeue.ttf') format('truetype'),
		url('assets/BebasNeue.svg#Bebas%20Neue%20Bold%20Regular') format('svg');
		font-weight: normal;
		font-style: normal;
	}

</style>

If you didn’t add your font parameters to this - font will be wrong drawing.
And maybe need to to load not woff2, but just woff.

I see. I was in fact expecting something like that. Since I’m unable to know what fonts will be used beforehand, I managed to calculate a width by getting metrics for individual chars on my string and apply it to the TextField manually.

1 Like