diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:50:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:50:49 +0000 |
commit | c853ffb5b2f75f5a889ed2e3ef89b818a736e87a (patch) | |
tree | 7d13a0883bb7936b84d6ecdd7bc332b41ed04bee /share/extensions/hpgl_parser.py | |
parent | Initial commit. (diff) | |
download | inkscape-c853ffb5b2f75f5a889ed2e3ef89b818a736e87a.tar.xz inkscape-c853ffb5b2f75f5a889ed2e3ef89b818a736e87a.zip |
Adding upstream version 1.3+ds.upstream/1.3+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'share/extensions/hpgl_parser.py')
-rw-r--r-- | share/extensions/hpgl_parser.py | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/share/extensions/hpgl_parser.py b/share/extensions/hpgl_parser.py new file mode 100644 index 0000000..bb6e97e --- /dev/null +++ b/share/extensions/hpgl_parser.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2022 Jonathan Neuhauser (jonathan.neuhauser@outlook.com) +# +# 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. +# + +"""Grammar for parsing HPGL input files""" + +import pyparsing as pp +from hpgl_input_sm import HPGLStateMachine + +pp.ParserElement.enablePackrat() +pp.enable_all_warnings() + +integer = pp.pyparsing_common.integer +sinteger = pp.pyparsing_common.signed_integer +flt = pp.pyparsing_common.number +comma = pp.Optional(pp.Suppress(",")) + +cpair = flt("X*") + comma + flt("Y*") + + +def build_vector_parsers(stm: HPGLStateMachine): + """Parsers of the vector group""" + # Lines + line_command = pp.Group( + ( + (pp.Literal("PA") | "PR" | "PD" | "PU")("key") + + pp.Opt( + cpair + + pp.ZeroOrMore(comma + cpair) + + pp.Opt(comma + sinteger("leftover*")) + ) + ).add_parse_action(stm.line_command) + ) + # Circles and arcs + ci_command = pp.Group( + ( + "CI" + sinteger("Radius") + pp.Opt(comma + flt("Chord_angle")) + ).add_parse_action(stm.ci_command) + ) + + arc_command = pp.Group( + ( + (pp.Literal("AA") | "AR")("key") + + cpair + + comma + + sinteger("sweep") + + pp.Opt(comma + flt("Chord_angle*")) + ).add_parse_action(stm.arc_command) + ) + at_command = pp.Group( + ( + "AT" + cpair + comma + cpair + pp.Opt(comma + flt("Chord_angle*")) + ).add_parse_action(stm.at_command) + ) + + # Beziers + bezier = cpair + comma + cpair + comma + cpair + bezier_command = pp.Group( + ( + (pp.Literal("BR") | "BZ")("key") + + bezier("B*") + + pp.ZeroOrMore(comma + bezier("B*")) + ).add_parse_action(stm.bezier_command) + ) + # Polyline encoded + pe_command = pp.Group( + ( + "PE" + pp.Regex("[^;]*").setWhitespaceChars("")("data") + pp.Suppress(";") + ).add_parse_action(stm.polyline_encoded) + ) + + return ( + line_command + | ci_command + | arc_command + | bezier_command + | at_command + | pe_command + ) + + +def build_polygon_parsers(stm: HPGLStateMachine): + """Build parser object from the polygon group""" + pm_command = pp.Group( + ("PM" + pp.Opt(pp.Word("012", exact=1), default="0")("value")).add_parse_action( + stm.pm_command + ) + ) + rectangle_command = pp.Group( + ((pp.Literal("EA") | "ER" | "RA" | "RR")("key") + cpair).add_parse_action( + stm.rectangle_command + ) + ) + polygon_command = pp.Group( + ( + ( + pp.Literal("FP")("key") + + pp.Opt(pp.Word("01", exact=1), default="0")("fillmode") + ) + | pp.Literal("EP")("key") + ).add_parse_action(stm.edge_fill_polygon) + ) + wedge_command = pp.Group( + ( + (pp.Literal("EW") | "WG")("key") + + sinteger("radius") + + comma + + flt("start_angle") + + comma + + flt("sweep") + + pp.Opt(comma + flt("Chord_angle*")) + ).add_parse_action(stm.wedge_command) + ) + return pm_command | rectangle_command | polygon_command | wedge_command + + +def build_linefill_parsers(stm: HPGLStateMachine): + """Build parsers from the Line and Fill Attributes Group""" + + kind = pp.Word("123", exact=1)("kind*") + la_command = pp.Group( + "LA" + + pp.Opt(kind + comma + integer("value*")) + + (comma + kind + comma + integer("value*")) * (0, 2) + ) + lt_command = pp.Group( + "LT" + + pp.Opt( + integer("linetype") + + pp.Opt(comma + flt("pattern_length") + pp.Opt(comma + flt("mode"))) + ) + ) + pw_command = pp.Group("PW" + pp.Opt(flt("width") + pp.Opt(comma + integer("pen")))) + # maybe we can combine those two? + ft_command = pp.Group( + "FT" + + pp.Opt( + (pp.Literal("1") | "2" | "3" | "4" | "10" | "11" | "21" | "22")("type") + + pp.Opt(comma + flt("option1") + pp.Opt(comma + flt("option2"))) + ) + ) + tr_command = pp.Group("TR" + pp.Opt(pp.Literal("0") | "1", "1")("transparency")) + ul_command = pp.Group( + "UL" + pp.Opt(integer("index") + (comma + flt("gap*")) * (0, 20)) + ) + wu_command = pp.Group("WU" + pp.Opt(pp.Word("01", exact=1)("units"))) + sp_command = pp.Group("SP" + pp.Opt(integer("pen"), 0)) + return ( + sp_command + | la_command + | lt_command + | pw_command + | ft_command + | tr_command + | ul_command + | wu_command + ).add_parse_action(stm.style_command) + + +def build_configuration_parser(stm: HPGLStateMachine): + """Commands of the configurtion group""" + co_command = pp.Literal("CO") + pp.Suppress('"') + ... + pp.Suppress('"') + in_command = pp.Literal("IN").add_parse_action(stm.initialize) + ip_command = pp.Group( + (pp.Literal("IP") | "IR")("key") + pp.Opt(cpair + pp.Opt(comma + cpair)) + ) + ro_command = pp.Group( + "RO" + pp.Optional(pp.Literal("0") | "90" | "180" | "270", "0")("angle") + ) + iw_command = pp.Group("IW" + pp.Opt(cpair + comma + cpair)) + sc_command = pp.Group( + pp.Literal("SC") + + ( + pp.Optional( + flt("Xmin") + + comma + + flt("Xmax") + + comma + + flt("Ymin") + + comma + + flt("Ymax") + + pp.Optional( + (comma + (pp.Literal("0") | "2")("type")) + | ( + comma + + pp.Literal("1")("type") + + pp.Optional(comma + flt("left") + comma + flt("bottom")) + ) + ) + ) + ) + ) + + return (in_command | co_command) | ( + ip_command | sc_command | ro_command | iw_command + ).add_parse_action(stm.transform_command) + + +def build_parser(stm: HPGLStateMachine): + """Assemble the command groups""" + + command = ( + build_configuration_parser(stm) + | build_vector_parsers(stm) + | build_polygon_parsers(stm) + | build_linefill_parsers(stm) + # Commands we don't understand + | pp.Group(pp.Word(pp.alphas, exact=2) + pp.Opt(pp.Word(pp.nums + ",. ")))("u*") + ) + # The parse actions of the documents are final cleanup + document = pp.ZeroOrMore(command + pp.Opt(pp.Suppress(";"))).add_parse_action( + stm.finalize_path + ) + pp.autoname_elements() + return document |