Поиск фактической высоты текста AS3

Как получить фактическую высоту текста в AS3 TextField? Похоже, TextField.textHeight сообщает некоторое фиксированное значение, которое не зависит от содержимого TextField.

Ниже приведен пример кода ниже:

text=o p g y d j
textWidth=120.8
textHeight=**96**

text=o
textWidth=15
textHeight=**96**

text=oW
textWidth=43.3
textHeight=**96**

Очевидно, высота должна быть разной для "o" и "p" и т.д.

Код AS3:

import flash.text.TextField;

        var format : TextFormat = new TextFormat();
        format.font = "Times New Roman";
        format.size = 30;
        format.align = TextFormatAlign.CENTER;


        var textField1 : TextField = new TextField();       
        textField1.defaultTextFormat = format;      

        textField1.selectable = false;              
        textField1.sharpness = 0;   
        textField1.embedFonts = true;   
        textField1.multiline = false;

        textField1.height = 50;
        textField1.width = 200;
        textField1.x = 10;
        textField1.y = 10;

        addChild(textField1);

        textField1.text = "o p g y d j";    
        trace("text=" + textField1.text);
        trace("textWidth=" + textField1.textWidth);
        trace("textHeight=" + textField1.textHeight);       

        textField1.text = "o";      
        trace("\ntext=" + textField1.text);
        trace("textWidth=" + textField1.textWidth);
        trace("textHeight=" + textField1.textHeight);   

        textField1.text = "oW";     
        trace("\ntext=" + textField1.text);
        trace("textWidth=" + textField1.textWidth);
        trace("textHeight=" + textField1.textHeight);       

        stop();

Я думаю, TextField.textHeight не является правильной переменной, но что я должен использовать вместо этого?

Ответ 1

Марк Фокс прав, что textHeight не представляет фактическую высоту текста - и что классический TextField во Flash не имеет никакой поддержки для получения фактической высоты пикселя визуализированного текста. То, что textHeight представляет собой высоту линии - это ее восхождение (высота шрифта выше базовой линии), спуск (высота шрифта ниже базовой линии) и ведущий (пробел между линиями) в сочетании. Как подразумевается, высота постоянна, основываясь на восхождении и спуске шрифта, а не на фактическом тексте. (Принимая это во внимание, см. Adobe обзор условий здесь - и обратите внимание, что TextLineMetrics вам тоже не поможет).

"Новый" Flash Text Engine (flash.text.engine) включает в себя свойства, позволяющие получить фактическую высоту текста, отображаемого с использованием этой технологии (например, TextLine.totalHeight), но затем мы попадаем в низкоуровневый рендеринг текста. Если вам нужно использовать "классический" TextField s, это не поможет вам в любом случае измерить текст, поскольку Flash Text Engine имеет свой собственный рендерер, который не обязательно отображает текст с одинаковой высотой и шириной, как "классический".

Вместо этого вы можете отредактировать TextField до BitmapData, затем измерить границы текста:

// Create a completely transparent BitmapData:
var bmd:BitmapData = new BitmapData(
                            textfield.width, 
                            textfield.height, 
                            true,
                            0x00ffffff);

// Note that some cases may require you to render a Sprite/MovieClip
// CONTAINING the TextField for anything to get drawn.
// For example, AntiAliasType.ADVANCED (antialias for readability) is known to 
// not be renderable in some cases - other settings may cause nothing to be
// rendered too. In that case, simply wrap add the TextField as a child of an 
// otherwise empty Sprite/MovieClip, and pass that to draw() instead:
bmd.draw(textfield);

// This gets the bounds of pixels that are not completely transparent.
// Param 1: mask  = specifies which color components to check (0xAARRGGBB)
// Param 2: color = is the color to check for.
// Param 3: findColor = whether to bound pixels OF the specified color (true),
//                      or NOT OF the specified color (false)
//
// In this case, we're interested in:
// 1: the alpha channel (0xff000000)
// 2: being 00 (0x00......)
// 3: and want the bounding box of pixels that DON'T meet that criterium (false)
var rect:Rectangle = bmd.getColorBoundsRect(0xff000000, 0x00000000, false);

// Do remember to dispose BitmapData when done with it:
bmd.dispose();

trace("text height = " + rect.height);
trace("text width = " + rect.width);

Примечание по точности

Это может быть совершенно неактуально, в зависимости от того, что вы собираетесь использовать для этого, но стоит иметь в виду:

Этот метод, очевидно, всегда будет возвращать результат в целые пиксели - фактический рендеринг глифов, однако, использует субпиксели.

Другими словами, если вы добавите результаты измерения ширины "V" и "o", а затем сравните их с результатом "Vo", они могут не совпадать. Вы можете получить "40 + 35 = 74". Игнорирование этого кернинга и т.д. Может сблизить буквы друг с другом, рендеринг каждой буквы (размещение, сглаживание и т.д.) Также может быть различным, в зависимости от его контекста.

Ответ 2

В вашем вопросе подчеркивается наследие слабой семантики в типовых API-интерфейсах Flash.

Свойство textHeight представляет относительный размер шрифта в пикселях, оно не учитывает пиксельное представление конкретных глифов (отдельных форм букв) в TextField.

Насколько я знаю, нет прямого программного способа измерения глифа с помощью Flash. Однако вы можете растроить текстовое поле и использовать getPixel для угадывания:

var tf:TextField = …your textfield…
var wide:int = tf.width;
var tall:int = tf.height;
var bmpd:BitmapData = new BitmapData(wide, tall, true,0xFFFFFFFF);
bmpd.draw( tf );
var totalPixels:int = wide * tall;
var index:int = totalPixels + 1;
var useIndex:int;
var xPixel:int;
var yPixel:int;
while (--index > 0) {
    useIndex = index - 1;
    xPixel = useIndex % wide;
    yPixel = int(useIndex / wide);
    var pixelColor:uint = bmpd.getPixel(xPixel, yPixel);
    // write some logic to find the y extremes where the pixelColor values are not white (or whatever background color specified when you created the BitmapData)
}

Ответ 3

Вы можете сделать это с помощью "textHeight";

// Create TextField
var tf:TextField = new TextField();
tf.wordWrap = true;
tf.multiline = true;
tf.selectable = false;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.autoSize = TextFieldAutoSize.LEFT; // It should not be "=TextFieldAutoSize.NONE;"
tf.embedFonts = true;
tf.text = "Your text here";
this.addChild(tf); 

trace(tf.textHeight);

Надеюсь, что это поможет