Теперь мы готовы к следующему шагу: выделению методов из makeDrawCmds.
Начнем с самого первого case: FormatSVG.MOVE_TO_ABSOLUTE.
- копируем содержимое case до строки break.
- создаем метод createMoveToCommand
- вставляем скопированное в метод.
- задаем аргументы, одноименные с переменными, вызывающими ошибку.
Получаем такой метод:
Код AS3:
private function createMoveToCommand(firstP:Point, lastP:Point, svgCmds:Array, j:int) : void {
// moveTo point
firstP = lastP = new Point(Number(svgCmds[j]), Number(svgCmds[j + 1]));
drawingCommands.push(new FillCommand(fill.color, fill.alpha));
drawingCommands.push(new StyleCommand(stroke.width, stroke.color, stroke.alpha));
drawingCommands.push(new MoveCommand(firstP.clone()));
j += 2;
if (j < svgCmds.length && !isNaN(Number(svgCmds[j]))) {
do {
// if multiple points listed, add the rest as lineTo points
lastP = new Point(Number(svgCmds[j]), Number(svgCmds[j + 1]));
drawingCommands.push(new LineCommand(lastP.clone()));
firstP = lastP;
j += 2;
} while (j < svgCmds.length && !isNaN(Number(svgCmds[j])));
}
}
Тестируем, получаем ошибку, разбираемся в чем дело.
Видим, что в методе изменяется значение переменной j, которая в дальнейшем используется в коде. Добавляем возвращаемое значение:
Код AS3:
private function createMoveToCommand(firstP:Point, lastP:Point, svgCmds:Array, j:int) : int {
.........
return j;
}
И в месте вызова добавляем присвоение нового значения j:
Код AS3:
j = createMoveToCommand(firstP, lastP, svgCmds, j);
Тестируем, получаем ошибку.
Вот сейчас пишу и понятия не имею, что это за ошибка и откуда она взялась. Нет, конечно я мог бы вначале добиться результата и затем с видом умника достать рояль из кустов. Но ведь так не бывает в реальной жизни. Я вначале пишу что и как хочу сделать, затем пытаюсь это реализовать и пишу что получилось. Вот сейчас на непонятность нарвался, и буду рассказывать как я в таких случаях поступаю.
Еще раз проверил старый код: закомментировал вызов метода, раскомментировал код, протестировал, всё работает.
Возвращаем комментарии обратно и смотрим, что еще может сносить.
Вполне реально - переприсвоение firstP и lastP. Встречается в четырех строках метода. И, если первую строку мы в состоянии вынести за пределы метода, то остальные две не получится.
Попробуем решить проблему так:
- вынесем объявление точек из метод в класс, сделаем переменные приватными.
Код AS3:
private var firstP:Point;
private var lastP:Point;
private var lastC:Point;
- добавим в начало метода обнуление переменных
Код AS3:
firstP = lastP = lastC = null;
- удалим первые два аргумента в вызове метода и в методе.
Тестируем. Работает.
Становится понятна причина: в аргументах мы объявили точки, и присвоение новых значений переменным, объявленным в аргументах не давало требуемой замены одноименных переменных в методе makeDrawCmds.
Копируем вызов:
Код AS3:
j = createMoveToCommand(svgCmds, j);
переходим на case FormatSVG.LINE_TO_RELATIVE и вставляем. Переименовываем в createLineToRelativeCommand. После чего с помощью CTRL+1 создаем метод.
Копируем и комментируем дальнейший код до break. Переходим на новый метод и вставляем в него скопированный код. Заменяем return null на return j. Тестируем. Работает.
Аналогично двигаемся дальше. После каждого шага тестируем.
Первой остановкой на этом пути стало появление сubicBezier. Поиском по коду смотрим каким образом она применяется. В коде нет случаев, когда сubicBezier присваивается другой переменной. Попробуем объявить ее локальной переменной.
И не забываем изменить возвращаемое значение с null на j. Тестируем, всё ок. Дальше планируем в аналогичных случаях поступать также.
Если по ходу дела нарываемся на бесконечный цикл, значит попросту забыли заменить null на return j. Нарывался два раза.
После того, как закончили и протестировали, сносим закомментированные строки и ненужное более объявление переменной сubicBezier.
В итоге должен получиться вот такой метод:
Код AS3:
private function makeDrawCmds(svgCmds:Array):void {
var j:Number = 0;
var cmd:String;
firstP = lastP = lastC = null;
do {
cmd = svgCmds[j++];
switch (cmd) {
case FormatSVG.MOVE_TO_ABSOLUTE :
j = createMoveToCommand(svgCmds, j);
break;
case FormatSVG.LINE_TO_RELATIVE :
j = createLineToRelativeCommand(svgCmds, j);
break;
case FormatSVG.LINE_TO_ABSOLUTE :
j = createLineToCommand(svgCmds, j);
break;
case FormatSVG.HORIZONTAL_LINE_TO_RELATIVE :
j = createHorizontalLineToRelativeCommand(svgCmds, j);
break;
case FormatSVG.HORIZONTAL_LINE_TO_ABSOLUTE :
j = createHorizontalLineToCommand(svgCmds, j);
break;
case FormatSVG.VERTICAL_LINE_TO_RELATIVE :
j = createVerticalLineToRelativeCommand(svgCmds, j);
break;
case FormatSVG.VERTICAL_LINE_TO_ABSOLUTE :
j = createVerticalLineToCommand(svgCmds, j);
break;
case FormatSVG.QUADRATIC_CURVE_TO_RELATIVE :
j = createQuadraticCurveToRelativeCommand(svgCmds, j);
break;
case FormatSVG.QUADRATIC_CURVE_TO_ABSOLUTE :
j = createQuadraticCurveToCommand(svgCmds, j);
break;
case FormatSVG.CUBIC_CURVE_TO_RELATIVE :
j = createCubicCurveToRelativeCommand(svgCmds, j);
break;
case FormatSVG.CUBIC_CURVE_TO_ABSOLUTE :
j = createCubicCurveToCommand(svgCmds, j);
break;
case FormatSVG.CUBIC_SMOOTH_CURVE_TO_RELATIVE :
j = createCubicSmoothCurveToRelativeCommand(svgCmds, j);
break;
case FormatSVG.CUBIC_SMOOTH_CURVE_TO_ABSOLUTE:
j = createCubicSmoothCurveToCommand(svgCmds, j);
break;
case FormatSVG.CLOSEPATH_RELATIVE :
case FormatSVG.CLOSEPATH_ABSOLUTE :
j = createClosePathCommand(svgCmds, j);
break;
} // end switch
} while (j < svgCmds.length);
}
Не фонтан, конечно, но это уже кое-что: мы в состоянии увидеть логику метода.