In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

SvgConvertTest

Get Adobe Flash player
by bigchu 08 May 2009

    Tags

    svg
    Embed
package{
import flash.display.*;
import flash.text.*;
import flash.geom.Point;

[SWF(backgroundColor="#ffffff")]
public class EasySvgConvert extends Sprite{
	private var canvas:Sprite;
	private var source:TextField;
	
	public function EasySvgConvert(){
		stage.scaleMode ="noScale";
		stage.align = "TL";

		canvas = new Sprite();
		canvas.x = 100; canvas.y = 300;
		addChild(canvas);

		source = new TextField();
		source.x = 300;
		source.width = 200;
		source.height = 250;
		source.multiline = source.border = true;
		addChild(source);
		
		var button:Button = new Button("convert");
		button.y = 260;
		addChild(button);
		button.addEventListener("click", function(event:*):void{
			//try{
				convert(tf.text);
			//}catch(e:Error){
			//	tf.text = e.toString();
			//}
		});
		
		var tf:TextField = new TextField();
		tf.multiline = tf.border = true;
		tf.width = 250;
		tf.height = 250;
		tf.type = "input";
		tf.text = defaultSvg.replace(/\r\n/g, "\n");;
		addChild(tf);
	}

	private function convert(svg:String):void{
		canvas.graphics.clear();
		while(canvas.numChildren) canvas.removeChildAt(0);

		var converter:EasySvgConverter = new EasySvgConverter();
		source.text = "";
		var ret:String = "";

		for each(var path:String in svg.match(/ d="[^"]+"/g)){
			path = path.substr(0, path.length - 1).substr(4);

			converter.convert(path);
			var points:Array = converter.getArray();
			var convex:Array = converter.calcConvexHull(points);

			draw(points, convex);
			ret += getText(points, convex);
		}
		source.text = "{'areas': [\n" + ret + "]}";
	}

	private function draw(points:Array, convex:Array):void{
		canvas.graphics.beginFill(0x0, .2);
		canvas.graphics.lineStyle(1, 0x0, .4);

		var moveFlag:Boolean = false;
		for each(var pt:Point in points){
			if(isNaN(pt.x) || isNaN(pt.y)){
				moveFlag = true;
				continue;
			}
			if(moveFlag){
				canvas.graphics.moveTo(pt.x, pt.y);
				moveFlag = false;
			}else{
				canvas.graphics.lineTo(pt.x, pt.y);
			}
		}
		canvas.graphics.endFill();

		moveFlag = true;
		canvas.graphics.lineStyle(1, 0x3399ff);
		for each(pt in convex){
			if(moveFlag){
				canvas.graphics.moveTo(pt.x, pt.y);
				moveFlag = false;
			}
			else{
				canvas.graphics.lineTo(pt.x, pt.y);
				canvas.addChild(new Circle(pt.x, pt.y));
			}
		}
	}

	private function getText(points:Array, convex:Array):String{
		convex = convex.reverse();

		var ret:String = "{'convex': [";
		for each(var pt:Point in convex){
			ret += pt.x + "," + pt.y + ",";
		}
		ret += "], 'pt': [";
		for each(pt in points){
			ret += pt.x + "," + pt.y + ",";
		}
		ret += "]},\n";

		return ret;
	}
}
}

import flash.display.*;
import flash.geom.*;
import flash.text.*;

class EasySvgConverter{
	private var svg:String;
	private var pos:int;
	private var path:Array;

	public function convert(_svg:String):void{
		svg = _svg;
		pos = 0;
		path = [];

		var token:String;
		while((token = getToken()) != ""){
			var isUpper:Boolean = (token == token.toUpperCase());
			switch(token.toLowerCase()){
				case "m":
					path.push(new SvgMove(
						parseFloat(getToken()), parseFloat(getToken()), 
						isUpper
					));
					break;

				case "c":
					path.push(new SvgBezier(
						parseFloat(getToken()), parseFloat(getToken()), 
						parseFloat(getToken()), parseFloat(getToken()), 
						parseFloat(getToken()), parseFloat(getToken()), 
						isUpper
					));
					break;

				case "s":
					path.push(new SvgBezier(
						0, 0,
						parseFloat(getToken()), parseFloat(getToken()), 
						parseFloat(getToken()), parseFloat(getToken()), 
						isUpper
					));
					break;

				case "h":
					path.push(new SvgLineTo(parseFloat(getToken()), NaN, isUpper));
					break;

				case "v":
					path.push(new SvgLineTo(NaN, parseFloat(getToken()), isUpper));
					break;

				case "l":
					path.push(new SvgLineTo(parseFloat(getToken()), parseFloat(getToken()), isUpper));
					break;

				case "z":
					// assume that start point and end point are equal
					break;

				default:
					throw new Error("not implemented: " + token);
			}
		}
	}

	private function getToken():String{
		var sub:String = svg.substr(pos);
		var matches:Array;

		if((matches = sub.match(/^[ \t,\r\n]+/))){
			pos += matches[0].length;
			sub = sub.substr(matches[0].length);
		}

		if(sub.match(/^[a-z]/i)){
			pos++;
			return sub.charAt(0);
		}

		if((matches = sub.match(/^-?\d*(?:\.\d*)?/))){
			pos += matches[0].length;
			return matches[0];
		}

		return "";
	}

	public function getArray():Array{
		var ret:Array = [];
		var pt:Point = new Point();
		for each(var obj:ISvgDrawable in path){
			obj.addArray(ret, pt);
		}
		return ret;
	}

	public function calcConvexHull(points:Array):Array{
		var ret:Array = [];

		// 開始ポイント(Y座標が最大のもの)を求める
		var maxY:Number = -Infinity;
		var start:Point;
		for each(var pt:Point in points){
			if(maxY < pt.y){
				maxY = pt.y;
				start = pt;
			}
		}
		ret.push(start);

		// ...
		var cur:Point = start;
		var vecX:Point = new Point(1, 0);
		while(true){
			var maxCos:Number = -2;
			var nextPt:Point;

			for each(pt in points){
				if(pt == cur) continue;

				// 内積を使って cosθ を求める
				var cos:Number = (pt.x - cur.x) * vecX.x + (pt.y - cur.y) * vecX.y;
				cos /= Point.distance(pt, cur);

				if(cos > maxCos){
					maxCos = cos;
					nextPt = pt;
				}
			}

			if(start == nextPt) break;

			ret.push(nextPt);
			vecX = nextPt.subtract(cur);
			vecX.normalize(1);
			cur = nextPt;
		}

		return ret;
	}
}

interface ISvgDrawable{
	function addArray(arr:Array, pt:Point):void;
}

function roundPoint(pt:Point):void{
	pt.x = Math.round(pt.x * 10000) / 10000;
	pt.y = Math.round(pt.y * 10000) / 10000;
}

class SvgMove implements ISvgDrawable{
	public var x:Number;
	public var y:Number;
	public var absolute:Boolean;
	public function SvgMove(_x:Number, _y:Number, _absolute:Boolean){
		x = _x;
		y = _y;
		absolute = _absolute;
	}

	public function addArray(arr:Array, pt:Point):void{
		if(absolute){
			pt.x = x; pt.y = y;
		}else{
			pt.x += x; pt.y += y;
		}
		roundPoint(pt);
		arr.push(new Point(NaN, NaN)); // notify 'moveTo'
		arr.push(pt.clone());
	}
}

// only draws a line from p1 to p4.
class SvgBezier implements ISvgDrawable{
	public var p2x:Number;
	public var p2y:Number;
	public var p3x:Number;
	public var p3y:Number;
	public var p4x:Number;
	public var p4y:Number;
	public var absolute:Boolean;
	public function SvgBezier(_p2x:Number, _p2y:Number, _p3x:Number, _p3y:Number, _p4x:Number, _p4y:Number, _absolute:Boolean){
		p2x = _p2x; p2y = _p2y;
		p3x = _p3x; p3y = _p3y;
		p4x = _p4x; p4y = _p4y;
		absolute = _absolute;
	}

	public function addArray(arr:Array, pt:Point):void{
		if(absolute){
			pt.x = p4x; pt.y = p4y;
		}else{
			pt.x += p4x; pt.y += p4y;
		}
		roundPoint(pt);
		arr.push(pt.clone());
	}
}

class SvgLineTo implements ISvgDrawable{
	public var x:Number;
	public var y:Number;
	public var absolute:Boolean;
	public function SvgLineTo(_px:Number, _py:Number, _absolute:Boolean){
		x = _px; y = _py;
		absolute = _absolute;
	}

	public function addArray(arr:Array, pt:Point):void{
		if(absolute){
			if(!isNaN(x)) pt.x = x;
			if(!isNaN(y)) pt.y = y;
		}else{
			if(!isNaN(x)) pt.x += x;
			if(!isNaN(y)) pt.y += y;
		}
		roundPoint(pt);
		arr.push(pt.clone());
	}
}

class Circle extends Sprite{
	public function Circle(x:Number, y:Number){
		graphics.beginFill(0x3399ff);
		graphics.drawCircle(x, y, 2);
		graphics.endFill();
	}
}

class Button extends Sprite{
	public function Button(label:String){
		graphics.beginFill(0xcccccc);
		graphics.drawRect(0, 0, 50, 30);
		graphics.endFill();
		buttonMode = useHandCursor = true;
		mouseChildren = false;

		var tf:TextField = new TextField();
		tf.text = label;
		addChild(tf);
	}
}

// Hokkaido svg
var defaultSvg:String = '<path i:knockout="Off" fill="#333333" d="M339.326,445.156c0,0-7.5,3.25-10.5-1.5c0,0-1.5-3.125,0-6.375c0,0,1.833-2.375,2.354-4.25c0,0,0.854-7,0-9.375\n'
+ 'c0,0-2.729-0.375-4.729,0c0,0-1.125-1.375-1.25-7.5c0,0,0-3,0.75-8.25c0,0-0.5-2-2.875-4.5c0,0-4.75-3.375-9.875-7\n'
+ 'c0,0-8.875-5.75-11.75-10.75h-3.625c0,0,0.25-2.25-1.75-6.125c0,0-2.125-0.375-5.125,0c0,0,0.875,0.75-5.375,10.125\n'
+'c0,0-7.375,9.125-12.25,10.5c0,0-2.375,4.625-6.875,9.625c0,0-0.375,3.5-2.375,9c0,0-1.25,2.125-3.375,3.625c0,0-2,5.125-2.125,11\n'
+'c0,0.75-2,0-2.875,1.625c0,0-1.875-2-2.75-1.75c0,0-0.625-2.625-2.25-2.75c0,0-1.625,1.125-1.875,5.125c0,0,0.875,0.75,0.625,4.25\n'
+ 'c0,0-0.125,4.75,0,7.875c0,0,0.5,1.25-0.625,3.5c0,0-1.625,1.125-3.625,0.625c0,0-1.375,1.006-2.875,0.128c0,0-2.75,1.196-3.5-0.628\n'
+ 'c0,0-3,0.875-3.25-0.875c0,0-2.75,1-2.625-1.5c0,0,2.125-4.25,4.625-10c0,0,1.25-1.875,1.125-4c0,0-0.75-2.125,1.125-3.625\n'
+ 'c0,0,1-2.5,1.375-5.125c0,0,0.375,0-1.625-1.375c0,0-0.875,0.75,1-5c0,0,1.625-3.5,2.625-8.875c0,0,2.375-8.125,4.5-12.25\n'
+ 'c0,0-1.625-5.75,4.625-9c0,0,4.75-7.75,7.5-13.5c0,0,4.625-10.875,8.375-15.375c0,0,3.75-5.25,5.875-7.125c0,0-0.5-2.5-1.25-7.625\n'
+ 'c0,0-0.5-6.75-1.375-9.75c0,0,0.625-1,0.25-5c0,0-3.375-6-2.5-10c0,0-1.875-0.75-1.625-5.625c0,0,0.625-4,3.875-8.125\n'
+ 'c0,0,0.75-0.375,3.875-4c0,0,2.625-2.125,6.75-2.375c0,0,1.5-0.5,3.75,0l1.875-1.25h1.75l2.75-1.125c0,0,8.125-0.25,8.625,0\n'
+ 's2.75-0.111,2.75-0.111s0.5-1.889,1.5-3.889l1-3.75c0,0,2.375-3.375,5.125-6c0,0,5.75-2.625,9.875-1.25c0,0,6.75,1.875,8.75,4.75\n'
+ 'c0,0-0.167,2.237,1.917,1.487c0,0-0.326,1.03-1.076,1.266c0,0,0.659-0.378-0.466,0.247c0,0,0.675,0.795,2.25,0.875\n'
+ 'c0,0-1.83,0.601-2.875,1.875c0,0-0.625,0.75-0.25,3l-0.125,2l-1.125,1c0,0-0.125,2.25,0.5,4l-1.375,1.5c0,0,1.625-0.375,2,1.875\n'
+ 'c0,0,0.5,1.375,3,1.125c0,0,3.75,0.75,5.625,3c0,0,1.25,1.375,3.375,2.625c0,0,1.5,2.25,2.875,2.5c0,0-0.125,1.25,1.125,2.75\n'
+ 'c0,0-1.125,1.5-3.125,1.875c0,0,0.875,0.875,0,4.875c0,0,0,0.625,3.125-0.75c0,0,3,0.125,4.625,1.125c0,0,1.25,1.875,3.875,4.75\n'
+ 'c0,0,2.125,3.375,2.75,5.75v3.75l-2.875,2l-2.125,1.125c0,0,0.125,2.25-1.75,4.25l-2.25,1.5c0,0-0.125,0-1.25,3\n'
+ 'c0,0,0.375,1.25-3.125,1.375c0,0-4-0.125-5.875-4.5c0,0-2.875-1.125-4.625-4.75l-0.75-3.25l-2.75-3l-1.125-3.375l-3.625,0.125\n'
+ 'c0,0,0.125,1.75-1.125,5.875c0,0-5.625,3.625-8,6.875c0,0-1.75,3.125-1.125,5.75l1.75,2.375c0,0,8,6.25,15.5,13.75\n'
+ 'c0,0,9.75,10.625,12.625,15.75c0,0,2.125,3.125,2.375,9.5c0,0,1.5,4,3.5,5.875c0,0,1,4.625,0.25,12.75c0,0,0.625,0.875,2.125,2.25\n'
+ 'c0,0,0.75,0.5,0.125,3c0,0-2.125-0.75-4.375,0.5c0,0-3.042,1.249-3.875,0.916c0,0-1.833,2.167-2.667,2.917c0,0-0.583,6,1.75,8.583\n'
+ 'c0,0,6.333,3.166,10.083,4.083c0,0,1.442,0.95,3.5,1.334c0,0,4.146,1.343,6.239,2.338c0,0,4.677,0.994,5.177,1.578\n'
+ 'c0,0,1.669,3.104-2.499,4.261c0,0-6.584-0.344-9.418-1.094C356.243,444.822,342.576,444.407,339.326,445.156z"/>';