LineDrawingTest2
package
{
import flash.display.*;
import flash.events.Event;
import flash.text.*;
import flash.utils.*;
public class LineDrawingTest2 extends Sprite {
private var _BMD:BitmapData;
private var _Logger:TextField = new TextField();
private const NUM_LINES_TO_DRAW:int = 30000;
private var _Result:Bitmap = new Bitmap();
private var _SpiralData:Vector.<Vector.<Number>>;
private var _TestSequence:Array;
public function LineDrawingTest2() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
_Logger.autoSize = TextFieldAutoSize.LEFT;
addChild(_Logger);
_BMD = new BitmapData(1000, 1000, false, 0xffffff);
addChild(_Result);
_Result.x = 300;
//Generate the data arrays...
_SpiralData = _GenerateSpiral(NUM_LINES_TO_DRAW, 2, 500); // (30000, 2, 500) matches original LineDrawingTest
_TestSequence = [
[_TestEFLA, ["Spiral - EFLA: ", _SpiralData, ]],
[_TestLineTo, ["Spiral - lineTo(LOW): ", StageQuality.LOW, _SpiralData]],
[_TestLineTo, ["Spiral - lineTo(MEDIUM): ", StageQuality.MEDIUM, _SpiralData]],
[_TestLineTo, ["Spiral - lineTo(HIGH): ", StageQuality.HIGH, _SpiralData]],
[_TestLineTo, ["Spiral - lineTo(BEST): ", StageQuality.BEST, _SpiralData]],
[_TestDrawPath, ["Spiral - drawPath(MEDIUM): ", StageQuality.MEDIUM, _SpiralData]],
[_TestDrawPath, ["Spiral - drawPath(HIGH): ", StageQuality.HIGH, _SpiralData]],
[_TestDrawPath, ["Spiral - drawPath(BEST): ", StageQuality.BEST, _SpiralData]],
[_TestDrawPath, ["Spiral - drawPath(LOW): ", StageQuality.LOW, _SpiralData]],
];
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void {
var curTest:Array;
var func:Function;
var funcArgs:Array;
curTest = _TestSequence.shift();
if(_TestSequence.length == 0) {
stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
func = curTest[0] as Function;
funcArgs = curTest[1] as Array;
func.apply(this, funcArgs);
}
private function _GenerateSpiral(NumLines:uint, dv:Number, Size:uint):Vector.<Vector.<Number>> {
// returns two Number vectors, the x array and y array
var numOrbits:uint = Size / 4;
var linesDrawn:uint = 0;
var xData:Vector.<Number> = new Vector.<Number>();
var yData:Vector.<Number> = new Vector.<Number>();
var dx:uint = 0;
var dy:uint = 0;
var i:uint;
while(linesDrawn < NumLines) {
dx = dy = 0;
for(i = 0; i < numOrbits; ++i) {
//top left....
xData.push(dx);
yData.push(dy);
//top right...
xData.push(Size - dx);
yData.push(dy);
//bottom right...
xData.push(Size - dx);
yData.push(Size - dy);
// bottom left...
dx += 2;
xData.push(dx);
yData.push(Size - dy);
//set up top left again...
dy += 2;
//exit check...
linesDrawn += 4;
if (linesDrawn >= NumLines) {
break;
}
}
}
var ret:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
ret.push(xData);
ret.push(yData);
return ret;
}
private function _TestEFLA(LogMsg:String, Data:Vector.<Vector.<Number>>):void {
var startTime_ms:uint;
var numPts:uint = Data[0].length;
var i:uint;
var bmd:BitmapData = new BitmapData(1000, 1000, false, 0xffffff);
var xData:Vector.<Number> = Data[0];
var yData:Vector.<Number> = Data[1];
var lineColor:uint = 0x0000ff;
startTime_ms = getTimer();
for(i = 1; i < numPts; ++i) {
EFLA(xData[i - 1], yData[i - 1], xData[i], yData[i], lineColor, bmd);
}
log(LogMsg + (getTimer() - startTime_ms + "ms"));
_Result.bitmapData = bmd;
}
private function _TestLineTo(LogMsg:String, StageQuality:String, Data:Vector.<Vector.<Number>>):void {
var startTime_ms:uint;
var numPts:uint = Data[0].length;
var i:uint;
var bmd:BitmapData = new BitmapData(1000, 1000, false, 0xffffff);
var xData:Vector.<Number> = Data[0];
var yData:Vector.<Number> = Data[1];
var lineColor:uint = 0x00ff00;
var shape:Shape = new Shape();
var graphics:Graphics = shape.graphics;
stage.quality = StageQuality;
graphics.lineStyle(0, lineColor, 1);
graphics.moveTo(xData[0], yData[0]);
for(i = 1; i < numPts; ++i) {
graphics.lineTo(xData[i], yData[i]);
}
startTime_ms = getTimer();
bmd.draw(shape);
log(LogMsg + (getTimer() - startTime_ms) + " ms");
_Result.bitmapData = bmd;
}
private function _TestDrawPath(LogMsg:String, StageQuality:String, Data:Vector.<Vector.<Number>>):void {
var startTime_ms:uint;
var numPts:uint = Data[0].length;
var i:uint;
var bmd:BitmapData = new BitmapData(1000, 1000, false, 0xffffff);
var xData:Vector.<Number> = Data[0];
var yData:Vector.<Number> = Data[1];
var lineColor:uint = 0xff0000;
var shape:Shape = new Shape();
var graphics:Graphics = shape.graphics;
// make the required drawPath vectors
var commands:Vector.<int> = new Vector.<int>();
var dataPts:Vector.<Number> = new Vector.<Number>();
stage.quality = StageQuality;
graphics.lineStyle(0, lineColor, 1);
startTime_ms = getTimer();
//Generate the drawing commands...
commands.push(GraphicsPathCommand.MOVE_TO);
dataPts.push(xData[0]); // moveto x
dataPts.push(yData[0]); // moveto y
for(i = 1; i < numPts; ++i) {
commands.push(GraphicsPathCommand.LINE_TO);
dataPts.push(xData[i] as uint); // lineto x
dataPts.push(yData[i] as uint); // lineto y
}
// Execute drawPath (which just queues up the commands)...
shape.graphics.drawPath(commands, dataPts);
//log("full drawPath pt generation time: " + (getTimer() - beforeTime) + "ms");
//Actually draw to the bitmap...
startTime_ms = getTimer();
bmd.draw(shape);
log(LogMsg + (getTimer() - startTime_ms) + " ms");
_Result.bitmapData = bmd;
}
private function log(msg:*):void {
_Logger.appendText(msg + "\n");
}
//"Extremely Fast Line Algorithm"
// - algorithm author is Po-Han Lin (original version: http://www.edepot.com/algorithm.html)
// - AS3 port by Simo Santavirta (http://www.simppa.fi/blog/?p=521)
// - further tweaks by Jackson Dunstan (http://jacksondunstan.com/articles/506)
private function EFLA(x:int, y:int, x2:int, y2:int, color:uint, bmd:BitmapData): void {
var shortLen:int = y2-y;
var longLen:int = x2-x;
if ((shortLen ^ (shortLen >> 31)) - (shortLen >> 31) > (longLen ^ (longLen >> 31)) - (longLen >> 31)) {
shortLen ^= longLen;
longLen ^= shortLen;
shortLen ^= longLen;
var yLonger:Boolean = true;
}
else {
yLonger = false;
}
var inc:int = longLen < 0 ? -1 : 1;
var multDiff:Number = longLen == 0 ? shortLen : shortLen / longLen;
if (yLonger) {
for (var i:int = 0; i != longLen; i += inc) {
bmd.setPixel(x + i*multDiff, y+i, color);
}
}
else {
for (i = 0; i != longLen; i += inc) {
bmd.setPixel(x+i, y+i*multDiff, color);
}
}
}
} // end of class def
} // end of package def