19 августа 2009, 13:11
Темы: flash, actionscript, flex
Введение
Закончился период отпусков и авральных возвращений к работе. Акклиматизация пройдена успешно, и настала пора возобновить ведение блога.
Задача
Возможно, это уже давно всем известно, но тем не менее, мне бы хотелось об этом написать. В ActionScript существует как минимум два способа обращаться с цветом. Если мы работаем с BitmapData, то используется ARGB, то есть прозрачность и цвет задаются одним числом типа uint. Кстати, 0xffffffff непрозрачный белый цвет максимальное число этого типа.
Когда же мы работаем с, например, Graphics, то цвет и прозрачность задаются отдельно друг от друга. Причём прозрачность в диапазоне от 0 до 1. Хотелось бы быстро раскладывать ARGB на части и снова собирать.
Решение
В одну сторону:
var argb:uint = 0xccabcdef;
var a:Number = (argb >>> 24) / 255.0;
var rgb:uint = argb & 0xffffff;
Аналогично, кстати, можно выделить и каналы по отдельности:
var red:uint =(argb & 0xff0000) >>> 16;
var green:uint =(argb & 0xff00) >>> 8;
var blue:uint =(argb & 0xff);
Оператор >>> вместо >> используется чтобы избежать проблем со знаком.
В обратную сторону, соответственно:
argb = (uint(a*255) << 24) | rgb;
argb = (uint(a*255) << 24) | (red << 16) | (green << 8) | blue;
Всё совершенно логично. Чтобы разделить, используется бинарное и, а чтобы объединить бинарное или.
Для возобновления трансляции, как мне кажется, этого материала достаточно.
16 мая 2009, 00:10
Темы: actionscript, regexp, flex, flash
В последнее время моя работа в текущем проекте заключается в отладке, оптимизации и отлове багов. Поэтому в самой работе практически не встречается того, о чём можно было бы здесь написать. Но на помощь пришла гугл-группа ruFlash и комьюнити молодых программистов. :)
Задача
Один из участников попросил составить выражение для удаления из текста ссылок с определенным текстом внутри целиком. Например, в выражении:
var str:String = '<a href="somelink"><i>some text</i></a> ';
str += 'More text! ';
str += '<a href="anotherlink"><b>remove me</b></a> ';
str += '<a href="yetanotherlink"><s>another text</s></a>';
Нужно удалить целиком ссылку, содержащую фразу remove me.
Понятно, что первое приходящее в голову выражение /<a.+?remove me.*?<\/a>/ захватит две первые ссылки. И «жадность» не поможет, т.к. поиск осуществляется по порядку, и, найдя первый <a, выражение не остановится до самого remove me.
Решение номер один
Поскольку к концу недели отладки и пересмотра одного и того же кода голова моя не была готова что-то изобретать, я последовал пути, предлагавшемуся одним из ответивших, слегка его доделав:
var re0:RegExp = /<a[^>]+>[^a]*remove me.*?<\/a>/g;
trace(str.replace(re0, "!removed!"));
Недостаток его очевиден. Хотя для приведенного примера он работает, но всё-таки, может и отказать, если встретит a между > и remove me. Например:
str += '<a href="anotherlink">eh! ah? <b>remove me</b></a> ';
Решение номер два (рекурсивное)
Поскольку к этому моменту мозг ещё не расслабился окончательно и не готов был отказаться от выбранного способа думать о задаче, второе решение, пришедшее сразу за первым, было значительно сложнее.
Оно использовало возможность подсовывать функцию в качестве аргумента. Вот оно:
var re1:RegExp = /<a(.+?remove me.*?<\/a>)/g;
var replacer1:Function = function():String {
var s:String = arguments[1].toString();
if (s.indexOf("<a") > 0) {
return "<a" + s.replace(re1, replacer1);
} else {
return "!removed!";
}
}
trace(str.replace(re1, replacer1));
Здесь речь идёт о том, чтобы в группе (см. скобки), следующей после <a проверять наличие ещё одного <a. И в случае его наличия запускать ту же процедуру замены, но уже на группе.
Довольный собой, я запостил своё решение в ruFlash и поехал домой. По дороге домой мозг окончательно расслабился, и я смог увидеть задачу в отрыве от способа думать, который я выбрал изначально. И мне пришло
Решение номер три
Зачем городить рекурсию, когда можно просто перебирать все ссылки и заменять (удалять) только те, что нужно?
var re2:RegExp = /<a[^>]+>(.+?)<\/a>/g;
var replacer2:Function = function():String {
var s:String = arguments[1].toString();
if (s.indexOf("remove me") > 0) {
return "!removed!";
} else {
return arguments[0];
}
}
trace(str.replace(re2, replacer2));
Это ли не чудесно?
Выводы
- Решайте задачи.
- Решив (или не решив), записывайте то, что получилось, покажите кому-нибудь. Это позволит выкинуть решение из головы.
- Если есть решение лучше, то оно придет на освободившееся место.
07 мая 2009, 23:45
Темы: actionscript, regexp, flex
Введение
Я снова вернулся к работе над флэшовым проектом. Поэтому немного об ActionScript. Описанная здесь задача сейчас мне не кажется такой сложной, какой она казалась, когда я впервые с ней столкнулся. Но тем не менее.
Задача
Имеется строка, содержащая разметку для замены её составляющих. Одна из разметок: #[some_url] должна быть заменена содержимым этого самого some_url. Для замены с помощью регулярных выражений в ActionScript 3 существует функция String#replace. Но всё, что связано с загрузкой из внешних источников, создает асинхронность. А любая попытка остановить код, сделать паузу, приводит к огромной потере производительности и ошибкам, которые генерирует плеер, когда долго не может завершить вызов. «Как быть?» спросит меня пытливый читатель.
Решение
Решение состоит в том, чтобы заменять все вхождения ключевого выражения по-очереди и когда всё заменено, создавать событие.
Приведу основную часть. Файл AsyncStringReplaceExample.as
package {
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class AsyncStringReplaceExample {
public static const RE_URL:RegExp = /#\[([^\]]+)\]/g;
private var _str:String;
private var _currentExpr:String;
private var _ldr:URLLoader;
private var _loaded:Boolean;
public function AsyncStringReplaceExample(str:String) {
_str = str;
_ldr = new URLLoader();
_ldr.addEventListener(Event.COMPLETE, ldrCompleteHandler);
_loaded = false;
}
public function replace():Boolean {
_loaded = true;
_str = _str.replace(RE_URL, replaceURL);
return _loaded;
}
public function get string():String {
return _str;
}
private function replaceURL():String {
if (!_currentExpr) {
_loaded = false;
_currentExpr = arguments[0];
_ldr.load(new URLRequest(arguments[1]));
}
return arguments[0];
}
private function ldrCompleteHandler(evt:Event):void {
_str = _str.replace(_currentExpr, evt.target.data);
_currentExpr = null;
if (replace()) {
trace(_str); // здесь желанное событие
}
}
}
}
Теперь остается только использовать написанное нами богатство:
var str:String = "строка для примера\n";
str += "добавим: #[http://some.url/file.txt] или";
str += "ещё добавим: #[http://another.url/another/file.txt]! хватит?";
var asyncString:AsyncStringReplaceExample = new AsyncStringReplaceExample(str);
if (asyncString.replace()) {
trace(asyncString.string); //не нужно ничего заменять
} else {
asyncString.addEventListener(......)
}
...
// внутри обрабочика событий
trace(asyncString.string);
Выводы
Сразу видно, что последнее время я забросил ActionScript и занимался больше Ruby. Потому что подсветка синтаксиса в Ruby красивее. Но это не страшно. :)
Упражнения
Мне было бы интересно написать функцию, которая могла бы работать сколь угодно долго. Например, рекурсивную, или долгую по любой другой причине. Но ActionScript принудительно завершает процессы, которые долго не подают признаков жизни.
Как быть?
11 марта 2009, 00:27
Темы: ruby, rails, actionscript, xml, flex, ide
Сегодня я хочу поделиться своими ресурсами для разработки. В частности, хочу рассказать про IDE. Основную часть рабочего времени я провожу под кубунту. После долгих метаний и проб я остановился на GEdit, как на универсальном средстве разработки.
Установка
Для работы нам понадобятся плагины для GEdit. Они содержат основной набор вкусностей: code snippets, file browser pane, terminal pane и тому подобное. Поэтому устанавливаем:
sudo apt-get install gedit gedit-plugins
Дополнительные файлы, которые понадобятся, находятся в теле поста.
Ruby и Ruby on Rails
Подсветка синтаксиса и сниппеты для ruby уже поставляются из коробки. Единственное, если вы откроете файл со спецификацией подсветки синтаксиса для ruby, то обнаружите там пометку FIXME, касающуюся подсветки интерполяции внутри строки. Это связано с особенностями обработки правил подсветки самим редактором. Эти особенности удалось обойти, присвоив этому правилу измененный цвет фона.
Подсветку синтаксиса Ruby положить в /usr/share/gtksourceview-2.0/language-specs/
Для корректной работы подсветки, потребуется определить стиль для ruby:interpolation. Я использую тему darkmate, в которой определил необходимые дополнительные цвета на свой вкус. Положить следует в /usr/share/gtksourceview-2.0/styles/, а затем выбрать эту тему в установках редактора.
Язык для описания подсветки синтаксиса достаточно прост. Кроме всего прочего он позволяет ссылаться из правил одного языка на правила другого. Что, собственно, нам и понадобится для подсветки языка темплейтов erb. Ведь erb это по сути html со вставками ruby. Теперь, когда у нас есть оба описания, берём описание для html и вставляем в него ссылку на ruby.
Так же следует определить mime-type для erb. Правила подсветки erb предполагают, что в системе определен mime-type text/erb. В четвертом KDE описать свои типы файлов можно в System->System Settings->Advanced->File Associacions
Мой файл использует цвет erb:background, который так же определен в файле с темой.
Подсмотрев code snippets для других языков, а так же в процессе использования, вполне можно самостоятельно написать пару-тройку полезных выражений.
Flash и Flex
Для работы с flex нам понадобится flex sdk, а так же отладочная версия standalone flash player. Я уж не буду вдаваться в подробности, как там написать компилирующий или запускающий скрипт. А выложу сразу подсветку синтаксиса.
Если определить тип (mime-type) text/x-shockwave, то можно использовать правила для подсветки ActionScript3. Которые следует положить по адресу, указаному выше.
Так же, используя описанное выше знание, легко создать описание подсветки синтаксиса mxml, зная, что это xml, со вставками actionscript. Для корректной работы следует определить mime-type text/mxml.
Заключение
Все файлы, выложенные в посте, можно смело изменять под свои нужды. Если вы используете GEdit, чтобы писать под рельсы или флекс. Я не стал выкладывать сниппеты, потому что на мой взгляд, это вопрос личной привычки. А подсветку синтаксиса, конечно, можно улучшать.