--- SvgParser-alpha1.1.4.lua 2012-04-17 08:27:20.000000000 +0100 +++ SvgParser.lua 2012-04-20 14:08:50.000000000 +0100 @@ -1,6 +1,37 @@ SvgParser = Core.class() +-- New declarations for SVG symbol processing +-- Added by AWB 20/APR/2012 +local symbols={} +function table.deepcopy(object) + local lookup_table = {} + local function _copy(object) + if type(object) ~= "table" then + return object + elseif lookup_table[object] then + return lookup_table[object] + end + local new_table = {} + lookup_table[object] = new_table + for index, value in pairs(object) do + new_table[_copy(index)] = _copy(value) + end + return setmetatable(new_table, getmetatable(object)) + end + return _copy(object) +end + +function Matrix:multiply(matrix) + local tx = self:getTx() + matrix:getTx() + local ty = self:getTy() + matrix:getTy() + local m11 = matrix:getM11() * self:getM11() + matrix:getM12() * self:getM21() + local m21 = matrix:getM21() * self:getM11() + matrix:getM22() * self:getM21() + local m12 = matrix:getM11() * self:getM12() + matrix:getM12() * self:getM22() + local m22 = matrix:getM21() * self:getM12() + matrix:getM22() * self:getM22() + return Matrix.new(m11, m12, m21, m22, tx, ty) +end +--- End AWB 20/APR/2012 ----------------------------------------------------------------------------------------------------------- --[[ PRIVATE ]] @@ -224,6 +255,54 @@ obj:setMatrix( matrix ) -- Matrix end + --[[ ADDED BY AWB 20/APR/2012 ]] + if t.Name == "symbol" then + -- Register a Symbol with our symbol table. + -- print("symbol", t.Attributes.id, t.Attributes.viewBox, t.ChildNodes) + + for i,child in ipairs( t.ChildNodes ) do -- restart cycle + -- I'm not sure if symbols can contain more than one node in their definition + -- but here we only allow a single node + assert(i==1, "found more than one symbol node") + + -- print( string.format("recording symbol: %s as %s", t.Attributes.id, child.Name )) + -- Record the child node in our symbol table + symbols["#"..t.Attributes.id]=child + end + end + + --[[ ADDED BY AWB 20/APR/2012]] + if t.Name == "use" then + -- Use a pre-registered symbol. Fetch a copy of the definition node from the symbol table. + -- We have to make a deep copy because process_data() will modify it. Note, it would + -- be more efficient to change process_data() keep the node it is processing intact. + + local symbol=table.deepcopy(symbols[t.Attributes.href]) + -- print( string.format("use symbol: %s(%s)", t.Attributes.href, symbolChild.Name)) + + -- Process the node and retrieve the object instance that has been created + process_data( symbol, groups ) + obj=groups:getChildAt(groups:getNumChildren()) + + -- Symbol "use" nodes that have transforms appear to have a coordinate system based around the + -- centre of the symbol viewport. Here we must create a translation to account for this. + x=Matrix.new() + if symbol.Attributes.transform then + local w=obj:getWidth() + local h=obj:getHeight() + local sx=matrix:getM11() + local sy=-matrix:getM22() + local tx=w/2-w*sx/2 + local ty=-h/2-h*sy/2 + local t=Matrix.new(1, 0, 0, 1, tx, ty) + x=x:multiply(t) + end + + -- Apply the instance transformation and our translation matrix (if any) + x=x:multiply(matrix):multiply(obj:getMatrix()) + obj:setMatrix(x) + end + ----------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------