Changeset 10630:b16cd8b6a93e in orange for Orange/utils/render.py


Ignore:
Timestamp:
03/23/12 19:38:45 (2 years ago)
Author:
mstajdohar
Branch:
default
Message:

Added Times-Roman font.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/utils/render.py

    r10582 r10630  
    1414import numpy 
    1515import math 
    16  
     16import os.path 
     17 
     18from Orange.misc.environ import install_dir 
    1719 
    1820class GeneratorContextManager(object): 
     
    8284    def __init__(self, colors, gamma=None, overflow=(255, 255, 255), underflow=(255, 255, 255), unknown=(0, 0, 0)): 
    8385        self.colors = colors 
    84         self.gamma_func = lambda x, gamma:((math.exp(gamma*math.log(2*x-1)) if x > 0.5 else -math.exp(gamma*math.log(-2*x+1)) if x!=0.5 else 0.0)+1)/2.0 
     86        self.gamma_func = lambda x, gamma:((math.exp(gamma * math.log(2 * x - 1)) if x > 0.5 else -math.exp(gamma * math.log(-2 * x + 1)) if x != 0.5 else 0.0) + 1) / 2.0 
    8587        self.gamma = gamma 
    8688        self.overflow = overflow 
     
    106108                x = self.gamma_func(x, gamma) 
    107109            return [(c2 - c1) * x + c1 for c1, c2 in [(red1, red2), (green1, green2), (blue1, blue2)]] 
    108          
     110 
    109111    def __call__(self, val, gamma=None): 
    110112        return self.get_rgb(val, gamma) 
    111      
     113 
    112114def as_open_file(file, mode="rb"): 
    113115    if isinstance(file, basestring): 
     
    119121class Renderer(object): 
    120122    render_state_attributes = ["font", "stroke_color", "fill_color", "render_hints", "transform", "gradient", "text_alignment"] 
    121      
     123 
    122124    ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER = range(3) 
    123        
     125 
    124126    def __init__(self, width, height): 
    125127        self.width = width 
     
    136138        self.render_state["render_hints"] = {} 
    137139        self.render_state_stack = [] 
    138          
     140 
    139141    def font(self): 
    140142        return self.render_state["font"] 
    141      
     143 
    142144    def set_font(self, family, size): 
    143145        self.render_state["font"] = family, size 
     
    145147    def fill_color(self): 
    146148        return self.render_state["fill_color"] 
    147      
     149 
    148150    def set_fill_color(self, color): 
    149151        self.render_state["fill_color"] = color 
    150          
     152 
    151153    def set_gradient(self, gradient): 
    152154        self.render_state["gradient"] = gradient 
    153          
     155 
    154156    def gradient(self): 
    155157        return self.render_state["gradient"] 
    156          
     158 
    157159    def stroke_color(self): 
    158160        return self.render_state["stroke_color"] 
    159      
     161 
    160162    def set_stroke_color(self, color): 
    161163        self.render_state["stroke_color"] = color 
    162      
     164 
    163165    def stroke_width(self): 
    164166        return self.render_state["stroke_width"] 
    165      
     167 
    166168    def set_stroke_width(self, width): 
    167169        self.render_state["stroke_width"] = width 
    168          
     170 
    169171    def set_text_alignment(self, align): 
    170172        self.render_state["text_alignment"] = align 
    171          
     173 
    172174    def text_alignment(self): 
    173175        return self.render_state["text_alignment"] 
    174          
     176 
    175177    def transform(self): 
    176178        return self.render_state["transform"] 
    177      
     179 
    178180    def set_transform(self, transform): 
    179181        self.render_state["transform"] = transform 
    180          
     182 
    181183    def render_hints(self): 
    182184        return self.render_state["render_hints"] 
    183      
     185 
    184186    def set_render_hints(self, hints): 
    185187        self.render_state["render_hints"].update(hints) 
    186      
     188 
    187189    def save_render_state(self): 
    188190        import copy 
    189191        self.render_state_stack.append(copy.deepcopy(self.render_state)) 
    190      
     192 
    191193    def restore_render_state(self): 
    192194        self.render_state = self.render_state_stack.pop(-1) 
    193          
     195 
    194196    def apply_transform(self, transform): 
    195197        self.render_state["transform"] = self.render_state["transform"] * transform 
    196           
     198 
    197199    def translate(self, x, y): 
    198200        transform = numpy.eye(3) 
    199201        transform[:, 2] = x, y, 1 
    200202        self.apply_transform(transform) 
    201      
     203 
    202204    def rotate(self, angle): 
    203205        angle *= 2 * math.pi / 360.0 
     
    205207        transform[:2, :2] = [[math.cos(angle), -math.sin(angle)], [math.sin(angle), math.cos(angle)]] 
    206208        self.apply_transform(transform) 
    207      
     209 
    208210    def scale(self, sx, sy): 
    209211        transform = numpy.eye(3) 
    210         transform[(0, 1), (0, 1)] = sx, sy  
     212        transform[(0, 1), (0, 1)] = sx, sy 
    211213        self.apply_transform(transform) 
    212          
     214 
    213215    def skew(self, sx, sy): 
    214216        transform = numpy.eye(3) 
    215217        transform[(1, 0), (0, 1)] = numpy.array([sx, sy]) * 2 * math.pi / 360.0 
    216218        self.apply_transform(transform) 
    217      
     219 
    218220    def draw_line(self, sx, sy, ex, ey, **kwargs): 
    219221        raise NotImplementedError 
    220      
     222 
    221223    def draw_lines(self, points, **kwargs): 
    222224        raise NotImplementedError 
    223      
     225 
    224226    def draw_rect(self, x, y, w, h, **kwargs): 
    225227        raise NotImplementedError 
    226      
     228 
    227229    def draw_polygon(self, vertices, **kwargs): 
    228230        raise NotImplementedError 
     
    230232    def draw_arch(self, something, **kwargs): 
    231233        raise NotImplementedError 
    232      
     234 
    233235    def draw_text(self, x, y, text, **kwargs): 
    234236        raise NotImplementedError 
    235      
     237 
    236238    def string_size_hint(self, text, **kwargs): 
    237239        raise NotImpemented 
    238      
     240 
    239241    @contextmanager 
    240242    def state(self, **kwargs): 
     
    249251        finally: 
    250252            self.restore_render_state() 
    251              
     253 
    252254    def save(self, file): 
    253255        raise NotImplementedError 
    254      
     256 
    255257    def close(self, file): 
    256258        pass 
    257      
     259 
    258260class EPSRenderer(Renderer): 
    259261    EPS_DRAW_RECT = """/draw_rect  
     
    267269 closepath 
    268270} def""" 
    269      
     271 
    270272    EPS_SET_GRADIENT = """<< /PatternType 2 
    271273 /Shading 
     
    315317                                 fill_color=lambda color:"%f %f %f setrgbcolor" % tuple(255.0 / c for c in color), 
    316318                                 stroke_width=lambda w: "%f setlinewidth" % w) 
    317          
     319 
    318320    def set_font(self, family, size): 
    319321        Renderer.set_font(self, family, size) 
    320322        self._eps.write("/%s findfont %f scalefont setfont\n" % self.font()) 
    321          
     323 
    322324    def set_fill_color(self, color): 
    323325        Renderer.set_fill_color(self, color) 
    324         self._eps.write("%f %f %f setrgbcolor\n" % tuple(c/255.0 for c in color)) 
    325          
     326        self._eps.write("%f %f %f setrgbcolor\n" % tuple(c / 255.0 for c in color)) 
     327 
    326328    def set_gradient(self, gradient): 
    327329        Renderer.set_gradient(self, gradient) 
     
    329331        binary = "".join([chr(int(c)) for p, s in samples for c in s]) 
    330332        import binascii 
    331         self._eps.write(self.EPS_SET_GRADIENT % (x1, y1, x2, y2, len(samples), binascii.hexlify(binary)))  
    332          
     333        self._eps.write(self.EPS_SET_GRADIENT % (x1, y1, x2, y2, len(samples), binascii.hexlify(binary))) 
     334 
    333335    def set_stroke_color(self, color): 
    334336        Renderer.set_stroke_color(self, color) 
    335         self._eps.write("%f %f %f setrgbcolor\n" % tuple(c/255.0 for c in color)) 
    336          
     337        self._eps.write("%f %f %f setrgbcolor\n" % tuple(c / 255.0 for c in color)) 
     338 
    337339    def set_stroke_width(self, width): 
    338340        Renderer.set_stroke_width(self, width) 
    339341        self._eps.write("%f setlinewidth\n" % width) 
    340          
     342 
    341343    def set_render_hints(self, hints): 
    342344        Renderer.set_render_hints(self, hints) 
     
    344346            map = {"butt":0, "round":1, "rect":2} 
    345347            self._eps.write("%i setlinecap\n" % (map.get(hints.get("linecap"), 0))) 
    346         
    347     @with_state  
     348 
     349    @with_state 
    348350    def draw_line(self, sx, sy, ex, ey, **kwargs): 
    349351        self._eps.write("newpath\n%f %f moveto %f %f lineto\nstroke\n" % (sx, -sy, ex, -ey)) 
    350          
     352 
    351353    @with_state 
    352354    def draw_rect(self, x, y, w, h, **kwargs): 
    353         self._eps.write("newpath\n%(x)f %(y)f moveto %(w)f 0 rlineto\n0 %(h)f rlineto %(w)f neg 0 rlineto\nclosepath\n" % dict(x=x,y=-y, w=w, h=-h)) 
     355        self._eps.write("newpath\n%(x)f %(y)f moveto %(w)f 0 rlineto\n0 %(h)f rlineto %(w)f neg 0 rlineto\nclosepath\n" % dict(x=x, y= -y, w=w, h= -h)) 
    354356        self._eps.write("gsave\n") 
    355357        if self.gradient(): 
     
    360362        self.set_stroke_color(self.stroke_color()) 
    361363        self._eps.write("stroke\n") 
    362          
     364 
    363365    @with_state 
    364366    def draw_polygon(self, vertices, **kwargs): 
     
    372374        self.set_stroke_color(self.stroke_color()) 
    373375        self._eps.write("stroke\n") 
    374          
     376 
    375377    @with_state 
    376378    def draw_text(self, x, y, text, **kwargs): 
    377379        show = ["show", "right_align_show", "center_align_show"][self.text_alignment()] 
    378380        self._eps.write("%f %f moveto (%s) %s\n" % (x, -y, text, show)) 
    379          
     381 
    380382    def save_render_state(self): 
    381383        Renderer.save_render_state(self) 
    382384        self._eps.write("gsave\n") 
    383          
     385 
    384386    def restore_render_state(self): 
    385387        Renderer.restore_render_state(self) 
    386388        self._eps.write("grestore\n") 
    387          
     389 
    388390    def translate(self, dx, dy): 
    389391        Renderer.translate(self, dx, dy) 
    390392        self._eps.write("%f %f translate\n" % (dx, -dy)) 
    391          
     393 
    392394    def rotate(self, angle): 
    393395        Renderer.rotate(self, angle) 
    394396        self._eps.write("%f rotate\n" % -angle) 
    395          
     397 
    396398    def scale(self, sx, sy): 
    397399        Renderer.scale(self, sx, sy) 
    398400        self._eps.write("%f %f scale\n" % (sx, sy)) 
    399      
     401 
    400402    def skew(self, sx, sy): 
    401403        Renderer.skew(self, sx, sy) 
    402404        self._eps.write("%f %f skew\n" % (sx, sy)) 
    403          
     405 
    404406    def save(self, file): 
    405407        file = as_open_file(file, "wb") 
    406408        file.write(self._eps.getvalue()) 
    407          
     409 
    408410    def string_size_hint(self, text, **kwargs): 
    409411        import warnings 
    410412        warnings.warn("EpsRenderer class does not suport exact string width estimation", stacklevel=2) 
    411413        return len(text) * self.font()[1] 
    412          
     414 
    413415def _int_color(color): 
    414416    """ Transform the color tuple (with floats) to tuple with ints 
     
    422424        import Image, ImageDraw, ImageFont 
    423425        self._pil_image = Image.new("RGB", (int(width), int(height)), (255, 255, 255)) 
    424         self._draw =  ImageDraw.Draw(self._pil_image, "RGB") 
     426        self._draw = ImageDraw.Draw(self._pil_image, "RGB") 
    425427        self._pil_font = ImageFont.load_default() 
    426428 
     
    428430        p = self.transform() * [[x], [y], [1]] 
    429431        return p[0, 0], p[1, 0] 
    430      
     432 
    431433    def set_font(self, family, size): 
    432434        Renderer.set_font(self, family, size) 
    433435        import ImageFont 
    434436        try: 
    435             self._pil_font = ImageFont.load(family + ".ttf", size) 
     437            font_file = os.path.join(install_dir, "utils", family + ".ttf") 
     438            if os.path.exists(font_file): 
     439                self._pil_font = ImageFont.truetype(font_file, int(size)) 
     440            else: 
     441                self._pil_font = ImageFont.truetype(family + ".ttf", int(size)) 
    436442        except Exception: 
    437443            import warnings 
    438             warnings.warn("Could not load %s.ttf font!", stacklevel=2) 
     444            warnings.warn("Could not load %s.ttf font!" % family, stacklevel=2) 
    439445            try: 
    440                 self._pil_font = ImageFont.load("cour.ttf", size) 
     446                self._pil_font = ImageFont.truetype("cour.ttf", int(size)) 
    441447            except Exception: 
    442448                warnings.warn("Could not load the cour.ttf font!! Loading the default", stacklevel=2) 
    443449                self._pil_font = ImageFont.load_default() 
    444          
     450 
    445451    @with_state 
    446452    def draw_line(self, sx, sy, ex, ey, **kwargs): 
     
    454460        x1, y1 = self._transform(x, y) 
    455461        x2, y2 = self._transform(x + w, y + h) 
    456         self._draw.rectangle((x1, y1, x2 ,y2), fill=_int_color(self.fill_color()), 
     462        self._draw.rectangle((x1, y1, x2 , y2), fill=_int_color(self.fill_color()), 
    457463                             outline=_int_color(self.stroke_color())) 
    458          
     464 
    459465    @with_state 
    460466    def draw_text(self, x, y, text, **kwargs): 
     
    462468        self._draw.text((x, y), text, font=self._pil_font, 
    463469                        fill=_int_color(self.stroke_color())) 
    464          
     470 
    465471    def save(self, file, format=None): 
    466472        if isinstance(file, basestring): 
     
    469475            file = as_open_file(file, "wb") 
    470476            self._pil_image.save(file, format) 
    471          
     477 
    472478    def string_size_hint(self, text, **kwargs): 
    473479        return self._pil_font.getsize(text)[1] 
    474      
     480 
    475481 
    476482class SVGRenderer(Renderer): 
     
    490496        self._defs = StringIO.StringIO() 
    491497        self._gradients = {} 
    492          
     498 
    493499    def set_gradient(self, gradient): 
    494500        Renderer.set_gradient(self, gradient) 
     
    498504            (x1, y1, x2, y2), stops = gradient 
    499505            (x1, y1, x2, y2) = (0, 0, 100, 0) 
    500              
     506 
    501507            self._defs.write('<linearGradient id="%s" x1="%f%%" y1="%f%%" x2="%f%%" y2="%f%%">\n' % (id, x1, y1, x2, y2)) 
    502508            for offset, color in stops: 
    503509                self._defs.write('<stop offset="%f" style="stop-color:rgb(%i, %i, %i); stop-opacity:1"/>\n' % ((offset,) + color)) 
    504510            self._defs.write('</linearGradient>\n') 
    505          
     511 
    506512    def get_fill(self): 
    507513        if self.render_state["gradient"]: 
     
    509515        else: 
    510516            return 'fill="rgb(%i %i %i)"' % self.fill_color() 
    511          
     517 
    512518    def get_stroke(self): 
    513519#        if self.render_state["gradient"]: 
     
    515521#        else: 
    516522            return 'stroke="rgb(%i, %i, %i)"' % self.stroke_color() + ' stroke-width="%f"' % self.stroke_width() 
    517          
     523 
    518524    def get_text_alignment(self): 
    519525        return 'text-anchor="%s"' % (["start", "end", "middle"][self.text_alignment()]) 
    520      
     526 
    521527    def get_linecap(self): 
    522528        return 'stroke-linecap="%s"' % self.render_hints().get("linecap", "butt") 
    523          
     529 
    524530    @with_state 
    525531    def draw_line(self, sx, sy, ex, ey): 
    526532        self._svg.write('<line x1="%f" y1="%f" x2="%f" y2="%f" %s %s/>\n' % ((sx, sy, ex, ey) + (self.get_stroke(), self.get_linecap()))) 
    527          
     533 
    528534#    @with_state 
    529535#    def draw_lines(self): 
    530          
     536 
    531537    @with_state 
    532538    def draw_rect(self, x, y, w, h): 
    533539        self._svg.write('<rect x="%f" y="%f" width="%f" height="%f" %s %s/>\n' % ((x, y, w, h) + (self.get_fill(),) + (self.get_stroke(),))) 
    534              
     540 
    535541    @with_state 
    536542    def draw_polygon(self, vertices, **kwargs): 
     
    539545        path += " z" 
    540546        self._svg.write('<path d="%s" %s/>' % ((path,) + (self.get_stroke(),))) 
    541          
     547 
    542548    @with_state 
    543549    def draw_text(self, x, y, text): 
    544         self._svg.write('<text x="%f" y="%f" font-family="%s" font-size="%f" %s>%s</text>\n' % ((x, y) + self.font() +(self.get_text_alignment(), text))) 
    545          
     550        self._svg.write('<text x="%f" y="%f" font-family="%s" font-size="%f" %s>%s</text>\n' % ((x, y) + self.font() + (self.get_text_alignment(), text))) 
     551 
    546552    def translate(self, x, y): 
    547553        self._svg.write('<g transform="translate(%f,%f)">\n' % (x, y)) 
    548554        self.transform_count_stack[-1] = self.transform_count_stack[-1] + 1 
    549          
     555 
    550556    def rotate(self, angle): 
    551557        self._svg.write('<g transform="rotate(%f)">\n' % angle) 
    552558        self.transform_count_stack[-1] = self.transform_count_stack[-1] + 1 
    553          
     559 
    554560    def scale(self, sx, sy): 
    555561        self._svg.write('<g transform="scale(%f,%f)">\n' % (sx, sy)) 
    556562        self.transform_count_stack[-1] = self.transform_count_stack[-1] + 1 
    557          
     563 
    558564    def skew(self, sx, sy): 
    559565        self._svg.write('<g transform="skewX(%f)">' % sx) 
     
    564570        Renderer.save_render_state(self) 
    565571        self.transform_count_stack.append(0) 
    566          
     572 
    567573    def restore_render_state(self): 
    568574        Renderer.restore_render_state(self) 
    569575        count = self.transform_count_stack.pop(-1) 
    570576        self._svg.write('</g>\n' * count) 
    571          
     577 
    572578    def save(self, file): 
    573579        file = as_open_file(file, "wb") 
    574580        file.write(self.SVG_HEADER % (self.height, self.width, self._defs.getvalue(), self._svg.getvalue())) 
    575          
     581 
    576582class CairoRenderer(Renderer): 
    577583    def __init__(self, width, height): 
    578584        Renderer.__init__(self, width, height) 
    579          
     585 
Note: See TracChangeset for help on using the changeset viewer.