Skip to content

Commit

Permalink
Merge pull request #176 from xyz2tex/174-misplacement-of-element
Browse files Browse the repository at this point in the history
Misplacement of Nodes
  • Loading branch information
ldevillez authored Nov 29, 2023
2 parents c47f77c + 814b774 commit 92ea970
Show file tree
Hide file tree
Showing 5 changed files with 429 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
- Fixing error on treating polylines and polygones
- Verbose option to add name of shapes and layers
- Converting line tag
- Transformation matrix for nodes
### Security

## v2.1.0 - 2023/06/28
Expand Down
45 changes: 33 additions & 12 deletions svg2tikz/tikz_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,14 @@ def marking_interpret(marker):
return raw_marker


def options_to_str(options: list) -> str:
"""
Convert a list of options to a str with comma separated value.
If the list is empty, return an empty str
"""
return f"[{','.join(options)}]" if len(options) > 0 else ""


def return_arg_parser_doc():
"""
Methode to return the arg parser of TikzPathExporter to help generate the doc
Expand Down Expand Up @@ -858,7 +866,7 @@ def style_to_tz(self, node=None):

return options

def trans_to_tz(self, node=None):
def trans_to_tz(self, node=None, is_node=False):
"""
Convert inkex transform to tikz code
"""
Expand All @@ -876,9 +884,13 @@ def trans_to_tz(self, node=None):
if trans.is_translate():
tr = self.convert_unit_coord(Vector2d(trans.e, trans.f), False)

if not self.options.noreversey:
# Global scale do not impact transform
if not self.options.noreversey or is_node:
tr.y *= -1

tr.x *= self.options.scale
tr.y *= self.options.scale

options.append("shift={" + self.coord_to_tz(tr) + "}")

# Rotation
Expand All @@ -905,20 +917,25 @@ def trans_to_tz(self, node=None):
options.append(f"xscale={x},yscale={y}")

elif "matrix" in str(trans):
# print(trans)
tr = self.convert_unit_coord(Vector2d(trans.e, trans.f), False)
a = self.round_value(trans.a)
b = self.round_value(trans.b)
c = self.round_value(trans.c)
d = self.round_value(trans.d)

if not self.options.noreversey:
# globalscale do not impact transform
if not self.options.noreversey or is_node:
tr.y *= -1
b *= -1
c *= -1
tr.y *= -1

if not self.options.noreversey and not is_node:
tr.x += -c * self.update_height(0)
tr.y += self.update_height(0) * (1 - d)
tr.y += (1 - d) * self.update_height(0)

tr.x *= self.options.scale
tr.y *= self.options.scale
options.append(f"cm={{ {a},{b},{c}" f",{d},{self.coord_to_tz(tr)}}}")

# Not possible to get them directly
Expand Down Expand Up @@ -1235,16 +1252,19 @@ def _handle_text(self, node):
if trans.is_rotate():
# get angle
ang = atan2(trans.b, trans.a)
p = self.rotate_coord(p, ang)
p = self.convert_unit_coord(self.rotate_coord(p, ang))

p = self.round_coord(self.convert_unit_coord(p))
# scale do not impact node
if self.options.noreversey:
p.y *= -1

return f"({node.get_id()}) at {self.coord_to_tz(p)}" + "{" + f"{textstr}" + "}"

def get_text(self, node):
"""Return content of a text node as string"""
return etree.tostring(node, method="text").decode("utf-8")

# pylint: disable=too-many-branches
def _output_group(self, group):
"""Process a group of SVG nodes and return corresponding TikZ code
Expand All @@ -1266,7 +1286,9 @@ def _output_group(self, group):
string += self._handle_group(node)
continue
try:
goptions = self.style_to_tz(node) + self.trans_to_tz(node)
goptions = self.style_to_tz(node) + self.trans_to_tz(
node, node.TAG in ["text", "flowRoot", "image"]
)
except AttributeError as msg:
attr = msg.args[0].split("attribute")[1].split(".")[0]
logging.warning("%s attribute cannot be represented", attr)
Expand All @@ -1277,16 +1299,15 @@ def _output_group(self, group):
string += self.text_indent + f"%{node.get_id()}\n"

if node.TAG == "path":
optionscode = f"[{','.join(goptions)}]" if len(goptions) > 0 else ""
optionscode = options_to_str(goptions)

pathcode = f"\\path{optionscode} {self.convert_path_to_tikz(node.path)}"

elif node.TAG in LIST_OF_SHAPES:
# Add indent
pathcode, options = self._handle_shape(node)

goptions += options
optionscode = f"[{','.join(goptions)}]" if len(goptions) > 0 else ""
optionscode = options_to_str(goptions + options)

pathcode = f"\\path{optionscode} {pathcode}"

Expand All @@ -1301,7 +1322,7 @@ def _output_group(self, group):
if not contains_anchor:
goptions += ["anchor=south west"]

optionscode = f"[{','.join(goptions)}]" if len(goptions) > 0 else ""
optionscode = options_to_str(goptions)
# Convert a rotate around to a rotate option
if "rotate around={" in optionscode:
splited_options = optionscode.split("rotate around={")
Expand Down
5 changes: 5 additions & 0 deletions tests/test_complete_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ def test_wrap(self):
filename = "rectangle_wrap"
create_test_from_filename(filename, self, wrap=True)

def test_nodes_and_transform(self):
"""Test complete convert transformation on nodes"""
filename = "nodes_and_transform"
create_test_from_filename(filename, self)


if __name__ == "__main__":
unittest.main()
Loading

0 comments on commit 92ea970

Please sign in to comment.