mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-05 22:04:27 +08:00
301 lines
9.3 KiB
Python
Executable File
301 lines
9.3 KiB
Python
Executable File
# lots to do:
|
|
# __ native drawLines
|
|
# __ add native drawCurve method
|
|
# __ native rectangle/round rect method
|
|
# __ native drawEllipse
|
|
# __ native drawArc
|
|
# __ drawImage support (work on Pyart side of things)
|
|
import pyart
|
|
from sping.pid import *
|
|
from sping.PDF import pdfmetrics
|
|
import Fontmapping # helps by mapping pid font classes to Pyart font names
|
|
|
|
# note for now I'm just going to do the standard PDF fonts & forget the rest
|
|
|
|
|
|
|
|
|
|
class PyartCanvas(Canvas):
|
|
"note the default face is 'times' and is set in Fontmapping.py"
|
|
|
|
def __init__(self,size=(300,300),name='PyartCanvas.png'):
|
|
|
|
self._pycan = pyart.Canvas(size[0], size[1], dpi=72)
|
|
self.filename = name
|
|
|
|
|
|
Canvas.__init__(self, size, name)
|
|
|
|
# self.defaultFillColor = transparent
|
|
|
|
# now we need to setup our tracking of the defaults vs the current state
|
|
|
|
# see if the __setattr__ approach is any better than the _updateXX strategy
|
|
def __setattr__(self, name, value):
|
|
if name == 'defaultLineColor':
|
|
if value:
|
|
# print 'setting defaultLineColor to %s, 0x%x' % (value, value.toHexRGB())
|
|
if value != transparent:
|
|
self._pycan.gstate.stroke = value.toHexRGB()
|
|
self.__dict__[name] = value
|
|
elif name == 'defaultFillColor':
|
|
if value:
|
|
if value != transparent:
|
|
self._pycan.gstate.fill = value.toHexRGB()
|
|
self.__dict__[name] = value
|
|
elif name == 'defaultLineWidth' :
|
|
if value:
|
|
self._pycan.gstate.stroke_width = value
|
|
self.__dict__[name] = value
|
|
elif name == 'defaultFont':
|
|
if value:
|
|
self.__dict__[name] = value
|
|
self._setPyartFont(value)
|
|
else: # received None so set to default font face & size=12
|
|
self.__dict__[name] = Font(face='times')
|
|
self._setPyartFont(self.__dict__[name])
|
|
|
|
else:
|
|
self.__dict__[name] = value
|
|
|
|
|
|
|
|
|
|
## Private methods ##
|
|
def _protectArtState(self, bool):
|
|
if bool:
|
|
self._pycan.gsave()
|
|
return bool
|
|
|
|
def _restoreArtState(self, bool):
|
|
if bool:
|
|
self._pycan.grestore()
|
|
|
|
|
|
def _setPyartFont(self, fontInstance):
|
|
# accounts for "None" option
|
|
# does not act on self.defaultFont at all
|
|
|
|
fontsize = fontInstance.size
|
|
self._pycan.gstate.font_size = fontsize
|
|
# map pid name for font to Pyart name
|
|
pyartname = Fontmapping.getPyartName(fontInstance)
|
|
self._pycan.gstate.setfont(pyartname)
|
|
|
|
|
|
# # # # #
|
|
|
|
|
|
### public PID Canvas methods ##
|
|
|
|
def clear(self):
|
|
pass
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
|
|
def save(self, file=None, format=None):
|
|
# fileobj = getFileObject(file)
|
|
|
|
if not file:
|
|
file = self.filename
|
|
|
|
if isinstance(file, StringType):
|
|
self._pycan.save(file)
|
|
else:
|
|
raise NotImplementedError
|
|
|
|
|
|
def _findExternalFontName(self, font): #copied from piddlePDF by cwl- hack away!
|
|
"""Attempts to return proper font name.
|
|
PDF uses a standard 14 fonts referred to
|
|
by name. Default to self.defaultFont('Helvetica').
|
|
The dictionary allows a layer of indirection to
|
|
support a standard set of PIDDLE font names."""
|
|
|
|
piddle_font_map = {
|
|
'Times':'Times',
|
|
'times':'Times',
|
|
'Courier':'Courier',
|
|
'courier':'Courier',
|
|
'helvetica':'Helvetica',
|
|
'Helvetica':'Helvetica',
|
|
'symbol':'Symbol',
|
|
'Symbol':'Symbol',
|
|
'monospaced':'Courier',
|
|
'serif':'Times',
|
|
'sansserif':'Helvetica',
|
|
'ZapfDingbats':'ZapfDingbats',
|
|
'zapfdingbats':'ZapfDingbats',
|
|
'arial':'Helvetica'
|
|
}
|
|
|
|
try:
|
|
face = piddle_font_map[string.lower(font.face)]
|
|
except:
|
|
return 'Helvetica'
|
|
|
|
name = face + '-'
|
|
if font.bold and face in ['Courier','Helvetica','Times']:
|
|
name = name + 'Bold'
|
|
if font.italic and face in ['Courier', 'Helvetica']:
|
|
name = name + 'Oblique'
|
|
elif font.italic and face == 'Times':
|
|
name = name + 'Italic'
|
|
|
|
if name == 'Times-':
|
|
name = name + 'Roman'
|
|
# symbol and ZapfDingbats cannot be modified!
|
|
|
|
#trim and return
|
|
if name[-1] == '-':
|
|
name = name[0:-1]
|
|
return name
|
|
|
|
|
|
def stringWidth(self, s, font=None):
|
|
if not font:
|
|
font = self.defaultFont
|
|
fontname = Fontmapping.getPdfName(font)
|
|
return pdfmetrics.stringwidth(s, fontname) * font.size * 0.001
|
|
|
|
|
|
def fontAscent(self, font=None):
|
|
if not font:
|
|
font = self.defaultFont
|
|
fontname = Fontmapping.getPdfName(font)
|
|
return pdfmetrics.ascent_descent[fontname][0] * 0.001 * font.size
|
|
|
|
|
|
def fontDescent(self, font=None):
|
|
if not font:
|
|
font = self.defaultFont
|
|
fontname = Fontmapping.getPdfName(font)
|
|
return -pdfmetrics.ascent_descent[fontname][1] * 0.001 * font.size
|
|
|
|
|
|
def drawLine(self, x1, y1, x2, y2, color=None, width=None):
|
|
## standard code ##
|
|
color = color or self.defaultLineColor
|
|
width = width or self.defaultLineWidth
|
|
if color != transparent:
|
|
changed = self._protectArtState( (color != self.defaultLineColor) or
|
|
(width != self.defaultLineWidth) )
|
|
if color != self.defaultLineColor:
|
|
self._pycan.gstate.stroke = color.toHexRGB()
|
|
# print "color is %s <-> %s" % (color, color.toHexStr())
|
|
if width != self.defaultLineWidth:
|
|
self._pycan.gstate.stroke_width = width
|
|
###################
|
|
|
|
# actual drawing
|
|
p = pyart.VectorPath(3)
|
|
p.moveto_open(x1,y1)
|
|
p.lineto(x2,y2)
|
|
self._pycan.stroke(p)
|
|
|
|
## standard code ##
|
|
if changed:
|
|
self._pycan.grestore()
|
|
###################
|
|
|
|
# def drawLines(self, lineList, color=None, width=None):
|
|
# pass
|
|
|
|
def drawString(self, s, x, y, font=None, color=None, angle=0):
|
|
# start w/ the basics
|
|
self._pycan.drawString(x,y, s)
|
|
|
|
def drawPolygon(self, pointlist,
|
|
edgeColor=None, edgeWidth=None, fillColor=None, closed=0):
|
|
|
|
eColor = edgeColor or self.defaultLineColor
|
|
fColor = fillColor or self.defaultFillColor
|
|
eWidth = edgeWidth or self.defaultLineWidth
|
|
|
|
changed = self._protectArtState( (eColor != self.defaultLineColor) or
|
|
(eWidth != self.defaultLineWidth) or
|
|
(fColor != self.defaultFillColor) )
|
|
|
|
if eColor != self.defaultLineColor:
|
|
self._pycan.gstate.stroke = eColor.toHexRGB()
|
|
|
|
if fColor != self.defaultFillColor:
|
|
self._pycan.gstate.fill = fColor.toHexRGB()
|
|
|
|
if eWidth != self.defaultLineWidth:
|
|
self._pycan.gstate.stroke_width = eWidth
|
|
|
|
path = pyart.VectorPath(len(pointlist)+1)
|
|
if closed:
|
|
path.moveto_closed(pointlist[0][0], pointlist[0][1])
|
|
else:
|
|
path.moveto_open(pointlist[0][0], pointlist[0][1])
|
|
|
|
for pt in pointlist[1:]:
|
|
path.lineto(pt[0],pt[1])
|
|
|
|
if closed:
|
|
path.close()
|
|
|
|
if fColor != transparent and closed:
|
|
self._pycan.fill(path)
|
|
|
|
if eColor != transparent:
|
|
self._pycan.stroke(path)
|
|
|
|
self._restoreArtState(changed)
|
|
|
|
|
|
|
|
#def drawCurve(self, x1, y1, x2, y2, x3, y3, x4, y4,
|
|
# edgeColor=None, edgeWidth=None, fillColor=None, closed=0):
|
|
# pass
|
|
|
|
# def drawRoundRect(self, x1,y1, x2,y2, rx=8, ry=8,
|
|
# edgeColor=None, edgeWidth=None, fillColor=None):
|
|
# pass
|
|
|
|
# def drawEllipse(self, x1,y1, x2,y2, edgeColor=None, edgeWidth=None,
|
|
# fillColor=None):
|
|
# pass
|
|
|
|
# def drawArc(self, x1,y1, x2,y2, startAng=0, extent=360, edgeColor=None,
|
|
# edgeWidth=None, fillColor=None):
|
|
|
|
# pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# def drawFigure(self, partList,
|
|
# edgeColor=None, edgeWidth=None, fillColor=None, closed=0):
|
|
# pass
|
|
|
|
|
|
# def drawImage(self, image, x1, y1, x2=None,y2=None):
|
|
# pass
|
|
|
|
|
|
|
|
## basic tests ##
|
|
if __name__=='__main__':
|
|
import sping.tests.pidtest
|
|
can = PyartCanvas(size=(300,300), name='basictest.png')
|
|
|
|
#can.defaultLineColor = Color(0.7, 0.7, 1.0)
|
|
#can.drawLine(10,10, 290,290)
|
|
#can.drawLine(10,10, 50, 10, color=green, width = 4.5)
|
|
sping.tests.pidtest.drawBasics(can)
|
|
can.save(file='basicTest.png')
|
|
print 'saving basicTest.png'
|
|
|
|
can = PyartCanvas(size=(400,400), name='test-strings.png')
|
|
sping.tests.pidtest.drawStrings(can)
|
|
can.save()
|
|
|
|
|