#!/usr/bin/env python # coding=utf-8 # # Copyright (C) 2009 Kevin Lindsey, https://github.com/thelonious/DM2SVG # 2011 Nikita Kitaev, https://github.com/nikitakit/DM2SVG # Chris Morgan, https://gist.github.com/1471691 # 2019 Martin Owens, # # 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 a DHW file from ACECAD DigiMemo, a hardware based digitiser """ import struct import inkex from inkex import AbortExtension, errormsg, Group, Polyline from inkex.localization import inkex_gettext as _ inkex.NSS["dm"] = "http://github.com/nikitakit/DM2SVG" class DhwInput(inkex.InputExtension): """Open DHW files and convert to svg on the fly""" template = """ """ def load(self, stream): """Load the steam as if it were an open DHW file""" header = list(struct.unpack("<32sBHHBxx", stream.read(40))) doc = header.pop(0).decode() if doc != "ACECAD_DIGIMEMO_HANDWRITING_____": raise AbortExtension(_("Could not load file, not a ACECAD DHW file!")) height = int(header[2]) doc = self.get_template(**dict(zip(("v", "w", "h", "p"), header))) svg = doc.getroot() timestamp = 0 layer = svg.getElementById("layer1") while True: tag = stream.read(1) if tag == b"": break if ord(tag) <= 128: errormsg(_("Unsupported tag: {}\n").format(tag)) continue if tag == b"\x90": # New Layer element timestamp = 0 name = "layer{:d}".format(ord(stream.read(1)) + 1) layer = svg.add(Group(inkscape_groupmode="layer", id=name)) elif tag == b"\x88": # Read the timestamp next timestamp += ord(stream.read(1)) * 20 else: # Pen down coords = [p for p in iter(lambda: read_point(stream, height), None)] # Pen up coords.append(read_point(stream, height)) poly = layer.add(Polyline()) poly.path = coords poly.set("dm:timestamp", timestamp) return doc def read_point(stream, ymax): """If the next byte is a stop byte, return None. Otherwise read 4 bytes (in total) and return a 2D point. """ # read first byte, it might be a stop byte x1 = struct.unpack("B", stream.read(1))[0] if x1 >= 0x80: return None x2, y1, y2 = struct.unpack("BBB", stream.read(3)) x = x1 | x2 << 7 y = y1 | y2 << 7 return x, ymax - y if __name__ == "__main__": DhwInput().run()