1
2
3
4
5
6
7
8
9
10
11 from aggdraw import Brush, Pen
12 from aggdraw import Font
13 import math
14 from rdkit import RDConfig
15 import os,re
16
17 from aggdraw import Draw
18 from rdkit.Chem.Draw.canvasbase import CanvasBase
19
20 faceMap={'sans':os.path.join(RDConfig.RDCodeDir,'Chem','Draw','FreeSans.ttf')}
21
23 color = (int(color[0]*255),int(color[1]*255),int(color[2]*255))
24 return color
25
27
28
29 fontScale=1.2
30 - def __init__(self, img=None,
31 imageType=None,
32 fileName=None,
33 size=None,
34 ):
35 if img is None:
36 try:
37 import Image
38 except ImportError:
39 from PIL import Image
40 if size is None:
41 raise ValueError('please provide either an image or a size')
42 img = Image.new('RGBA',size,"white")
43 self.image = img
44 self.draw = Draw(img)
45 self.draw.setantialias(True)
46 if size is None:
47 self.size = self.draw.size
48 else:
49 self.size = size
50 if imageType and imageType not in ('png','jpg'):
51 raise ValueError('unsupported image type for agg canvas')
52 self.drawType=imageType
53 self.fileName=fileName
54
55 - def _doLine(self, p1, p2, pen, **kwargs):
56 if kwargs.get('dash',(0,0)) == (0,0):
57 self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen)
58 else:
59 dash = kwargs['dash']
60 pts = self._getLinePoints(p1,p2,dash)
61
62 currDash = 0
63 dashOn = True
64 while currDash<(len(pts)-1):
65 if dashOn:
66 p1 = pts[currDash]
67 p2 = pts[currDash+1]
68 self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen)
69 currDash+=1
70 dashOn = not dashOn
71
72 - def addCanvasLine(self, p1, p2, color=(0,0,0), color2=None, **kwargs):
73 if color2 and color2!=color:
74 mp = (p1[0]+p2[0])/2.,(p1[1]+p2[1])/2.
75 color = convertColor(color)
76 self._doLine(p1,mp,Pen(color,kwargs.get('linewidth',1)),**kwargs)
77 color2 = convertColor(color2)
78 self._doLine(mp,p2,Pen(color2,kwargs.get('linewidth',1)),**kwargs)
79 else:
80 color = convertColor(color)
81 self._doLine(p1,p2,Pen(color,kwargs.get('linewidth',1)),**kwargs)
82
83 - def addCanvasText(self,text,pos,font,color=(0,0,0),**kwargs):
84 orientation=kwargs.get('orientation','E')
85 color = convertColor(color)
86 aggFont = Font(color,faceMap[font.face],size=font.size*self.fontScale)
87
88 blocks = list(re.finditer(r'\<(.+?)\>(.+?)\</\1\>',text))
89 w,h = 0,0
90 supH=0
91 subH=0
92 if not len(blocks):
93 w,h=self.draw.textsize(text,aggFont)
94 tw,th=w,h
95 offset = w*pos[2]
96 dPos = pos[0]-w/2.+offset,pos[1]-h/2.
97 self.draw.text(dPos,text,aggFont)
98 else:
99 dblocks=[]
100 idx=0
101 for block in blocks:
102 blockStart,blockEnd=block.span(0)
103 if blockStart != idx:
104
105 tblock = text[idx:blockStart]
106 tw,th=self.draw.textsize(tblock,aggFont)
107 w+=tw
108 h = max(h,th)
109 dblocks.append((tblock,'',tw,th))
110 fmt = block.groups()[0]
111 tblock = block.groups()[1]
112 if fmt in ('sub','sup'):
113 lFont = Font(color,faceMap[font.face],size=0.8*font.size*self.fontScale)
114 else:
115 lFont = aggFont
116 tw,th=self.draw.textsize(tblock,lFont)
117 w+=tw
118 if fmt == 'sub':
119 subH = max(subH,th)
120 elif fmt=='sup':
121 supH = max(supH,th)
122 else:
123 h = max(h,th)
124 dblocks.append((tblock,fmt,tw,th))
125 idx = blockEnd
126 if idx!=len(text):
127
128 tblock = text[idx:]
129 tw,th=self.draw.textsize(tblock,aggFont)
130 w+=tw
131 h = max(h,th)
132 dblocks.append((tblock,'',tw,th))
133
134 supH *= 0.5
135 subH *= 0.5
136 h += supH + subH
137 bw,bh=w+h*0.4,w*1.4
138 offset = w*pos[2]
139
140 dPos = [pos[0]-w/2.+offset,pos[1]-h/2.]
141 if orientation=='W':
142 dPos = [pos[0]-w+offset,pos[1]-h/2.]
143 elif orientation=='E':
144 dPos = [pos[0]+offset,pos[1]-h/2.]
145 else:
146 dPos = [pos[0]-w/2+offset,pos[1]-h/2.]
147
148 if supH: dPos[1]+=supH
149 for txt,fmt,tw,th in dblocks:
150 tPos = dPos[:]
151 if fmt=='sub':
152 tPos[1]+=subH
153 elif fmt=='sup':
154 tPos[1]-=supH
155 if fmt in ('sub','sup'):
156 lFont = Font(color,faceMap[font.face],size=0.8*font.size*self.fontScale)
157 else:
158 lFont = aggFont
159 self.draw.text(tPos,txt,lFont)
160 dPos[0]+=tw
161 return (tw+th*.4,th+th*.4,offset)
162
163
165 if not fill and not stroke: return
166 dps = []
167 for p in ps:
168 dps.extend(p)
169 color = convertColor(color)
170 brush=None
171 pen=None
172 if fill:
173 brush = Brush(color)
174 if stroke:
175 pen = Pen(color)
176 self.draw.polygon(dps,pen,brush)
177
178 - def addCanvasDashedWedge(self,p1,p2,p3,dash=(2,2),color=(0,0,0),
179 color2=None,**kwargs):
180 pen = Pen(color,kwargs.get('linewidth',1))
181 dash = (3,3)
182 pts1 = self._getLinePoints(p1,p2,dash)
183 pts2 = self._getLinePoints(p1,p3,dash)
184
185 if len(pts2)<len(pts1): pts2,pts1=pts1,pts2
186
187 for i in range(len(pts1)):
188 self.draw.line((pts1[i][0],pts1[i][1],pts2[i][0],pts2[i][1]),pen)
189
191 self.draw.flush()
192 if self.fileName:
193 self.image.save(self.fileName)
194