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

Source Code for Module rdkit.Chem.Draw.cairoCanvas

  1  # 
  2  # 
  3  #  Copyright (C) 2008 Greg Landrum 
  4  #  Copyright (C) 2009 Uwe Hoffmann 
  5  # 
  6  #   @@ All Rights Reserved  @@ 
  7  # 
  8  import cairo  
  9  import math 
 10  import rdkit.RDConfig 
 11  import os 
 12  import array 
 13   
 14  #missing up to now 
 15  #faceMap={'sans':os.path.join( 
 16  #    rdkit.RDConfig.RDCodeDir,'Chem','Draw','FreeSans.ttf')} 
 17   
18 -class Canvas(object):
19 - def __init__(self, 20 image=None, # PIL image 21 size=None, 22 ctx=None, 23 imageType=None, # determines file type 24 fileName=None, # if set determines output file name 25 ):
26 """ 27 Canvas can be used in four modes: 28 1) using the supplied PIL image 29 2) using the supplied cairo context ctx 30 3) writing to a file fileName with image type imageType 31 4) creating a cairo surface and context within the constructor 32 """ 33 self.image=None 34 self.imageType=imageType 35 if image is not None: 36 imgd = image.tostring() 37 a = array.array('B',imgd) 38 stride = cairo.ImageSurface.format_stride_for_width (cairo.FORMAT_ARGB32, 39 image.size[0]) 40 if stride != image.size[0] * 4: 41 raise Exception ,"invalid stride" 42 surface = cairo.ImageSurface.create_for_data ( 43 a, cairo.FORMAT_ARGB32, 44 image.size[0], image.size[1], stride) 45 ctx = cairo.Context(surface) 46 size=image.size[0], image.size[1] 47 self.image=image 48 elif size is not None: 49 ##cairo.HAS_GLITZ_SURFACE 50 #cairo.HAS_IMAGE_SURFACE 51 ##cairo.HAS_QUARTZ_SURFACE 52 ##cairo.HAS_USER_FONT 53 #cairo.HAS_WIN32_SURFACE 54 #cairo.HAS_XCB_SURFACE 55 ##cairo.HAS_XLIB_SURFACE 56 #cairo.HAS_PNG_FUNCTIONS 57 #print imageType 58 if cairo.HAS_PDF_SURFACE and imageType == "pdf": 59 surface = cairo.PDFSurface (fileName, size[0], size[1]) 60 elif cairo.HAS_SVG_SURFACE and imageType == "svg": 61 surface = cairo.SVGSurface (fileName, size[0], size[1]) 62 elif cairo.HAS_PS_SURFACE and imageType == "ps": 63 surface = cairo.PSSurface (fileName, size[0], size[1]) 64 elif cairo.HAS_IMAGE_SURFACE and imageType == "png": 65 surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, size[0], size[1]) 66 else: 67 raise Exception, "Wrong file type" 68 ctx = cairo.Context(surface) 69 ctx.set_source_rgb(255,255,255) 70 ctx.paint() 71 else: 72 surface=ctx.get_target() 73 try: 74 size=surface.get_width(),surface.get_height() 75 except AttributeError: 76 size=None 77 self.ctx=ctx 78 self.size=size 79 self.surface=surface 80 self.fileName=fileName
81 82
83 - def flush(self):
84 """temporary interface, must be splitted to different methods, 85 (elif self.imageType == "png":)""" 86 try: 87 if self.fileName: 88 self.surface.write_to_png(self.fileName) 89 except AttributeError: 90 pass 91 if self.image is not None: 92 self.image.fromstring(self.surface.get_data(), 93 "raw","RGBA",0,1) 94 self.surface.finish() 95 elif self.imageType == "png": 96 buffer=self.surface.get_data() 97 return buffer
98 99
100 -def convertColor(color):
101 color = (int(color[0]*255),int(color[1]*255),int(color[2]*255)) 102 return color
103
104 -def _getLinePoints(p1,p2,dash):
105 x1,y1=p1 106 x2,y2=p2 107 dx = x2-x1 108 dy = y2-y1 109 lineLen = math.sqrt(dx*dx+dy*dy) 110 theta = math.atan2(dy,dx) 111 cosT = math.cos(theta) 112 sinT = math.sin(theta) 113 114 pos = (x1,y1) 115 pts = [pos] 116 dist = 0 117 currDash = 0 118 while dist < lineLen: 119 currL = dash[currDash%len(dash)] 120 if(dist+currL > lineLen): currL = lineLen-dist 121 endP = (pos[0] + currL*cosT, pos[1] + currL*sinT) 122 pts.append(endP) 123 pos = endP 124 dist += currL 125 currDash += 1 126 return pts
127
128 -def _doLine(canvas,p1,p2,**kwargs):
129 if kwargs.get('dashes',(0,0)) == (0,0): 130 canvas.ctx.move_to(p1[0],p1[1]) 131 canvas.ctx.line_to(p2[0],p2[1]) 132 else: 133 # the antialiasing makes the dashes appear too small 134 dash = [x*4 for x in kwargs['dashes']] 135 pts = _getLinePoints(p1,p2,dash) 136 137 currDash = 0 138 dashOn = True 139 while currDash<(len(pts)-1): 140 if dashOn: 141 p1 = pts[currDash] 142 p2 = pts[currDash+1] 143 canvas.ctx.move_to(p1[0],p1[1]) 144 canvas.ctx.line_to(p2[0],p2[1]) 145 currDash+=1 146 dashOn = not dashOn
147
148 -def addCanvasLine(canvas,p1,p2,color=(0,0,0),color2=None,**kwargs):
149 canvas.ctx.set_line_width(kwargs.get('linewidth',1)) 150 if color2 and color2!=color: 151 mp = (p1[0]+p2[0])/2.,(p1[1]+p2[1])/2. 152 color = convertColor(color) 153 canvas.ctx.set_source_rgb(*color) 154 _doLine(canvas,p1,mp,**kwargs) 155 canvas.ctx.stroke() 156 color2 = convertColor(color2) 157 canvas.ctx.set_source_rgb(*color2) 158 _doLine(canvas,mp,p2,**kwargs) 159 canvas.ctx.stroke() 160 else: 161 color = convertColor(color) 162 canvas.ctx.set_source_rgb(*color) 163 _doLine(canvas,p1,p2,**kwargs) 164 canvas.ctx.stroke()
165
166 -def addCanvasText(canvas,text,pos,font,color=(0,0,0),**kwargs):
167 color = convertColor(color) 168 canvas.ctx.select_font_face("Georgia", 169 cairo.FONT_SLANT_NORMAL, 170 cairo.FONT_WEIGHT_BOLD) 171 canvas.ctx.set_font_size(font.size) 172 w,h=canvas.ctx.text_extents(text)[2:4] 173 bw,bh=w*1.8,h*1.4 174 dPos = pos[0]-bw/2.,pos[1]-bh/2. 175 bgColor=kwargs.get('bgColor',(1,1,1)) 176 bgColor = convertColor(bgColor) 177 canvas.ctx.set_source_rgb(*bgColor) 178 canvas.ctx.rectangle(dPos[0],dPos[1],bw,bh) 179 canvas.ctx.fill() 180 dPos = pos[0]-w/2.,pos[1]+h/2. 181 canvas.ctx.set_source_rgb(*color) 182 canvas.ctx.move_to(*dPos) 183 canvas.ctx.show_text(text)
184
185 -def addCanvasPolygon(canvas,ps,color=(0,0,0),**kwargs):
186 dps = [] 187 color = convertColor(color) 188 canvas.ctx.set_source_rgb(*color) 189 canvas.ctx.move_to(ps[0][0],ps[0][1]) 190 for p in ps[1:]: 191 canvas.ctx.move_to(p[0],p[1]) 192 canvas.ctx.close_path() 193 canvas.ctx.fill()
194
195 -def addCanvasDashedWedge(canvas,p1,p2,p3,dash=(2,2),color=(0,0,0), 196 color2=None,**kwargs):
197 canvas.ctx.set_line_width(kwargs.get('linewidth',1)) 198 color = convertColor(color) 199 canvas.ctx.set_source_rgb(*color) 200 dash = (3,3) 201 pts1 = _getLinePoints(p1,p2,dash) 202 pts2 = _getLinePoints(p1,p3,dash) 203 204 if len(pts2)<len(pts1): pts2,pts1=pts1,pts2 205 206 for i in range(len(pts1)): 207 canvas.ctx.move_to(pts1[i][0],pts1[i][1]) 208 canvas.ctx.line_to(pts2[i][0],pts2[i][1]) 209 canvas.ctx.stroke()
210