77d04ceab8
Updated build script to create win32/linux/macos versions. Fixed the defaults to they work with PLA. Fixed the temperature plugin default "ON" problem. Removed all profiles except for PLA.
955 lines
38 KiB
Python
955 lines
38 KiB
Python
"""
|
|
Svg reader.
|
|
|
|
"""
|
|
|
|
|
|
from __future__ import absolute_import
|
|
#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
|
|
import __init__
|
|
|
|
from fabmetheus_utilities.geometry.solids import triangle_mesh
|
|
from fabmetheus_utilities.xml_simple_reader import DocumentNode
|
|
from fabmetheus_utilities import archive
|
|
from fabmetheus_utilities import euclidean
|
|
from fabmetheus_utilities import gcodec
|
|
from fabmetheus_utilities import intercircle
|
|
from fabmetheus_utilities import settings
|
|
from fabmetheus_utilities import svg_writer
|
|
import math
|
|
import os
|
|
import sys
|
|
import traceback
|
|
|
|
|
|
__author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
|
|
__credits__ = 'Nophead <http://hydraraptor.blogspot.com/>\nArt of Illusion <http://www.artofillusion.org/>'
|
|
__date__ = '$Date: 2008/21/04 $'
|
|
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
|
|
|
|
|
globalNumberOfCornerPoints = 11
|
|
globalNumberOfBezierPoints = globalNumberOfCornerPoints + globalNumberOfCornerPoints
|
|
globalNumberOfCirclePoints = 4 * globalNumberOfCornerPoints
|
|
|
|
|
|
def addFunctionsToDictionary( dictionary, functions, prefix ):
|
|
"Add functions to dictionary."
|
|
for function in functions:
|
|
dictionary[ function.__name__[ len( prefix ) : ] ] = function
|
|
|
|
def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation):
|
|
'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes'
|
|
if begin == end:
|
|
print('Warning, begin equals end in getArcComplexes in svgReader')
|
|
print(begin)
|
|
print(end)
|
|
return []
|
|
if radius.imag < 0.0:
|
|
print('Warning, radius.imag is less than zero in getArcComplexes in svgReader')
|
|
print(radius)
|
|
radius = complex(radius.real, abs(radius.imag))
|
|
if radius.real < 0.0:
|
|
print('Warning, radius.real is less than zero in getArcComplexes in svgReader')
|
|
print(radius)
|
|
radius = complex(abs(radius.real), radius.imag)
|
|
if radius.imag <= 0.0:
|
|
print('Warning, radius.imag is too small for getArcComplexes in svgReader')
|
|
print(radius)
|
|
return [end]
|
|
if radius.real <= 0.0:
|
|
print('Warning, radius.real is too small for getArcComplexes in svgReader')
|
|
print(radius)
|
|
return [end]
|
|
xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation)
|
|
reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag)
|
|
beginRotated = begin * reverseXAxisRotationComplex
|
|
endRotated = end * reverseXAxisRotationComplex
|
|
beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag)
|
|
endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag)
|
|
midpointTransformed = 0.5 * (beginTransformed + endTransformed)
|
|
midMinusBeginTransformed = midpointTransformed - beginTransformed
|
|
midMinusBeginTransformedLength = abs(midMinusBeginTransformed)
|
|
if midMinusBeginTransformedLength > 1.0:
|
|
print('The ellipse radius is too small for getArcComplexes in svgReader.')
|
|
print('So the ellipse will be scaled to fit, according to the formulas in "Step 3: Ensure radii are large enough" of:')
|
|
print('http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii')
|
|
print('')
|
|
radius *= midMinusBeginTransformedLength
|
|
beginTransformed /= midMinusBeginTransformedLength
|
|
endTransformed /= midMinusBeginTransformedLength
|
|
midpointTransformed /= midMinusBeginTransformedLength
|
|
midMinusBeginTransformed /= midMinusBeginTransformedLength
|
|
midMinusBeginTransformedLength = 1.0
|
|
midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real)
|
|
midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength
|
|
if midWiddershinsLengthSquared < 0.0:
|
|
midWiddershinsLengthSquared = 0.0
|
|
midWiddershinsLength = math.sqrt(midWiddershinsLengthSquared)
|
|
midWiddershinsTransformed *= midWiddershinsLength / abs(midWiddershinsTransformed)
|
|
centerTransformed = midpointTransformed
|
|
if largeArcFlag == sweepFlag:
|
|
centerTransformed -= midWiddershinsTransformed
|
|
else:
|
|
centerTransformed += midWiddershinsTransformed
|
|
beginMinusCenterTransformed = beginTransformed - centerTransformed
|
|
beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed)
|
|
if beginMinusCenterTransformedLength <= 0.0:
|
|
return end
|
|
beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real)
|
|
endMinusCenterTransformed = endTransformed - centerTransformed
|
|
angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCenterTransformed, beginMinusCenterTransformed)
|
|
if sweepFlag:
|
|
if angleDifference < 0.0:
|
|
angleDifference += 2.0 * math.pi
|
|
else:
|
|
if angleDifference > 0.0:
|
|
angleDifference -= 2.0 * math.pi
|
|
global globalSideAngle
|
|
sides = int(math.ceil(abs(angleDifference) / globalSideAngle))
|
|
sideAngle = angleDifference / float(sides)
|
|
arcComplexes = []
|
|
center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex
|
|
for side in xrange(1, sides):
|
|
unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle + float(side) * sideAngle)
|
|
circumferential = complex(unitPolar.real * radius.real, unitPolar.imag * radius.imag) * beginMinusCenterTransformedLength
|
|
point = center + circumferential * xAxisRotationComplex
|
|
arcComplexes.append(point)
|
|
arcComplexes.append(end)
|
|
return arcComplexes
|
|
|
|
def getChainMatrixSVG(elementNode, matrixSVG):
|
|
"Get chain matrixSVG by svgElement."
|
|
matrixSVG = matrixSVG.getOtherTimesSelf(getMatrixSVG(elementNode).tricomplex)
|
|
if elementNode.parentNode != None:
|
|
matrixSVG = getChainMatrixSVG(elementNode.parentNode, matrixSVG)
|
|
return matrixSVG
|
|
|
|
def getChainMatrixSVGIfNecessary(elementNode, yAxisPointingUpward):
|
|
"Get chain matrixSVG by svgElement and yAxisPointingUpward."
|
|
matrixSVG = MatrixSVG()
|
|
if yAxisPointingUpward:
|
|
return matrixSVG
|
|
return getChainMatrixSVG(elementNode, matrixSVG)
|
|
|
|
def getCubicPoint( along, begin, controlPoints, end ):
|
|
'Get the cubic point.'
|
|
segmentBegin = getQuadraticPoint( along, begin, controlPoints[0], controlPoints[1] )
|
|
segmentEnd = getQuadraticPoint( along, controlPoints[0], controlPoints[1], end )
|
|
return ( 1.0 - along ) * segmentBegin + along * segmentEnd
|
|
|
|
def getCubicPoints( begin, controlPoints, end, numberOfBezierPoints=globalNumberOfBezierPoints):
|
|
'Get the cubic points.'
|
|
bezierPortion = 1.0 / float(numberOfBezierPoints)
|
|
cubicPoints = []
|
|
for bezierIndex in xrange( 1, numberOfBezierPoints + 1 ):
|
|
cubicPoints.append(getCubicPoint(bezierPortion * bezierIndex, begin, controlPoints, end))
|
|
return cubicPoints
|
|
|
|
def getFontReader(fontFamily):
|
|
'Get the font reader for the fontFamily.'
|
|
fontLower = fontFamily.lower().replace(' ', '_')
|
|
global globalFontReaderDictionary
|
|
if fontLower in globalFontReaderDictionary:
|
|
return globalFontReaderDictionary[fontLower]
|
|
global globalFontFileNames
|
|
if globalFontFileNames == None:
|
|
globalFontFileNames = archive.getFileNamesByFilePaths(archive.getFilePathsByDirectory(getFontsDirectoryPath()))
|
|
if fontLower not in globalFontFileNames:
|
|
print('Warning, the %s font was not found in the fabmetheus_utilities/fonts folder, so Gentium Basic Regular will be substituted.' % fontFamily)
|
|
print('The available fonts are:')
|
|
globalFontFileNames.sort()
|
|
print(globalFontFileNames)
|
|
print('')
|
|
fontLower = 'gentium_basic_regular'
|
|
fontReader = FontReader(fontLower)
|
|
globalFontReaderDictionary[fontLower] = fontReader
|
|
return fontReader
|
|
|
|
def getFontsDirectoryPath():
|
|
"Get the fonts directory path."
|
|
return archive.getFabmetheusUtilitiesPath('fonts')
|
|
|
|
def getLabelString(dictionary):
|
|
"Get the label string for the dictionary."
|
|
for key in dictionary:
|
|
labelIndex = key.find('label')
|
|
if labelIndex >= 0:
|
|
return dictionary[key]
|
|
return ''
|
|
|
|
def getMatrixSVG(elementNode):
|
|
"Get matrixSVG by svgElement."
|
|
matrixSVG = MatrixSVG()
|
|
if 'transform' not in elementNode.attributes:
|
|
return matrixSVG
|
|
transformWords = []
|
|
for transformWord in elementNode.attributes['transform'].replace(')', '(').split('('):
|
|
transformWordStrip = transformWord.strip()
|
|
if transformWordStrip != '': # workaround for split(character) bug which leaves an extra empty element
|
|
transformWords.append(transformWordStrip)
|
|
global globalGetTricomplexDictionary
|
|
getTricomplexDictionaryKeys = globalGetTricomplexDictionary.keys()
|
|
for transformWordIndex, transformWord in enumerate(transformWords):
|
|
if transformWord in getTricomplexDictionaryKeys:
|
|
transformString = transformWords[transformWordIndex + 1].replace(',', ' ')
|
|
matrixSVG = matrixSVG.getSelfTimesOther(globalGetTricomplexDictionary[ transformWord ](transformString.split()))
|
|
return matrixSVG
|
|
|
|
def getQuadraticPoint( along, begin, controlPoint, end ):
|
|
'Get the quadratic point.'
|
|
oneMinusAlong = 1.0 - along
|
|
segmentBegin = oneMinusAlong * begin + along * controlPoint
|
|
segmentEnd = oneMinusAlong * controlPoint + along * end
|
|
return oneMinusAlong * segmentBegin + along * segmentEnd
|
|
|
|
def getQuadraticPoints(begin, controlPoint, end, numberOfBezierPoints=globalNumberOfBezierPoints):
|
|
'Get the quadratic points.'
|
|
bezierPortion = 1.0 / float(numberOfBezierPoints)
|
|
quadraticPoints = []
|
|
for bezierIndex in xrange(1, numberOfBezierPoints + 1):
|
|
quadraticPoints.append(getQuadraticPoint(bezierPortion * bezierIndex, begin, controlPoint, end))
|
|
return quadraticPoints
|
|
|
|
def getRightStripAlphabetPercent(word):
|
|
"Get word with alphabet characters and the percent sign stripped from the right."
|
|
word = word.strip()
|
|
for characterIndex in xrange(len(word) - 1, -1, -1):
|
|
character = word[characterIndex]
|
|
if not character.isalpha() and not character == '%':
|
|
return float(word[: characterIndex + 1])
|
|
return None
|
|
|
|
def getRightStripMinusSplit(lineString):
|
|
"Get string with spaces after the minus sign stripped."
|
|
oldLineStringLength = -1
|
|
while oldLineStringLength < len(lineString):
|
|
oldLineStringLength = len(lineString)
|
|
lineString = lineString.replace('- ', '-')
|
|
return lineString.split()
|
|
|
|
def getStrokeRadius(elementNode):
|
|
"Get the stroke radius."
|
|
return 0.5 * getRightStripAlphabetPercent(getStyleValue('1.0', elementNode, 'stroke-width'))
|
|
|
|
def getStyleValue(defaultValue, elementNode, key):
|
|
"Get the stroke value string."
|
|
if 'style' in elementNode.attributes:
|
|
line = elementNode.attributes['style']
|
|
strokeIndex = line.find(key)
|
|
if strokeIndex > -1:
|
|
words = line[strokeIndex :].replace(':', ' ').replace(';', ' ').split()
|
|
if len(words) > 1:
|
|
return words[1]
|
|
if key in elementNode.attributes:
|
|
return elementNode.attributes[key]
|
|
if elementNode.parentNode == None:
|
|
return defaultValue
|
|
return getStyleValue(defaultValue, elementNode.parentNode, key)
|
|
|
|
def getTextComplexLoops(fontFamily, fontSize, text, yAxisPointingUpward=True):
|
|
"Get text as complex loops."
|
|
textComplexLoops = []
|
|
fontReader = getFontReader(fontFamily)
|
|
horizontalAdvanceX = 0.0
|
|
for character in text:
|
|
glyph = fontReader.getGlyph(character, yAxisPointingUpward)
|
|
textComplexLoops += glyph.getSizedAdvancedLoops(fontSize, horizontalAdvanceX, yAxisPointingUpward)
|
|
horizontalAdvanceX += glyph.horizontalAdvanceX
|
|
return textComplexLoops
|
|
|
|
def getTransformedFillOutline(elementNode, loop, yAxisPointingUpward):
|
|
"Get the loops if fill is on, otherwise get the outlines."
|
|
fillOutlineLoops = None
|
|
if getStyleValue('none', elementNode, 'fill').lower() == 'none':
|
|
fillOutlineLoops = intercircle.getAroundsFromLoop(loop, getStrokeRadius(elementNode))
|
|
else:
|
|
fillOutlineLoops = [loop]
|
|
return getChainMatrixSVGIfNecessary(elementNode, yAxisPointingUpward).getTransformedPaths(fillOutlineLoops)
|
|
|
|
def getTransformedOutlineByPath(elementNode, path, yAxisPointingUpward):
|
|
"Get the outline from the path."
|
|
aroundsFromPath = intercircle.getAroundsFromPath(path, getStrokeRadius(elementNode))
|
|
return getChainMatrixSVGIfNecessary(elementNode, yAxisPointingUpward).getTransformedPaths(aroundsFromPath)
|
|
|
|
def getTransformedOutlineByPaths(elementNode, paths, yAxisPointingUpward):
|
|
"Get the outline from the paths."
|
|
aroundsFromPaths = intercircle.getAroundsFromPaths(paths, getStrokeRadius(elementNode))
|
|
return getChainMatrixSVGIfNecessary(elementNode, yAxisPointingUpward).getTransformedPaths(aroundsFromPaths)
|
|
|
|
def getTricomplexmatrix(transformWords):
|
|
"Get matrixSVG by transformWords."
|
|
tricomplex = [euclidean.getComplexByWords(transformWords)]
|
|
tricomplex.append(euclidean.getComplexByWords(transformWords, 2))
|
|
tricomplex.append(euclidean.getComplexByWords(transformWords, 4))
|
|
return tricomplex
|
|
|
|
def getTricomplexrotate(transformWords):
|
|
"Get matrixSVG by transformWords."
|
|
rotate = euclidean.getWiddershinsUnitPolar(math.radians(float(transformWords[0])))
|
|
return [rotate, complex(-rotate.imag,rotate.real), complex()]
|
|
|
|
def getTricomplexscale(transformWords):
|
|
"Get matrixSVG by transformWords."
|
|
scale = euclidean.getComplexByWords(transformWords)
|
|
return [complex(scale.real,0.0), complex(0.0,scale.imag), complex()]
|
|
|
|
def getTricomplexskewX(transformWords):
|
|
"Get matrixSVG by transformWords."
|
|
skewX = math.tan(math.radians(float(transformWords[0])))
|
|
return [complex(1.0, 0.0), complex(skewX, 1.0), complex()]
|
|
|
|
def getTricomplexskewY(transformWords):
|
|
"Get matrixSVG by transformWords."
|
|
skewY = math.tan(math.radians(float(transformWords[0])))
|
|
return [complex(1.0, skewY), complex(0.0, 1.0), complex()]
|
|
|
|
def getTricomplexTimesColumn(firstTricomplex, otherColumn):
|
|
"Get this matrix multiplied by the otherColumn."
|
|
dotProductX = firstTricomplex[0].real * otherColumn.real + firstTricomplex[1].real * otherColumn.imag
|
|
dotProductY = firstTricomplex[0].imag * otherColumn.real + firstTricomplex[1].imag * otherColumn.imag
|
|
return complex(dotProductX, dotProductY)
|
|
|
|
def getTricomplexTimesOther(firstTricomplex, otherTricomplex):
|
|
"Get the first tricomplex multiplied by the other tricomplex."
|
|
#A down, B right from http://en.wikipedia.org/wiki/Matrix_multiplication
|
|
tricomplexTimesOther = [getTricomplexTimesColumn(firstTricomplex, otherTricomplex[0])]
|
|
tricomplexTimesOther.append(getTricomplexTimesColumn(firstTricomplex, otherTricomplex[1]))
|
|
tricomplexTimesOther.append(getTricomplexTimesColumn(firstTricomplex, otherTricomplex[2]) + firstTricomplex[2])
|
|
return tricomplexTimesOther
|
|
|
|
def getTricomplextranslate(transformWords):
|
|
"Get matrixSVG by transformWords."
|
|
translate = euclidean.getComplexByWords(transformWords)
|
|
return [complex(1.0, 0.0), complex(0.0, 1.0), translate]
|
|
|
|
def processSVGElementcircle( elementNode, svgReader ):
|
|
"Process elementNode by svgReader."
|
|
attributes = elementNode.attributes
|
|
center = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributes, 'cx', 'cy')
|
|
radius = euclidean.getFloatDefaultByDictionary( 0.0, attributes, 'r')
|
|
if radius == 0.0:
|
|
print('Warning, in processSVGElementcircle in svgReader radius is zero in:')
|
|
print(attributes)
|
|
return
|
|
global globalNumberOfCirclePoints
|
|
global globalSideAngle
|
|
loop = []
|
|
loopLayer = svgReader.getLoopLayer()
|
|
for side in xrange( globalNumberOfCirclePoints ):
|
|
unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle )
|
|
loop.append( center + radius * unitPolar )
|
|
loopLayer.loops += getTransformedFillOutline(elementNode, loop, svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementellipse( elementNode, svgReader ):
|
|
"Process elementNode by svgReader."
|
|
attributes = elementNode.attributes
|
|
center = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributes, 'cx', 'cy')
|
|
radius = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributes, 'rx', 'ry')
|
|
if radius.real == 0.0 or radius.imag == 0.0:
|
|
print('Warning, in processSVGElementellipse in svgReader radius is zero in:')
|
|
print(attributes)
|
|
return
|
|
global globalNumberOfCirclePoints
|
|
global globalSideAngle
|
|
loop = []
|
|
loopLayer = svgReader.getLoopLayer()
|
|
for side in xrange( globalNumberOfCirclePoints ):
|
|
unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle )
|
|
loop.append( center + complex( unitPolar.real * radius.real, unitPolar.imag * radius.imag ) )
|
|
loopLayer.loops += getTransformedFillOutline(elementNode, loop, svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementg(elementNode, svgReader):
|
|
'Process elementNode by svgReader.'
|
|
if 'id' not in elementNode.attributes:
|
|
return
|
|
idString = elementNode.attributes['id']
|
|
if 'beginningOfControlSection' in elementNode.attributes:
|
|
if elementNode.attributes['beginningOfControlSection'].lower()[: 1] == 't':
|
|
svgReader.stopProcessing = True
|
|
return
|
|
idStringLower = idString.lower()
|
|
zIndex = idStringLower.find('z:')
|
|
if zIndex < 0:
|
|
idStringLower = getLabelString(elementNode.attributes)
|
|
zIndex = idStringLower.find('z:')
|
|
if zIndex < 0:
|
|
return
|
|
floatFromValue = euclidean.getFloatFromValue(idStringLower[zIndex + len('z:') :].strip())
|
|
if floatFromValue != None:
|
|
svgReader.z = floatFromValue
|
|
|
|
def processSVGElementline(elementNode, svgReader):
|
|
"Process elementNode by svgReader."
|
|
begin = euclidean.getComplexDefaultByDictionaryKeys(complex(), elementNode.attributes, 'x1', 'y1')
|
|
end = euclidean.getComplexDefaultByDictionaryKeys(complex(), elementNode.attributes, 'x2', 'y2')
|
|
loopLayer = svgReader.getLoopLayer()
|
|
loopLayer.loops += getTransformedOutlineByPath(elementNode, [begin, end], svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementpath( elementNode, svgReader ):
|
|
"Process elementNode by svgReader."
|
|
if 'd' not in elementNode.attributes:
|
|
print('Warning, in processSVGElementpath in svgReader can not get a value for d in:')
|
|
print(elementNode.attributes)
|
|
return
|
|
loopLayer = svgReader.getLoopLayer()
|
|
PathReader(elementNode, loopLayer.loops, svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementpolygon( elementNode, svgReader ):
|
|
"Process elementNode by svgReader."
|
|
if 'points' not in elementNode.attributes:
|
|
print('Warning, in processSVGElementpolygon in svgReader can not get a value for d in:')
|
|
print(elementNode.attributes)
|
|
return
|
|
loopLayer = svgReader.getLoopLayer()
|
|
words = getRightStripMinusSplit(elementNode.attributes['points'].replace(',', ' '))
|
|
loop = []
|
|
for wordIndex in xrange( 0, len(words), 2 ):
|
|
loop.append(euclidean.getComplexByWords(words[wordIndex :]))
|
|
loopLayer.loops += getTransformedFillOutline(elementNode, loop, svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementpolyline(elementNode, svgReader):
|
|
"Process elementNode by svgReader."
|
|
if 'points' not in elementNode.attributes:
|
|
print('Warning, in processSVGElementpolyline in svgReader can not get a value for d in:')
|
|
print(elementNode.attributes)
|
|
return
|
|
loopLayer = svgReader.getLoopLayer()
|
|
words = getRightStripMinusSplit(elementNode.attributes['points'].replace(',', ' '))
|
|
path = []
|
|
for wordIndex in xrange(0, len(words), 2):
|
|
path.append(euclidean.getComplexByWords(words[wordIndex :]))
|
|
loopLayer.loops += getTransformedOutlineByPath(elementNode, path, svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementrect( elementNode, svgReader ):
|
|
"Process elementNode by svgReader."
|
|
attributes = elementNode.attributes
|
|
height = euclidean.getFloatDefaultByDictionary( 0.0, attributes, 'height')
|
|
if height == 0.0:
|
|
print('Warning, in processSVGElementrect in svgReader height is zero in:')
|
|
print(attributes)
|
|
return
|
|
width = euclidean.getFloatDefaultByDictionary( 0.0, attributes, 'width')
|
|
if width == 0.0:
|
|
print('Warning, in processSVGElementrect in svgReader width is zero in:')
|
|
print(attributes)
|
|
return
|
|
center = euclidean.getComplexDefaultByDictionaryKeys(complex(), attributes, 'x', 'y')
|
|
inradius = 0.5 * complex( width, height )
|
|
cornerRadius = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributes, 'rx', 'ry')
|
|
loopLayer = svgReader.getLoopLayer()
|
|
if cornerRadius.real == 0.0 and cornerRadius.imag == 0.0:
|
|
inradiusMinusX = complex( - inradius.real, inradius.imag )
|
|
loop = [center + inradius, center + inradiusMinusX, center - inradius, center - inradiusMinusX]
|
|
loopLayer.loops += getTransformedFillOutline(elementNode, loop, svgReader.yAxisPointingUpward)
|
|
return
|
|
if cornerRadius.real == 0.0:
|
|
cornerRadius = complex( cornerRadius.imag, cornerRadius.imag )
|
|
elif cornerRadius.imag == 0.0:
|
|
cornerRadius = complex( cornerRadius.real, cornerRadius.real )
|
|
cornerRadius = complex( min( cornerRadius.real, inradius.real ), min( cornerRadius.imag, inradius.imag ) )
|
|
ellipsePath = [ complex( cornerRadius.real, 0.0 ) ]
|
|
inradiusMinusCorner = inradius - cornerRadius
|
|
loop = []
|
|
global globalNumberOfCornerPoints
|
|
global globalSideAngle
|
|
for side in xrange( 1, globalNumberOfCornerPoints ):
|
|
unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle )
|
|
ellipsePath.append( complex( unitPolar.real * cornerRadius.real, unitPolar.imag * cornerRadius.imag ) )
|
|
ellipsePath.append( complex( 0.0, cornerRadius.imag ) )
|
|
cornerPoints = []
|
|
for point in ellipsePath:
|
|
cornerPoints.append( point + inradiusMinusCorner )
|
|
cornerPointsReversed = cornerPoints[: : -1]
|
|
for cornerPoint in cornerPoints:
|
|
loop.append( center + cornerPoint )
|
|
for cornerPoint in cornerPointsReversed:
|
|
loop.append( center + complex( - cornerPoint.real, cornerPoint.imag ) )
|
|
for cornerPoint in cornerPoints:
|
|
loop.append( center - cornerPoint )
|
|
for cornerPoint in cornerPointsReversed:
|
|
loop.append( center + complex( cornerPoint.real, - cornerPoint.imag ) )
|
|
loop = euclidean.getLoopWithoutCloseSequentialPoints( 0.0001 * abs(inradius), loop )
|
|
loopLayer.loops += getTransformedFillOutline(elementNode, loop, svgReader.yAxisPointingUpward)
|
|
|
|
def processSVGElementtext(elementNode, svgReader):
|
|
"Process elementNode by svgReader."
|
|
if svgReader.yAxisPointingUpward:
|
|
return
|
|
fontFamily = getStyleValue('Gentium Basic Regular', elementNode, 'font-family')
|
|
fontSize = getRightStripAlphabetPercent(getStyleValue('12.0', elementNode, 'font-size'))
|
|
matrixSVG = getChainMatrixSVGIfNecessary(elementNode, svgReader.yAxisPointingUpward)
|
|
loopLayer = svgReader.getLoopLayer()
|
|
translate = euclidean.getComplexDefaultByDictionaryKeys(complex(), elementNode.attributes, 'x', 'y')
|
|
for textComplexLoop in getTextComplexLoops(fontFamily, fontSize, elementNode.getTextContent(), svgReader.yAxisPointingUpward):
|
|
translatedLoop = []
|
|
for textComplexPoint in textComplexLoop:
|
|
translatedLoop.append(textComplexPoint + translate )
|
|
loopLayer.loops.append(matrixSVG.getTransformedPath(translatedLoop))
|
|
|
|
|
|
class FontReader:
|
|
"Class to read a font in the fonts folder."
|
|
def __init__(self, fontFamily):
|
|
"Initialize."
|
|
self.fontFamily = fontFamily
|
|
self.glyphDictionary = {}
|
|
self.glyphElementNodeDictionary = {}
|
|
self.missingGlyph = None
|
|
fileName = os.path.join(getFontsDirectoryPath(), fontFamily + '.svg')
|
|
documentElement = DocumentNode(fileName, archive.getFileText(fileName)).getDocumentElement()
|
|
self.fontElementNode = documentElement.getFirstChildByLocalName('defs').getFirstChildByLocalName('font')
|
|
self.fontFaceElementNode = self.fontElementNode.getFirstChildByLocalName('font-face')
|
|
self.unitsPerEM = float(self.fontFaceElementNode.attributes['units-per-em'])
|
|
glyphElementNodes = self.fontElementNode.getChildElementsByLocalName('glyph')
|
|
for glyphElementNode in glyphElementNodes:
|
|
self.glyphElementNodeDictionary[glyphElementNode.attributes['unicode']] = glyphElementNode
|
|
|
|
def getGlyph(self, character, yAxisPointingUpward):
|
|
"Get the glyph for the character."
|
|
if character not in self.glyphElementNodeDictionary:
|
|
if self.missingGlyph == None:
|
|
missingGlyphElementNode = self.fontElementNode.getFirstChildByLocalName('missing-glyph')
|
|
self.missingGlyph = Glyph(missingGlyphElementNode, self.unitsPerEM, yAxisPointingUpward)
|
|
return self.missingGlyph
|
|
if character not in self.glyphDictionary:
|
|
self.glyphDictionary[character] = Glyph(self.glyphElementNodeDictionary[character], self.unitsPerEM, yAxisPointingUpward)
|
|
return self.glyphDictionary[character]
|
|
|
|
|
|
class Glyph:
|
|
"Class to handle a glyph."
|
|
def __init__(self, elementNode, unitsPerEM, yAxisPointingUpward):
|
|
"Initialize."
|
|
self.horizontalAdvanceX = float(elementNode.attributes['horiz-adv-x'])
|
|
self.loops = []
|
|
self.unitsPerEM = unitsPerEM
|
|
elementNode.attributes['fill'] = ''
|
|
if 'd' not in elementNode.attributes:
|
|
return
|
|
PathReader(elementNode, self.loops, yAxisPointingUpward)
|
|
|
|
def getSizedAdvancedLoops(self, fontSize, horizontalAdvanceX, yAxisPointingUpward=True):
|
|
"Get loops for font size, advanced horizontally."
|
|
multiplierX = fontSize / self.unitsPerEM
|
|
multiplierY = multiplierX
|
|
if not yAxisPointingUpward:
|
|
multiplierY = -multiplierY
|
|
sizedLoops = []
|
|
for loop in self.loops:
|
|
sizedLoop = []
|
|
sizedLoops.append(sizedLoop)
|
|
for point in loop:
|
|
sizedLoop.append( complex(multiplierX * (point.real + horizontalAdvanceX), multiplierY * point.imag))
|
|
return sizedLoops
|
|
|
|
|
|
class MatrixSVG:
|
|
"Two by three svg matrix."
|
|
def __init__(self, tricomplex=None):
|
|
"Initialize."
|
|
self.tricomplex = tricomplex
|
|
|
|
def __repr__(self):
|
|
"Get the string representation of this two by three svg matrix."
|
|
return str(self.tricomplex)
|
|
|
|
def getOtherTimesSelf(self, otherTricomplex):
|
|
"Get the other matrix multiplied by this matrix."
|
|
if otherTricomplex == None:
|
|
return MatrixSVG(self.tricomplex)
|
|
if self.tricomplex == None:
|
|
return MatrixSVG(otherTricomplex)
|
|
return MatrixSVG(getTricomplexTimesOther(otherTricomplex, self.tricomplex))
|
|
|
|
def getSelfTimesOther(self, otherTricomplex):
|
|
"Get this matrix multiplied by the other matrix."
|
|
if otherTricomplex == None:
|
|
return MatrixSVG(self.tricomplex)
|
|
if self.tricomplex == None:
|
|
return MatrixSVG(otherTricomplex)
|
|
return MatrixSVG(getTricomplexTimesOther(self.tricomplex, otherTricomplex))
|
|
|
|
def getTransformedPath(self, path):
|
|
"Get transformed path."
|
|
if self.tricomplex == None:
|
|
return path
|
|
complexX = self.tricomplex[0]
|
|
complexY = self.tricomplex[1]
|
|
complexTranslation = self.tricomplex[2]
|
|
transformedPath = []
|
|
for point in path:
|
|
x = complexX.real * point.real + complexY.real * point.imag
|
|
y = complexX.imag * point.real + complexY.imag * point.imag
|
|
transformedPath.append(complex(x, y) + complexTranslation)
|
|
return transformedPath
|
|
|
|
def getTransformedPaths(self, paths):
|
|
"Get transformed paths."
|
|
if self.tricomplex == None:
|
|
return paths
|
|
transformedPaths = []
|
|
for path in paths:
|
|
transformedPaths.append(self.getTransformedPath(path))
|
|
return transformedPaths
|
|
|
|
|
|
class PathReader:
|
|
"Class to read svg path."
|
|
def __init__(self, elementNode, loops, yAxisPointingUpward):
|
|
"Add to path string to loops."
|
|
self.controlPoints = None
|
|
self.elementNode = elementNode
|
|
self.loops = loops
|
|
self.oldPoint = None
|
|
self.outlinePaths = []
|
|
self.path = []
|
|
self.yAxisPointingUpward = yAxisPointingUpward
|
|
pathString = elementNode.attributes['d'].replace(',', ' ')
|
|
global globalProcessPathWordDictionary
|
|
processPathWordDictionaryKeys = globalProcessPathWordDictionary.keys()
|
|
for processPathWordDictionaryKey in processPathWordDictionaryKeys:
|
|
pathString = pathString.replace( processPathWordDictionaryKey, ' %s ' % processPathWordDictionaryKey )
|
|
self.words = getRightStripMinusSplit(pathString)
|
|
for self.wordIndex in xrange( len( self.words ) ):
|
|
word = self.words[ self.wordIndex ]
|
|
if word in processPathWordDictionaryKeys:
|
|
globalProcessPathWordDictionary[word](self)
|
|
if len(self.path) > 0:
|
|
self.outlinePaths.append(self.path)
|
|
self.loops += getTransformedOutlineByPaths(elementNode, self.outlinePaths, yAxisPointingUpward)
|
|
|
|
def addPathArc( self, end ):
|
|
"Add an arc to the path."
|
|
begin = self.getOldPoint()
|
|
self.controlPoints = None
|
|
radius = self.getComplexByExtraIndex(1)
|
|
xAxisRotation = math.radians(float(self.words[self.wordIndex + 3]))
|
|
largeArcFlag = euclidean.getBooleanFromValue(self.words[ self.wordIndex + 4 ])
|
|
sweepFlag = euclidean.getBooleanFromValue(self.words[ self.wordIndex + 5 ])
|
|
self.path += getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation)
|
|
self.wordIndex += 8
|
|
|
|
def addPathCubic( self, controlPoints, end ):
|
|
"Add a cubic curve to the path."
|
|
begin = self.getOldPoint()
|
|
self.controlPoints = controlPoints
|
|
self.path += getCubicPoints( begin, controlPoints, end )
|
|
self.wordIndex += 7
|
|
|
|
def addPathCubicReflected( self, controlPoint, end ):
|
|
"Add a cubic curve to the path from a reflected control point."
|
|
begin = self.getOldPoint()
|
|
controlPointBegin = begin
|
|
if self.controlPoints != None:
|
|
if len(self.controlPoints) == 2:
|
|
controlPointBegin = begin + begin - self.controlPoints[-1]
|
|
self.controlPoints = [controlPointBegin, controlPoint]
|
|
self.path += getCubicPoints(begin, self.controlPoints, end)
|
|
self.wordIndex += 5
|
|
|
|
def addPathLine(self, lineFunction, point):
|
|
"Add a line to the path."
|
|
self.controlPoints = None
|
|
self.path.append(point)
|
|
self.wordIndex += 3
|
|
self.addPathLineByFunction(lineFunction)
|
|
|
|
def addPathLineAxis(self, point):
|
|
"Add an axis line to the path."
|
|
self.controlPoints = None
|
|
self.path.append(point)
|
|
self.wordIndex += 2
|
|
|
|
def addPathLineByFunction( self, lineFunction ):
|
|
"Add a line to the path by line function."
|
|
while 1:
|
|
if self.getFloatByExtraIndex() == None:
|
|
return
|
|
self.path.append(lineFunction())
|
|
self.wordIndex += 2
|
|
|
|
def addPathMove( self, lineFunction, point ):
|
|
"Add an axis line to the path."
|
|
self.controlPoints = None
|
|
if len(self.path) > 0:
|
|
self.outlinePaths.append(self.path)
|
|
self.oldPoint = self.path[-1]
|
|
self.path = [point]
|
|
self.wordIndex += 3
|
|
self.addPathLineByFunction(lineFunction)
|
|
|
|
def addPathQuadratic( self, controlPoint, end ):
|
|
"Add a quadratic curve to the path."
|
|
begin = self.getOldPoint()
|
|
self.controlPoints = [controlPoint]
|
|
self.path += getQuadraticPoints(begin, controlPoint, end)
|
|
self.wordIndex += 5
|
|
|
|
def addPathQuadraticReflected( self, end ):
|
|
"Add a quadratic curve to the path from a reflected control point."
|
|
begin = self.getOldPoint()
|
|
controlPoint = begin
|
|
if self.controlPoints != None:
|
|
if len( self.controlPoints ) == 1:
|
|
controlPoint = begin + begin - self.controlPoints[-1]
|
|
self.controlPoints = [ controlPoint ]
|
|
self.path += getQuadraticPoints(begin, controlPoint, end)
|
|
self.wordIndex += 3
|
|
|
|
def getComplexByExtraIndex( self, extraIndex=0 ):
|
|
'Get complex from the extraIndex.'
|
|
return euclidean.getComplexByWords(self.words, self.wordIndex + extraIndex)
|
|
|
|
def getComplexRelative(self):
|
|
"Get relative complex."
|
|
return self.getComplexByExtraIndex() + self.getOldPoint()
|
|
|
|
def getFloatByExtraIndex( self, extraIndex=0 ):
|
|
'Get float from the extraIndex.'
|
|
totalIndex = self.wordIndex + extraIndex
|
|
if totalIndex >= len(self.words):
|
|
return None
|
|
word = self.words[totalIndex]
|
|
if word[: 1].isalpha():
|
|
return None
|
|
return euclidean.getFloatFromValue(word)
|
|
|
|
def getOldPoint(self):
|
|
'Get the old point.'
|
|
if len(self.path) > 0:
|
|
return self.path[-1]
|
|
return self.oldPoint
|
|
|
|
def processPathWordA(self):
|
|
'Process path word A.'
|
|
self.addPathArc( self.getComplexByExtraIndex( 6 ) )
|
|
|
|
def processPathWorda(self):
|
|
'Process path word a.'
|
|
self.addPathArc(self.getComplexByExtraIndex(6) + self.getOldPoint())
|
|
|
|
def processPathWordC(self):
|
|
'Process path word C.'
|
|
end = self.getComplexByExtraIndex( 5 )
|
|
self.addPathCubic( [ self.getComplexByExtraIndex( 1 ), self.getComplexByExtraIndex(3) ], end )
|
|
|
|
def processPathWordc(self):
|
|
'Process path word C.'
|
|
begin = self.getOldPoint()
|
|
end = self.getComplexByExtraIndex( 5 )
|
|
self.addPathCubic( [ self.getComplexByExtraIndex( 1 ) + begin, self.getComplexByExtraIndex(3) + begin ], end + begin )
|
|
|
|
def processPathWordH(self):
|
|
"Process path word H."
|
|
beginY = self.getOldPoint().imag
|
|
self.addPathLineAxis(complex(float(self.words[self.wordIndex + 1]), beginY))
|
|
while 1:
|
|
floatByExtraIndex = self.getFloatByExtraIndex()
|
|
if floatByExtraIndex == None:
|
|
return
|
|
self.path.append(complex(floatByExtraIndex, beginY))
|
|
self.wordIndex += 1
|
|
|
|
def processPathWordh(self):
|
|
"Process path word h."
|
|
begin = self.getOldPoint()
|
|
self.addPathLineAxis(complex(float(self.words[self.wordIndex + 1]) + begin.real, begin.imag))
|
|
while 1:
|
|
floatByExtraIndex = self.getFloatByExtraIndex()
|
|
if floatByExtraIndex == None:
|
|
return
|
|
self.path.append(complex(floatByExtraIndex + self.getOldPoint().real, begin.imag))
|
|
self.wordIndex += 1
|
|
|
|
def processPathWordL(self):
|
|
"Process path word L."
|
|
self.addPathLine(self.getComplexByExtraIndex, self.getComplexByExtraIndex( 1 ))
|
|
|
|
def processPathWordl(self):
|
|
"Process path word l."
|
|
self.addPathLine(self.getComplexRelative, self.getComplexByExtraIndex(1) + self.getOldPoint())
|
|
|
|
def processPathWordM(self):
|
|
"Process path word M."
|
|
self.addPathMove(self.getComplexByExtraIndex, self.getComplexByExtraIndex(1))
|
|
|
|
def processPathWordm(self):
|
|
"Process path word m."
|
|
self.addPathMove(self.getComplexRelative, self.getComplexByExtraIndex(1) + self.getOldPoint())
|
|
|
|
def processPathWordQ(self):
|
|
'Process path word Q.'
|
|
self.addPathQuadratic( self.getComplexByExtraIndex( 1 ), self.getComplexByExtraIndex(3) )
|
|
|
|
def processPathWordq(self):
|
|
'Process path word q.'
|
|
begin = self.getOldPoint()
|
|
self.addPathQuadratic(self.getComplexByExtraIndex(1) + begin, self.getComplexByExtraIndex(3) + begin)
|
|
|
|
def processPathWordS(self):
|
|
'Process path word S.'
|
|
self.addPathCubicReflected( self.getComplexByExtraIndex( 1 ), self.getComplexByExtraIndex(3) )
|
|
|
|
def processPathWords(self):
|
|
'Process path word s.'
|
|
begin = self.getOldPoint()
|
|
self.addPathCubicReflected(self.getComplexByExtraIndex(1) + begin, self.getComplexByExtraIndex(3) + begin)
|
|
|
|
def processPathWordT(self):
|
|
'Process path word T.'
|
|
self.addPathQuadraticReflected( self.getComplexByExtraIndex( 1 ) )
|
|
|
|
def processPathWordt(self):
|
|
'Process path word t.'
|
|
self.addPathQuadraticReflected(self.getComplexByExtraIndex(1) + self.getOldPoint())
|
|
|
|
def processPathWordV(self):
|
|
"Process path word V."
|
|
beginX = self.getOldPoint().real
|
|
self.addPathLineAxis(complex(beginX, float(self.words[self.wordIndex + 1])))
|
|
while 1:
|
|
floatByExtraIndex = self.getFloatByExtraIndex()
|
|
if floatByExtraIndex == None:
|
|
return
|
|
self.path.append(complex(beginX, floatByExtraIndex))
|
|
self.wordIndex += 1
|
|
|
|
def processPathWordv(self):
|
|
"Process path word v."
|
|
begin = self.getOldPoint()
|
|
self.addPathLineAxis(complex(begin.real, float(self.words[self.wordIndex + 1]) + begin.imag))
|
|
while 1:
|
|
floatByExtraIndex = self.getFloatByExtraIndex()
|
|
if floatByExtraIndex == None:
|
|
return
|
|
self.path.append(complex(begin.real, floatByExtraIndex + self.getOldPoint().imag))
|
|
self.wordIndex += 1
|
|
|
|
def processPathWordZ(self):
|
|
"Process path word Z."
|
|
self.controlPoints = None
|
|
if len(self.path) < 1:
|
|
return
|
|
self.loops.append(getChainMatrixSVGIfNecessary(self.elementNode, self.yAxisPointingUpward).getTransformedPath(self.path))
|
|
self.oldPoint = self.path[0]
|
|
self.path = []
|
|
|
|
def processPathWordz(self):
|
|
"Process path word z."
|
|
self.processPathWordZ()
|
|
|
|
|
|
class SVGReader:
|
|
"An svg carving."
|
|
def __init__(self):
|
|
"Add empty lists."
|
|
self.loopLayers = []
|
|
self.sliceDictionary = None
|
|
self.stopProcessing = False
|
|
self.z = 0.0
|
|
|
|
def flipDirectLayer(self, loopLayer):
|
|
"Flip the y coordinate of the layer and direct the loops."
|
|
for loop in loopLayer.loops:
|
|
for pointIndex, point in enumerate(loop):
|
|
loop[pointIndex] = complex(point.real, -point.imag)
|
|
triangle_mesh.sortLoopsInOrderOfArea(True, loopLayer.loops)
|
|
for loopIndex, loop in enumerate(loopLayer.loops):
|
|
isInsideLoops = euclidean.getIsInFilledRegion(loopLayer.loops[: loopIndex], euclidean.getLeftPoint(loop))
|
|
intercircle.directLoop((not isInsideLoops), loop)
|
|
|
|
def getLoopLayer(self):
|
|
"Return the rotated loop layer."
|
|
if self.z != None:
|
|
loopLayer = euclidean.LoopLayer(self.z)
|
|
self.loopLayers.append(loopLayer)
|
|
self.z = None
|
|
return self.loopLayers[-1]
|
|
|
|
def parseSVG(self, fileName, svgText):
|
|
"Parse SVG text and store the layers."
|
|
self.fileName = fileName
|
|
xmlParser = DocumentNode(fileName, svgText)
|
|
self.documentElement = xmlParser.getDocumentElement()
|
|
if self.documentElement == None:
|
|
print('Warning, documentElement was None in parseSVG in SVGReader, so nothing will be done for:')
|
|
print(fileName)
|
|
return
|
|
self.parseSVGByElementNode(self.documentElement)
|
|
|
|
def parseSVGByElementNode(self, elementNode):
|
|
"Parse SVG by elementNode."
|
|
self.sliceDictionary = svg_writer.getSliceDictionary(elementNode)
|
|
self.yAxisPointingUpward = euclidean.getBooleanFromDictionary(False, self.sliceDictionary, 'yAxisPointingUpward')
|
|
self.processElementNode(elementNode)
|
|
if not self.yAxisPointingUpward:
|
|
for loopLayer in self.loopLayers:
|
|
self.flipDirectLayer(loopLayer)
|
|
|
|
def processElementNode(self, elementNode):
|
|
'Process the xml element.'
|
|
if self.stopProcessing:
|
|
return
|
|
lowerLocalName = elementNode.getNodeName().lower()
|
|
global globalProcessSVGElementDictionary
|
|
if lowerLocalName in globalProcessSVGElementDictionary:
|
|
try:
|
|
globalProcessSVGElementDictionary[lowerLocalName](elementNode, self)
|
|
except:
|
|
print('Warning, in processElementNode in svg_reader, could not process:')
|
|
print(elementNode)
|
|
traceback.print_exc(file=sys.stdout)
|
|
for childNode in elementNode.childNodes:
|
|
self.processElementNode(childNode)
|
|
|
|
|
|
globalFontFileNames = None
|
|
globalFontReaderDictionary = {}
|
|
globalGetTricomplexDictionary = {}
|
|
globalGetTricomplexFunctions = [
|
|
getTricomplexmatrix,
|
|
getTricomplexrotate,
|
|
getTricomplexscale,
|
|
getTricomplexskewX,
|
|
getTricomplexskewY,
|
|
getTricomplextranslate ]
|
|
globalProcessPathWordFunctions = [
|
|
PathReader.processPathWordA,
|
|
PathReader.processPathWorda,
|
|
PathReader.processPathWordC,
|
|
PathReader.processPathWordc,
|
|
PathReader.processPathWordH,
|
|
PathReader.processPathWordh,
|
|
PathReader.processPathWordL,
|
|
PathReader.processPathWordl,
|
|
PathReader.processPathWordM,
|
|
PathReader.processPathWordm,
|
|
PathReader.processPathWordQ,
|
|
PathReader.processPathWordq,
|
|
PathReader.processPathWordS,
|
|
PathReader.processPathWords,
|
|
PathReader.processPathWordT,
|
|
PathReader.processPathWordt,
|
|
PathReader.processPathWordV,
|
|
PathReader.processPathWordv,
|
|
PathReader.processPathWordZ,
|
|
PathReader.processPathWordz ]
|
|
globalProcessPathWordDictionary = {}
|
|
globalProcessSVGElementDictionary = {}
|
|
globalProcessSVGElementFunctions = [
|
|
processSVGElementcircle,
|
|
processSVGElementellipse,
|
|
processSVGElementg,
|
|
processSVGElementline,
|
|
processSVGElementpath,
|
|
processSVGElementpolygon,
|
|
processSVGElementpolyline,
|
|
processSVGElementrect,
|
|
processSVGElementtext ]
|
|
globalSideAngle = 0.5 * math.pi / float( globalNumberOfCornerPoints )
|
|
|
|
|
|
addFunctionsToDictionary( globalGetTricomplexDictionary, globalGetTricomplexFunctions, 'getTricomplex')
|
|
addFunctionsToDictionary( globalProcessPathWordDictionary, globalProcessPathWordFunctions, 'processPathWord')
|
|
addFunctionsToDictionary( globalProcessSVGElementDictionary, globalProcessSVGElementFunctions, 'processSVGElement')
|