diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index b6d8e43535..45aa204568 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -98,6 +98,7 @@ SET(Draft_functions draftfunctions/scale.py draftfunctions/split.py draftfunctions/svg.py + draftfunctions/svgtext.py draftfunctions/upgrade.py draftfunctions/README.md ) diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index 04b98b29fd..3ceb6e5216 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -33,13 +33,13 @@ may not be removed completely yet. This must be checked. # \brief Provides functions to return the SVG representation of shapes. import math -import six import lazy_loader.lazy_loader as lz import FreeCAD as App import DraftVecUtils import WorkingPlane import draftutils.utils as utils +import draftfunctions.svgtext as svgtext from draftutils.utils import param from draftutils.messages import _msg, _wrn @@ -354,194 +354,6 @@ def getOvershoot(point, shootsize, color, linewidth, angle=0): return get_overshoot(point, shootsize, color, linewidth, angle) -def _get_text_techdraw(text, tcolor, fontsize, anchor, - align, fontname, angle, base, - linespacing): - """Return the SVG representation of text for TechDraw display. - - `text` is a list of textual elements; they are iterated, styled, - and added around a `` tag. - :: - text[0] - text[1] - """ - svg = "" - for i in range(len(text)): - _t = text[i].replace("&", "&") - _t = _t.replace("<", "<") - t = _t.replace(">", ">") - - if six.PY2 and not isinstance(t, six.text_type): - t = t.decode("utf8") - - # possible workaround if UTF8 is unsupported - # import unicodedata as U - # v = list() - # for c in U.normalize("NFKD", t): - # if not U.combining(c): - # v.append(c) - # - # t = u"".join(v) - # t = t.encode("utf8") - - svg += ' tag with style options. - - The text must be added after this tag, and then must be closed. - :: - - ... - - """ - svg = ' 0.1: - angle = -angle.Angle - else: - angle = angle.Angle - elif abs(plane.axis.getAngle(angle.Axis) - math.pi/2) < 0.001: - # text is perpendicular to view, so it shouldn't appear - return "" - else: - # TODO maybe there is something better to do here? - angle = 0 - - # text should be a list of strings separated by a newline - if not isinstance(text, list): - text = text.split("\n") - - if align.lower() == "center": - anchor = "middle" - elif align.lower() == "left": - anchor = "start" - else: - anchor = "end" - - if techdraw: - # For TechDraw display each item in the text list is placed - # in an individual tag. - # text[0] - # text[1] - svg = _get_text_techdraw(text, tcolor, fontsize, anchor, - align, fontname, angle, base, - linespacing) - else: - # If the SVG is not for TechDraw, and there is a single item - # in the text list, place it in a single tag. - # text - # - # For multiple elements, place each element inside a tag. - # - # text[0] - # text[1] - # - svg = _get_text_header(tcolor, fontsize, anchor, align, - fontname, angle, base, flip) - - if len(text) == 1: - try: - _t = text[0].replace("&", "&").replace("<", "<") - svg += _t.replace(">", ">") - except: - # TODO: trap only specific exception; what is the problem? - # Bad UTF8 string specification? This can be removed - # once the code is only used with Python 3. - _t = text[0].decode("utf8") - _t = _t.replace("&", "&").replace("<", "<") - svg += _t.replace(">", ">") - else: - for i in range(len(text)): - if i == 0: - svg += '' - else: - svg += ''.format(linespacing) - - try: - _t = text[i].replace("&", "&").replace("<", "<") - svg += _t.replace(">", ">") - except: - # TODO: trap only specific exception; what is the problem? - # Bad UTF8 string specification? This can be removed - # once the code is only used with Python 3. - _t = text[i].decode("utf8") - _t = _t.replace("&", "&").replace("<", "<") - svg += _t.replace(">", ">") - - svg += '\n' - svg += '\n' - return svg - - -def getText(plane, techdraw, - tcolor, fontsize, fontname, - angle, base, text, - linespacing=0.5, align="center", flip=True): - """Get the SVG representation of a textual element. DEPRECATED.""" - utils.use_instead("get_text") - return get_text(plane, techdraw, - tcolor, fontsize, fontname, - angle, base, text, - linespacing, align, flip) - - def format_point(coords, action='L'): """Return a string with a formatted point.""" return "{action}{x},{y}".format(x=coords.x, y=coords.y, action=action) @@ -1066,9 +878,9 @@ def get_svg(obj, angle + math.pi) # drawing text - svg += get_text(plane, techdraw, - stroke, fontsize, vobj.FontName, - tangle, tbase, prx.string) + svg += svgtext.get_text(plane, techdraw, + stroke, fontsize, vobj.FontName, + tangle, tbase, prx.string) elif utils.get_type(obj) == "AngularDimension": if not App.GuiUp: @@ -1160,9 +972,10 @@ def get_svg(obj, tangle = 0 tbase = get_proj(prx.tbase, plane) - svg += get_text(plane, techdraw, - stroke, fontsize, obj.ViewObject.FontName, - tangle, tbase, prx.string) + svg += svgtext.get_text(plane, techdraw, + stroke, fontsize, + obj.ViewObject.FontName, + tangle, tbase, prx.string) elif utils.get_type(obj) == "Label": if getattr(obj.ViewObject, "Line", True): @@ -1204,10 +1017,10 @@ def get_svg(obj, rotation = obj.Placement.Rotation justification = obj.ViewObject.TextAlignment text = obj.Text - svg += get_text(plane, techdraw, - stroke, fontsize, fontname, - rotation, position, text, - linespacing, justification) + svg += svgtext.get_text(plane, techdraw, + stroke, fontsize, fontname, + rotation, position, text, + linespacing, justification) elif utils.get_type(obj) in ["Annotation", "DraftText", "Text"]: # returns an svg representation of a document annotation @@ -1226,10 +1039,10 @@ def get_svg(obj, t = obj.Text j = obj.ViewObject.Justification - svg += get_text(plane, techdraw, - stroke, fontsize, n, - r, p, t, - linespacing, j) + svg += svgtext.get_text(plane, techdraw, + stroke, fontsize, n, + r, p, t, + linespacing, j) elif utils.get_type(obj) == "Axis": # returns the SVG representation of an Arch Axis system @@ -1365,20 +1178,20 @@ def get_svg(obj, lspc = App.Vector(_h) p1 = p2 + lspc j = vobj.TextAlign - t3 = get_text(plane, techdraw, - c, f1, n, - a, get_proj(p1, plane), t1, - linespacing, j, flip=True) + t3 = svgtext.get_text(plane, techdraw, + c, f1, n, + a, get_proj(p1, plane), t1, + linespacing, j, flip=True) svg += t3 if t2: ofs = App.Vector(0, -lspc.Length, 0) if a: Z = App.Vector(0, 0, 1) ofs = App.Rotation(Z, -rotation).multVec(ofs) - t4 = get_text(plane, techdraw, - c, fontsize, n, - a, get_proj(p1, plane).add(ofs), t2, - linespacing, j, flip=True) + t4 = svgtext.get_text(plane, techdraw, + c, fontsize, n, + a, get_proj(p1, plane).add(ofs), t2, + linespacing, j, flip=True) svg += t4 elif hasattr(obj, 'Shape'): diff --git a/src/Mod/Draft/draftfunctions/svgtext.py b/src/Mod/Draft/draftfunctions/svgtext.py new file mode 100644 index 0000000000..cb0d775d64 --- /dev/null +++ b/src/Mod/Draft/draftfunctions/svgtext.py @@ -0,0 +1,227 @@ +# -*- coding: utf8 -*- +# *************************************************************************** +# * Copyright (c) 2009 Yorik van Havre * +# * Copyright (c) 2018 George Shuklin (amarao) * +# * Copyright (c) 2020 Eliud Cabrera Castillo * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * 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 Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** +"""Provides functions to return the SVG representation of text elements.""" +## @package svgtext +# \ingroup draftfuctions +# \brief Provides functions to return the SVG representation of text elements. + +import math +import six + +import FreeCAD as App +import draftutils.utils as utils + +## \addtogroup draftfuctions +# @{ + + +def _get_text_techdraw(text, tcolor, fontsize, anchor, + align, fontname, angle, base, + linespacing): + """Return the SVG representation of text for TechDraw display. + + `text` is a list of textual elements; they are iterated, styled, + and added around a `` tag. + :: + text[0] + text[1] + """ + svg = "" + for i in range(len(text)): + _t = text[i].replace("&", "&") + _t = _t.replace("<", "<") + t = _t.replace(">", ">") + + # TODO: remove when Python 2 is no longer supported + if six.PY2 and not isinstance(t, six.text_type): + t = t.decode("utf8") + + # possible workaround if UTF8 is unsupported + # import unicodedata as U + # v = list() + # for c in U.normalize("NFKD", t): + # if not U.combining(c): + # v.append(c) + # + # t = u"".join(v) + # t = t.encode("utf8") + + svg += ' tag with style options. + + The text must be added after this tag, and then must be closed. + :: + + ... + + """ + svg = ' 0.1: + angle = -angle.Angle + else: + angle = angle.Angle + elif abs(plane.axis.getAngle(angle.Axis) - math.pi/2) < 0.001: + # text is perpendicular to view, so it shouldn't appear + return "" + else: + # TODO maybe there is something better to do here? + angle = 0 + + # text should be a list of strings separated by a newline + if not isinstance(text, list): + text = text.split("\n") + + if align.lower() == "center": + anchor = "middle" + elif align.lower() == "left": + anchor = "start" + else: + anchor = "end" + + if techdraw: + # For TechDraw display each item in the text list is placed + # in an individual tag. + # text[0] + # text[1] + svg = _get_text_techdraw(text, tcolor, fontsize, anchor, + align, fontname, angle, base, + linespacing) + else: + # If the SVG is not for TechDraw, and there is a single item + # in the text list, place it in a single tag. + # text + # + # For multiple elements, place each element inside a tag. + # + # text[0] + # text[1] + # + svg = _get_text_header(tcolor, fontsize, anchor, align, + fontname, angle, base, flip) + + if len(text) == 1: + try: + _t = text[0].replace("&", "&").replace("<", "<") + svg += _t.replace(">", ">") + except: + # TODO: trap only specific exception; what is the problem? + # Bad UTF8 string specification? This can be removed + # once the code is only used with Python 3. + _t = text[0].decode("utf8") + _t = _t.replace("&", "&").replace("<", "<") + svg += _t.replace(">", ">") + else: + for i in range(len(text)): + if i == 0: + svg += '' + else: + svg += ''.format(linespacing) + + try: + _t = text[i].replace("&", "&").replace("<", "<") + svg += _t.replace(">", ">") + except: + # TODO: trap only specific exception; what is the problem? + # Bad UTF8 string specification? This can be removed + # once the code is only used with Python 3. + _t = text[i].decode("utf8") + _t = _t.replace("&", "&").replace("<", "<") + svg += _t.replace(">", ">") + + svg += '\n' + svg += '\n' + return svg + + +def getText(plane, techdraw, + tcolor, fontsize, fontname, + angle, base, text, + linespacing=0.5, align="center", flip=True): + """Get the SVG representation of a textual element. DEPRECATED.""" + utils.use_instead("get_text") + return get_text(plane, techdraw, + tcolor, fontsize, fontname, + angle, base, text, + linespacing, align, flip) + +## @}