示例#1
0
def test_path():
    from aggdraw import Draw, Path
    Path()
    Path([0, 0])
    Path([0, 0, 0, 0])

    p = Path()
    p.moveto(0, 0)
    p.lineto(1, 1)
    assert p.coords() == [0.0, 0.0, 1.0, 1.0]

    p.curveto(0, 0, 0, 0, 0, 0)
    p.close()
    p.coords()
    assert p.coords() == [0.0, 0.0, 1.0, 1.0, 0.125, 0.125, 0.0, 0.0]

    draw = Draw("RGB", (800, 600))
    draw.line(p)
    draw.polygon(p)
    draw.symbol((0, 0), p)
示例#2
0
def test_path():
    from aggdraw import Draw, Path
    Path()
    Path([0, 0])
    Path([0, 0, 0, 0])

    p = Path()
    p.moveto(0, 0)
    p.lineto(1, 1)
    assert p.coords() == [0.0, 0.0, 1.0, 1.0]

    p.curveto(2, 1, 2, 1, 2, 0)
    p.close()
    p.coords()
    # Changed test w.r.t. aggdraw for agg 2.4
    # Correctness of this may be seen in the file test-path-proof.ps
    assert p.coords() == [0.0, 0.0, 1.0, 1.0, 1.625, 1.0, 2.0, 0.625, 2.0, 0.0]

    draw = Draw("RGB", (800, 600))
    draw.line(p)
    draw.polygon(p)
    draw.symbol((0, 0), p)
示例#3
0
def test_graphics():
    from aggdraw import Draw, Pen, Brush
    draw = Draw("RGB", (500, 500))

    pen = Pen("black")
    brush = Brush("black")

    draw.line((50, 50, 100, 100), pen)

    draw.rectangle((50, 150, 100, 200), pen)
    draw.rectangle((50, 220, 100, 270), brush)
    draw.rectangle((50, 290, 100, 340), brush, pen)
    draw.rectangle((50, 360, 100, 410), pen, brush)

    draw.ellipse((120, 150, 170, 200), pen)
    draw.ellipse((120, 220, 170, 270), brush)
    draw.ellipse((120, 290, 170, 340), brush, pen)
    draw.ellipse((120, 360, 170, 410), pen, brush)

    draw.polygon((190+25, 150, 190, 200, 190+50, 200), pen)
    draw.polygon((190+25, 220, 190, 270, 190+50, 270), brush)
    draw.polygon((190+25, 290, 190, 340, 190+50, 340), brush, pen)
    draw.polygon((190+25, 360, 190, 410, 190+50, 410), pen, brush)
示例#4
0
class Canvas(CanvasBase):
  # fonts appear smaller in aggdraw than with cairo
  # fix that here:
  fontScale = 1.2

  def __init__(self,
               img=None,
               imageType=None,  # determines file type
               fileName=None,  # if set determines output file name
               size=None, ):
    if img is None:
      try:
        import Image
      except ImportError:
        from PIL import Image
      if size is None:
        raise ValueError('please provide either an image or a size')
      img = Image.new('RGBA', size, "white")
    self.image = img
    self.draw = Draw(img)
    self.draw.setantialias(True)
    if size is None:
      self.size = self.draw.size
    else:
      self.size = size
    if imageType and imageType not in ('png', 'jpg'):
      raise ValueError('unsupported image type for agg canvas')
    self.drawType = imageType
    self.fileName = fileName

  def _doLine(self, p1, p2, pen, **kwargs):
    if kwargs.get('dash', (0, 0)) == (0, 0):
      self.draw.line((p1[0], p1[1], p2[0], p2[1]), pen)
    else:
      dash = kwargs['dash']
      pts = self._getLinePoints(p1, p2, dash)

      currDash = 0
      dashOn = True
      while currDash < (len(pts) - 1):
        if dashOn:
          p1 = pts[currDash]
          p2 = pts[currDash + 1]
          self.draw.line((p1[0], p1[1], p2[0], p2[1]), pen)
        currDash += 1
        dashOn = not dashOn

  def addCanvasLine(self, p1, p2, color=(0, 0, 0), color2=None, **kwargs):
    if color2 and color2 != color:
      mp = (p1[0] + p2[0]) / 2., (p1[1] + p2[1]) / 2.
      color = convertColor(color)
      self._doLine(p1, mp, Pen(color, kwargs.get('linewidth', 1)), **kwargs)
      color2 = convertColor(color2)
      self._doLine(mp, p2, Pen(color2, kwargs.get('linewidth', 1)), **kwargs)
    else:
      color = convertColor(color)
      self._doLine(p1, p2, Pen(color, kwargs.get('linewidth', 1)), **kwargs)

  def addCanvasText(self, text, pos, font, color=(0, 0, 0), **kwargs):
    orientation = kwargs.get('orientation', 'E')
    color = convertColor(color)
    aggFont = Font(color, faceMap[font.face], size=font.size * self.fontScale)

    blocks = list(re.finditer(r'\<(.+?)\>(.+?)\</\1\>', text))
    w, h = 0, 0
    supH = 0
    subH = 0
    if not len(blocks):
      w, h = self.draw.textsize(text, aggFont)
      tw, th = w, h
      offset = w * pos[2]
      dPos = pos[0] - w / 2. + offset, pos[1] - h / 2.
      self.draw.text(dPos, text, aggFont)
    else:
      dblocks = []
      idx = 0
      for block in blocks:
        blockStart, blockEnd = block.span(0)
        if blockStart != idx:
          # untagged text:
          tblock = text[idx:blockStart]
          tw, th = self.draw.textsize(tblock, aggFont)
          w += tw
          h = max(h, th)
          dblocks.append((tblock, '', tw, th))
        fmt = block.groups()[0]
        tblock = block.groups()[1]
        if fmt in ('sub', 'sup'):
          lFont = Font(color, faceMap[font.face], size=0.8 * font.size * self.fontScale)
        else:
          lFont = aggFont
        tw, th = self.draw.textsize(tblock, lFont)
        w += tw
        if fmt == 'sub':
          subH = max(subH, th)
        elif fmt == 'sup':
          supH = max(supH, th)
        else:
          h = max(h, th)
        dblocks.append((tblock, fmt, tw, th))
        idx = blockEnd
      if idx != len(text):
        # untagged text:
        tblock = text[idx:]
        tw, th = self.draw.textsize(tblock, aggFont)
        w += tw
        h = max(h, th)
        dblocks.append((tblock, '', tw, th))

      supH *= 0.5
      subH *= 0.5
      h += supH + subH
      offset = w * pos[2]
      if orientation == 'W':
        dPos = [pos[0] - w + offset, pos[1] - h / 2.]
      elif orientation == 'E':
        dPos = [pos[0] + offset, pos[1] - h / 2.]
      else:
        dPos = [pos[0] - w / 2. + offset, pos[1] - h / 2.]

      if supH:
        dPos[1] += supH
      for txt, fmt, tw, th in dblocks:
        tPos = dPos.copy()
        if fmt == 'sub':
          tPos[1] += subH
        elif fmt == 'sup':
          tPos[1] -= supH
        if fmt in ('sub', 'sup'):
          lFont = Font(color, faceMap[font.face], size=0.8 * font.size * self.fontScale)
        else:
          lFont = aggFont
        self.draw.text(tPos, txt, lFont)
        dPos[0] += tw
    return (tw + th * .4, th + th * .4, offset)

  def addCanvasPolygon(self, ps, color=(0, 0, 0), fill=True, stroke=False, **kwargs):
    if not fill and not stroke:
      return 
    dps = []
    for p in ps:
      dps.extend(p)
    color = convertColor(color)
    brush = None
    pen = None
    if fill:
      brush = Brush(color)
    if stroke:
      pen = Pen(color)
    self.draw.polygon(dps, pen, brush)

  def addCanvasDashedWedge(self, p1, p2, p3, dash=(2, 2), color=(0, 0, 0), color2=None, **kwargs):
    pen = Pen(color, kwargs.get('linewidth', 1))
    dash = (3, 3)
    pts1 = self._getLinePoints(p1, p2, dash)
    pts2 = self._getLinePoints(p1, p3, dash)

    if len(pts2) < len(pts1):
      pts2, pts1 = pts1, pts2

    for i in range(len(pts1)):
      self.draw.line((pts1[i][0], pts1[i][1], pts2[i][0], pts2[i][1]), pen)

  def flush(self):
    self.draw.flush()
    if self.fileName:
      self.image.save(self.fileName)
示例#5
0
文件: aggCanvas.py 项目: ashwin/rdkit
class Canvas(CanvasBase):
  # fonts appear smaller in aggdraw than with cairo
  # fix that here:
  fontScale=1.2
  def __init__(self, img=None,
               imageType=None, # determines file type
               fileName=None,  # if set determines output file name
               size=None,
               ):
    if img is None:
      import Image
      if size is None:
        raise ValueError,'please provide either an image or a size'
      img = Image.new('RGBA',size,"white")
    self.image = img
    self.draw = Draw(img)
    self.draw.setantialias(True)
    if size is None:
      self.size = self.draw.size
    else:
      self.size = size
    if imageType and imageType not in ('png','jpg'):
      raise ValueError,'unsupported image type for agg canvas'
    self.drawType=imageType
    self.fileName=fileName
    
  def _doLine(self, p1, p2, pen, **kwargs):
    if kwargs.get('dash',(0,0)) == (0,0):
      self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen)
    else:
      dash = kwargs['dash']
      pts = self._getLinePoints(p1,p2,dash)

      currDash = 0
      dashOn = True
      while currDash<(len(pts)-1):
        if dashOn:
          p1 = pts[currDash]
          p2 = pts[currDash+1]
          self.draw.line((p1[0],p1[1],p2[0],p2[1]),pen)
        currDash+=1
        dashOn = not dashOn

  def addCanvasLine(self, p1, p2, color=(0,0,0), color2=None, **kwargs):
    if color2 and color2!=color:
      mp = (p1[0]+p2[0])/2.,(p1[1]+p2[1])/2.
      color = convertColor(color)
      self._doLine(p1,mp,Pen(color,kwargs.get('linewidth',1)),**kwargs)
      color2 = convertColor(color2)
      self._doLine(mp,p2,Pen(color2,kwargs.get('linewidth',1)),**kwargs)
    else:
      color = convertColor(color)
      self._doLine(p1,p2,Pen(color,kwargs.get('linewidth',1)),**kwargs)

  def addCanvasText(self,text,pos,font,color=(0,0,0),**kwargs):
    orientation=kwargs.get('orientation','E')
    color = convertColor(color)
    aggFont = Font(color,faceMap[font.face],size=font.size*self.fontScale)

    blocks = list(re.finditer(r'\<(.+?)\>(.+?)\</\1\>',text))
    w,h = 0,0
    supH=0
    subH=0
    if not len(blocks):
      w,h=self.draw.textsize(text,aggFont)
      bw,bh=w*1.1,h*1.1
      dPos = pos[0]-bw/2.,pos[1]-bh/2.
      bgColor=kwargs.get('bgColor',(1,1,1))
      bgColor = convertColor(bgColor)
      self.draw.rectangle((dPos[0],dPos[1],dPos[0]+bw,dPos[1]+bh),
                       None,Brush(bgColor))
      dPos = pos[0]-w/2.,pos[1]-h/2.
      self.draw.text(dPos,text,aggFont)
    else:
      dblocks=[]
      idx=0
      for block in blocks:
        blockStart,blockEnd=block.span(0)
        if blockStart != idx:
          # untagged text:
          tblock = text[idx:blockStart]
          tw,th=self.draw.textsize(tblock,aggFont)
          w+=tw
          h = max(h,th)
          dblocks.append((tblock,'',tw,th))
        fmt = block.groups()[0]
        tblock = block.groups()[1]
        if fmt in ('sub','sup'):
          lFont = Font(color,faceMap[font.face],size=0.8*font.size*self.fontScale)
        else:
          lFont = aggFont
        tw,th=self.draw.textsize(tblock,lFont)
        w+=tw
        if fmt == 'sub':
          subH = max(subH,th)
        elif fmt=='sup':
          supH = max(supH,th)
        else:
          h = max(h,th)
        dblocks.append((tblock,fmt,tw,th))
        idx = blockEnd
      if idx!=len(text):
        # untagged text:
        tblock = text[idx:]
        tw,th=self.draw.textsize(tblock,aggFont)
        w+=tw
        h = max(h,th)
        dblocks.append((tblock,'',tw,th))
        
      supH *= 0.25
      subH *= 0.25
      h += supH + subH
      bw,bh=w*1.1,h
      #dPos = pos[0]-bw/2.,pos[1]-bh/2.
      dPos = [pos[0]-w/2.,pos[1]-h/2.]
      if orientation=='W':
        dPos = [pos[0]-w,pos[1]-h/2.]
      elif orientation=='E':
        dPos = [pos[0],pos[1]-h/2.]
      else:
        dPos = [pos[0]-w/2,pos[1]-h/2.]

      bgColor=kwargs.get('bgColor',(1,1,1))
      bgColor = convertColor(bgColor)
      self.draw.rectangle((dPos[0],dPos[1],dPos[0]+bw,dPos[1]+bh),
                          None,Brush(bgColor))
      if supH: dPos[1]+=supH
      for txt,fmt,tw,th in dblocks:
        tPos = dPos[:]
        if fmt=='sub':
          tPos[1]+=subH
        elif fmt=='sup':
          tPos[1]-=supH
        if fmt in ('sub','sup'):
          lFont = Font(color,faceMap[font.face],size=0.8*font.size*self.fontScale)
        else:
          lFont = aggFont
        self.draw.text(tPos,txt,lFont)
        dPos[0]+=tw


  def addCanvasPolygon(self,ps,color=(0,0,0),fill=True,stroke=False,**kwargs):
    if not fill and not stroke: return
    dps = []
    for p in ps:
      dps.extend(p)
    color = convertColor(color)
    brush=None
    pen=None
    if fill:
      brush = Brush(color)
    if stroke:
      pen = Pen(color)
    self.draw.polygon(dps,pen,brush)
 
  def addCanvasDashedWedge(self,p1,p2,p3,dash=(2,2),color=(0,0,0),
                           color2=None,**kwargs):
    pen = Pen(color,kwargs.get('linewidth',1))
    dash = (3,3)
    pts1 = self._getLinePoints(p1,p2,dash)
    pts2 = self._getLinePoints(p1,p3,dash)

    if len(pts2)<len(pts1): pts2,pts1=pts1,pts2

    for i in range(len(pts1)):
      self.draw.line((pts1[i][0],pts1[i][1],pts2[i][0],pts2[i][1]),pen)

  def flush(self):
    self.draw.flush()
    if self.fileName:
      self.image.save(self.fileName)
示例#6
0
class ELCustomDisplay(pylink.EyeLinkCustomDisplay, EnvAgent):

    #TODO: add scaling support for images without ruining performance (OpenGL scale?)

    def __init__(self):
        EnvAgent.__init__(self)
        self.size = (0, 0)
        self.imagebuffer = []
        self.palette = []
        self.img = None  # PIL.Image
        self.drawer = None  # aggdraw Draw with self.img as context
        self.title = None

        self.txtm.add_style("el_setup",
                            "20px",
                            P.default_color,
                            font_label="Hind-Medium")
        self.dc_target = drift_correct_target()

        pylink.EyeLinkCustomDisplay.__init__(self)

        # If using an EyeLink 1000 or newer, these commands need to be sent
        # to the tracker for everything to work correctly
        if self.el.getTrackerVersion() >= EYELINK_1000:
            self.el.sendCommand("enable_search_limits=YES")
            self.el.sendCommand("track_search_limits=YES")
            self.el.sendCommand("autothreshold_click=YES")
            self.el.sendCommand("autothreshold_repeat=YES")
            self.el.sendCommand("enable_camera_position_detect=YES")

        # Define dict mapping sdl2 keycodes to pylink keycodes
        self.pylink_keycodes = dict([(sdl2.SDLK_F1, pylink.F1_KEY),
                                     (sdl2.SDLK_F2, pylink.F2_KEY),
                                     (sdl2.SDLK_F3, pylink.F3_KEY),
                                     (sdl2.SDLK_F4, pylink.F4_KEY),
                                     (sdl2.SDLK_F5, pylink.F5_KEY),
                                     (sdl2.SDLK_F6, pylink.F6_KEY),
                                     (sdl2.SDLK_F7, pylink.F7_KEY),
                                     (sdl2.SDLK_F8, pylink.F8_KEY),
                                     (sdl2.SDLK_F9, pylink.F9_KEY),
                                     (sdl2.SDLK_F10, pylink.F10_KEY),
                                     (sdl2.SDLK_PAGEUP, pylink.PAGE_UP),
                                     (sdl2.SDLK_PAGEDOWN, pylink.PAGE_DOWN),
                                     (sdl2.SDLK_UP, pylink.CURS_UP),
                                     (sdl2.SDLK_DOWN, pylink.CURS_DOWN),
                                     (sdl2.SDLK_LEFT, pylink.CURS_LEFT),
                                     (sdl2.SDLK_RIGHT, pylink.CURS_RIGHT),
                                     (sdl2.SDLK_RETURN, pylink.ENTER_KEY),
                                     (sdl2.SDLK_ESCAPE, pylink.ESC_KEY),
                                     (sdl2.SDLK_BACKSPACE, ord('\b')),
                                     (sdl2.SDLK_TAB, ord('\t'))])

        # Define dict mapping pylink colour constants to RGB colours
        self.pylink_colors = [
            (0, 0, 0),  # 0 = placeholder (transparent)
            (255, 255, 255),  # 1 = pylink.CR_HAIR_COLOR (white)        
            (255, 255, 255),  # 2 = pylink.PUPIL_HAIR_COLOR (white)
            (0, 255, 0),  # 3 = pylink.PUPIL_BOX_COLOR (green)
            (255, 0, 0),  # 4 = pylink.SEARCH_LIMIT_BOX_COLOR (red)
            (255, 0, 0)  # 5 = pylink.MOUSE_CURSOR_COLOR (red)
        ]

        try:
            self.__target_beep__ = AudioClip("target_beep.wav")
            self.__target_beep__done__ = AudioClip("target_beep_done.wav")
            self.__target_beep__error__ = AudioClip("target_beep_error.wav")
        except:
            self.__target_beep__ = None
            self.__target_beep__done__ = None
            self.__target_beep__error__ = None

    def record_abort_hide(self):
        pass

    def clear_cal_display(self):
        fill()
        flip()
        fill()

    def setup_cal_display(self):
        self.clear_cal_display()

    def exit_cal_display(self):
        self.clear_cal_display()

    def draw_cal_target(self, x, y=None, pump_events=True):
        fill()
        if pump_events: pump()
        if y is None:
            y = x[1]
            x = x[0]
        blit(self.dc_target, 5, (int(x), int(y)))
        flip()

    def erase_cal_target(self):
        self.clear_cal_display()

    def play_beep(self, clip):
        try:
            if clip in [pylink.DC_TARG_BEEP, pylink.CAL_TARG_BEEP]:
                self.__target_beep__.play()
            elif clip in [pylink.CAL_ERR_BEEP, pylink.DC_ERR_BEEP]:
                self.__target_beep__error__.play()
            else:
                self.__target_beep__done__.play()
        except:
            pass

    def get_input_key(self):
        keys = []
        for event in pump(True):
            if event.type == sdl2.SDL_KEYDOWN:
                keysym = event.key.keysym
                if not self.el._quitting:
                    # don't process quit requests while already quitting
                    ui_request(keysym)
                try:
                    key = self.pylink_keycodes[keysym.sym]
                except KeyError:
                    key = keysym.sym
                # don't allow escape to control tracker unless calibrating
                if key == pylink.ESC_KEY and not self.el.in_setup:
                    key = pylink.JUNK_KEY
                keys.append(pylink.KeyInput(key, keysym.mod))
        return keys

    def get_mouse_state(self):
        x, y, b = mouse_pos(pump_event_queue=False, return_button_state=True)
        x = int(x) - (P.screen_c[0] - self.size[0] / 2)
        y = int(y) - (P.screen_c[1] - self.size[1] / 2)
        # Restrict mouse coords to within bounds of camera image
        x = clip(x, minimum=0, maximum=self.size[0])
        y = clip(y, minimum=0, maximum=self.size[1])
        if b != 1:  # Register left clicks only
            b = 0
        return ((x, y), b)

    def alert_printf(self, message):
        print("EyeLink Alert: {0}".format(message))

    def setup_image_display(self, width, height):
        '''Sets camera image to the provided size, returns 1 on success.'''
        self.size = (width, height)
        self.clear_cal_display()
        return 1

    def exit_image_display(self):
        self.clear_cal_display()

    def image_title(self, text):
        self.title = message(text, "el_setup", blit_txt=False)

    def set_image_palette(self, r, g, b):
        '''
		Sets the palette to use for the camera image and clears the image buffer.
		Converts r,g,b (lists containing the RGB palette) to a list of colours
		([R,G,B,R,G,B,...]) that can be used by PIL.Image.
		'''
        self.imagebuffer = []
        self.palette = list(sum(zip(r, g, b), ()))

    def draw_image_line(self, width, line, totlines, buff):
        '''
		Reads in the buffer from the EyeLink camera image line by line and writes it
		into a buffer of size (width * totlines). Once the last line of the image
		has been read into the buffer, the image buffer is placed in a PIL.Image
		with the palette set by set_image_palette, converted to RGBA, resized,
		and then rendered to the middle of the screen. After rendering, the image
		buffer is cleared.
		'''
        if len(self.imagebuffer) > (width * totlines):
            self.imagebuffer = []
        self.imagebuffer += buff
        if int(line) == int(totlines):
            # Render complete camera image and resize to self.size
            img = Image.new("P", (width, totlines), 0)
            img.putpalette(self.palette)
            img.putdata(self.imagebuffer)
            self.img = img.convert('RGBA').resize(self.size, Image.BILINEAR)
            # Set up aggdraw to draw crosshair/bounds/etc. on image surface
            self.drawer = Draw(self.img)
            self.drawer.setantialias(True)
            self.draw_cross_hair()
            self.drawer.flush()
            # Draw complete image to screen
            fill()
            blit(asarray(self.img), 5, P.screen_c)
            if self.title:
                loc_x = (P.screen_c[0])
                loc_y = (P.screen_c[1] + self.size[1] / 2 + 20)
                blit(self.title, 8, (loc_x, loc_y))
            flip()
            # Clear image buffer
            self.imagebuffer = []

    def draw_lozenge(self, x, y, width, height, colorindex):
        lozenge_pen = Pen(self.pylink_colors[colorindex], 3, 255)
        if width > height:
            gap = width - height
            middle = x + width / 2.0
            arc_left = (x, y, x + height, y + height)
            arc_right = (x + gap, y, x + width, y + height)
            line_top = (floor(middle - gap / 2.0), y, ceil(middle + gap / 2.0),
                        y)
            line_bottom = (floor(middle - gap / 2.0), y + height,
                           ceil(middle + gap / 2.0), y + height)
            self.drawer.arc(arc_left, 90, 270, lozenge_pen)
            self.drawer.arc(arc_right, -90, 90, lozenge_pen)
            self.drawer.line(line_top, lozenge_pen)
            self.drawer.line(line_bottom, lozenge_pen)
        elif height > width:
            gap = height - width
            middle = y + height / 2.0
            arc_top = (x, y, x + width, y + width)
            arc_bottom = (x, y + gap, x + width, y + height)
            line_left = (x, floor(middle - gap / 2.0), x,
                         ceil(middle + gap / 2.0))
            line_right = (x + width, floor(middle - gap / 2.0), x + width,
                          ceil(middle + gap / 2.0))
            self.drawer.arc(arc_top, 0, 180, lozenge_pen)
            self.drawer.arc(arc_bottom, 180, 360, lozenge_pen)
            self.drawer.line(line_left, lozenge_pen)
            self.drawer.line(line_right, lozenge_pen)
        else:
            self.drawer.ellipse((x, y, x + width, y + height), lozenge_pen)

    def draw_line(self, x1, y1, x2, y2, colorindex):
        line_pen = Pen(self.pylink_colors[colorindex], 3, 255)
        self.drawer.line((x1, y1, x2, y2), line_pen)