Package rdkit :: Package Chem :: Package Draw :: Module aggCanvas
[hide private]
[frames] | no frames]

Source Code for Module rdkit.Chem.Draw.aggCanvas

  1  # $Id: aggCanvas.py 1763 2011-06-18 04:48:57Z glandrum $ 
  2  # 
  3  #  Copyright (C) 2008 Greg Landrum 
  4  # 
  5  #   @@ All Rights Reserved @@ 
  6  #  This file is part of the RDKit. 
  7  #  The contents are covered by the terms of the BSD license 
  8  #  which is included in the file license.txt, found at the root 
  9  #  of the RDKit source tree. 
 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 canvasbase import CanvasBase 
 19   
 20  faceMap={'sans':os.path.join(RDConfig.RDCodeDir,'Chem','Draw','FreeSans.ttf')} 
 21   
22 -def convertColor(color):
23 color = (int(color[0]*255),int(color[1]*255),int(color[2]*255)) 24 return color
25
26 -class Canvas(CanvasBase):
27 # fonts appear smaller in aggdraw than with cairo 28 # fix that here: 29 fontScale=1.2
30 - def __init__(self, img=None, 31 imageType=None, # determines file type 32 fileName=None, # if set determines output file name 33 size=None, 34 ):
35 if img is None: 36 import Image 37 if size is None: 38 raise ValueError,'please provide either an image or a size' 39 img = Image.new('RGBA',size,"white") 40 self.image = img 41 self.draw = Draw(img) 42 self.draw.setantialias(True) 43 if size is None: 44 self.size = self.draw.size 45 else: 46 self.size = size 47 if imageType and imageType not in ('png','jpg'): 48 raise ValueError,'unsupported image type for agg canvas' 49 self.drawType=imageType 50 self.fileName=fileName
51
52 - def _doLine(self, p1, p2, pen, **kwargs):
53 if kwargs.get('dash',(0,0)) == (0,0): 54 self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen) 55 else: 56 dash = kwargs['dash'] 57 pts = self._getLinePoints(p1,p2,dash) 58 59 currDash = 0 60 dashOn = True 61 while currDash<(len(pts)-1): 62 if dashOn: 63 p1 = pts[currDash] 64 p2 = pts[currDash+1] 65 self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen) 66 currDash+=1 67 dashOn = not dashOn
68
69 - def addCanvasLine(self, p1, p2, color=(0,0,0), color2=None, **kwargs):
70 if color2 and color2!=color: 71 mp = (p1[0]+p2[0])/2.,(p1[1]+p2[1])/2. 72 color = convertColor(color) 73 self._doLine(p1,mp,Pen(color,kwargs.get('linewidth',1)),**kwargs) 74 color2 = convertColor(color2) 75 self._doLine(mp,p2,Pen(color2,kwargs.get('linewidth',1)),**kwargs) 76 else: 77 color = convertColor(color) 78 self._doLine(p1,p2,Pen(color,kwargs.get('linewidth',1)),**kwargs)
79
80 - def addCanvasText(self,text,pos,font,color=(0,0,0),**kwargs):
81 orientation=kwargs.get('orientation','E') 82 color = convertColor(color) 83 font = Font(color,faceMap[font.face],size=font.size*self.fontScale) 84 85 blocks = list(re.finditer(r'\<(.+?)\>(.+?)\</\1\>',text)) 86 w,h = 0,0 87 supH=0 88 subH=0 89 if not len(blocks): 90 w,h=self.draw.textsize(text,font) 91 bw,bh=w*1.1,h*1.1 92 dPos = pos[0]-bw/2.,pos[1]-bh/2. 93 bgColor=kwargs.get('bgColor',(1,1,1)) 94 bgColor = convertColor(bgColor) 95 self.draw.rectangle((dPos[0],dPos[1],dPos[0]+bw,dPos[1]+bh), 96 None,Brush(bgColor)) 97 dPos = pos[0]-w/2.,pos[1]-h/2. 98 self.draw.text(dPos,text,font) 99 else: 100 dblocks=[] 101 idx=0 102 for block in blocks: 103 blockStart,blockEnd=block.span(0) 104 if blockStart != idx: 105 # untagged text: 106 tblock = text[idx:blockStart] 107 tw,th=self.draw.textsize(tblock,font) 108 w+=tw 109 h = max(h,th) 110 dblocks.append((tblock,'',tw,th)) 111 fmt = block.groups()[0] 112 tblock = block.groups()[1] 113 tw,th=self.draw.textsize(tblock,font) 114 w+=tw 115 if fmt == 'sub': 116 subH = max(subH,th) 117 elif fmt=='sup': 118 supH = max(supH,th) 119 else: 120 h = max(h,th) 121 dblocks.append((tblock,fmt,tw,th)) 122 idx = blockEnd 123 if idx!=len(text): 124 # untagged text: 125 tblock = text[idx:] 126 tw,th=self.draw.textsize(tblock,font) 127 w+=tw 128 h = max(h,th) 129 dblocks.append((tblock,'',tw,th)) 130 131 supH *= 0.25 132 subH *= 0.25 133 h += supH + subH 134 bw,bh=w*1.1,h 135 #dPos = pos[0]-bw/2.,pos[1]-bh/2. 136 dPos = [pos[0]-w/2.,pos[1]-h/2.] 137 if orientation=='W': 138 dPos = [pos[0]-w,pos[1]-h/2.] 139 elif orientation=='E': 140 dPos = [pos[0],pos[1]-h/2.] 141 else: 142 dPos = [pos[0]-w/2,pos[1]-h/2.] 143 144 bgColor=kwargs.get('bgColor',(1,1,1)) 145 bgColor = convertColor(bgColor) 146 self.draw.rectangle((dPos[0],dPos[1],dPos[0]+bw,dPos[1]+bh), 147 None,Brush(bgColor)) 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 self.draw.text(tPos,txt,font) 156 dPos[0]+=tw
157 158
159 - def addCanvasPolygon(self,ps,color=(0,0,0),fill=True,stroke=False,**kwargs):
160 if not fill and not stroke: return 161 dps = [] 162 for p in ps: 163 dps.extend(p) 164 color = convertColor(color) 165 brush=None 166 pen=None 167 if fill: 168 brush = Brush(color) 169 if stroke: 170 pen = Pen(color) 171 self.draw.polygon(dps,pen,brush)
172
173 - def addCanvasDashedWedge(self,p1,p2,p3,dash=(2,2),color=(0,0,0), 174 color2=None,**kwargs):
175 pen = Pen(color,kwargs.get('linewidth',1)) 176 dash = (3,3) 177 pts1 = self._getLinePoints(p1,p2,dash) 178 pts2 = self._getLinePoints(p1,p3,dash) 179 180 if len(pts2)<len(pts1): pts2,pts1=pts1,pts2 181 182 for i in range(len(pts1)): 183 self.draw.line((pts1[i][0],pts1[i][1],pts2[i][0],pts2[i][1]),pen)
184
185 - def flush(self):
186 self.draw.flush() 187 if self.fileName: 188 self.image.save(self.fileName)
189