#!/usr/bin/env python3 ''' Defintion of Common functions and variables used by stroke font extensions Copyright (C) 2019 Shrinivas Kulkarni This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ''' import sys, os, fileinput, re, locale from inkex import errormsg, addNS, NSS from xml.dom.minidom import parse, Document from math import ceil # TODO: Find inkscape version try: from lxml import etree from inkex import Style, Boolean from inkex.paths import Path, CubicSuperPath, Transform from inkex import bezier ver = 1.0 except: from inkex import etree import simplestyle, cubicsuperpath, simplepath, simpletransform from cubicsuperpath import CubicSuperPath ver = 0.92 try: from simpletransform import computePointInNode oldVersion = False except: oldVersion = True # older than 0.92 # sys path already includes the module folder from stroke_font_manager import CharData, getFontNames, xAscent, \ xDescent, xCapHeight, xXHeight, xSpaceROff, xFontId, xSize class CommonDefs: inkVer = ver pyVer = sys.version_info.major # inx filed that have the font list to be synchronized inxFilesWithDynFont = ['render_stroke_font_text.inx', 'edit_stroke_font.inx'] vgScaleFact = 2. lineT = .005 idAttribName = 'id' hGuideIDPrefix = 'h_' lvGuideIDPrefix = 'lv_' rvGuideIDPrefix = 'rv_' fontOtherInfo = 'otherInfo' encoding = sys.stdin.encoding if(encoding == 'cp0' or encoding is None): encoding = locale.getpreferredencoding() ######### Function variants for 1.0 and 0.92 - Start ########## # Used only in 0.92 def getPartsFromCubicSuper(csp): parts = [] for subpath in csp: part = [] prevBezPt = None for i, bezierPt in enumerate(subpath): if(prevBezPt != None): seg = [prevBezPt[1], prevBezPt[2], bezierPt[0], bezierPt[1]] part.append(seg) prevBezPt = bezierPt parts.append(part) return parts def formatStyle(styleStr): if(CommonDefs.inkVer == 1.0): return str(Style(styleStr)) else: return simplestyle.formatStyle(styleStr) def getCubicSuperPath(d = None): if(CommonDefs.inkVer == 1.0): if(d == None): return CubicSuperPath([]) return CubicSuperPath(Path(d).to_superpath()) else: if(d == None): return [] return CubicSuperPath(simplepath.parsePath(d)) def getCubicLength(csp): if(CommonDefs.inkVer == 1.0): return bezier.csplength(csp)[1] else: parts = getPartsFromCubicSuper(cspath) curveLen = 0 for i, part in enumerate(parts): for j, seg in enumerate(part): curveLen += bezmisc.bezierlengthSimpson((seg[0], seg[1], seg[2], seg[3]), \ tolerance = tolerance) return curveLen def getCubicBoundingBox(csp): if(CommonDefs.inkVer == 1.0): bbox = csp.to_path().bounding_box() return bbox.left, bbox.right, bbox.top, bbox.bottom else: return simpletransform.refinedBBox(csp) def formatSuperPath(csp): if(CommonDefs.inkVer == 1.0): return csp.__str__() else: return cubicsuperpath.formatPath(csp) def getParsedPath(d): if(CommonDefs.inkVer == 1.0): # Copied from Path.to_arrays for compatibility return [[seg.letter, list(seg.args)] for seg in Path(d).to_absolute()] else: return simplepath.parsePath(d) def applyTransform(mat, csp): if(CommonDefs.inkVer == 1.0): csp.transform(mat) else: simpletransform.applyTransformToPath(mat, csp) def getTranslatedPath(d, posX, posY): if(CommonDefs.inkVer == 1.0): path = Path(d) path.translate(posX, posY, inplace = True) return path.to_superpath().__str__() else: path = simplepath.parsePath(d) simplepath.translatePath(path, posX, posY) return simplepath.formatPath(path) def getTransformMat(matAttr): if(CommonDefs.inkVer == 1.0): return Transform(matAttr) else: return simpletransform.parseTransform(matAttr) def getCurrentLayer(effect): if(CommonDefs.inkVer == 1.0): return effect.svg.get_current_layer() else: return effect.current_layer def getViewCenter(effect): if(CommonDefs.inkVer == 1.0): return effect.svg.namedview.center else: return effect.view_center def computePtInNode(vc, layer): if(CommonDefs.inkVer == 1.0): # ~ return (-Transform(layer.transform * mat)).apply_to_point(vc) return (-layer.transform).apply_to_point(vc) else: if(oldVersion): return list(vc) else: return computePointInNode(list(vc), layer) def getSelectedElements(effect): if(CommonDefs.inkVer == 1.0): return effect.svg.selected else: return effect.selected def getEtree(): return etree def getAddFnTypes(effect): if(CommonDefs.inkVer == 1.0): addFn = effect.arg_parser.add_argument typeFloat = float typeInt = int typeString = str typeBool = Boolean else: addFn = effect.OptionParser.add_option typeFloat = 'float' typeInt = 'int' typeString = 'string' typeBool = 'inkbool' return addFn, typeFloat, typeInt, typeString, typeBool def runEffect(effect): if(CommonDefs.inkVer == 1.0): effect.run() else: effect.affect() ######### Function variants for 1.0 and 0.92 - End ########## def getDecodedChars(chars): if(CommonDefs.pyVer == 2): return chars.decode(CommonDefs.encoding) else: #if? return chars def indentStr(cnt): ostr = '' for i in range(0, cnt): ostr += ' ' return ostr def getXMLItemsStr(sectMarkerLine, sectMarker, fontNames): lSpaces = sectMarkerLine.find(sectMarker) outStr = indentStr(lSpaces) + sectMarker + ' [start] -->\n' for fName in fontNames: outStr += indentStr(lSpaces + 4) + '' + fName + '\n' outStr += indentStr(lSpaces) + sectMarker + ' [end] -->\n' return outStr def syncFontList(extPath): sectMarker = '