From fbf58a06c24712d2afdeff9f08378b87b5cb1452 Mon Sep 17 00:00:00 2001 From: zjnue Date: Thu, 13 Sep 2012 14:47:51 +0100 Subject: [PATCH 01/19] minor class reference fix --- format/svg/SVG2Gfx.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format/svg/SVG2Gfx.hx b/format/svg/SVG2Gfx.hx index 11d3901..28871f6 100644 --- a/format/svg/SVG2Gfx.hx +++ b/format/svg/SVG2Gfx.hx @@ -6,7 +6,7 @@ import Xml; class SVG2Gfx { - var renderer : SvgRenderer; + var renderer : SVGRenderer; public function new (inXml:Xml) { From a7acb0cfa7c1573dde2431a982bca30df19a2d82 Mon Sep 17 00:00:00 2001 From: zjnue Date: Sun, 7 Apr 2013 16:22:41 +0200 Subject: [PATCH 02/19] define more readable parser tokens --- format/svg/PathParser.hx | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/format/svg/PathParser.hx b/format/svg/PathParser.hx index f11a279..d99f606 100644 --- a/format/svg/PathParser.hx +++ b/format/svg/PathParser.hx @@ -15,26 +15,26 @@ class PathParser { static var sCommandArgs:Array; - static inline var MOVE = 77; //"M".charCodeAt(0); - static inline var MOVER = 109; //"m".charCodeAt(0); - static inline var LINE = 76; // "L".charCodeAt(0); - static inline var LINER = 108; // "l".charCodeAt(0); - static inline var HLINE = 72; // "H".charCodeAt(0); - static inline var HLINER = 104; // "h".charCodeAt(0); - static inline var VLINE = 86; // "V".charCodeAt(0); - static inline var VLINER = 118; // "v".charCodeAt(0); - static inline var CUBIC = 67; // "C".charCodeAt(0); - static inline var CUBICR = 99; // "c".charCodeAt(0); - static inline var SCUBIC = 83; // "S".charCodeAt(0); - static inline var SCUBICR = 115; // "s".charCodeAt(0); - static inline var QUAD = 81; // "Q".charCodeAt(0); - static inline var QUADR = 113; // "q".charCodeAt(0); - static inline var SQUAD = 84; // "T".charCodeAt(0); - static inline var SQUADR = 116; // "t".charCodeAt(0); - static inline var ARC = 65; // "A".charCodeAt(0); - static inline var ARCR = 97; // "a".charCodeAt(0); - static inline var CLOSE = 90; // "Z".charCodeAt(0); - static inline var CLOSER = 122; // "z".charCodeAt(0); + static inline var MOVE = "M".code; + static inline var MOVER = "m".code; + static inline var LINE = "L".code; + static inline var LINER = "l".code; + static inline var HLINE = "H".code; + static inline var HLINER = "h".code; + static inline var VLINE = "V".code; + static inline var VLINER = "v".code; + static inline var CUBIC = "C".code; + static inline var CUBICR = "c".code; + static inline var SCUBIC = "S".code; + static inline var SCUBICR = "s".code; + static inline var QUAD = "Q".code; + static inline var QUADR = "q".code; + static inline var SQUAD = "T".code; + static inline var SQUADR = "t".code; + static inline var ARC = "A".code; + static inline var ARCR = "a".code; + static inline var CLOSE = "Z".code; + static inline var CLOSER = "z".code; static var UNKNOWN = -1; static var SEPARATOR = -2; From 3c77f7198c3821c4549b1c6bfb0a2626af9630c3 Mon Sep 17 00:00:00 2001 From: zjnue Date: Sun, 7 Apr 2013 16:25:33 +0200 Subject: [PATCH 03/19] inline more statics --- format/svg/PathParser.hx | 12 ++++++------ format/svg/SVGData.hx | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/format/svg/PathParser.hx b/format/svg/PathParser.hx index d99f606..188bb94 100644 --- a/format/svg/PathParser.hx +++ b/format/svg/PathParser.hx @@ -36,12 +36,12 @@ class PathParser { static inline var CLOSE = "Z".code; static inline var CLOSER = "z".code; - static var UNKNOWN = -1; - static var SEPARATOR = -2; - static var FLOAT = -3; - static var FLOAT_SIGN = -4; - static var FLOAT_DOT = -5; - static var FLOAT_EXP = -6; + static inline var UNKNOWN = -1; + static inline var SEPARATOR = -2; + static inline var FLOAT = -3; + static inline var FLOAT_SIGN = -4; + static inline var FLOAT_DOT = -5; + static inline var FLOAT_EXP = -6; diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 85dbe8c..02dc3e8 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -27,8 +27,8 @@ typedef StringMap = Hash; class SVGData extends Group { - private static var SIN45:Float = 0.70710678118654752440084436210485; - private static var TAN22:Float = 0.4142135623730950488016887242097; + private static inline var SIN45:Float = 0.70710678118654752440084436210485; + private static inline var TAN22:Float = 0.4142135623730950488016887242097; private static var mStyleSplit = ~/;/g; private static var mStyleValue = ~/\s*(.*)\s*:\s*(.*)\s*/; private static var mTranslateMatch = ~/translate\((.*)[, ](.*)\)/; From 65b7d2255b72db82a89c9b8e4e312c8d186416a0 Mon Sep 17 00:00:00 2001 From: zjnue Date: Sun, 7 Apr 2013 16:30:53 +0200 Subject: [PATCH 04/19] support basic viewBox offset - helps multi-page svg export --- format/svg/SVGData.hx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 02dc3e8..4ea24a5 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -68,9 +68,26 @@ class SVGData extends Group { else if (height == 0) height = width; - loadGroup(this, svg, new Matrix (), null); + var viewBox = new Rectangle(0, 0, width, height); + + if (svg.exists("viewBox")) { + + var vbox = svg.get("viewBox"); + var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); + viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); + + } + + loadGroup(this, svg, new Matrix (1, 0, 0, 1, -viewBox.x, -viewBox.y), null); } + + + inline function trimToFloat (value:String) { + + return Std.parseFloat( StringTools.trim(value) ); + + } private function applyTransform (ioMatrix:Matrix, inTrans:String):Float { From 351d440fcfb7235e2de9ef107aa21bab284b1b29 Mon Sep 17 00:00:00 2001 From: zjnue Date: Sun, 7 Apr 2013 16:39:39 +0200 Subject: [PATCH 05/19] support inner-g opacity --- format/svg/SVGData.hx | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 4ea24a5..c7aaa00 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -456,7 +456,30 @@ class SVGData extends Group { } var styles = getStyles (inG, inStyles); - + + /* + supports eg: + + + + + + + */ + if (inG.exists("opacity")) { + + var opacity = inG.get("opacity"); + + if (styles == null) + styles = new StringMap(); + + if (styles.exists("opacity")) + opacity = Std.string( Std.parseFloat(opacity) * Std.parseFloat(styles.get("opacity")) ); + + styles.set("opacity", opacity); + + } + for (el in inG.elements ()) { var name = el.nodeName; From f1f24c48356dc5c48d9bc57e62e5c4f588273aa5 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Sun, 16 Feb 2014 19:35:26 -0800 Subject: [PATCH 06/19] added patterns and symbol links --- format/gfx/BitmapFill.hx | 16 ++++++++ format/gfx/Gfx.hx | 1 + format/gfx/GfxGraphics.hx | 5 +++ format/svg/BitmapDataManager.hx | 36 +++++++++--------- format/svg/BitmapFill.hx | 38 +++++++++++++++++++ format/svg/FillType.hx | 1 + format/svg/SVGData.hx | 66 +++++++++++++++++++++++++++++---- format/svg/SVGRenderer.hx | 5 ++- 8 files changed, 143 insertions(+), 25 deletions(-) create mode 100644 format/gfx/BitmapFill.hx create mode 100644 format/svg/BitmapFill.hx diff --git a/format/gfx/BitmapFill.hx b/format/gfx/BitmapFill.hx new file mode 100644 index 0000000..b1cf842 --- /dev/null +++ b/format/gfx/BitmapFill.hx @@ -0,0 +1,16 @@ +package format.gfx; + +import flash.geom.Matrix; +import flash.display.BitmapData; + +class BitmapFill { + public function new() { + matrix = new Matrix(); + } + + public var bitmapData:BitmapData; + public var matrix: Matrix; + public var repeat: Bool = true; + public var smooth: Bool = false; +} + diff --git a/format/gfx/Gfx.hx b/format/gfx/Gfx.hx index b865ae4..13aaa1c 100644 --- a/format/gfx/Gfx.hx +++ b/format/gfx/Gfx.hx @@ -16,6 +16,7 @@ class Gfx public function geometryOnly() { return false; } public function size(inWidth:Float,inHeight:Float) { } public function beginGradientFill(grad:Gradient) { } + public function beginBitmapFill(bitmap: BitmapFill) {} public function beginFill(color:Int, alpha:Float) { } public function endFill() { } diff --git a/format/gfx/GfxGraphics.hx b/format/gfx/GfxGraphics.hx index 233e7d9..83ed428 100644 --- a/format/gfx/GfxGraphics.hx +++ b/format/gfx/GfxGraphics.hx @@ -25,6 +25,11 @@ class GfxGraphics extends Gfx graphics.beginGradientFill(grad.type,grad.colors,grad.alphas,grad.ratios,grad.matrix,grad.spread,grad.interp,grad.focus); } + override public function beginBitmapFill(fill:BitmapFill) + { + graphics.beginBitmapFill(fill.bitmapData, fill.matrix, fill.repeat, fill.smooth); + } + override public function beginFill(color:Int, alpha:Float) { graphics.beginFill(color,alpha); } override public function endFill() { graphics.endFill(); } diff --git a/format/svg/BitmapDataManager.hx b/format/svg/BitmapDataManager.hx index f04199e..6ddff22 100644 --- a/format/svg/BitmapDataManager.hx +++ b/format/svg/BitmapDataManager.hx @@ -1,8 +1,9 @@ package format.svg; //import gm2d.reso.Resources; -import format.svg.SvgRenderer; +//import format.svg.SVGRenderer; +import flash.display.DisplayObjectContainer; import flash.geom.Matrix; import flash.display.Shape; import flash.display.Bitmap; @@ -11,36 +12,37 @@ import flash.display.BitmapData; class BitmapDataManager { - static var bitmaps = new Hash(); + public static var bitmaps = new Map(); + public static var stage: DisplayObjectContainer; static var mScale = 0.0; public static function create(inSVG:String, inGroup:String, inScale:Float, inCache=false) { - var key = inSVG + " : " + inGroup + " : " +inScale; + var key = inGroup + " : " +inScale; if (bitmaps.exists(key)) return bitmaps.get(key); - //var svg:SvgRenderer = new SvgRenderer( Resources.loadSvg(inSVG) ); var svg = null; - return; - + var shape = new Shape(); - if (inGroup=="") - svg.RenderObject(shape,shape.graphics); - else - svg.RenderObject(shape,shape.graphics,null, function(_,groups) { return groups[0]==inGroup; }); +// if (inGroup=="") +// svg.RenderObject(shape,shape.graphics); +// else +// svg.RenderObject(shape,shape.graphics,null, function(_,groups) { return groups[0]==inGroup; }); + + svg = new SVG(inSVG); + svg.render(shape.graphics, 0, 0); var matrix = new Matrix(); matrix.scale(inScale,inScale); - var w = Std.int(svg.width*inScale + 0.99); - var h = Std.int(svg.height*inScale + 0.99); + var w = Std.int(svg.data.width); + var h = Std.int(svg.data.height); var bmp = new BitmapData(w,h,true,0x00); - var q = gm2d.Lib.current.stage.quality; - flash.Lib.current.stage.quality = flash.display.StageQuality.BEST; +// var q = gm2d.Lib.current.stage.quality; +// flash.Lib.current.stage.quality = flash.display.StageQuality.BEST; bmp.draw(shape,matrix); - flash.Lib.current.stage.quality = q; - +// flash.Lib.current.stage.quality = q; if (inCache) bitmaps.set(key,bmp); return bmp; @@ -50,7 +52,7 @@ class BitmapDataManager { if (inScale!=mScale) { - bitmaps = new Hash(); + bitmaps = new Map(); mScale = inScale; } } diff --git a/format/svg/BitmapFill.hx b/format/svg/BitmapFill.hx new file mode 100644 index 0000000..00e4c61 --- /dev/null +++ b/format/svg/BitmapFill.hx @@ -0,0 +1,38 @@ +package format.svg; + +import flash.geom.Matrix; +import flash.display.BitmapData; + +class BitmapFill extends format.gfx.BitmapFill { + public var fillMatrix: Matrix; + public var x1:Float; + public var y1:Float; + public var x2:Float; + public var y2:Float; + + public function new() { + super(); + fillMatrix = new Matrix(); + x1 = 0.0; + y1 = 0.0; + x2 = 0.0; + y2 = 0.0; + } + + public function updateMatrix(inMatrix:Matrix) + { + var dx = x2 - x1; + var dy = y2 - y1; + var theta = Math.atan2(dy,dx); + var len = Math.sqrt(dx*dx+dy*dy); + + var mtx = new Matrix(); + + mtx.rotate(theta); + mtx.translate(x1,y1); + mtx.concat(fillMatrix); + mtx.concat(inMatrix); + matrix = mtx; + } +} + diff --git a/format/svg/FillType.hx b/format/svg/FillType.hx index 787d6b5..aacea99 100644 --- a/format/svg/FillType.hx +++ b/format/svg/FillType.hx @@ -4,6 +4,7 @@ enum FillType { FillGrad(grad:Grad); FillSolid(colour:Int); + BitmapFill(fill: BitmapFill); FillNone; } diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index c7aaa00..9a1df2e 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -42,9 +42,10 @@ class SVGData extends Group { private var mConvertCubics:Bool; private var mGrads:GradHash; + private var mPatterns: Map; private var mPathParser:PathParser; - - + private var symbols: Map; + public function new (inXML:Xml, inConvertCubics:Bool = false) { super(); @@ -53,9 +54,11 @@ class SVGData extends Group { if (svg == null || (svg.nodeName != "svg" && svg.nodeName != "svg:svg")) throw "Not an SVG file (" + (svg==null ? "null" : svg.nodeName) + ")"; - + mGrads = new GradHash (); mPathParser = new PathParser (); + symbols = new Map(); + mPatterns = new Map(); mConvertCubics = inConvertCubics; width = getFloatStyle ("width", svg, null, 0.0); @@ -211,7 +214,9 @@ class SVGData extends Group { return FillGrad(mGrads.get(url)); - } + } else if(mPatterns.exists(url)) { + return BitmapFill(mPatterns.get(url)); + } throw ("Unknown url:" + url); @@ -361,7 +366,36 @@ class SVGData extends Group { } } - + + private function loadPattern(inPattern: Xml, inCrossLink: Bool) { + var name = inPattern.get("id"); + var pattern = new BitmapFill(); + + if (inCrossLink && inPattern.exists("xlink:href")) { + + var xlink = inPattern.get ("xlink:href"); + + if (xlink.charAt(0) != "#") + throw ("xlink - unkown syntax : " + xlink); + + var base = mPatterns.get (xlink.substr (1)); + + if (base != null) { + mPatterns.set(inPattern.get("id"), base); + } else { + + throw ("Unknown xlink : " + xlink); + + } + + } else { + inPattern.nodeName = "svg"; + var bitmapData = BitmapDataManager.create(inPattern.toString(), name, 1, true); + pattern.bitmapData = bitmapData; + + mPatterns.set(name, pattern); + } + } private function loadGradient (inGrad:Xml, inType:GradientType, inCrossLink:Bool) { @@ -493,7 +527,11 @@ class SVGData extends Group { if (name == "defs") { loadDefs (el); - + + } else if(name == "symbol") { + saveSymbol(el); + } else if(name == "use") { + applyRef(g, el, matrix, styles); } else if (name == "g") { if (!(el.exists("display") && el.get("display") == "none")) { @@ -533,7 +571,9 @@ class SVGData extends Group { } else if (name == "radialGradient") { loadGradient (el, GradientType.RADIAL, true); - + + } else if (name == "pattern") { + loadPattern(el, true); } else { // throw("Unknown child : " + el.nodeName ); @@ -545,6 +585,18 @@ class SVGData extends Group { return g; } + + public inline function saveSymbol(inText: Xml): Void { + symbols.set(inText.get("id"), inText.firstElement()); + } + + public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Void { + var id: String = inText.get("xlink:href"); + var svg: Xml = symbols.get(id.substring(1)); //Remove the # + if(svg != null) { + loadGroup(g, svg, matrix, inStyles); + } + } public function loadPath (inPath:Xml, matrix:Matrix, inStyles:StringMap, inIsRect:Bool, inIsEllipse:Bool, inIsCircle:Bool=false):Path { diff --git a/format/svg/SVGRenderer.hx b/format/svg/SVGRenderer.hx index 720084c..2817af7 100644 --- a/format/svg/SVGRenderer.hx +++ b/format/svg/SVGRenderer.hx @@ -115,13 +115,16 @@ class SVGRenderer // 4. continue with "real" drawing inPath.segments[0].toGfx(mGfx, context); - switch(inPath.fill) + switch(inPath.fill) { case FillGrad(grad): grad.updateMatrix(m); mGfx.beginGradientFill(grad); case FillSolid(colour): mGfx.beginFill(colour,inPath.fill_alpha*inPath.alpha); + case BitmapFill(fill): + fill.updateMatrix(m); + mGfx.beginBitmapFill(fill); case FillNone: //mGfx.endFill(); } From 08fcb6a68f4e37cae6b7b550092eee28aec98c1f Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Sun, 16 Feb 2014 19:38:51 -0800 Subject: [PATCH 07/19] code cleanuup --- format/svg/BitmapDataManager.hx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/format/svg/BitmapDataManager.hx b/format/svg/BitmapDataManager.hx index 6ddff22..4fa5feb 100644 --- a/format/svg/BitmapDataManager.hx +++ b/format/svg/BitmapDataManager.hx @@ -12,8 +12,7 @@ import flash.display.BitmapData; class BitmapDataManager { - public static var bitmaps = new Map(); - public static var stage: DisplayObjectContainer; + static var bitmaps = new Map(); static var mScale = 0.0; public static function create(inSVG:String, inGroup:String, inScale:Float, inCache=false) @@ -25,10 +24,6 @@ class BitmapDataManager var svg = null; var shape = new Shape(); -// if (inGroup=="") -// svg.RenderObject(shape,shape.graphics); -// else -// svg.RenderObject(shape,shape.graphics,null, function(_,groups) { return groups[0]==inGroup; }); svg = new SVG(inSVG); svg.render(shape.graphics, 0, 0); @@ -39,10 +34,7 @@ class BitmapDataManager var w = Std.int(svg.data.width); var h = Std.int(svg.data.height); var bmp = new BitmapData(w,h,true,0x00); -// var q = gm2d.Lib.current.stage.quality; -// flash.Lib.current.stage.quality = flash.display.StageQuality.BEST; bmp.draw(shape,matrix); -// flash.Lib.current.stage.quality = q; if (inCache) bitmaps.set(key,bmp); return bmp; From 051469915a7ad5218f9e4f91c7e5339fdea8b761 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Mon, 17 Feb 2014 12:46:35 -0800 Subject: [PATCH 08/19] optimized when the pattern fill is actually cached and added opacity to the bitmap fill --- format/gfx/BitmapFill.hx | 15 +++++++++++++++ format/svg/SVGData.hx | 15 +++++++++------ format/svg/SVGRenderer.hx | 1 + 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/format/gfx/BitmapFill.hx b/format/gfx/BitmapFill.hx index b1cf842..f1ee88a 100644 --- a/format/gfx/BitmapFill.hx +++ b/format/gfx/BitmapFill.hx @@ -1,5 +1,7 @@ package format.gfx; +import flash.geom.ColorTransform; +import flash.geom.Rectangle; import flash.geom.Matrix; import flash.display.BitmapData; @@ -12,5 +14,18 @@ class BitmapFill { public var matrix: Matrix; public var repeat: Bool = true; public var smooth: Bool = false; + @:isVar + public var alpha(default, set): Float = 1; + + private function set_alpha(value:Float):Float { + alpha = value; + if(bitmapData != null && value < 1) { + bitmapData.lock(); + var rect: Rectangle = new Rectangle(0,0,bitmapData.width,bitmapData.height); + bitmapData.colorTransform(rect, new ColorTransform(1,1,1,alpha)); + bitmapData.unlock(rect); + } + return alpha; + } } diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 9a1df2e..850321f 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -43,6 +43,7 @@ class SVGData extends Group { private var mConvertCubics:Bool; private var mGrads:GradHash; private var mPatterns: Map; + private var mPatternsSVG: Map; private var mPathParser:PathParser; private var symbols: Map; @@ -59,6 +60,7 @@ class SVGData extends Group { mPathParser = new PathParser (); symbols = new Map(); mPatterns = new Map(); + mPatternsSVG = new Map(); mConvertCubics = inConvertCubics; width = getFloatStyle ("width", svg, null, 0.0); @@ -369,7 +371,6 @@ class SVGData extends Group { private function loadPattern(inPattern: Xml, inCrossLink: Bool) { var name = inPattern.get("id"); - var pattern = new BitmapFill(); if (inCrossLink && inPattern.exists("xlink:href")) { @@ -381,6 +382,11 @@ class SVGData extends Group { var base = mPatterns.get (xlink.substr (1)); if (base != null) { + var svg: Xml = mPatternsSVG.get(xlink.substr (1)); + svg.nodeName = "svg"; + var bitmapData = BitmapDataManager.create(svg.toString(), name, 1, true); + base.bitmapData = bitmapData; + mPatterns.set(inPattern.get("id"), base); } else { @@ -389,10 +395,8 @@ class SVGData extends Group { } } else { - inPattern.nodeName = "svg"; - var bitmapData = BitmapDataManager.create(inPattern.toString(), name, 1, true); - pattern.bitmapData = bitmapData; - + var pattern = new BitmapFill(); + mPatternsSVG.set(name, inPattern); mPatterns.set(name, pattern); } } @@ -611,7 +615,6 @@ class SVGData extends Group { var styles = getStyles (inPath, inStyles); var name = inPath.exists ("id") ? inPath.get ("id") : ""; var path = new Path (); - path.fill = getFillStyle ("fill", inPath, styles); path.alpha = getFloatStyle ("opacity", inPath, styles, 1.0); path.fill_alpha = getFloatStyle ("fill-opacity", inPath, styles, 1.0); diff --git a/format/svg/SVGRenderer.hx b/format/svg/SVGRenderer.hx index 2817af7..7c9fb81 100644 --- a/format/svg/SVGRenderer.hx +++ b/format/svg/SVGRenderer.hx @@ -124,6 +124,7 @@ class SVGRenderer mGfx.beginFill(colour,inPath.fill_alpha*inPath.alpha); case BitmapFill(fill): fill.updateMatrix(m); + fill.alpha = inPath.alpha; mGfx.beginBitmapFill(fill); case FillNone: //mGfx.endFill(); From 20f2f27534f6e2d2f4fd8693069460847c2e4db9 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Mon, 17 Feb 2014 21:07:22 -0800 Subject: [PATCH 09/19] bug fix: the optimization didn't catch all cases --- format/svg/SVGData.hx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 850321f..179c343 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -382,11 +382,6 @@ class SVGData extends Group { var base = mPatterns.get (xlink.substr (1)); if (base != null) { - var svg: Xml = mPatternsSVG.get(xlink.substr (1)); - svg.nodeName = "svg"; - var bitmapData = BitmapDataManager.create(svg.toString(), name, 1, true); - base.bitmapData = bitmapData; - mPatterns.set(inPattern.get("id"), base); } else { @@ -396,6 +391,10 @@ class SVGData extends Group { } else { var pattern = new BitmapFill(); + inPattern.nodeName = "svg"; + var bitmapData = BitmapDataManager.create(inPattern.toString(), name, 1, true); + pattern.bitmapData = bitmapData; + mPatternsSVG.set(name, inPattern); mPatterns.set(name, pattern); } From 730bd38109e61fa6ef7d1d984231a720a4773584 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Wed, 26 Feb 2014 17:05:47 -0800 Subject: [PATCH 10/19] bug fix to pattern caching and fix for opacity on gradients --- format/svg/BitmapDataManager.hx | 8 +++++--- format/svg/SVGData.hx | 34 ++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/format/svg/BitmapDataManager.hx b/format/svg/BitmapDataManager.hx index 4fa5feb..eec7088 100644 --- a/format/svg/BitmapDataManager.hx +++ b/format/svg/BitmapDataManager.hx @@ -17,9 +17,11 @@ class BitmapDataManager public static function create(inSVG:String, inGroup:String, inScale:Float, inCache=false) { - var key = inGroup + " : " +inScale; - if (bitmaps.exists(key)) - return bitmaps.get(key); + var key = inSVG + " : " + inGroup + " : " +inScale; + if (bitmaps.exists(key)) { + trace("getting cache " + key); + return bitmaps.get(key); + } var svg = null; diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 179c343..43bd7e1 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -321,7 +321,6 @@ class SVGData extends Group { var style = inNode.get ("style"); var strings = mStyleSplit.split (style); - for (s in strings) { if (mStyleValue.match (s)) { @@ -590,20 +589,33 @@ class SVGData extends Group { } public inline function saveSymbol(inText: Xml): Void { - symbols.set(inText.get("id"), inText.firstElement()); + symbols.set(inText.get("id"), inText); } public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Void { var id: String = inText.get("xlink:href"); var svg: Xml = symbols.get(id.substring(1)); //Remove the # + if(svg != null) { - loadGroup(g, svg, matrix, inStyles); + var viewBox = new Rectangle(0, 0, width, height); + if (svg.exists("viewBox")) { + var vbox = svg.get("viewBox"); + var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); + viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); + + } + for(attr in inText.attributes()) { + var value = inText.get(attr); + if(value != null && !svg.firstElement().exists(attr) && attr != "xlink:href") { + svg.firstElement().set(attr, value); + } + } + loadGroup(g, svg.firstElement(), new Matrix (1, 0, 0, 1, -viewBox.x, -viewBox.y), null); } } public function loadPath (inPath:Xml, matrix:Matrix, inStyles:StringMap, inIsRect:Bool, inIsEllipse:Bool, inIsCircle:Bool=false):Path { - if (inPath.exists ("transform")) { matrix = matrix.clone (); @@ -612,11 +624,19 @@ class SVGData extends Group { } var styles = getStyles (inPath, inStyles); - var name = inPath.exists ("id") ? inPath.get ("id") : ""; + var name = inPath.exists ("id") ? inPath.get ("id") : ""; var path = new Path (); path.fill = getFillStyle ("fill", inPath, styles); - path.alpha = getFloatStyle ("opacity", inPath, styles, 1.0); - path.fill_alpha = getFloatStyle ("fill-opacity", inPath, styles, 1.0); + path.alpha = getFloatStyle ("opacity", inPath, styles, 1.0); + switch(path.fill) { + case FillGrad(grad): + var alphas: Array = grad.alphas; + for(i in 0...alphas.length) { + alphas[i] = alphas[i] * path.alpha; + } + default: + } + path.fill_alpha = getFloatStyle ("fill-opacity", inPath, styles, 1.0); path.stroke_alpha = getFloatStyle ("stroke-opacity", inPath, styles, 1.0); path.stroke_colour = getStrokeStyle ("stroke", inPath, styles, null); path.stroke_width = getFloatStyle ("stroke-width", inPath, styles, 1.0); From 3917399e683bac17a1a4b0097ea44541434547d4 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Sun, 2 Mar 2014 11:42:13 -0800 Subject: [PATCH 11/19] remove cache key logging --- format/svg/BitmapDataManager.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/format/svg/BitmapDataManager.hx b/format/svg/BitmapDataManager.hx index eec7088..6a396a5 100644 --- a/format/svg/BitmapDataManager.hx +++ b/format/svg/BitmapDataManager.hx @@ -19,7 +19,6 @@ class BitmapDataManager { var key = inSVG + " : " + inGroup + " : " +inScale; if (bitmaps.exists(key)) { - trace("getting cache " + key); return bitmaps.get(key); } From 259fe87d9fff39b20a93daab1551f1aae6e90233 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Wed, 5 Mar 2014 16:26:51 -0800 Subject: [PATCH 12/19] fixed when adding offsets and reusing symbols --- format/svg/SVGData.hx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 43bd7e1..071704f 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -602,15 +602,24 @@ class SVGData extends Group { var vbox = svg.get("viewBox"); var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); + } + var xOffset: Float = Std.parseFloat(inText.get("x")); + if(Math.isNaN(xOffset)) { + xOffset = 0; + } + var yOffset: Float = Std.parseFloat(inText.get("y")); + if(Math.isNaN(yOffset)) { + yOffset = 0; } + for(attr in inText.attributes()) { var value = inText.get(attr); - if(value != null && !svg.firstElement().exists(attr) && attr != "xlink:href") { + if(value != null && attr != "xlink:href") { svg.firstElement().set(attr, value); } } - loadGroup(g, svg.firstElement(), new Matrix (1, 0, 0, 1, -viewBox.x, -viewBox.y), null); + loadGroup(g, svg.firstElement(), new Matrix (1, 0, 0, 1, -viewBox.x + xOffset, -viewBox.y + yOffset), null); } } From 146a5024871dadef023c269250e529885b801404 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Wed, 5 Mar 2014 19:15:17 -0800 Subject: [PATCH 13/19] nested symbols are working non-recursively --- format/svg/SVGData.hx | 61 ++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index 071704f..e3fe6cd 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -543,7 +543,6 @@ class SVGData extends Group { } } else if (name == "path" || name == "line" || name == "polyline") { - g.children.push (DisplayPath (loadPath (el, matrix, styles, false, false))); } else if (name == "rect") { @@ -592,25 +591,30 @@ class SVGData extends Group { symbols.set(inText.get("id"), inText); } - public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Void { - var id: String = inText.get("xlink:href"); + private inline function getLinkXml(id: String, inText: Xml): Xml { var svg: Xml = symbols.get(id.substring(1)); //Remove the # if(svg != null) { - var viewBox = new Rectangle(0, 0, width, height); - if (svg.exists("viewBox")) { - var vbox = svg.get("viewBox"); - var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); - viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); - } - - var xOffset: Float = Std.parseFloat(inText.get("x")); - if(Math.isNaN(xOffset)) { - xOffset = 0; - } - var yOffset: Float = Std.parseFloat(inText.get("y")); - if(Math.isNaN(yOffset)) { - yOffset = 0; + if(svg.firstElement().get("operated") == null) { + var newParent: Xml = Xml.createElement("g"); + newParent.set("operated", "true"); + var newChildren: List = new List(); + while(svg.firstElement() != null) { + var linkId: String = svg.firstElement().get("xlink:href"); + if(linkId != null) { + var link: Xml = getLinkXml(linkId, svg.firstElement()); + link = Xml.parse(link.toString()); + newChildren.add(link.firstElement().firstElement()); + svg.removeChild(svg.firstElement()); + } else { + newChildren.add(svg.firstElement()); + svg.removeChild(svg.firstElement()); + } + } + svg.addChild(newParent); + for(child in newChildren) { + newParent.addChild(child); + } } for(attr in inText.attributes()) { @@ -619,8 +623,29 @@ class SVGData extends Group { svg.firstElement().set(attr, value); } } - loadGroup(g, svg.firstElement(), new Matrix (1, 0, 0, 1, -viewBox.x + xOffset, -viewBox.y + yOffset), null); } + return svg; + } + + public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Void { + var id: String = inText.get("xlink:href"); + var svg: Xml = getLinkXml(id, inText); + var viewBox = new Rectangle(0, 0, width, height); + if (svg.exists("viewBox")) { + var vbox = svg.get("viewBox"); + var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); + viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); + } + + var xOffset: Float = Std.parseFloat(inText.get("x")); + if(Math.isNaN(xOffset)) { + xOffset = 0; + } + var yOffset: Float = Std.parseFloat(inText.get("y")); + if(Math.isNaN(yOffset)) { + yOffset = 0; + } + loadGroup(g, svg.firstElement(), new Matrix (1, 0, 0, 1, -viewBox.x + xOffset, -viewBox.y + yOffset), null); } From d5bde39c537c2490b8ba742c6f2f6f8ec390ef18 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Thu, 6 Mar 2014 11:03:06 -0800 Subject: [PATCH 14/19] Got recursive symbols working --- format/svg/SVGData.hx | 1351 ++++++++++++++++++++--------------------- 1 file changed, 663 insertions(+), 688 deletions(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index e3fe6cd..c7de699 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -25,348 +25,348 @@ typedef StringMap = Hash; class SVGData extends Group { - - - private static inline var SIN45:Float = 0.70710678118654752440084436210485; - private static inline var TAN22:Float = 0.4142135623730950488016887242097; - private static var mStyleSplit = ~/;/g; - private static var mStyleValue = ~/\s*(.*)\s*:\s*(.*)\s*/; - private static var mTranslateMatch = ~/translate\((.*)[, ](.*)\)/; - private static var mScaleMatch = ~/scale\((.*)\)/; - private static var mMatrixMatch = ~/matrix\((.*)[, ](.*)[, ](.*)[, ](.*)[, ](.*)[, ](.*)\)/; - private static var mURLMatch = ~/url\(#(.*)\)/; - private static var defaultFill = FillSolid(0x000000); - - public var height (default, null):Float; - public var width (default, null):Float; - - private var mConvertCubics:Bool; - private var mGrads:GradHash; + + + private static inline var SIN45:Float = 0.70710678118654752440084436210485; + private static inline var TAN22:Float = 0.4142135623730950488016887242097; + private static var mStyleSplit = ~/;/g; + private static var mStyleValue = ~/\s*(.*)\s*:\s*(.*)\s*/; + private static var mTranslateMatch = ~/translate\((.*)[, ](.*)\)/; + private static var mScaleMatch = ~/scale\((.*)\)/; + private static var mMatrixMatch = ~/matrix\((.*)[, ](.*)[, ](.*)[, ](.*)[, ](.*)[, ](.*)\)/; + private static var mURLMatch = ~/url\(#(.*)\)/; + private static var defaultFill = FillSolid(0x000000); + + public var height (default, null):Float; + public var width (default, null):Float; + + private var mConvertCubics:Bool; + private var mGrads:GradHash; private var mPatterns: Map; private var mPatternsSVG: Map; - private var mPathParser:PathParser; + private var mPathParser:PathParser; private var symbols: Map; - public function new (inXML:Xml, inConvertCubics:Bool = false) { - - super(); - - var svg = inXML.firstElement(); - - if (svg == null || (svg.nodeName != "svg" && svg.nodeName != "svg:svg")) - throw "Not an SVG file (" + (svg==null ? "null" : svg.nodeName) + ")"; - - mGrads = new GradHash (); - mPathParser = new PathParser (); + public function new (inXML:Xml, inConvertCubics:Bool = false) { + + super(); + + var svg = inXML.firstElement(); + + if (svg == null || (svg.nodeName != "svg" && svg.nodeName != "svg:svg")) + throw "Not an SVG file (" + (svg==null ? "null" : svg.nodeName) + ")"; + + mGrads = new GradHash (); + mPathParser = new PathParser (); symbols = new Map(); mPatterns = new Map(); mPatternsSVG = new Map(); - mConvertCubics = inConvertCubics; - - width = getFloatStyle ("width", svg, null, 0.0); - height = getFloatStyle ("height", svg, null, 0.0); - - if (width == 0 && height == 0) - width = height = 400; - else if (width == 0) - width = height; - else if (height == 0) - height = width; - - var viewBox = new Rectangle(0, 0, width, height); - - if (svg.exists("viewBox")) { - - var vbox = svg.get("viewBox"); - var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); - viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); - - } - - loadGroup(this, svg, new Matrix (1, 0, 0, 1, -viewBox.x, -viewBox.y), null); - - } - - - inline function trimToFloat (value:String) { - - return Std.parseFloat( StringTools.trim(value) ); - - } - - - private function applyTransform (ioMatrix:Matrix, inTrans:String):Float { - - var scale = 1.0; - - if (mTranslateMatch.match(inTrans)) - { - // TODO: Pre-translate - - ioMatrix.translate (Std.parseFloat (mTranslateMatch.matched (1)), Std.parseFloat (mTranslateMatch.matched (2))); - - } else if (mScaleMatch.match (inTrans)) { - - // TODO: Pre-scale - var s = Std.parseFloat (mScaleMatch.matched (1)); - ioMatrix.scale (s, s); - scale = s; - - } else if (mMatrixMatch.match (inTrans)) { - - var m = new Matrix ( - Std.parseFloat (mMatrixMatch.matched (1)), - Std.parseFloat (mMatrixMatch.matched (2)), - Std.parseFloat (mMatrixMatch.matched (3)), - Std.parseFloat (mMatrixMatch.matched (4)), - Std.parseFloat (mMatrixMatch.matched (5)), - Std.parseFloat (mMatrixMatch.matched (6)) - ); - - m.concat (ioMatrix); - - ioMatrix.a = m.a; - ioMatrix.b = m.b; - ioMatrix.c = m.c; - ioMatrix.d = m.d; - ioMatrix.tx = m.tx; - ioMatrix.ty = m.ty; - - scale = Math.sqrt (ioMatrix.a * ioMatrix.a + ioMatrix.c * ioMatrix.c); - - } else { - - trace("Warning, unknown transform:" + inTrans); - - } - - return scale; - - } - - - private function dumpGroup (g:Group, indent:String) { - - trace (indent + "Group:" + g.name); - indent += " "; - - for (e in g.children) { - - switch (e) { - - case DisplayPath (path): trace (indent + "Path" + " " + path.matrix); - case DisplayGroup (group): dumpGroup (group, indent+" "); - case DisplayText (text): trace (indent + "Text " + text.text); - - } - - } - - } - - - private function getColorStyle (inKey:String, inNode:Xml, inStyles:StringMap , inDefault:Int) { - - var s = getStyle (inKey, inNode, inStyles, ""); - - if (s == "") { - - return inDefault; - - } - - if (s.charAt (0) == '#') { - - return Std.parseInt ("0x" + s.substr (1)); - - } - - return Std.parseInt (s); - - } - - - private function getFillStyle (inKey:String, inNode:Xml, inStyles:StringMap) { - - var s = getStyle (inKey, inNode, inStyles, ""); - - if (s == "") { - - return defaultFill; - - } - - if (s.charAt (0) == '#') { - - return FillSolid (Std.parseInt ("0x" + s.substr (1))); - - } - - if (s == "none") { - - return FillNone; - - } - - if (mURLMatch.match (s)) { - - var url = mURLMatch.matched (1); - - if (mGrads.exists (url)) { - - return FillGrad(mGrads.get(url)); - - } else if(mPatterns.exists(url)) { + mConvertCubics = inConvertCubics; + + width = getFloatStyle ("width", svg, null, 0.0); + height = getFloatStyle ("height", svg, null, 0.0); + + if (width == 0 && height == 0) + width = height = 400; + else if (width == 0) + width = height; + else if (height == 0) + height = width; + + var viewBox = new Rectangle(0, 0, width, height); + + if (svg.exists("viewBox")) { + + var vbox = svg.get("viewBox"); + var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); + viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); + + } + + loadGroup(this, svg, new Matrix (1, 0, 0, 1, -viewBox.x, -viewBox.y), null); + + } + + + inline function trimToFloat (value:String) { + + return Std.parseFloat( StringTools.trim(value) ); + + } + + + private function applyTransform (ioMatrix:Matrix, inTrans:String):Float { + + var scale = 1.0; + + if (mTranslateMatch.match(inTrans)) + { + // TODO: Pre-translate + + ioMatrix.translate (Std.parseFloat (mTranslateMatch.matched (1)), Std.parseFloat (mTranslateMatch.matched (2))); + + } else if (mScaleMatch.match (inTrans)) { + + // TODO: Pre-scale + var s = Std.parseFloat (mScaleMatch.matched (1)); + ioMatrix.scale (s, s); + scale = s; + + } else if (mMatrixMatch.match (inTrans)) { + + var m = new Matrix ( + Std.parseFloat (mMatrixMatch.matched (1)), + Std.parseFloat (mMatrixMatch.matched (2)), + Std.parseFloat (mMatrixMatch.matched (3)), + Std.parseFloat (mMatrixMatch.matched (4)), + Std.parseFloat (mMatrixMatch.matched (5)), + Std.parseFloat (mMatrixMatch.matched (6)) + ); + + m.concat (ioMatrix); + + ioMatrix.a = m.a; + ioMatrix.b = m.b; + ioMatrix.c = m.c; + ioMatrix.d = m.d; + ioMatrix.tx = m.tx; + ioMatrix.ty = m.ty; + + scale = Math.sqrt (ioMatrix.a * ioMatrix.a + ioMatrix.c * ioMatrix.c); + + } else { + + trace("Warning, unknown transform:" + inTrans); + + } + + return scale; + + } + + + private function dumpGroup (g:Group, indent:String) { + + trace (indent + "Group:" + g.name); + indent += " "; + + for (e in g.children) { + + switch (e) { + + case DisplayPath (path): trace (indent + "Path" + " " + path.matrix); + case DisplayGroup (group): dumpGroup (group, indent+" "); + case DisplayText (text): trace (indent + "Text " + text.text); + + } + + } + + } + + + private function getColorStyle (inKey:String, inNode:Xml, inStyles:StringMap , inDefault:Int) { + + var s = getStyle (inKey, inNode, inStyles, ""); + + if (s == "") { + + return inDefault; + + } + + if (s.charAt (0) == '#') { + + return Std.parseInt ("0x" + s.substr (1)); + + } + + return Std.parseInt (s); + + } + + + private function getFillStyle (inKey:String, inNode:Xml, inStyles:StringMap) { + + var s = getStyle (inKey, inNode, inStyles, ""); + + if (s == "") { + + return defaultFill; + + } + + if (s.charAt (0) == '#') { + + return FillSolid (Std.parseInt ("0x" + s.substr (1))); + + } + + if (s == "none") { + + return FillNone; + + } + + if (mURLMatch.match (s)) { + + var url = mURLMatch.matched (1); + + if (mGrads.exists (url)) { + + return FillGrad(mGrads.get(url)); + + } else if(mPatterns.exists(url)) { return BitmapFill(mPatterns.get(url)); } - - throw ("Unknown url:" + url); - - } - - throw ("Unknown fill string:" + s); - - return FillNone; - - } - - - private function getFloat (inXML:Xml, inName:String, inDef:Float = 0.0):Float { - - if (inXML.exists (inName)) - return Std.parseFloat (inXML.get (inName)); - - return inDef; - - } - - - private function getFloatStyle (inKey:String, inNode:Xml, inStyles:StringMap, inDefault:Float) { - - var s = getStyle (inKey, inNode, inStyles, ""); - - if (s == "") { - - return inDefault; - - } - - return Std.parseFloat (s); - - } - - - private function getStrokeStyle (inKey:String, inNode:Xml, inStyles:StringMap , inDefault:Null) { - - var s = getStyle (inKey, inNode, inStyles, ""); - - if (s == "") { - - return inDefault; - - } - - if (s == "none") { - - return null; - - } - - if (s.charAt (0) == '#') { - - return Std.parseInt ("0x" + s.substr (1)); - - } - - return Std.parseInt (s); - - } - - - private function getStyle (inKey:String, inNode:Xml, inStyles:StringMap , inDefault:String) { - - if (inNode != null && inNode.exists (inKey)) { - - return inNode.get (inKey); - - } - - if (inStyles != null && inStyles.exists (inKey)) { - - return inStyles.get (inKey); - - } - - return inDefault; - - } - - - private function getStyles (inNode:Xml, inPrevStyles:StringMap):StringMap { - - if (!inNode.exists ("style")) - return inPrevStyles; - - var styles = new StringMap (); - - if (inPrevStyles != null) { - - for (s in inPrevStyles.keys ()) { - - styles.set (s, inPrevStyles.get (s)); - - } - - } - - var style = inNode.get ("style"); - var strings = mStyleSplit.split (style); - for (s in strings) { - - if (mStyleValue.match (s)) { - - styles.set (mStyleValue.matched (1), mStyleValue.matched (2)); - - } - - } - - return styles; - - } - - - private function loadDefs (inXML:Xml) { - - // Two passes - to allow forward xlinks - - for (pass in 0...2) { - - for (def in inXML.elements ()) { - - var name = def.nodeName; - - if (name.substr (0, 4) == "svg:") { - - name = name.substr (4); - - } - - if (name == "linearGradient") { - - loadGradient (def, GradientType.LINEAR, pass == 1); - - } else if (name == "radialGradient") { - - loadGradient (def, GradientType.RADIAL, pass == 1); - - } - - } - - } - - } + + throw ("Unknown url:" + url); + + } + + throw ("Unknown fill string:" + s); + + return FillNone; + + } + + + private function getFloat (inXML:Xml, inName:String, inDef:Float = 0.0):Float { + + if (inXML.exists (inName)) + return Std.parseFloat (inXML.get (inName)); + + return inDef; + + } + + + private function getFloatStyle (inKey:String, inNode:Xml, inStyles:StringMap, inDefault:Float) { + + var s = getStyle (inKey, inNode, inStyles, ""); + + if (s == "") { + + return inDefault; + + } + + return Std.parseFloat (s); + + } + + + private function getStrokeStyle (inKey:String, inNode:Xml, inStyles:StringMap , inDefault:Null) { + + var s = getStyle (inKey, inNode, inStyles, ""); + + if (s == "") { + + return inDefault; + + } + + if (s == "none") { + + return null; + + } + + if (s.charAt (0) == '#') { + + return Std.parseInt ("0x" + s.substr (1)); + + } + + return Std.parseInt (s); + + } + + + private function getStyle (inKey:String, inNode:Xml, inStyles:StringMap , inDefault:String) { + + if (inNode != null && inNode.exists (inKey)) { + + return inNode.get (inKey); + + } + + if (inStyles != null && inStyles.exists (inKey)) { + + return inStyles.get (inKey); + + } + + return inDefault; + + } + + + private function getStyles (inNode:Xml, inPrevStyles:StringMap):StringMap { + + if (!inNode.exists ("style")) + return inPrevStyles; + + var styles = new StringMap (); + + if (inPrevStyles != null) { + + for (s in inPrevStyles.keys ()) { + + styles.set (s, inPrevStyles.get (s)); + + } + + } + + var style = inNode.get ("style"); + var strings = mStyleSplit.split (style); + for (s in strings) { + + if (mStyleValue.match (s)) { + + styles.set (mStyleValue.matched (1), mStyleValue.matched (2)); + + } + + } + + return styles; + + } + + + private function loadDefs (inXML:Xml) { + + // Two passes - to allow forward xlinks + + for (pass in 0...2) { + + for (def in inXML.elements ()) { + + var name = def.nodeName; + + if (name.substr (0, 4) == "svg:") { + + name = name.substr (4); + + } + + if (name == "linearGradient") { + + loadGradient (def, GradientType.LINEAR, pass == 1); + + } else if (name == "radialGradient") { + + loadGradient (def, GradientType.RADIAL, pass == 1); + + } + + } + + } + + } private function loadPattern(inPattern: Xml, inCrossLink: Bool) { var name = inPattern.get("id"); @@ -398,218 +398,213 @@ class SVGData extends Group { mPatterns.set(name, pattern); } } - - private function loadGradient (inGrad:Xml, inType:GradientType, inCrossLink:Bool) { - - var name = inGrad.get ("id"); - var grad = new Grad (inType); - - if (inCrossLink && inGrad.exists("xlink:href")) { - - var xlink = inGrad.get ("xlink:href"); - - if (xlink.charAt(0) != "#") - throw ("xlink - unkown syntax : " + xlink); - - var base = mGrads.get (xlink.substr (1)); - - if (base != null) { - - grad.colors = base.colors; - grad.alphas = base.alphas; - grad.ratios = base.ratios; - grad.gradMatrix = base.gradMatrix.clone (); - grad.spread = base.spread; - grad.interp = base.interp; - grad.radius = base.radius; - - } else { - - throw ("Unknown xlink : " + xlink); - - } - - } - - if (inGrad.exists ("x1")) { - - grad.x1 = getFloat (inGrad, "x1"); - grad.y1 = getFloat (inGrad, "y1"); - grad.x2 = getFloat (inGrad, "x2"); - grad.y2 = getFloat (inGrad, "y2"); - - } else { - - grad.x1 = getFloat (inGrad, "cx"); - grad.y1 = getFloat (inGrad, "cy"); - grad.x2 = getFloat (inGrad, "fx", grad.x1); - grad.y2 = getFloat (inGrad, "fy", grad.y1); - - } - - grad.radius = getFloat (inGrad, "r"); - - if (inGrad.exists ("gradientTransform")) { - - applyTransform (grad.gradMatrix, inGrad.get ("gradientTransform")); - - } - - // todo - grad.spread = base.spread; - - for (stop in inGrad.elements ()) { - - var styles = getStyles (stop, null); - - grad.colors.push (getColorStyle ("stop-color", stop, styles, 0x000000)); - grad.alphas.push (getFloatStyle ("stop-opacity", stop, styles, 1.0)); - grad.ratios.push (Std.int (Std.parseFloat (stop.get ("offset")) * 255.0)); - - } - - mGrads.set (name, grad); - - } - - - public function loadGroup (g:Group, inG:Xml, matrix:Matrix, inStyles:StringMap ):Group { - - if (inG.exists ("transform")) { - - matrix = matrix.clone (); - applyTransform (matrix, inG.get ("transform")); - - } - - if (inG.exists ("inkscape:label")) { - - g.name = inG.get ("inkscape:label"); - - } else if (inG.exists ("id")) { - - g.name = inG.get ("id"); - - } - - var styles = getStyles (inG, inStyles); - - /* - supports eg: - - - - - - - */ - if (inG.exists("opacity")) { - - var opacity = inG.get("opacity"); - - if (styles == null) - styles = new StringMap(); - - if (styles.exists("opacity")) - opacity = Std.string( Std.parseFloat(opacity) * Std.parseFloat(styles.get("opacity")) ); - - styles.set("opacity", opacity); - - } - - for (el in inG.elements ()) { - - var name = el.nodeName; - - if (name.substr (0, 4) == "svg:") { - - name = name.substr(4); - - } - - if (name == "defs") { - - loadDefs (el); + + private function loadGradient (inGrad:Xml, inType:GradientType, inCrossLink:Bool) { + + var name = inGrad.get ("id"); + var grad = new Grad (inType); + + if (inCrossLink && inGrad.exists("xlink:href")) { + + var xlink = inGrad.get ("xlink:href"); + + if (xlink.charAt(0) != "#") + throw ("xlink - unkown syntax : " + xlink); + + var base = mGrads.get (xlink.substr (1)); + + if (base != null) { + + grad.colors = base.colors; + grad.alphas = base.alphas; + grad.ratios = base.ratios; + grad.gradMatrix = base.gradMatrix.clone (); + grad.spread = base.spread; + grad.interp = base.interp; + grad.radius = base.radius; + + } else { + + throw ("Unknown xlink : " + xlink); + + } + + } + + if (inGrad.exists ("x1")) { + + grad.x1 = getFloat (inGrad, "x1"); + grad.y1 = getFloat (inGrad, "y1"); + grad.x2 = getFloat (inGrad, "x2"); + grad.y2 = getFloat (inGrad, "y2"); + + } else { + + grad.x1 = getFloat (inGrad, "cx"); + grad.y1 = getFloat (inGrad, "cy"); + grad.x2 = getFloat (inGrad, "fx", grad.x1); + grad.y2 = getFloat (inGrad, "fy", grad.y1); + + } + + grad.radius = getFloat (inGrad, "r"); + + if (inGrad.exists ("gradientTransform")) { + + applyTransform (grad.gradMatrix, inGrad.get ("gradientTransform")); + + } + + // todo - grad.spread = base.spread; + + for (stop in inGrad.elements ()) { + + var styles = getStyles (stop, null); + + grad.colors.push (getColorStyle ("stop-color", stop, styles, 0x000000)); + grad.alphas.push (getFloatStyle ("stop-opacity", stop, styles, 1.0)); + grad.ratios.push (Std.int (Std.parseFloat (stop.get ("offset")) * 255.0)); + + } + + mGrads.set (name, grad); + + } + + + public function loadGroup (g:Group, inG:Xml, matrix:Matrix, inStyles:StringMap ):Group { + + if (inG.exists ("transform")) { + + matrix = matrix.clone (); + applyTransform (matrix, inG.get ("transform")); + + } + + if (inG.exists ("inkscape:label")) { + + g.name = inG.get ("inkscape:label"); + + } else if (inG.exists ("id")) { + + g.name = inG.get ("id"); + + } + + var styles = getStyles (inG, inStyles); + + /* + supports eg: + + + + + + + */ + if (inG.exists("opacity")) { + + var opacity = inG.get("opacity"); + + if (styles == null) + styles = new StringMap(); + + if (styles.exists("opacity")) + opacity = Std.string( Std.parseFloat(opacity) * Std.parseFloat(styles.get("opacity")) ); + + styles.set("opacity", opacity); + + } + + for (el in inG.elements ()) { + + var name = el.nodeName; + + if (name.substr (0, 4) == "svg:") { + + name = name.substr(4); + + } + + if (name == "defs") { + + loadDefs (el); } else if(name == "symbol") { saveSymbol(el); } else if(name == "use") { - applyRef(g, el, matrix, styles); - } else if (name == "g") { - - if (!(el.exists("display") && el.get("display") == "none")) { - - g.children.push (DisplayGroup (loadGroup (new Group (), el, matrix, styles))); - - } - - } else if (name == "path" || name == "line" || name == "polyline") { - g.children.push (DisplayPath (loadPath (el, matrix, styles, false, false))); - - } else if (name == "rect") { - - g.children.push (DisplayPath (loadPath (el, matrix, styles, true, false))); - - } else if (name == "polygon") { - - g.children.push (DisplayPath (loadPath (el, matrix, styles, false, false))); - - } else if (name == "ellipse") { - - g.children.push (DisplayPath (loadPath (el, matrix, styles, false, true))); - - } else if (name == "circle") { - - g.children.push (DisplayPath (loadPath (el, matrix, styles, false, true, true))); - - } else if (name == "text") { - - g.children.push (DisplayText (loadText (el, matrix, styles))); - - } else if (name == "linearGradient") { - - loadGradient (el, GradientType.LINEAR, true); - - } else if (name == "radialGradient") { - - loadGradient (el, GradientType.RADIAL, true); + g.children.push (DisplayGroup (applyRef(new Group(), el, matrix, styles))); + } else if (name == "g") { + + if (!(el.exists("display") && el.get("display") == "none")) { + + g.children.push (DisplayGroup (loadGroup (new Group (), el, matrix, styles))); + + } + + } else if (name == "path" || name == "line" || name == "polyline") { + + g.children.push (DisplayPath (loadPath (el, matrix, styles, false, false))); + + } else if (name == "rect") { + + g.children.push (DisplayPath (loadPath (el, matrix, styles, true, false))); + + } else if (name == "polygon") { + + g.children.push (DisplayPath (loadPath (el, matrix, styles, false, false))); + + } else if (name == "ellipse") { + + g.children.push (DisplayPath (loadPath (el, matrix, styles, false, true))); + + } else if (name == "circle") { + + g.children.push (DisplayPath (loadPath (el, matrix, styles, false, true, true))); + + } else if (name == "text") { + + g.children.push (DisplayText (loadText (el, matrix, styles))); + + } else if (name == "linearGradient") { + + loadGradient (el, GradientType.LINEAR, true); + + } else if (name == "radialGradient") { + + loadGradient (el, GradientType.RADIAL, true); } else if (name == "pattern") { loadPattern(el, true); - } else { - - // throw("Unknown child : " + el.nodeName ); - - } - - } - - return g; - - } + } else { + + // throw("Unknown child : " + el.nodeName ); + + } + + } + + return g; + + } public inline function saveSymbol(inText: Xml): Void { symbols.set(inText.get("id"), inText); } - private inline function getLinkXml(id: String, inText: Xml): Xml { + public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Group { + var id: String = inText.get("xlink:href"); var svg: Xml = symbols.get(id.substring(1)); //Remove the # if(svg != null) { + if(svg.firstElement().get("operated") == null) { var newParent: Xml = Xml.createElement("g"); newParent.set("operated", "true"); var newChildren: List = new List(); while(svg.firstElement() != null) { - var linkId: String = svg.firstElement().get("xlink:href"); - if(linkId != null) { - var link: Xml = getLinkXml(linkId, svg.firstElement()); - link = Xml.parse(link.toString()); - newChildren.add(link.firstElement().firstElement()); - svg.removeChild(svg.firstElement()); - } else { - newChildren.add(svg.firstElement()); - svg.removeChild(svg.firstElement()); - } + newChildren.add(svg.firstElement()); + svg.removeChild(svg.firstElement()); } svg.addChild(newParent); for(child in newChildren) { @@ -623,44 +618,24 @@ class SVGData extends Group { svg.firstElement().set(attr, value); } } + return loadGroup(g, svg.firstElement(), matrix, null); } - return svg; + return g; } - public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Void { - var id: String = inText.get("xlink:href"); - var svg: Xml = getLinkXml(id, inText); - var viewBox = new Rectangle(0, 0, width, height); - if (svg.exists("viewBox")) { - var vbox = svg.get("viewBox"); - var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); - viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); - } - var xOffset: Float = Std.parseFloat(inText.get("x")); - if(Math.isNaN(xOffset)) { - xOffset = 0; - } - var yOffset: Float = Std.parseFloat(inText.get("y")); - if(Math.isNaN(yOffset)) { - yOffset = 0; + public function loadPath (inPath:Xml, matrix:Matrix, inStyles:StringMap, inIsRect:Bool, inIsEllipse:Bool, inIsCircle:Bool=false):Path { + if (inPath.exists ("transform")) { + + matrix = matrix.clone (); + applyTransform (matrix, inPath.get ("transform")); + } - loadGroup(g, svg.firstElement(), new Matrix (1, 0, 0, 1, -viewBox.x + xOffset, -viewBox.y + yOffset), null); - } - - - public function loadPath (inPath:Xml, matrix:Matrix, inStyles:StringMap, inIsRect:Bool, inIsEllipse:Bool, inIsCircle:Bool=false):Path { - if (inPath.exists ("transform")) { - - matrix = matrix.clone (); - applyTransform (matrix, inPath.get ("transform")); - - } - - var styles = getStyles (inPath, inStyles); + + var styles = getStyles (inPath, inStyles); var name = inPath.exists ("id") ? inPath.get ("id") : ""; - var path = new Path (); - path.fill = getFillStyle ("fill", inPath, styles); + var path = new Path (); + path.fill = getFillStyle ("fill", inPath, styles); path.alpha = getFloatStyle ("opacity", inPath, styles, 1.0); switch(path.fill) { case FillGrad(grad): @@ -671,135 +646,135 @@ class SVGData extends Group { default: } path.fill_alpha = getFloatStyle ("fill-opacity", inPath, styles, 1.0); - path.stroke_alpha = getFloatStyle ("stroke-opacity", inPath, styles, 1.0); - path.stroke_colour = getStrokeStyle ("stroke", inPath, styles, null); - path.stroke_width = getFloatStyle ("stroke-width", inPath, styles, 1.0); - path.stroke_caps = CapsStyle.ROUND; - path.joint_style = JointStyle.ROUND; - path.miter_limit = getFloatStyle ("stroke-miterlimit", inPath, styles, 3.0); - path.segments = []; - path.matrix = matrix; - path.name = name; - - if (inIsRect) { - - var x = inPath.exists ("x") ? Std.parseFloat (inPath.get ("x")) : 0; - var y = inPath.exists ("y") ? Std.parseFloat (inPath.get ("y")) : 0; - var w = Std.parseFloat (inPath.get ("width")); - var h = Std.parseFloat (inPath.get ("height")); - var rx = inPath.exists ("rx") ? Std.parseFloat (inPath.get ("rx")) : 0.0; - var ry = inPath.exists ("ry") ? Std.parseFloat (inPath.get ("ry")) : 0.0; - - if (rx == 0 || ry == 0) { - - path.segments.push (new MoveSegment (x , y)); - path.segments.push (new DrawSegment (x + w, y)); - path.segments.push (new DrawSegment (x + w, y + h)); - path.segments.push (new DrawSegment (x, y + h)); - path.segments.push (new DrawSegment (x, y)); - - } else { - - path.segments.push (new MoveSegment (x, y + ry)); - - // top-left - path.segments.push (new QuadraticSegment (x, y, x + rx, y)); - path.segments.push (new DrawSegment (x + w - rx, y)); - - // top-right - path.segments.push (new QuadraticSegment (x + w, y, x + w, y + rx)); - path.segments.push (new DrawSegment (x + w, y + h - ry)); - - // bottom-right - path.segments.push (new QuadraticSegment (x + w, y + h, x + w - rx, y + h)); - path.segments.push (new DrawSegment (x + rx, y + h)); - - // bottom-left - path.segments.push (new QuadraticSegment (x, y + h, x, y + h - ry)); - path.segments.push (new DrawSegment (x, y + ry)); - - } - - } else if (inIsEllipse) { - - var x = inPath.exists ("cx") ? Std.parseFloat (inPath.get ("cx")) : 0; - var y = inPath.exists ("cy") ? Std.parseFloat (inPath.get ("cy")) : 0; - var r = inIsCircle && inPath.exists ("r") ? Std.parseFloat (inPath.get ("r")) : 0.0; - var w = inIsCircle ? r : inPath.exists ("rx") ? Std.parseFloat (inPath.get ("rx")) : 0.0; - var w_ = w * SIN45; - var cw_ = w * TAN22; - var h = inIsCircle ? r : inPath.exists ("ry") ? Std.parseFloat (inPath.get ("ry")) : 0.0; - var h_ = h * SIN45; - var ch_ = h * TAN22; - - path.segments.push (new MoveSegment (x + w, y)); - path.segments.push (new QuadraticSegment (x + w, y + ch_, x + w_, y + h_)); - path.segments.push (new QuadraticSegment (x + cw_, y + h, x, y + h)); - path.segments.push (new QuadraticSegment (x - cw_, y + h, x - w_, y + h_)); - path.segments.push (new QuadraticSegment (x - w, y + ch_, x - w, y)); - path.segments.push (new QuadraticSegment (x - w, y - ch_, x - w_, y - h_)); - path.segments.push (new QuadraticSegment (x - cw_, y - h, x, y - h)); - path.segments.push (new QuadraticSegment (x + cw_, y - h, x + w_, y - h_)); - path.segments.push (new QuadraticSegment (x + w, y - ch_, x + w, y)); - - } else { - - var d = inPath.exists ("points") ? ("M" + inPath.get ("points") + "z") : - inPath.exists ("x1") ? ("M" + inPath.get ("x1") + "," + inPath.get ("y1") + " " + inPath.get ("x2") + "," + inPath.get ("y2") + "z") : - inPath.get ("d"); - - for (segment in mPathParser.parse (d, mConvertCubics)) { - - path.segments.push (segment); - - } - - } - - return path; - - } - - - public function loadText (inText:Xml, matrix:Matrix, inStyles:StringMap ):Text { - - if (inText.exists ("transform")) { - - matrix = matrix.clone (); - applyTransform (matrix, inText.get ("transform")); - - } - - var styles = getStyles (inText, inStyles); - var text = new Text (); - - text.matrix = matrix; - text.name = inText.exists ("id") ? inText.get ("id") : ""; - text.x = getFloat (inText, "x", 0.0); - text.y = getFloat (inText, "y", 0.0); - text.fill = getFillStyle ("fill", inText, styles); - text.fill_alpha = getFloatStyle ("fill-opacity", inText, styles, 1.0); - text.stroke_alpha = getFloatStyle ("stroke-opacity", inText, styles, 1.0); - text.stroke_colour = getStrokeStyle ("stroke", inText, styles, null); - text.stroke_width = getFloatStyle ("stroke-width", inText, styles, 1.0); - text.font_family = getStyle ("font-family", inText, styles, ""); - text.font_size = getFloatStyle ("font-size", inText, styles, 12); - text.letter_spacing = getFloatStyle ("letter-spacing", inText, styles, 0); - text.kerning = getFloatStyle ("kerning", inText, styles, 0); - - var string = ""; - - for (el in inText.elements ()) { - - string += el.toString(); - - } - - //trace(string); - text.text = string; - return text; - - } - - + path.stroke_alpha = getFloatStyle ("stroke-opacity", inPath, styles, 1.0); + path.stroke_colour = getStrokeStyle ("stroke", inPath, styles, null); + path.stroke_width = getFloatStyle ("stroke-width", inPath, styles, 1.0); + path.stroke_caps = CapsStyle.ROUND; + path.joint_style = JointStyle.ROUND; + path.miter_limit = getFloatStyle ("stroke-miterlimit", inPath, styles, 3.0); + path.segments = []; + path.matrix = matrix; + path.name = name; + + if (inIsRect) { + + var x = inPath.exists ("x") ? Std.parseFloat (inPath.get ("x")) : 0; + var y = inPath.exists ("y") ? Std.parseFloat (inPath.get ("y")) : 0; + var w = Std.parseFloat (inPath.get ("width")); + var h = Std.parseFloat (inPath.get ("height")); + var rx = inPath.exists ("rx") ? Std.parseFloat (inPath.get ("rx")) : 0.0; + var ry = inPath.exists ("ry") ? Std.parseFloat (inPath.get ("ry")) : 0.0; + + if (rx == 0 || ry == 0) { + + path.segments.push (new MoveSegment (x , y)); + path.segments.push (new DrawSegment (x + w, y)); + path.segments.push (new DrawSegment (x + w, y + h)); + path.segments.push (new DrawSegment (x, y + h)); + path.segments.push (new DrawSegment (x, y)); + + } else { + + path.segments.push (new MoveSegment (x, y + ry)); + + // top-left + path.segments.push (new QuadraticSegment (x, y, x + rx, y)); + path.segments.push (new DrawSegment (x + w - rx, y)); + + // top-right + path.segments.push (new QuadraticSegment (x + w, y, x + w, y + rx)); + path.segments.push (new DrawSegment (x + w, y + h - ry)); + + // bottom-right + path.segments.push (new QuadraticSegment (x + w, y + h, x + w - rx, y + h)); + path.segments.push (new DrawSegment (x + rx, y + h)); + + // bottom-left + path.segments.push (new QuadraticSegment (x, y + h, x, y + h - ry)); + path.segments.push (new DrawSegment (x, y + ry)); + + } + + } else if (inIsEllipse) { + + var x = inPath.exists ("cx") ? Std.parseFloat (inPath.get ("cx")) : 0; + var y = inPath.exists ("cy") ? Std.parseFloat (inPath.get ("cy")) : 0; + var r = inIsCircle && inPath.exists ("r") ? Std.parseFloat (inPath.get ("r")) : 0.0; + var w = inIsCircle ? r : inPath.exists ("rx") ? Std.parseFloat (inPath.get ("rx")) : 0.0; + var w_ = w * SIN45; + var cw_ = w * TAN22; + var h = inIsCircle ? r : inPath.exists ("ry") ? Std.parseFloat (inPath.get ("ry")) : 0.0; + var h_ = h * SIN45; + var ch_ = h * TAN22; + + path.segments.push (new MoveSegment (x + w, y)); + path.segments.push (new QuadraticSegment (x + w, y + ch_, x + w_, y + h_)); + path.segments.push (new QuadraticSegment (x + cw_, y + h, x, y + h)); + path.segments.push (new QuadraticSegment (x - cw_, y + h, x - w_, y + h_)); + path.segments.push (new QuadraticSegment (x - w, y + ch_, x - w, y)); + path.segments.push (new QuadraticSegment (x - w, y - ch_, x - w_, y - h_)); + path.segments.push (new QuadraticSegment (x - cw_, y - h, x, y - h)); + path.segments.push (new QuadraticSegment (x + cw_, y - h, x + w_, y - h_)); + path.segments.push (new QuadraticSegment (x + w, y - ch_, x + w, y)); + + } else { + + var d = inPath.exists ("points") ? ("M" + inPath.get ("points") + "z") : + inPath.exists ("x1") ? ("M" + inPath.get ("x1") + "," + inPath.get ("y1") + " " + inPath.get ("x2") + "," + inPath.get ("y2") + "z") : + inPath.get ("d"); + + for (segment in mPathParser.parse (d, mConvertCubics)) { + + path.segments.push (segment); + + } + + } + + return path; + + } + + + public function loadText (inText:Xml, matrix:Matrix, inStyles:StringMap ):Text { + + if (inText.exists ("transform")) { + + matrix = matrix.clone (); + applyTransform (matrix, inText.get ("transform")); + + } + + var styles = getStyles (inText, inStyles); + var text = new Text (); + + text.matrix = matrix; + text.name = inText.exists ("id") ? inText.get ("id") : ""; + text.x = getFloat (inText, "x", 0.0); + text.y = getFloat (inText, "y", 0.0); + text.fill = getFillStyle ("fill", inText, styles); + text.fill_alpha = getFloatStyle ("fill-opacity", inText, styles, 1.0); + text.stroke_alpha = getFloatStyle ("stroke-opacity", inText, styles, 1.0); + text.stroke_colour = getStrokeStyle ("stroke", inText, styles, null); + text.stroke_width = getFloatStyle ("stroke-width", inText, styles, 1.0); + text.font_family = getStyle ("font-family", inText, styles, ""); + text.font_size = getFloatStyle ("font-size", inText, styles, 12); + text.letter_spacing = getFloatStyle ("letter-spacing", inText, styles, 0); + text.kerning = getFloatStyle ("kerning", inText, styles, 0); + + var string = ""; + + for (el in inText.elements ()) { + + string += el.toString(); + + } + + //trace(string); + text.text = string; + return text; + + } + + } \ No newline at end of file From 1b5f18407200f6112a87093ee3d923afa7e9de03 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Thu, 6 Mar 2014 18:32:46 -0800 Subject: [PATCH 15/19] removed inline for applyRef --- format/svg/SVGData.hx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index c7de699..dcdf5a6 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -80,7 +80,6 @@ class SVGData extends Group { var vbox = svg.get("viewBox"); var params = vbox.indexOf(",") != -1 ? vbox.split(",") : vbox.split(" "); viewBox = new Rectangle( trimToFloat(params[0]), trimToFloat(params[1]), trimToFloat(params[2]), trimToFloat(params[3]) ); - } loadGroup(this, svg, new Matrix (1, 0, 0, 1, -viewBox.x, -viewBox.y), null); @@ -592,7 +591,7 @@ class SVGData extends Group { symbols.set(inText.get("id"), inText); } - public inline function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Group { + public function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Group { var id: String = inText.get("xlink:href"); var svg: Xml = symbols.get(id.substring(1)); //Remove the # @@ -777,4 +776,4 @@ class SVGData extends Group { } -} \ No newline at end of file +} From b9fdd538ebca05bee593c245d12f29d0361a9ba5 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Wed, 19 Mar 2014 11:59:18 -0700 Subject: [PATCH 16/19] added support for rgb style fills --- format/svg/SVGData.hx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx index dcdf5a6..6afb320 100644 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -186,7 +186,6 @@ class SVGData extends Group { private function getFillStyle (inKey:String, inNode:Xml, inStyles:StringMap) { - var s = getStyle (inKey, inNode, inStyles, ""); if (s == "") { @@ -223,6 +222,14 @@ class SVGData extends Group { } + if(StringTools.startsWith(s, "rgb")) { + var r: EReg = ~/rgb/g; + var rgbFull: Array = r.split(s); + var rgb: String = StringTools.replace(rgbFull[1], "(", ""); + rgb = StringTools.replace(rgb, ")", ""); + var frags: Array = rgb.split(","); + return FillSolid(rgbToHex(Std.parseInt(frags[0]), Std.parseInt(frags[1]), Std.parseInt(frags[2]))); + } throw ("Unknown fill string:" + s); return FillNone; @@ -776,4 +783,7 @@ class SVGData extends Group { } + private inline function rgbToHex(r: Int, g: Int, b: Int): Int { + return r << 16 ^ g << 8 ^ b; + } } From 624047b665fd6df27aa149bc7adb889bc13d7640 Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Fri, 23 May 2014 17:19:38 -0700 Subject: [PATCH 17/19] added clip paths --- .gitignore | 0 README.md | 0 format/SVG.hx | 0 format/gfx/BitmapFill.hx | 0 format/gfx/Gfx.hx | 0 format/gfx/Gfx2Haxe.hx | 0 format/gfx/GfxBytes.hx | 0 format/gfx/GfxExtent.hx | 0 format/gfx/GfxGraphics.hx | 0 format/gfx/GfxTextFinder.hx | 0 format/gfx/Gradient.hx | 0 format/gfx/LineStyle.hx | 0 format/svg/BitmapDataManager.hx | 0 format/svg/BitmapFill.hx | 0 format/svg/FillType.hx | 0 format/svg/Grad.hx | 0 format/svg/Gradient.hx | 0 format/svg/Group.hx | 0 format/svg/Path.hx | 0 format/svg/PathParser.hx | 0 format/svg/PathSegment.hx | 0 format/svg/RenderContext.hx | 0 format/svg/SVG2Gfx.hx | 0 format/svg/SVGData.hx | 85 +++++++++++++++++++++++++-------- format/svg/SVGRenderer.hx | 0 format/svg/Text.hx | 0 haxelib.xml | 0 27 files changed, 66 insertions(+), 19 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 README.md mode change 100644 => 100755 format/SVG.hx mode change 100644 => 100755 format/gfx/BitmapFill.hx mode change 100644 => 100755 format/gfx/Gfx.hx mode change 100644 => 100755 format/gfx/Gfx2Haxe.hx mode change 100644 => 100755 format/gfx/GfxBytes.hx mode change 100644 => 100755 format/gfx/GfxExtent.hx mode change 100644 => 100755 format/gfx/GfxGraphics.hx mode change 100644 => 100755 format/gfx/GfxTextFinder.hx mode change 100644 => 100755 format/gfx/Gradient.hx mode change 100644 => 100755 format/gfx/LineStyle.hx mode change 100644 => 100755 format/svg/BitmapDataManager.hx mode change 100644 => 100755 format/svg/BitmapFill.hx mode change 100644 => 100755 format/svg/FillType.hx mode change 100644 => 100755 format/svg/Grad.hx mode change 100644 => 100755 format/svg/Gradient.hx mode change 100644 => 100755 format/svg/Group.hx mode change 100644 => 100755 format/svg/Path.hx mode change 100644 => 100755 format/svg/PathParser.hx mode change 100644 => 100755 format/svg/PathSegment.hx mode change 100644 => 100755 format/svg/RenderContext.hx mode change 100644 => 100755 format/svg/SVG2Gfx.hx mode change 100644 => 100755 format/svg/SVGData.hx mode change 100644 => 100755 format/svg/SVGRenderer.hx mode change 100644 => 100755 format/svg/Text.hx mode change 100644 => 100755 haxelib.xml diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/format/SVG.hx b/format/SVG.hx old mode 100644 new mode 100755 diff --git a/format/gfx/BitmapFill.hx b/format/gfx/BitmapFill.hx old mode 100644 new mode 100755 diff --git a/format/gfx/Gfx.hx b/format/gfx/Gfx.hx old mode 100644 new mode 100755 diff --git a/format/gfx/Gfx2Haxe.hx b/format/gfx/Gfx2Haxe.hx old mode 100644 new mode 100755 diff --git a/format/gfx/GfxBytes.hx b/format/gfx/GfxBytes.hx old mode 100644 new mode 100755 diff --git a/format/gfx/GfxExtent.hx b/format/gfx/GfxExtent.hx old mode 100644 new mode 100755 diff --git a/format/gfx/GfxGraphics.hx b/format/gfx/GfxGraphics.hx old mode 100644 new mode 100755 diff --git a/format/gfx/GfxTextFinder.hx b/format/gfx/GfxTextFinder.hx old mode 100644 new mode 100755 diff --git a/format/gfx/Gradient.hx b/format/gfx/Gradient.hx old mode 100644 new mode 100755 diff --git a/format/gfx/LineStyle.hx b/format/gfx/LineStyle.hx old mode 100644 new mode 100755 diff --git a/format/svg/BitmapDataManager.hx b/format/svg/BitmapDataManager.hx old mode 100644 new mode 100755 diff --git a/format/svg/BitmapFill.hx b/format/svg/BitmapFill.hx old mode 100644 new mode 100755 diff --git a/format/svg/FillType.hx b/format/svg/FillType.hx old mode 100644 new mode 100755 diff --git a/format/svg/Grad.hx b/format/svg/Grad.hx old mode 100644 new mode 100755 diff --git a/format/svg/Gradient.hx b/format/svg/Gradient.hx old mode 100644 new mode 100755 diff --git a/format/svg/Group.hx b/format/svg/Group.hx old mode 100644 new mode 100755 diff --git a/format/svg/Path.hx b/format/svg/Path.hx old mode 100644 new mode 100755 diff --git a/format/svg/PathParser.hx b/format/svg/PathParser.hx old mode 100644 new mode 100755 diff --git a/format/svg/PathSegment.hx b/format/svg/PathSegment.hx old mode 100644 new mode 100755 diff --git a/format/svg/RenderContext.hx b/format/svg/RenderContext.hx old mode 100644 new mode 100755 diff --git a/format/svg/SVG2Gfx.hx b/format/svg/SVG2Gfx.hx old mode 100644 new mode 100755 diff --git a/format/svg/SVGData.hx b/format/svg/SVGData.hx old mode 100644 new mode 100755 index 6afb320..8dfc130 --- a/format/svg/SVGData.hx +++ b/format/svg/SVGData.hx @@ -46,6 +46,9 @@ class SVGData extends Group { private var mPatternsSVG: Map; private var mPathParser:PathParser; private var symbols: Map; + private var mLinkPaths: Map; + private var mClipPathLinks: Map; + private var clipIncId: Int = 1; public function new (inXML:Xml, inConvertCubics:Bool = false) { @@ -100,13 +103,13 @@ class SVGData extends Group { if (mTranslateMatch.match(inTrans)) { - // TODO: Pre-translate +// TODO: Pre-translate ioMatrix.translate (Std.parseFloat (mTranslateMatch.matched (1)), Std.parseFloat (mTranslateMatch.matched (2))); } else if (mScaleMatch.match (inTrans)) { - // TODO: Pre-scale +// TODO: Pre-scale var s = Std.parseFloat (mScaleMatch.matched (1)); ioMatrix.scale (s, s); scale = s; @@ -344,7 +347,7 @@ class SVGData extends Group { private function loadDefs (inXML:Xml) { - // Two passes - to allow forward xlinks +// Two passes - to allow forward xlinks for (pass in 0...2) { @@ -366,6 +369,11 @@ class SVGData extends Group { loadGradient (def, GradientType.RADIAL, pass == 1); + } else if(name == "path") { + if(mLinkPaths == null) { + mLinkPaths = new Map(); + } + mLinkPaths.set(def.get("id"), def); } } @@ -461,7 +469,7 @@ class SVGData extends Group { } - // todo - grad.spread = base.spread; +// todo - grad.spread = base.spread; for (stop in inGrad.elements ()) { @@ -499,15 +507,15 @@ class SVGData extends Group { var styles = getStyles (inG, inStyles); - /* - supports eg: - - - - - - - */ +/* +supports eg: + + + + + + +*/ if (inG.exists("opacity")) { var opacity = inG.get("opacity"); @@ -522,6 +530,28 @@ class SVGData extends Group { } + if(styles != null && styles.exists("clip-path")) { +//we're clipping +// we need to get the bitmap fill and apply it to the path + var clipFill = new BitmapFill(); + inG.nodeName = "svg"; + inG.remove("style"); + var inGString: String = inG.toString(); + var bitmapData = BitmapDataManager.create(inGString, inGString, 1, false); + clipFill.bitmapData = bitmapData; + + var clipId: String = styles.get("clip-path"); + clipId = clipId.substring(5, clipId.length - 1); + var pathId: String = mClipPathLinks.get(clipId); + var clipXml: Xml = mLinkPaths.get(pathId); + pathId += "_" + clipIncId++; + mPatterns.set(pathId, clipFill); + clipXml.set("style:fill", "url(#" + pathId + ")"); + styles.set("fill", "url(#" + pathId + ")"); + g.children.push (DisplayPath (loadPath (clipXml, matrix, styles, false, false))); + return g; + } + for (el in inG.elements ()) { var name = el.nodeName; @@ -582,9 +612,11 @@ class SVGData extends Group { } else if (name == "pattern") { loadPattern(el, true); + } else if (name == "clipPath") { + storeClipPath(el); } else { - // throw("Unknown child : " + el.nodeName ); +// throw("Unknown child : " + el.nodeName ); } @@ -598,6 +630,21 @@ class SVGData extends Group { symbols.set(inText.get("id"), inText); } + private inline function storeClipPath(inText: Xml): Void { + if(mClipPathLinks == null) { + mClipPathLinks = new Map(); + } + var linkUrl: String = ""; + for(el in inText.elements()) { + var name = el.nodeName; + if(name == "use") { + linkUrl = el.get("xlink:href"); + break; + } + } + mClipPathLinks.set(inText.get("id"), linkUrl.substring(1)); + } + public function applyRef(g:Group, inText:Xml, matrix:Matrix, inStyles:StringMap ): Group { var id: String = inText.get("xlink:href"); var svg: Xml = symbols.get(id.substring(1)); //Remove the # @@ -683,19 +730,19 @@ class SVGData extends Group { path.segments.push (new MoveSegment (x, y + ry)); - // top-left +// top-left path.segments.push (new QuadraticSegment (x, y, x + rx, y)); path.segments.push (new DrawSegment (x + w - rx, y)); - // top-right +// top-right path.segments.push (new QuadraticSegment (x + w, y, x + w, y + rx)); path.segments.push (new DrawSegment (x + w, y + h - ry)); - // bottom-right +// bottom-right path.segments.push (new QuadraticSegment (x + w, y + h, x + w - rx, y + h)); path.segments.push (new DrawSegment (x + rx, y + h)); - // bottom-left +// bottom-left path.segments.push (new QuadraticSegment (x, y + h, x, y + h - ry)); path.segments.push (new DrawSegment (x, y + ry)); @@ -776,7 +823,7 @@ class SVGData extends Group { } - //trace(string); +//trace(string); text.text = string; return text; diff --git a/format/svg/SVGRenderer.hx b/format/svg/SVGRenderer.hx old mode 100644 new mode 100755 diff --git a/format/svg/Text.hx b/format/svg/Text.hx old mode 100644 new mode 100755 diff --git a/haxelib.xml b/haxelib.xml old mode 100644 new mode 100755 From d6ac086be0e5e465a54224ca86ae2b62b4971d0e Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Thu, 11 Oct 2018 19:52:43 -0400 Subject: [PATCH 18/19] some fixes --- format/gfx/GfxBytes.hx | 19 +++++++++++++++++++ format/gfx/Gradient.hx | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/format/gfx/GfxBytes.hx b/format/gfx/GfxBytes.hx index df3ccdb..2e2a15a 100755 --- a/format/gfx/GfxBytes.hx +++ b/format/gfx/GfxBytes.hx @@ -118,7 +118,11 @@ class GfxBytes extends Gfx case GRADIENT_FILL: var grad = new Gradient(); + #if (openfl_legacy || openfl < 3.6) grad.type = Type.createEnumIndex(GradientType,buffer.readByte()); + #else + grad.type = cast buffer.readByte(); + #end var len = buffer.readByte(); for(i in 0...len) { @@ -208,7 +212,11 @@ class GfxBytes extends Gfx override public function beginGradientFill(grad:Gradient) { buffer.writeByte(GRADIENT_FILL); + #if (openfl_legacy || openfl < 3.6) buffer.writeByte(Type.enumIndex(grad.type)); + #else + buffer.writeByte(cast grad.type); + #end buffer.writeByte(grad.colors.length); for(i in 0...grad.colors.length) { @@ -222,8 +230,13 @@ class GfxBytes extends Gfx buffer.writeFloat(grad.matrix.d); buffer.writeFloat(grad.matrix.tx); buffer.writeFloat(grad.matrix.ty); + #if (openfl_legacy || openfl < 3.6) buffer.writeByte(Type.enumIndex(grad.spread)); buffer.writeByte(Type.enumIndex(grad.interp)); + #else + buffer.writeByte(cast grad.spread); + buffer.writeByte(cast grad.interp); + #end buffer.writeFloat(grad.focus); } @@ -245,9 +258,15 @@ class GfxBytes extends Gfx writeRGB(style.color); buffer.writeFloat(style.alpha); buffer.writeByte(style.pixelHinting?1:0); + #if (openfl_legacy || openfl < 3.6) buffer.writeByte(Type.enumIndex(style.scaleMode)); buffer.writeByte(Type.enumIndex(style.capsStyle)); buffer.writeByte(Type.enumIndex(style.jointStyle)); + #else + buffer.writeByte(cast style.scaleMode); + buffer.writeByte(cast style.capsStyle); + buffer.writeByte(cast style.jointStyle); + #end buffer.writeFloat(style.miterLimit); } diff --git a/format/gfx/Gradient.hx b/format/gfx/Gradient.hx index ba9e7e0..f1faf62 100755 --- a/format/gfx/Gradient.hx +++ b/format/gfx/Gradient.hx @@ -23,7 +23,7 @@ class Gradient } public var type:GradientType; - public var colors:Array; + public var colors:Array; public var alphas:Array; public var ratios:Array; public var matrix: Matrix; From 440fe031444f9770e8a501a1876d284c264f8f4f Mon Sep 17 00:00:00 2001 From: Skyler Parr Date: Mon, 29 Nov 2021 20:20:58 -0500 Subject: [PATCH 19/19] removed some legacy conditional compilation --- format/gfx/GfxBytes.hx | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/format/gfx/GfxBytes.hx b/format/gfx/GfxBytes.hx index 2e2a15a..c61c01e 100755 --- a/format/gfx/GfxBytes.hx +++ b/format/gfx/GfxBytes.hx @@ -118,11 +118,7 @@ class GfxBytes extends Gfx case GRADIENT_FILL: var grad = new Gradient(); - #if (openfl_legacy || openfl < 3.6) - grad.type = Type.createEnumIndex(GradientType,buffer.readByte()); - #else grad.type = cast buffer.readByte(); - #end var len = buffer.readByte(); for(i in 0...len) { @@ -212,11 +208,7 @@ class GfxBytes extends Gfx override public function beginGradientFill(grad:Gradient) { buffer.writeByte(GRADIENT_FILL); - #if (openfl_legacy || openfl < 3.6) - buffer.writeByte(Type.enumIndex(grad.type)); - #else buffer.writeByte(cast grad.type); - #end buffer.writeByte(grad.colors.length); for(i in 0...grad.colors.length) { @@ -230,13 +222,8 @@ class GfxBytes extends Gfx buffer.writeFloat(grad.matrix.d); buffer.writeFloat(grad.matrix.tx); buffer.writeFloat(grad.matrix.ty); - #if (openfl_legacy || openfl < 3.6) - buffer.writeByte(Type.enumIndex(grad.spread)); - buffer.writeByte(Type.enumIndex(grad.interp)); - #else buffer.writeByte(cast grad.spread); buffer.writeByte(cast grad.interp); - #end buffer.writeFloat(grad.focus); } @@ -258,15 +245,9 @@ class GfxBytes extends Gfx writeRGB(style.color); buffer.writeFloat(style.alpha); buffer.writeByte(style.pixelHinting?1:0); - #if (openfl_legacy || openfl < 3.6) - buffer.writeByte(Type.enumIndex(style.scaleMode)); - buffer.writeByte(Type.enumIndex(style.capsStyle)); - buffer.writeByte(Type.enumIndex(style.jointStyle)); - #else buffer.writeByte(cast style.scaleMode); buffer.writeByte(cast style.capsStyle); buffer.writeByte(cast style.jointStyle); - #end buffer.writeFloat(style.miterLimit); }