FontLoader v. 2.1
FontLoader обновился до версии 2.1. По просьбам зарубежных товарищей, FontLoader теперь работает в среде AIR, а также добавился новый метод loadBytes, аналогичный одноименному методу класса Loader.
16 comments
16 Comments so far
Leave a reply
Скачал последний FontLoader. Спасибо огромное – пример выглядит очень достояно.
Только у меня возникла одна проблема:
- беру от демку и собираю пример (как из фла так и только из .as) – все работает, даже с моими файлами со шрифтами.
- беру свой класс, включаю в него FontLoader, копирую из демки кусок загрузки шрифта. все собираю. при запуске вываливает exception: “тип файла не соответствует содержимому”.
установлен на машине: FP 10.0 r22
flashdevelop, flex sdk 3.4, flash cs4
при сборке как под 9 так и под 10 – картина идентичная.
подозреваю, что проблема кроется в пресловутой секъюрности. а именно: у меня есть главный swf приложения, который загружает в себя другие с того же домена, достает из них классы и создает объекты из этих классов на форме приложения.
класс по словам адобовских статей импортируется в сендбокс главной флешки
context.applicationDomain = ApplicationDomain.currentDomain;
//new ApplicationDomain();//если делать так – ниче не работает – т.к. запрещает общатся классам друг с другом
loader.load(urequest,context);
потом загруженный класс загружает шрифты из отдельного файлика и применяет к своим строчкам внутри.
заранее благодарен за помощь
есть проблемы в работе при загрузке шрифта подгруженным классом.
Это давний баг в плеере, FontLoader тут непричем. Решить проблему можно, если FontLoader будет находится в основном домене приложения.
Так оно все и находится в основном домене.
стартовый layout.swf, runningstring.swf, шрифты: ru_georgia.swf ru_myslcct.swf – все лежать в одном домене.
Изначально загружается layout.swf,
потом, используя ClassLoader подгружается runningstring.swf. При этом ClassLoader выполняет
context.applicationDomain = ApplicationDomain.currentDomain;
loader.load(urequest,context);
У него есть событие окончания загрузки, в котором:
var runtimeClassRef:Class = rsLoader.getClass(“RunningString”);
loRunningStringContainer = new runtimeClassRef();
Внутри класса RunningString в конструкторе создается FontLoader.
При загрузке шрифта rsFontLoader.addEventListener(Event.COMPLETE, fontsLoaded);
rsFontLoader.load(new URLRequest(fntHost+fntName+”.swf”));
в функции fontsLoaded:
trace(“fonts Loaded”);
trace(Font.enumerateFonts());
и далее по тексту применение шрифта…
При этом exception возникает еще до trace.
То как плеер работает со шрифтами я уже понял
даже официальный запрос на адоб нашел за решением этой проблемы. То, что шрифты, которые по идее регистрируются в системе видны только в рамках класса, который выполнил Font.registerFont(FontToLoad); я уже тоже ощутил.
я просто пытаюсь понять в чем проблема и как ее решить.
заранее благодарен.
П.С. а как код вкладывать, чтоб он красиво выглядел? с раскраской и номерами строчек?
Тег <code>, ftf к сожалению не работает.
А можно собрать примерчик с косяком?
ок, соберу, выложу с линком
после длительных поисков, косяк нашелся…
протупил я
основная идея в следующем:
сервер при неправильном линке выдает стартовую страницу.
по итогу:
- при правильном линке все отлично
- при битом линке возникает эксепшин и мувик останавливается.
есть предложение:
добавить в класс FontLoader обработку эесепшинов подобного плана и свои события:
public static var FONTS_LOADED:String = “fontsLoaded”;
public static var IO_LOAD_ERROR:String = “ioLoadError”;
public static var SEC_LOAD_ERROR:String = “secLoadError”;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
private function completeHandler(e:Event):void {
dispatchEvent(new Event(ClassLoader.CLASS_LOADED));
}
private function ioErrorHandler(e:Event):void {
dispatchEvent(new Event(ClassLoader.IO_LOAD_ERROR));
}
private function securityErrorHandler(e:Event):void {
dispatchEvent(new Event(ClassLoader.SEC_LOAD_ERROR));
}
а в местах возможного возникновения эксепшнов добавить их поимку и утилизацию с выдаванием ивента.
таким образом была бы модель нормальной обработки подобных ситуаций
Эмм, вообще говоря, все стандартные события Loader-а FontLoader высылает, в метатегах это указано дополнительно.
ок, ситуация следующая:
при битом линке на файл сервер выдает стартовую страницу. и вот здесь начинается самое интересное:
1.если использовать iFontLoader.load(new URLRequest(fntHost + fntName + “.swf”), true);
IOErrorEvent.IO_ERROR не подымается, а загрузчик переходит к функции
private function analyze(bytes:ByteArray, delayed:Boolean = false):void {
и отдает ей загруженные байты.
2. функция analyze абсолютно не в курче, что там в этих байтах лежит и начинает их обрабатывать как совершенно нормальный файл.
3. внутри функции чозается от этих байтов SWFByteArray(bytes), в котором ризбираются заголовки и т.д., где оно и падает окончательно, т.к. в байтах лежит html, а далеко не swf.
4. в конструкторе SWFByteArray подымается иксепшн, который нигде не ловится и не обрабатывается и не превращается в ивент, что не позволяет его обработать далее и валит все приложение, которое попыталось подгрузить несуществующий шрифт.
что нужно сделать для решения проблемы:
1. добавляем в class SWFByteArray
private var goodSWF:Boolean = true;
public function get swfIsGood():Boolean {
return goodSWF;
}
2. в конструкторе находим и комментируем строчку
throw new ArgumentError(‘Error #2124: Loaded file is an unknown type.!!!!’);
вместо нее вставляем
goodSWF = false;
3. кусок this.readHeader(); заменяем на
try {
this.readHeader();
}catch (error:Error) {
goodSWF = false;
}
4. косок
data.endian = endian;
data.position = position;
меняем на
try{
data.endian = endian;
data.position = position;
}catch (error:Error) {
goodSWF = false;
}
это нужно сделать т.к. в особо тяжких случаях возниказ иксепшн попытки чтения за пределами файла
5. в функции readFrameRate() класса SWFByteArray
перед блоком if добавляем try {
послеблока if (всего) добавляем
}catch (error:Error) {
goodSWF = false;
}
6. в функции readHeader() класса SWFByteArray
перед
this._rect = this.readRect();
this.readFrameRate();
super.readShort(); // num of frames
добавляем try {
после
}catch (error:Error) {
goodSWF = false;
}
и теперь самое главное:
в функции analyze класса FontLoader:
1. тип переменной data меняем на SWFByteArray, получая:
var data:SWFByteArray = new SWFByteArray(bytes);
2. добавляем еще одну переменную
var tmpData:ByteArray;
3. дальше собственно идет обработка загруженных данных, чтобы все не падало там делаем следующее:
перед циклом while (data.bytesAvailable) { добавляем
if (data.swfIsGood) {
после окончания последнего блока if (this._fontCount) {
(собственно в самом конце функции)
добавляем
else {
super.dispatchEvent(new Event(IOErrorEvent.IO_ERROR));
}
4. в цикле for (o in fontData) { меняем
data = fontData[o] as ByteArray; на
tmpData = fontData[o] as ByteArray;
затем меняем
if (data) { на
if (tmpData) {
затем меняем
tempData.writeBytes(data); на
tempData.writeBytes(tmpData);
ВСЕ!
!теперь мы можем нормально отреагировать на загрузку неправильного файла. и ничего в иксепшн не упадет.
собственно сам файлик с изменениями
http://avaks.kiev.ua/max/fontloader.as
В общем, суть понятна. Добавлю отправку события IO_ERROR при некорректном формате загруженных данных в ближайшее время.
trackback:
http://flexpletives.blogspot.com/2009/11/flex-embedded-fonts-images-and-compile.html
Скажите пожалуста эта прога может витянуть встроеный шрифт из swf-ки. Если нет, то не подскажите случайно чем это можна сделать.
Это не программа. И что значит «вытянуть»?
Витянуть значит экспортировать. Говарю сразу такие экспортери как Sothnic SWF Decompiler экспортируют шрифт только в еще одну swf, а толку от этого никакова. Мне нужен шрифт именно в ttf формате или ином юзабельном формате.
Извиняюсь про Fontloader я невнимательно прочел, как я понимаю это какаето библиотека класов что ли.
FontLoader, в общем, вам не подойдет.