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

Source Code for Module rdkit.Chem.Draw.aggCanvas

  1  # $Id$ 
  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  #@UnresolvedImport #pylint: disable=F0401 
 12  from aggdraw import Font  #@UnresolvedImport #pylint: disable=F0401 
 13  import math 
 14  from rdkit import RDConfig 
 15  import os,re 
 16   
 17  from aggdraw import Draw  #@UnresolvedImport #pylint: disable=F0401 
 18  from rdkit.Chem.Draw.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 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 # untagged text: 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 # untagged text: 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 #dPos = pos[0]-bw/2.,pos[1]-bh/2. 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
164 - def addCanvasPolygon(self,ps,color=(0,0,0),fill=True,stroke=False,**kwargs):
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
190 - def flush(self):
191 self.draw.flush() 192 if self.fileName: 193 self.image.save(self.fileName)
194