#!/usr/bin/env python
'''
dm2svg.py - import a DHW file from ACECAD DigiMemo

Copyright (C) 2009 Kevin Lindsey, https://github.com/thelonious/DM2SVG
Copyright (C) 2011 Nikita Kitaev, https://github.com/nikitakit/DM2SVG
Copyright (C) 2011 Chris Morgan,  https://gist.github.com/1471691

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'''

import struct

def process_file(filename):
    try:
        f = open(filename, 'rb')
    except IOError as e:
        print >> sys.stderr, 'Unable to open %s: %s' % (filename, e)
        return

    with f:
        height = emit_header(f)

        layer = 'layer1'
        timestamp = 0
        svg_element = '<g inkscape:groupmode="layer" id="%s">' % layer

        while True:
            tag = f.read(1)
            if tag == '':
                break

            if ord(tag) > 128:
                if tag == '\x90':
                    # Emit the current element and close the last layer
                    emit_element(svg_element)
                    emit_element('</g>')

                    # Start a new layer
                    layer = 'layer%d' % (ord(f.read(1)) + 1)
                    timestamp = 0
                    svg_element = '<g inkscape:groupmode="layer" id="%s">' % layer
                elif tag == '\x88':
                    # Read the timestamp next
                    timestamp += ord(f.read(1)) * 20
                else:
                    # Emit the current svg element
                    emit_element(svg_element)

                    coords = []

                    # Pen down
                    while True:
                        coords.append(read_point(f, height))
                        if ord(f.read(1)) >= 128:
                            break
                        f.seek(-1, 1)  # It wasn't the magic value, don't miss it

                    # Pen up
                    coords.append(read_point(f, height))
                    points = ' '.join(','.join(map(str, e)) for e in coords)
                    svg_element = '<polyline points="%s" dm:timestamp="%s" />' % (points, timestamp)
            else:
                print >> sys.stderr, 'Unsupported tag: %s\n' % tag

        # Emit the footer to finish it off
        print '\n</svg>\n'


def read_point(f, ymax):
    x1, x2, y1, y2 = map(ord, f.read(4))
    x = x1 | x2 << 7
    y = y1 | y2 << 7

    return x, ymax - y


def emit_header(f):
    id, version, width, height, page_type = struct.unpack('<32sBHHBxx', f.read(40))

    print '''
<svg viewBox="0 0 %(width)s %(height)s" fill="none" stroke="black" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  xmlns:dm="http://github.com/nikitakit/DM2SVG">
    <metadata>
      <dm:page
        id="%(id)s"
        version="%(version)s"
        width="%(width)s"
        height="%(height)s"
        page_type="%(page_type)s">
      </dm:page>
    </metadata>
    <rect width="%(width)s" height="%(height)s" fill="aliceblue"/>
''' % locals()

    return height


def emit_element(message):
    if message:
        print '%s\n' % message


if __name__ == '__main__':
    import sys

    if len(sys.argv) == 2:
        process_file(sys.argv[1])
    else:
        print >> sys.stderr, 'Usage: %s <dhw-file>' % sys.argv[0]
        
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
