среда, февраля 11, 2009

Как отображать шрифт без сглаживания (bitmap text) во Flex

Flex имеет некоторые ограничения в работе с внедренными шрифтами.
Если во Flash CS, мы можем просто так взять, да и указать тип рендеринга шрифтов "Bitmap text" (без антиалиасинга) и иметь полноценное отображение текста с неполной прозрачностью, наклоном и т.п., то во Flex мы можем только управлять параметрами сглаживания шрифта, или не внедрять шрифт совсем (тогда о прозрачности не может быть и речи).

Но если мне, всё-таки, нужен именно несглаженный полупрозрачный шрифт?
Проблема решается, как и многие другие во Flex, через "одно" место.
В лайфдоках, находим такую статейку: Embedding fonts from SWF files. Здесь рассказывается вообще о внедрении шрифта с использованием Flash CS. Пользуясь таким методом, можно внедрить любой шрифт, поддерживаемый Flash CS.

Однако, здесь не сказано ни слова про внедрение шрифта Bitmap text (без антиалиасинга). И вообще, в документации Flex, про это как-то совсем ничего нет. А ведь это странно и непонятно - Flex-приложения как раз направлены на отображение данных, а всем известно, что данные отображаются лучше несглаженным шрифтом. К чему тогда все эти эффекты с фэйдом и прочими трансформациями, если невнедренный шрифт их не отображает.

Нам на помощь приходит статья всеобщего друга всех флэшеров GSkinnerа Bitmap Fonts in Flex (via Flash). Правда, в ней всё несколько усложнено, но, подозреваю, что это из-за того, что писалось это для Flex 2. Ну а мы то уже на Flex 3, поэтому всё немного проще. Идея в том, что шрифт, внедренный как Bitmap text, меняет название в некую неприглядную форму, типа "Tahoma_12pt_st".

Итак, к чему мы пришли (опишу вкратце мои действия):

1. Создаем SWF-файл fonts.swf (можно любой другой). Версия Flash 9, ActionScript 3.0. Во всех статьях создается файл версии Flash 8, но, почему-то, у меня такой файл Flex не подцеплял/ - не может оттранскодить.

2. Создаем текстовые Dynamic-поля, в каждое из которых добавляем хотя-бы один символ нужного нам начертания. Соответственно, если все начертания нам нужны, то будет 4 текстовых поля: Normal, Bold, Italic, Bold Italic.

3. Устанавливаем размер шрифта, который мы будем использовать в Flex-приложении. Дело в том, что в приложении, корректно может быть отображен только один размер внедренного шрифта - тот который мы сейчас укажем. Если указать другой размер, шрифт некрасиво размажется. Я указываю 12.

4. Указываем в Embed... диапазоны, которые нам надо внедрить.
Кстати, можно пойти другим путем и, вместо текстовых полей, создать в библиотеке 4 символа-шрифта (New font...) и всё будет точно так же, за исключением того, что шрифт внедрится весь - без ограничений, что плохо для объема.

5. Компилируем и добавляем в папку проекта.

6. В CSS файле проекта (я отвел для этого специальный файл fonts.css) указываем следующий код:
/* CSS file */
@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: normal;
fontWeight: normal;
}

@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: normal;
fontWeight: bold;
}

@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: italic;
fontWeight: normal;
}

@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: italic;
fontWeight: bold;
}


7. Теперь, мы можем в любом стиле указать:
Text.Regular {
fontFamily: "Tahoma_12pt_st";
fontSize:12px;
fontAntiAliasType:normal;
}

Важно указать параметр fontAntiAliasType:normal. Если этого не сделать, шрифт в некоторых случаях будет отображаться размыто, а если это выделяемый текст - при его выделении будет твориться что-то невообразимое.
Ну и конечно, не забыть уточнить размер шрифта - иначе всё поедет.

8. Ну и собственно, применяем этот стиль к компоненту:
<mx:Text
width="100%"
styleName="Regular"
>
<mx:htmlText><![CDATA[<b>Максимальный</b> размер загружаемого файла — 3 Мб. Допустимые форматы: GIF, JPG, BMP, TIFF, PNG.]]>></mx:htmlText>
</mx:Text>

Если нам понадобится шрифт другого размера - уж не поленитесь, повторите всё со второго пункта - так уж положено.

* * *

Да, забыл добавить про то, что здорово помогает в разборках со шрифтами такой кусочек кода (взят из статьи):
var fontList:Array = Font.enumerateFonts(false);
for (var i:uint=0; i<fontList.length; i++) {
trace("font: "+fontList[i].fontName);
}

5 комментариев:

foreground комментирует...

Можешь еще сюда глянуть, на всякий http://www.derschmale.com/2009/01/23/stubborn-and-unexpected-embedded-font-weight-behaviour/
Можешь описать, что получается в декомпиленом виде из fonts.swf ?

Unknown комментирует...

Да, интересно. Кстати, про сглаживание шрифтов, вроде бы так и сказано в доках - во Flash CS и Flex происходит по-разному. Быть может, отчасти, причина в этом.

С декомпилером не смогу помочь - нет под рукой нормального декомпилера. Nemo440 ничего не показывает, в дампе только это:

Size: {0, 0, 11000, 8000}
Frame rate: 12
Frame count 1

[Tags]
FileAttributes: 4 bytes
SetBackgroundColor: 3 bytes
75 (invalid): 57880 bytes
73 (invalid): 5963 bytes
undefined: 61 bytes
DefineEditText: 167 bytes
PlaceObject2: 8 bytes
75 (invalid): 45205 bytes
73 (invalid): 5963 bytes
undefined: 66 bytes
DefineEditText: 172 bytes
PlaceObject2: 9 bytes
75 (invalid): 74385 bytes
73 (invalid): 5963 bytes
undefined: 61 bytes
DefineEditText: 175 bytes
PlaceObject2: 10 bytes
75 (invalid): 59507 bytes
73 (invalid): 5963 bytes
undefined: 61 bytes
DefineEditText: 187 bytes
PlaceObject2: 10 bytes
ShowFrame: 0 bytes
End: 0 bytes

foreground комментирует...

Могу дать asv .. пиши на почту >)
Или скинь мне свой файлик, плиз. Щас просто не до флэша - PHP дерево пишу.

Unknown комментирует...

Ну ты хоть намекни, куда скинуть :)

Unknown комментирует...

Декомпильнул - всё как и должно быть - один фрейм, 4 шрифта, 4 текстовых поля.