#!/usr/local/bin/python
# coding: iso-8859-1
# Copyright © 2009 by Amos Newcombe
# 
# 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 3 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, see <http://www.gnu.org/licenses/>.

'''a class to implement Drawings as SVG elements
'''

from Drawing import * # Drawing, Point, Line, Rectangle
from xmllib.xmllib import Element
from imagelib.SVG.SVG import SVGNamespace

def DrawPoint(drwg):
	lln = drwg.llnPoints
	cPoints = len(lln)
	if cPoints == 0:
		xml = None
	elif cPoints == 1:
		xml = MakePoint(lln[0], **drwg.dStyle)
	else:
		xml = Element(sTag='g', lContents=[
			MakePoint(ln, **drwg.dStyle)
			for ln in lln
		])
	return xml

def MakePoint(ln, **dStyle):
	return Element(sTag='rect', ltpAttr=MakeAttr(
		x=ln[0], width =.125, 
		y=ln[1], height=.125, 
	**dStyle))

def DrawLine(drwg):
	lln = drwg.llnPoints
	cPoints = len(lln)
	sName = 'polyline'
	if cPoints == 0:                # Empty polylines are
		xml = None                  # not drawn.
	elif cPoints <= 2:              # Small polylines are
		if cPoints == 1: lln *= 2   # (maybe degenerate)
		sName = 'line'              # lines.
		xml = Element(sTag=sName, ltpAttr=MakeAttr(
			x1=lln[0][0], y1=lln[0][1], 
			x2=lln[1][0], y2=lln[1][1], 
		**drwg.dStyle))
	else:
		if lln[0] == lln[-1]:       # Closed polylines are
			sName = 'polygon'       # polygons, and
			del lln[-1]             # don't need their final point.
		xml = Element(sTag=sName, ltpAttr=MakeAttr(
			points=' '.join([
				','.join([str(n) for n in ln])
				for ln in lln
			]), 
		**drwg.dStyle))
	return xml

def DrawRectangle(drwg):
	(nX0, nY0), (nX1, nY1) = drwg.llnCorners
	return Element(sTag='rect', ltpAttr=MakeAttr(
		x = nX0, width  = nX1 - nX0,
		y = nY0, height = nY1 - nY0,
	**drwg.dStyle))

def DrawEllipse(drwg):
	return Element(sTag='ellipse', ltpAttr=MakeAttr(
		cx = drwg.lnCenter[0], rx = drwg.lnRadius[0],
		cy = drwg.lnCenter[1], ry = drwg.lnRadius[1],
	**drwg.dStyle))

def DrawNothing(drwg):
	return None

dfDraw = {
	Point    : DrawPoint    ,
	Line     : DrawLine     ,
	Rectangle: DrawRectangle,
	Ellipse  : DrawEllipse  ,
	Circle   : DrawEllipse  ,
	CircleCP : DrawEllipse  ,
	Metadata : DrawNothing  ,
}

def DrawSVG(drwg):
	f = dfDraw.get(drwg.__class__)                  # Look for this drawing's function.
	return (
		f(drwg)                                         # Use it
		if f                                            # if you can find it,
		else Element(sTag='g', lContents=filter(None, [ # otherwise create a group
			DrawSVG(drwgT)                              # to wrap up the contents.
			for drwgT in drwg.lContents
		]))
	)

def SVGImage(tpsSize, tpImg, drwg, **d):
	return Element(sTag='svg', ltpAttr=[
		('version', '1.1'),
		('width', tpsSize[0]), ('height', tpsSize[1]),
		('viewbox', ' '.join(['0', '0'] + [str(n) for n in tpImg])),
	], lContents=[
		DrawSVG(drwg)
	], nsApplied=SVGNamespace(sPrefix='svg'),
	**d)

# SVG utilities

def MakeAttr(**d):
	ltp = [
		('color'    , 'stroke'          , '#000'),
		('fill '    , 'fill'            , 'none'),
		('linewidth', 'stroke-width'    ,  None ),
		('dasharray', 'stroke-dasharray',  None ),
		('pen'      ,  None             ,  None ),
	]
	ltpAttr = []
	for tp in ltp: AddAttribute(d, ltpAttr, *tp)
	ltpAttr.extend(d.items())
	return ltpAttr

def AddAttribute(d, ltpAttr, sDrawField, sSvgAttr, oDefault):
	if sSvgAttr == None:
		d.pop(sDrawField, None)
	if oDefault != None:
		ltpAttr.append((sSvgAttr, d.pop(sDrawField, oDefault)))
	else:
		try: ltpAttr.append((sSvgAttr, d.pop(sDrawField)))
		except KeyError: pass

if __name__ == '__main__':
	
	from imagelib.SVG.SVG import SVGDocument
	
	drwg = Drawing(
		Line((10, 100), (10, 10), (100, 10)),
		Rectangle((1, 1), (299, 299), color='blue', dasharray='1,4'),
		Point((20, 20), (20, 40), (40, 20)),
		Ellipse((65, 30), (35, 10), color='green'),
		Circle((75, 75), 25),
		CircleCP((30, 60), (50, 75), color='#ccc')
	)
	
	open('DrawSVG.svg', 'w').write(str(SVGDocument(xmlElem = SVGImage(
		('3in', '3in'), 
		( 300 ,  300 ), 
		drwg,
	))))
