Exemplo n.º 1
0
    def update_example(self, widget=None):
        start = 0
        end = len(self.example)

        attributes = pango.AttrList()

        attributes.insert(pango.AttrForeground(self.text_color.red, self.text_color.green,
                                               self.text_color.blue, start, end))
        attributes.insert(pango.AttrBackground(self.highlight_color.red,
                                               self.highlight_color.green,
                                               self.highlight_color.blue,
                                               start, end))

        # Bold verification
        if self.bold_tg_button.get_active():
            attributes.insert(pango.AttrWeight(pango.WEIGHT_HEAVY, start, end))
        else:
            attributes.insert(pango.AttrWeight(pango.WEIGHT_NORMAL, start, end))

        # Italic verification
        if self.italic_tg_button.get_active():
            attributes.insert(pango.AttrStyle(pango.STYLE_ITALIC, start, end))
        else:
            attributes.insert(pango.AttrStyle(pango.STYLE_NORMAL, start, end))

        # Underline verification
        if self.underline_tg_button.get_active():
            attributes.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end))
        else:
            attributes.insert(pango.AttrUnderline(pango.UNDERLINE_NONE, start, end))

        self.example_label.set_attributes(attributes)
Exemplo n.º 2
0
 def create_attribute(self, attribute, start, end):
     if attribute == 'bold':
         return pango.AttrWeight(pango.WEIGHT_BOLD, start, end)
     elif attribute == 'italic':
         return pango.AttrStyle(pango.STYLE_ITALIC, start, end)
     elif attribute == 'underline':
         return pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end)
Exemplo n.º 3
0
Arquivo: _gtk.py Projeto: zhou0/ibus
 def __init__(self, attrs, unistr):
     super(PangoAttrList, self).__init__()
     if attrs == None:
         return
     offsets = []
     offset = 0
     for c in unistr:
         offsets.append(offset)
         offset += len(c.encode("utf8"))
     offsets.append(offset)
     for attr in attrs:
         pango_attr = None
         start_index = attr.start_index if attr.start_index >= 0 else 0
         end_index = attr.end_index if attr.end_index >= 0 else 0
         start_index = offsets[start_index] if start_index < len(
             offsets) else offsets[-1]
         end_index = offsets[end_index] if end_index < len(
             offsets) else offsets[-1]
         if attr.type == ibus.ATTR_TYPE_FOREGROUND:
             r = (attr.value & 0x00ff0000) >> 8
             g = (attr.value & 0x0000ff00)
             b = (attr.value & 0x000000ff) << 8
             pango_attr = pango.AttrForeground(r, g, b, start_index,
                                               end_index)
         elif attr.type == ibus.ATTR_TYPE_BACKGROUND:
             r = (attr.value & 0x00ff0000) >> 8
             g = (attr.value & 0x0000ff00)
             b = (attr.value & 0x000000ff) << 8
             pango_attr = pango.AttrBackground(r, g, b, start_index,
                                               end_index)
         elif attr.type == ibus.ATTR_TYPE_UNDERLINE:
             pango_attr = pango.AttrUnderline(int(attr.value), start_index,
                                              end_index)
         if pango_attr != None:
             self.insert(pango_attr)
Exemplo n.º 4
0
    def add_pango_attributes(self, attrs, start_index, end_index):
        """Insert attributes for this StyleSpec into a pango.AttrList. Not every
        property of StyleSpec maps into a pango.Attribute - the ones that don't
        map are ignored and need to be handled separately.

        @param attrs: pango.AttrList to insert attributes into.
        @param start_index: byte offset of the start of the range this spec applies to
        @param end_index: byte offset of the ned of the range this spec applies to

        """

        if self.family is not None:
            attrs.insert(pango.AttrFamily(self.family, start_index, end_index))
        if self.foreground is not None:
            color = pango.Color(self.foreground)
            attrs.insert(
                pango.AttrForeground(color.red, color.green, color.blue,
                                     start_index, end_index))
        if self.style is not None:
            attrs.insert(pango.AttrStyle(self.style, start_index, end_index))
        if self.underline is not None:
            attrs.insert(
                pango.AttrUnderline(self.underline, start_index, end_index))
        if self.weight is not None:
            attrs.insert(pango.AttrWeight(self.weight, start_index, end_index))
        if self.weight is not None:
            attrs.insert(pango.AttrWeight(self.weight, start_index, end_index))
Exemplo n.º 5
0
    def _draw(self, xrandr, cr):
        cfg = xrandr.configuration
        state = xrandr.state

        cr.set_source_rgb(0.25, 0.25, 0.25)
        cr.rectangle(0, 0, *state.virtual.max)
        cr.fill()

        cr.set_source_rgb(0.5, 0.5, 0.5)
        cr.rectangle(0, 0, *cfg.virtual)
        cr.fill()

        for on in self.sequence:
            o = cfg.outputs[on]
            if not o.active: continue

            rect = (o.tentative_position if hasattr(o, 'tentative_position')
                    else o.position) + tuple(o.size)
            center = rect[0] + rect[2] / 2, rect[1] + rect[3] / 2

            # paint rectangle
            cr.set_source_rgba(1, 1, 1, 0.7)
            cr.rectangle(*rect)
            cr.fill()
            cr.set_source_rgb(0, 0, 0)
            cr.rectangle(*rect)
            cr.stroke()

            # set up for text
            cr.save()
            textwidth = rect[3 if o.rotation.is_odd else 2]
            widthperchar = textwidth / len(on)
            textheight = int(
                widthperchar * 0.8
            )  # i think this looks nice and won't overflow even for wide fonts

            newdescr = pango.FontDescription("sans")
            newdescr.set_size(textheight * pango.SCALE)

            # create text
            layout = cr.create_layout()
            layout.set_font_description(newdescr)
            if o.primary:
                attrs = pango.AttrList()
                attrs.insert(
                    pango.AttrUnderline(pango.UNDERLINE_SINGLE, end_index=-1))
                layout.set_attributes(attrs)

            layout.set_text(on)

            # position text
            layoutsize = layout.get_pixel_size()
            layoutoffset = -layoutsize[0] / 2, -layoutsize[1] / 2
            cr.move_to(*center)
            cr.rotate(o.rotation.angle)
            cr.rel_move_to(*layoutoffset)

            # pain text
            cr.show_layout(layout)
            cr.restore()
Exemplo n.º 6
0
 def setup_default_tags(self):
     self.italics = self.get_tags_from_attrs(None, None,
                                             [pango.AttrStyle('italic')])[0]
     self.bold = self.get_tags_from_attrs(None, None,
                                          [pango.AttrWeight('bold')])[0]
     self.underline = self.get_tags_from_attrs(
         None, None, [pango.AttrUnderline('single')])[0]
Exemplo n.º 7
0
 def create_attribute(self, attribute, start, end, value):
     if attribute == 'bold':
         return pango.AttrWeight(value, start, end)
     elif attribute == 'italic':
         return pango.AttrStyle(value, start, end)
     elif attribute == 'underline':
         return pango.AttrUnderline(value, start, end)
Exemplo n.º 8
0
    def load(self, node):
        self.index = int(node.getAttribute("cursor"))
        if node.hasAttribute("selection_end"):
            self.end_index = int(node.getAttribute("selection_end"))
        else:
            self.end_index = self.index
        tmp = node.getAttribute("ul-coords")
        self.ul = utils.parse_coords(tmp)
        tmp = node.getAttribute("lr-coords")
        self.lr = utils.parse_coords(tmp)
        self.identity = int(node.getAttribute("identity"))
        try:
            tmp = node.getAttribute("background-color")
            self.background_color = gtk.gdk.color_parse(tmp)
            tmp = node.getAttribute("foreground-color")
            self.foreground_color = gtk.gdk.color_parse(tmp)
        except ValueError:
            pass

        if node.hasAttribute("edit"):
            self.editing = True
        else:
            self.editing = False
            self.end_index = self.index

        self.am_selected = node.hasAttribute("current_root")
        self.am_primary = node.hasAttribute("primary_root")

        for n in node.childNodes:
            if n.nodeType == n.TEXT_NODE:
                self.text = n.data
            elif n.nodeName == "Extended":
                self.extended_buffer.load(n)
            elif n.nodeName == "attribute":
                attrType = n.getAttribute("type")
                start = int(n.getAttribute("start"))
                end = int(n.getAttribute("end"))

                if attrType == "bold":
                    attr = pango.AttrWeight(pango.WEIGHT_BOLD, start, end)
                elif attrType == "italics":
                    attr = pango.AttrStyle(pango.STYLE_ITALIC, start, end)
                elif attrType == "underline":
                    attr = pango.AttrUnderline(pango.UNDERLINE_SINGLE, start,
                                               end)
                elif attrType == "font":
                    font_name = str(n.getAttribute("value"))
                    pango_font = pango.FontDescription(font_name)
                    attr = pango.AttrFontDesc(pango_font, start, end)
                self.attributes.change(attr)
            else:
                print "Unknown: " + n.nodeName
        self.rebuild_byte_table()
        self.recalc_edges()
Exemplo n.º 9
0
 def _createLayout(self, text):
     """Produces a Pango layout describing this text in this __font"""
     # create layout
     layout = pango.Layout(gtk.gdk.pango_context_get())
     layout.set_font_description(self.fd)
     if self.underline:
         attrs = layout.get_attributes()
         if not attrs:
             attrs = pango.AttrList()
         attrs.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, 0, 32767))
         layout.set_attributes(attrs)
     layout.set_text(text)
     return layout
Exemplo n.º 10
0
    def set_font(self, pango_layout):
        """Sets the font for draw_text"""

        wx2pango_weights = {
            wx.FONTWEIGHT_BOLD: pango.WEIGHT_BOLD,
            wx.FONTWEIGHT_LIGHT: pango.WEIGHT_LIGHT,
            wx.FONTWEIGHT_NORMAL: None,  # Do not set a weight by default
        }

        wx2pango_styles = {
            wx.FONTSTYLE_NORMAL: None,  # Do not set a style by default
            wx.FONTSTYLE_SLANT: pango.STYLE_OBLIQUE,
            wx.FONTSTYLE_ITALIC: pango.STYLE_ITALIC,
        }

        cell_attributes = self.code_array.cell_attributes[self.key]

        # Text font attributes
        textfont = cell_attributes["textfont"]
        pointsize = cell_attributes["pointsize"]
        fontweight = cell_attributes["fontweight"]
        fontstyle = cell_attributes["fontstyle"]
        underline = cell_attributes["underline"]
        strikethrough = cell_attributes["strikethrough"]

        # Now construct the pango font
        font_description = pango.FontDescription(" ".join(
            [textfont, str(pointsize)]))
        pango_layout.set_font_description(font_description)

        attrs = pango.AttrList()

        # Underline
        attrs.insert(pango.AttrUnderline(underline, 0, MAX_RESULT_LENGTH))

        # Weight
        weight = wx2pango_weights[fontweight]
        if weight is not None:
            attrs.insert(pango.AttrWeight(weight, 0, MAX_RESULT_LENGTH))

        # Style
        style = wx2pango_styles[fontstyle]
        if style is not None:
            attrs.insert(pango.AttrStyle(style, 0, MAX_RESULT_LENGTH))

        # Strikethrough
        attrs.insert(
            pango.AttrStrikethrough(strikethrough, 0, MAX_RESULT_LENGTH))

        pango_layout.set_attributes(attrs)
Exemplo n.º 11
0
    def draw(self, context):
        cr = context.cairo
        if isinstance(cr, cairo.Context):
            cr = pangocairo.CairoContext(cr)
            layout = cr.create_layout()
            layout.set_font_description(pango.FontDescription(self.font))
            layout.set_text(self.render() or '')

            if hasattr(self.subject, 'isStatic') and self.subject.isStatic:
                attrlist = pango.AttrList()
                attrlist.insert(
                    pango.AttrUnderline(pango.UNDERLINE_SINGLE, 2, -1))
                layout.set_attributes(attrlist)
            cr.show_layout(layout)
Exemplo n.º 12
0
 def _set_underline(self, label, underline=False):
     # Set an underline in a label widget.
     att_list = label.get_attributes()
     if att_list is None:
         att_list = pango.AttrList()
     if underline:
         att_list.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE,
                                             start_index=0,
                                             end_index=-1))
     else:
         att_list = att_list.filter(lambda a:
                                    a.type != pango.ATTR_UNDERLINE)
         if att_list is None:
             att_list = pango.AttrList()
     label.set_attributes(att_list)
Exemplo n.º 13
0
 def on_timeout_min(self):
     attr = self.label.get_attributes()
     attr.change(pango.AttrUnderline(pango.UNDERLINE_NONE, 0, -1))
     self.label.set_attributes(attr)
Exemplo n.º 14
0
    def add_text(self, buddy, text, status_message=False):
        """Display text on screen, with name and colors.

        buddy -- buddy object or dict {nick: string, color: string}
                 (The dict is for loading the chat log from the journal,
                 when we don't have the buddy object any more.)
        text -- string, what the buddy said
        status_message -- boolean
            False: show what buddy said
            True: show what buddy did

        hippo layout:
        .------------- rb ---------------.
        | +name_vbox+ +----msg_vbox----+ |
        | |         | |                | |
        | | nick:   | | +--msg_hbox--+ | |
        | |         | | | text       | | |
        | +---------+ | +------------+ | |
        |             |                | |
        |             | +--msg_hbox--+ | |
        |             | | text | url | | |
        |             | +------------+ | |
        |             +----------------+ |
        `--------------------------------'
        """
        if not buddy:
            buddy = self.owner

        if type(buddy) is dict:
            # dict required for loading chat log from journal
            nick = buddy['nick']
            color = buddy['color']
        else:
            nick = buddy.props.nick
            color = buddy.props.color
        try:
            color_stroke_html, color_fill_html = color.split(',')
        except ValueError:
            color_stroke_html, color_fill_html = ('#000000', '#888888')

        # Select text color based on fill color:
        color_fill_rgba = Color(color_fill_html).get_rgba()
        color_fill_gray = (color_fill_rgba[0] + color_fill_rgba[1] +
                           color_fill_rgba[2]) / 3
        color_stroke = Color(color_stroke_html).get_int()
        color_fill = Color(color_fill_html).get_int()

        if color_fill_gray < 0.5:
            text_color = COLOR_WHITE.get_int()
        else:
            text_color = COLOR_BLACK.get_int()

        self._add_log(nick, color, text, status_message)

        # Check for Right-To-Left languages:
        if pango.find_base_dir(nick, -1) == pango.DIRECTION_RTL:
            lang_rtl = True
        else:
            lang_rtl = False

        # Check if new message box or add text to previous:
        new_msg = True
        if self._last_msg_sender:
            if not status_message:
                if buddy == self._last_msg_sender:
                    # Add text to previous message
                    new_msg = False

        if not new_msg:
            rb = self._last_msg
            msg_vbox = rb.get_children()[1]
            msg_hbox = hippo.CanvasBox(
                orientation=hippo.ORIENTATION_HORIZONTAL)
            msg_vbox.append(msg_hbox)
        else:
            rb = CanvasRoundBox(background_color=color_fill,
                                border_color=color_stroke,
                                padding=4)
            rb.props.border_color = color_stroke  # Bug #3742
            self._last_msg = rb
            self._last_msg_sender = buddy
            if not status_message:
                name = hippo.CanvasText(text=nick + ':   ', color=text_color)
                name_vbox = hippo.CanvasBox(
                    orientation=hippo.ORIENTATION_VERTICAL)
                name_vbox.append(name)
                rb.append(name_vbox)
            msg_vbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL)
            rb.append(msg_vbox)
            msg_hbox = hippo.CanvasBox(
                orientation=hippo.ORIENTATION_HORIZONTAL)
            msg_vbox.append(msg_hbox)

        if status_message:
            self._last_msg_sender = None

        match = URL_REGEXP.search(text)
        while match:
            # there is a URL in the text
            starttext = text[:match.start()]
            if starttext:
                message = hippo.CanvasText(
                    text=starttext,
                    size_mode=hippo.CANVAS_SIZE_WRAP_WORD,
                    color=text_color,
                    xalign=hippo.ALIGNMENT_START)
                msg_hbox.append(message)
            url = text[match.start():match.end()]

            message = CanvasLink(text=url, color=text_color)
            attrs = pango.AttrList()
            attrs.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, 0, 32767))
            message.set_property("attributes", attrs)
            message.connect('activated', self._link_activated_cb)

            # call interior magic which should mean just:
            # CanvasInvoker().parent = message
            CanvasInvoker(message)

            msg_hbox.append(message)
            text = text[match.end():]
            match = URL_REGEXP.search(text)

        if text:
            message = hippo.CanvasText(text=text,
                                       size_mode=hippo.CANVAS_SIZE_WRAP_WORD,
                                       color=text_color,
                                       xalign=hippo.ALIGNMENT_START)
            msg_hbox.append(message)

        # Order of boxes for RTL languages:
        if lang_rtl:
            msg_hbox.reverse()
            if new_msg:
                rb.reverse()

        if new_msg:
            box = hippo.CanvasBox(padding=2)
            box.append(rb)
            self._conversation.append(box)
Exemplo n.º 15
0
    def __expose_event(self, widget, event=None):
        """Handle drawing bread crumbs"""
        foreground_context = widget.get_style().fg_gc[self._state]
        background_context = widget.window.cairo_create()
        layout = widget.create_pango_layout('')

        text_to_draw = self._path
        path_length = len(self._path)

        # make sure we have allocation
        if self._allocation is None:
            self._allocation = widget.get_allocation()

        # create attributes
        attributes = pango.AttrList()

        # check if path is part of previous one
        if self._type is Breadcrumbs.TYPE_SMART \
        and self._previous_path is not None \
        and self._previous_path.startswith(self._path):
            smart_color = (self._smart_color.red, self._smart_color.green,
                           self._smart_color.blue)
            attributes.insert(
                pango.AttrForeground(*smart_color,
                                     start_index=path_length,
                                     end_index=len(self._previous_path)))
            text_to_draw = self._previous_path

        # calculate width of path elements
        if self._elements_width is None:
            path = None
            provider = self._parent._parent.get_provider()
            self._elements_size = []
            self._elements_width = []

            # split root element from others
            root_element = provider.get_root_path(text_to_draw)
            other_elements = text_to_draw[len(root_element):]

            # make sure our path doesn't begin with slash
            if other_elements.startswith(os.path.sep):
                other_elements = other_elements[1:]

            # split elements
            elements = other_elements.split(os.path.sep)
            elements.insert(0, root_element)

            for element in elements:
                # get path size
                path = os.path.join(path,
                                    element) if path is not None else element
                layout.set_text(path)

                # add width to the list
                width = layout.get_size()[0] / pango.SCALE
                self._elements_size.append(len(path))
                self._elements_width.append(width)

        # underline hovered path if specified
        if None not in (self._highlight_index, self._elements_size):
            width = self._elements_size[self._highlight_index]
            attributes.insert(
                pango.AttrUnderline(pango.UNDERLINE_SINGLE, 0, width))

        # prepare text for drawing
        layout.set_text(text_to_draw)
        layout.set_attributes(attributes)

        # draw background color
        background_context.set_source_color(self._colors[0])
        background_context.rectangle(0, 0, self._allocation[2],
                                     self._allocation[3])
        background_context.fill()

        # draw text
        widget.window.draw_layout(foreground_context, 0, 0, layout)

        return True
Exemplo n.º 16
0
 def get_calculated_rect(self, context, rect):
     angle = 2 * math.pi * self._rotation / 360.0
     
     if self._context == None:
         label = gtk.Label()
         self._context = label.create_pango_context()          
     pango_context = self._context
     
     attrs = pango.AttrList()
     attrs.insert(pango.AttrWeight(self._weight, 0, len(self._text)))
     attrs.insert(pango.AttrStyle(self._slant, 0, len(self._text)))
     attrs.insert(pango.AttrUnderline(self._underline, 0,
                     len(self._text)))
     if self._size != None:
         attrs.insert(pango.AttrSize(1000 * self._size, 0,
                         len(self._text)))
     
     if self._layout == None:
         self._layout = pango.Layout(pango_context)
     layout = self._layout
     if self._markup:
         layout.set_markup(self._text)
     else:
         layout.set_text(self._text)
         layout.set_attributes(attrs)
     
     #find out where to draw the layout and calculate the maximum width
     width = rect.width * math.cos(angle) + rect.height * math.sin(angle)
     if self._anchor in [ANCHOR_BOTTOM_LEFT, ANCHOR_TOP_LEFT,
                         ANCHOR_LEFT_CENTER]:
         width = rect.width - self._position[0]
     elif self._anchor in [ANCHOR_BOTTOM_RIGHT, ANCHOR_TOP_RIGHT,
                             ANCHOR_RIGHT_CENTER]:
         width = self._position[0]
     
     text_width, text_height = layout.get_pixel_size()
     width = min(width, self._max_width)
     
     if self._wrap:
         layout.set_wrap(pango.WRAP_WORD_CHAR)
     layout.set_width(int(1000 * width))
     
     #======================================================================
     text_width, text_height = layout.get_pixel_size()
     anchor = self._anchor
     x, y = self._position
 
     #anchor translation
     tx, ty = 0, 0
     ttx, tty = 0, 0
     if anchor == ANCHOR_BOTTOM_LEFT:
         tx = text_height * math.sin(angle)
         ty = text_height * math.cos(angle)
         ttx = 0
         tty = text_height
     elif anchor == ANCHOR_TOP_LEFT:
         tx = 0
         ty = 0
     elif anchor ==  ANCHOR_TOP_RIGHT:
         tx = text_width * math.cos(angle)
         ty = -text_width * math.sin(angle)
         ttx = text_width
         tty = 0
     elif anchor == ANCHOR_BOTTOM_RIGHT:
         tx = text_width * math.cos(angle) + text_height * math.sin(angle)
         ty = -text_width * math.sin(angle) + text_height * math.cos(angle)
         ttx = text_width
         tty = text_height
     elif anchor == ANCHOR_CENTER:
         tx = (text_width * math.cos(angle) + text_height * math.sin(angle)) / 2
         ty = (-text_width * math.sin(angle) + text_height * math.cos(angle)) / 2
         ttx = text_width / 2
         tty = text_height / 2
     elif anchor == ANCHOR_TOP_CENTER:
         tx = text_width * math.cos(angle) / 2
         ty = -text_width * math.sin(angle) / 2
         ttx = text_width / 2
         tty = 0
     elif anchor == ANCHOR_BOTTOM_CENTER:
         tx = text_width * math.cos(angle) / 2 + text_height * math.sin(angle)
         ty = -text_width * math.sin(angle) / 2 + text_height * math.cos(angle)
         ttx = text_width / 2
         tty = text_height
     elif anchor == ANCHOR_LEFT_CENTER:
         tx = text_height * math.sin(angle) / 2
         ty = text_height * math.cos(angle) / 2
         ttx = 0
         tty = text_height / 2
     elif anchor == ANCHOR_RIGHT_CENTER:
         tx = text_width * math.cos(angle) + text_height * math.sin(angle) / 2
         ty = -text_width * math.sin(angle) + text_height * math.cos(angle) / 2
         ttx = text_width
         tty = text_height / 2
     
     #calculate the bounding rect
     real_x = x - ttx
     real_y = y - tty
     top_left = real_x, real_y
     bottom_left = real_x , real_y + text_height
     bottom_right = real_x + text_width, real_y + text_height
     top_right = real_x + text_width, real_y
     
     offset = x, y
     
     n_top_left = rotate_vector(offset, top_left, angle)
     n_bottom_left = rotate_vector(offset, bottom_left, angle)
     n_bottom_right = rotate_vector(offset, bottom_right, angle)
     n_top_right = rotate_vector(offset, top_right, angle)
     
     alloc_x_min = int(min(n_top_left[0], n_bottom_left[0], n_bottom_right[0],
                         n_top_right[0]))
     alloc_x_max = int(max(n_top_left[0], n_bottom_left[0], n_bottom_right[0],
                         n_top_right[0]))
     alloc_y_min = int(min(n_top_left[1], n_bottom_left[1], n_bottom_right[1],
                         n_top_right[1]))
     alloc_y_max = int(max(n_top_left[1], n_bottom_left[1], n_bottom_right[1],
                         n_top_right[1]))
                         
     rect = gtk.gdk.Rectangle(alloc_x_min, alloc_y_min,
                                 alloc_x_max - alloc_x_min,
                                 alloc_y_max - alloc_y_min)
     return rect
Exemplo n.º 17
0
Arquivo: label.py Projeto: almuza/xen
    def get_calculated_dimensions(self, context, rect):
        angle = 2 * math.pi * self._rotation / 360.0

        if self._context == None:
            label = gtk.Label()
            self._context = label.create_pango_context()
        pango_context = self._context

        attrs = pango.AttrList()
        attrs.insert(pango.AttrWeight(self._weight, 0, len(self._text)))
        attrs.insert(pango.AttrStyle(self._slant, 0, len(self._text)))
        attrs.insert(pango.AttrUnderline(self._underline, 0, len(self._text)))
        if self._size != None:
            attrs.insert(pango.AttrSize(1000 * self._size, 0, len(self._text)))

        if self._layout == None:
            self._layout = pango.Layout(pango_context)
        layout = self._layout

        layout.set_text(self._text)
        layout.set_attributes(attrs)

        #find out where to draw the layout and calculate the maximum width
        width = rect.width
        if self._anchor in [
                ANCHOR_BOTTOM_LEFT, ANCHOR_TOP_LEFT, ANCHOR_LEFT_CENTER
        ]:
            width = rect.width - self._position[0]
        elif self._anchor in [
                ANCHOR_BOTTOM_RIGHT, ANCHOR_TOP_RIGHT, ANCHOR_RIGHT_CENTER
        ]:
            width = self._position[0]

        text_width, text_height = layout.get_pixel_size()
        width = width * math.cos(angle)
        width = min(width, self._max_width)

        if self._wrap:
            layout.set_wrap(pango.WRAP_WORD_CHAR)
        layout.set_width(int(1000 * width))

        x, y = get_text_pos(layout, self._position, self._anchor, angle)

        if not self._fixed:
            #Find already drawn labels that would intersect with the current one
            #and adjust position to avoid intersection.
            text_width, text_height = layout.get_pixel_size()
            real_width = abs(text_width * math.cos(angle)) + abs(
                text_height * math.sin(angle))
            real_height = abs(text_height * math.cos(angle)) + abs(
                text_width * math.sin(angle))

            other_labels = get_registered_labels()
            this_rect = gtk.gdk.Rectangle(int(x), int(y), int(real_width),
                                          int(real_height))
            for label in other_labels:
                label_rect = label.get_allocation()
                intersection = this_rect.intersect(label_rect)
                if intersection.width == 0 and intersection.height == 0:
                    continue

                y_diff = 0
                if label_rect.y <= y and label_rect.y + label_rect.height >= y:
                    y_diff = y - label_rect.y + label_rect.height
                elif label_rect.y > y and label_rect.y < y + real_height:
                    y_diff = label_rect.y - real_height - y
                y += y_diff

        #calculate the dimensions
        text_width, text_height = layout.get_pixel_size()
        real_width = abs(text_width * math.cos(angle)) + abs(
            text_height * math.sin(angle))
        real_height = abs(text_height * math.cos(angle)) + abs(
            text_width * math.sin(angle))
        return real_width, real_height
Exemplo n.º 18
0
    def render(self,
               text,
               antialias=True,
               color=(255, 255, 255),
               background=None):
        """Render the font onto a new Surface and return it.
        We ignore 'antialias' and use system settings.
        
        text -- (unicode) string with the text to render
        antialias -- attempt to antialias the text or not
        color -- three or four-tuple of 0-255 values specifying rendering 
            colour for the text 
        background -- three or four-tuple of 0-255 values specifying rendering 
            colour for the background, or None for trasparent background
        
        returns a pygame image instance
        """
        log.info('render: %r, antialias = %s, color=%s, background=%s', text,
                 antialias, color, background)

        # create layout
        layout = pango.Layout(gtk.gdk.pango_context_get())
        layout.set_font_description(self.fd)
        if self.underline:
            attrs = layout.get_attributes()
            if not attrs:
                attrs = pango.AttrList()
            attrs.insert(pango.AttrUnderline(pango.UNDERLINE_SINGLE, 0, 32767))
            layout.set_attributes(attrs)
        layout.set_text(text)

        # determine pixel size
        (logical, ink) = layout.get_pixel_extents()
        ink = pygame.rect.Rect(ink)

        # Create a new Cairo ImageSurface
        csrf, cctx = _cairoimage.newContext(ink.w, ink.h)
        cctx = pangocairo.CairoContext(cctx)

        # Mangle the colors on little-endian machines. The reason for this
        # is that Cairo writes native-endian 32-bit ARGB values whereas
        # Pygame expects endian-independent values in whatever format. So we
        # tell our users not to expect transparency here (avoiding the A issue)
        # and we swizzle all the colors around.

        # render onto it
        if background is not None:
            background = _cairoimage.mangle_color(background)
            cctx.set_source_rgba(*background)
            cctx.paint()

        log.debug('incoming color: %s', color)
        color = _cairoimage.mangle_color(color)
        log.debug('  translated color: %s', color)

        cctx.new_path()
        cctx.layout_path(layout)
        cctx.set_source_rgba(*color)
        cctx.fill()

        # Create and return a new Pygame Image derived from the Cairo Surface
        return _cairoimage.asImage(csrf)
Exemplo n.º 19
0
    def attrs_changed(self):
        bold = False
        italics = False
        underline = False
        pango_font = None
        del self.attrlist
        self.attrlist = pango.AttrList()
        # TODO: splice instead of own method
        it = self.attributes.get_iterator()

        while 1:
            at = it.get_attrs()
            for x in at:
                self.attrlist.insert(x)
            if it.next() == False:
                break
        if self.preedit:
            ins_text = self.preedit[0]
            ins_style = self.preedit[1]
            if self.index == len(self.text):
                show_text = self.text + ins_text
            elif self.index == 0:
                show_text = ins_text + self.text
            else:
                split1 = self.text[:self.index]
                split2 = self.text[self.index:]
                show_text = split1 + ins_text + split2
            self.attrlist.splice(ins_style, self.index, len(ins_text))
        else:
            show_text = self.text

        it = self.attributes.get_iterator()
        while (1):
            found = False
            r = it.range()
            if self.index == self.end_index:
                if r[0] <= self.index and r[1] > self.index:
                    found = True
            elif self.index < self.end_index:
                if r[0] > self.end_index:
                    break
                if self.index == self.end_index and \
                 r[0] < self.index and \
                 r[1] > self.index:
                    found = True
                elif self.index != self.end_index and r[0] <= self.index and \
                   r[1] >= self.end_index:
                    # We got a winner!
                    found = True
            else:
                if r[0] > self.index:
                    break
                if self.index == self.end_index and \
                 r[0] < self.index and \
                 r[1] > self.index:
                    found = True
                elif self.index != self.end_index and r[0] <= self.end_index and \
                   r[1] >= self.index:
                    # We got another winner!
                    found = True

            if found:
                # FIXME: the it.get() seems to crash python
                # through pango.
                attr = it.get_attrs()
                for x in attr:
                    if x.type == pango.ATTR_WEIGHT and \
                       x.value == pango.WEIGHT_BOLD:
                        bold = True
                    elif x.type == pango.ATTR_STYLE and \
                      x.value == pango.STYLE_ITALIC:
                        italics = True
                    elif x.type == pango.ATTR_UNDERLINE and \
                      x.value == pango.UNDERLINE_SINGLE:
                        underline = True
                    elif x.type == pango.ATTR_FONT_DESC:
                        pango_font = x.desc
            if it.next() == False:
                break
        to_add = []
        if bold:
            to_add.append(
                pango.AttrWeight(pango.WEIGHT_BOLD, self.index, self.index))
        if italics:
            to_add.append(
                pango.AttrStyle(pango.STYLE_ITALIC, self.index, self.index))
        if underline:
            to_add.append(
                pango.AttrUnderline(pango.UNDERLINE_SINGLE, self.index,
                                    self.index))
        if pango_font:
            to_add.append(
                pango.AttrFontDesc(pango_font, self.index, self.index))
        for x in self.current_attrs:
            if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD:
                bold = True
                to_add.append(x)
            if x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC:
                italics = True
                to_add.append(x)
            if x.type == pango.ATTR_UNDERLINE and x.value == pango.UNDERLINE_SINGLE:
                underline = True
                to_add.append(x)
            if x.type == pango.ATTR_FONT_DESC:
                pango_font = x.desc
                to_add.append(x)
        del self.current_attrs
        self.current_attrs = to_add
        self.emit("update-attrs", bold, italics, underline, pango_font)
        return show_text
Exemplo n.º 20
0
    def attrs_changed(self):
        bold = False
        italics = False
        underline = False
        pango_font = None
        del self.attrlist
        self.attrlist = self.attributes.copy()

        if self.preedit:
            ins_text = self.preedit[0]
            ins_style = self.preedit[1]
            if self.index == len(self.text):
                show_text = self.text + ins_text
            elif self.index == 0:
                show_text = ins_text + self.text
            else:
                split1 = self.text[:self.index]
                split2 = self.text[self.index:]
                show_text = split1 + ins_text + split2
            self.attrlist.splice(ins_style, self.index, len(ins_text))
        else:
            show_text = self.text

        it = wrap_attriterator(self.attributes.get_iterator())
        for attrs, (start, end) in it:
            found = False
            if self.index == self.end_index:
                if start <= self.index and end > self.index:
                    found = True
            elif self.index < self.end_index:
                if start > self.end_index:
                    break
                elif start <= self.index and \
                     end   >= self.end_index:
                    # We got a winner!
                    found = True
            else:  # i.e. self.index > self.end_index
                if start > self.index:
                    break
                elif start <= self.end_index and \
                     end   >= self.index:
                    # We got another winner!
                    found = True

            if found:
                for x in attrs:
                    if x.type == pango.ATTR_WEIGHT and \
                       x.value == pango.WEIGHT_BOLD:
                        bold = True
                    elif x.type == pango.ATTR_STYLE and \
                             x.value == pango.STYLE_ITALIC:
                        italics = True
                    elif x.type == pango.ATTR_UNDERLINE and \
                             x.value == pango.UNDERLINE_SINGLE:
                        underline = True
                    elif x.type == pango.ATTR_FONT_DESC:
                        pango_font = x.desc

        to_add = []
        if bold:
            to_add.append(
                pango.AttrWeight(pango.WEIGHT_BOLD, self.index, self.index))
        if italics:
            to_add.append(
                pango.AttrStyle(pango.STYLE_ITALIC, self.index, self.index))
        if underline:
            to_add.append(
                pango.AttrUnderline(pango.UNDERLINE_SINGLE, self.index,
                                    self.index))
        if pango_font:
            to_add.append(
                pango.AttrFontDesc(pango_font, self.index, self.index))
        for x in self.current_attrs:
            if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD:
                bold = True
                to_add.append(x)
            if x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC:
                italics = True
                to_add.append(x)
            if x.type == pango.ATTR_UNDERLINE and x.value == pango.UNDERLINE_SINGLE:
                underline = True
                to_add.append(x)
            if x.type == pango.ATTR_FONT_DESC:
                pango_font = x.desc
                to_add.append(x)
        del self.current_attrs
        self.current_attrs = to_add
        self.emit("update-attrs", bold, italics, underline, pango_font)
        return show_text
Exemplo n.º 21
0
def generate_images(opts,args):
    # Set up variables for drawing space
    width = 2550 # Will resize to match text; default 8.5"x11" @ 300dpi
    height = 3300
    MARGIN_X = 300
    MARGIN_Y = 300
    LINE_SPACE = 35 #TODO: Command-line opts
    LANG = "ka"
    TESS_LANG = "kat"
    # Set up decent spacing for box files
    attrs = pango.AttrList() #TODO: Command line opts or config
    attrs.insert(pango.AttrLanguage(LANG,0,-1))
    attrs.insert(pango.AttrLetterSpacing(10000,0,-1))
    attrs.insert(pango.AttrSize(48000,0,-1))
    attrs.insert(pango.AttrFallback(False,0,-1))
    attrs.insert(pango.AttrStyle(pango.STYLE_NORMAL,0,-1))
    attrs.insert(pango.AttrWeight(pango.WEIGHT_NORMAL,0,-1))
    attrs.insert(pango.AttrUnderline(pango.UNDERLINE_NONE,0,-1))

    # Instantiate Cairo surface and context
    surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
    context = pangocairo.CairoContext(cairo.Context(surf))

    # Instantiate PangoCairo context
    context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)

    #get font families:
    font_map = pangocairo.cairo_font_map_get_default()

    # to see family names:
    if opts.list_fonts:
        print [f.get_name() for f in font_map.list_families()]
        return

    # Set up pango layout
    layout = context.create_layout()
    layout.set_attributes(attrs)
    layout.set_width((width+MARGIN_X)*pango.SCALE)
    layout.set_spacing(LINE_SPACE*pango.SCALE)

    #print layout.get_width()

    # Read text from file TODO: Command line argument
    # TODO: Multiple files print to multiple image documents
    text = ''
    with codecs.open(opts.input_file) as text_file:
        for line in text_file:
            text += line + '\n'

    font_names = args

    # (variant, reset,"desc")
    #Font variants is an array of tuples consisting of: (AttrStyle, InverseAttrStyle, Name)
    font_variants = [
        (pango.AttrStyle(pango.STYLE_NORMAL,0,-1),pango.AttrStyle(pango.STYLE_NORMAL,0,-1),"")]

    #Add other stylings based on command-line options
    if opts.italic:
        font_variants.append((pango.AttrStyle(pango.STYLE_ITALIC,0,-1),pango.AttrStyle(pango.STYLE_NORMAL,0,-1),"italic"))
    if opts.bold:
        font_variants.append((pango.AttrWeight(pango.WEIGHT_HEAVY,0,-1),pango.AttrWeight(pango.WEIGHT_NORMAL,0,-1),"bold"))
    if opts.underline:
        font_variants.append((pango.AttrUnderline(pango.UNDERLINE_SINGLE,0,-1),pango.AttrUnderline(pango.UNDERLINE_NONE,0,-1),"underline"))

    #Generate pages for each font name and variation.
    for fn in font_names:
        for fvar in font_variants:
            # Change to a new variant
            attrs.change(fvar[0])
            layout.set_attributes(attrs)

            # Change to a new font
            fontname = fn
            font = pango.FontDescription(fontname + " 25")
            
            layout.set_font_description(font)
            layout.set_text(text)

            (ink, logical) = layout.get_pixel_extents()

            # If layout exceeds size of surface, change surface size
            if logical[2] > (width-MARGIN_X) or logical[3] > (height-MARGIN_Y):
                width = logical[2]+MARGIN_X
                height = logical[3]+MARGIN_Y
                surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
                context = pangocairo.CairoContext(cairo.Context(surf))
                context.update_layout(layout)

            #draw a background rectangle:
            context.rectangle(0,0,width,height)
            context.set_source_rgb(1, 1, 1)
            context.fill()

            # Translate context so that desired text upperleft corner is at 0,0
            context.translate(50,25)
            context.set_source_rgb(0, 0, 0)

            context.update_layout(layout)
            context.show_layout(layout)

            # Write to image 
            # TODO: Specify outfile on command line
            #print fontname
            #print fvar[2]
            with open(TESS_LANG+"."+fontname+fvar[2]+".exp0.png", "wb") as image_file:
                    surf.write_to_png(image_file)

            attrs.change(fvar[1])
            layout.set_attributes(attrs)
Exemplo n.º 22
0
    def update_surface(self, bbox, zoom, style, callback=lambda x=None: None):
        rendertimer = Timer("Rendering image")
        if "image" not in style.cache:
            style.cache["image"] = ImageLoader()

        timer = Timer("Getting data")
        self.zoom = zoom
        self.bbox = bbox
        self.bbox_p = projections.from4326(bbox, self.proj)

        print self.bbox_p
        scale = abs(self.w / (self.bbox_p[0] - self.bbox_p[2]) /
                    math.cos(math.pi *
                             (self.bbox[1] + self.bbox[3]) / 2 / 180))
        zscale = 0.5 * scale
        cr = cairo.Context(self.surface)
        # getting and setting canvas properties
        bgs = style.get_style("canvas", {}, self.zoom, scale, zscale)
        if not bgs:
            bgs = [{}]
        bgs = bgs[0]
        cr.rectangle(0, 0, self.w, self.h)
        # canvas color and opcity
        color = bgs.get("fill-color", (0.7, 0.7, 0.7))
        cr.set_source_rgba(color[0], color[1], color[2],
                           bgs.get("fill-opacity", 1))
        cr.fill()
        callback()

        # canvas antialiasing
        antialias = bgs.get("antialias", "full")
        if antialias == "none":
            "no antialiasing enabled"
            cr.set_antialias(1)
            #cr.font_options_set_antialias(1)
        elif antialias == "text":
            "only text antialiased"
            cr.set_antialias(1)
            #cr.font_options_set_antialias(2)
        else:
            "full antialias"
            cr.set_antialias(2)
            #cr.font_options_set_antialias(2)

        datatimer = Timer("Asking backend")
        if "get_sql_hints" in dir(style):
            hints = style.get_sql_hints('way', self.zoom)
        else:
            hints = None
        if "get_interesting_tags" in dir(style):
            itags = style.get_interesting_tags(zoom=self.zoom)
        else:
            itags = None

        # enlarge bbox by 20% to each side. results in more vectors, but makes less artifaces.
        span_x, span_y = bbox[2] - bbox[0], bbox[3] - bbox[1]
        bbox_expand = [
            bbox[0] - 0.2 * span_x, bbox[1] - 0.2 * span_y,
            bbox[2] + 0.2 * span_x, bbox[3] + 0.2 * span_y
        ]
        vectors = self.data.get_vectors(bbox_expand, self.zoom, hints,
                                        itags).values()
        datatimer.stop()
        datatimer = Timer("Applying styles")
        ww = []

        for way in vectors:
            type = "line"
            if way.coords[0] == way.coords[-1]:
                type == "area"
            st = style.get_style("area", way.tags, self.zoom, scale, zscale)
            if st:
                for fpt in st:
                    #debug(fpt)
                    ww.append([way.copy(), fpt])

        datatimer.stop()
        debug("%s objects on screen (%s in dataset)" % (len(ww), len(vectors)))

        er = Timer("Projecing data")
        if self.data.proj != self.proj:
            for w in ww:
                w[0].cs = [
                    self.lonlat2screen(coord)
                    for coord in projections.transform(
                        w[0].coords, self.data.proj, self.proj)
                ]
        else:
            for w in ww:
                w[0].cs = [self.lonlat2screen(coord) for coord in w[0].coords]
        for w in ww:
            if "offset" in w[1]:
                offset = float(w[1]["offset"])
                w[0] = w[0].copy()
                w[0].cs = offset_line(w[0].cs, offset)
            if "raise" in w[1] and not "extrude" in w[1]:
                w[0] = w[0].copy()
                offset = float(w[1]["raise"])
                w[0].cs_real = w[0].cs
                w[0].cs = [(x, y - offset) for x, y in w[0].cs]
            if "extrude" in w[1]:
                if w[1]["extrude"] < 2:
                    del w[1]["extrude"]
            if "extrude" in w[1] and "fill-color" not in w[1] and "width" in w[
                    1]:
                w[1]["fill-color"] = w[1].get("color", (0, 0, 0))
                w[1]["fill-opacity"] = w[1].get("opacity", 1)
                w[0] = w[0].copy()
                #print w[0].cs
                w[0].cs = offset_line(w[0].cs, w[1]["width"] / 2)
                #print w[0].cs
                aa = offset_line(w[0].cs, -w[1]["width"])
                del w[1]["width"]
                aa.reverse()
                w[0].cs.extend(aa)

        er.stop()

        ww.sort(key=lambda x: x[1]["layer"])
        layers = list(set([int(x[1]["layer"] / 100.) for x in ww]))
        layers.sort()
        objs_by_layers = {}
        for layer in layers:
            objs_by_layers[layer] = []
        for obj in ww:
            objs_by_layers[int(obj[1]["layer"] / 100.)].append(obj)

        del ww
        timer.stop()
        timer = Timer("Rasterizing image")
        linecaps = {"butt": 0, "round": 1, "square": 2}
        linejoin = {"miter": 0, "round": 1, "bevel": 2}

        text_rendered_at = set([(-100, -100)])
        for layer in layers:
            data = objs_by_layers[layer]
            #data.sort(lambda x,y:cmp(max([x1[1] for x1 in x[0].cs]), max([x1[1] for x1 in y[0].cs])))

            # - fill polygons
            for obj in data:
                if ("fill-color" in obj[1] or "fill-image" in obj[1]
                    ) and not "extrude" in obj[1]:  ## TODO: fill-image
                    color = obj[1].get("fill-color", (0, 0, 0))
                    cr.set_source_rgba(color[0], color[1], color[2],
                                       obj[1].get("fill-opacity", 1))

                    if "fill-image" in obj[1]:
                        image = style.cache["image"][obj[1]["fill-image"]]
                        if image:
                            pattern = cairo.SurfacePattern(image)
                            pattern.set_extend(cairo.EXTEND_REPEAT)
                            cr.set_source(pattern)
                    poly(cr, obj[0].cs)

            # - draw casings on layer
            for obj in data:
                ### Extras: casing-linecap, casing-linejoin
                if "casing-width" in obj[1] or "casing-color" in obj[
                        1] and "extrude" not in obj[1]:
                    cr.set_dash(obj[1].get("casing-dashes",
                                           obj[1].get("dashes", [])))
                    cr.set_line_join(
                        linejoin.get(
                            obj[1].get("casing-linejoin",
                                       obj[1].get("linejoin", "round")), 1))
                    color = obj[1].get("casing-color", (0, 0, 0))
                    cr.set_source_rgba(color[0], color[1], color[2],
                                       obj[1].get("casing-opacity", 1))
                    ## TODO: good combining of transparent lines and casing
                    ## Probable solution: render casing, render way as mask and put casing with mask chopped out onto image

                    cr.set_line_width(obj[1].get("width", 0) +
                                      obj[1].get("casing-width", 1))
                    cr.set_line_cap(
                        linecaps.get(
                            obj[1].get("casing-linecap",
                                       obj[1].get("linecap", "butt")), 0))
                    line(cr, obj[0].cs)

            # - draw line centers
            for obj in data:
                if ("width" in obj[1] or "color" in obj[1]
                        or "image" in obj[1]) and "extrude" not in obj[1]:
                    cr.set_dash(obj[1].get("dashes", []))
                    cr.set_line_join(
                        linejoin.get(obj[1].get("linejoin", "round"), 1))
                    color = obj[1].get("color", (0, 0, 0))
                    cr.set_source_rgba(color[0], color[1], color[2],
                                       obj[1].get("opacity", 1))
                    ## TODO: better overlapping of transparent lines.
                    ## Probable solution: render them (while they're of the same opacity and layer) on a temporary canvas that's merged into main later
                    cr.set_line_width(obj[1].get("width", 1))
                    cr.set_line_cap(
                        linecaps.get(obj[1].get("linecap", "butt"), 0))
                    if "image" in obj[1]:
                        image = style.cache["image"][obj[1]["image"]]
                        if image:
                            pattern = cairo.SurfacePattern(image)
                            pattern.set_extend(cairo.EXTEND_REPEAT)
                            cr.set_source(pattern)
                    line(cr, obj[0].cs)

            callback()

            # - extruding polygons
            #data.sort(lambda x,y:cmp(max([x1[1] for x1 in x[0].cs]), max([x1[1] for x1 in y[0].cs])))
            # Pass 1. Creating list of extruded polygons
            extlist = []
            # fromat: (coords, ("h"/"v", y,z), real_obj)
            for obj in data:
                if "extrude" in obj[1]:

                    def face_to_poly(face, hgt):
                        """
            Converts a line into height-up extruded poly
            """
                        return [
                            face[0], face[1], (face[1][0], face[1][1] - hgt),
                            (face[0][0], face[0][1] - hgt), face[0]
                        ]

                    hgt = obj[1]["extrude"]
                    raised = float(obj[1].get("raise", 0))
                    excoords = [(a[0], a[1] - hgt - raised) for a in obj[0].cs]

                    faces = []
                    coord = obj[0].cs[-1]
                    #p_coord = (coord[0],coord[1]-raised)
                    p_coord = False
                    for coord in obj[0].cs:
                        c = (coord[0], coord[1] - raised)
                        if p_coord:
                            extlist.append((face_to_poly([c, p_coord], hgt),
                                            ("v", min(coord[1],
                                                      p_coord[1]), hgt), obj))
                        p_coord = c

                    extlist.append(
                        (excoords, ("h", min(coord[1], p_coord[1]), hgt), obj))
                    #faces.sort(lambda x,y:cmp(max([x1[1] for x1 in x]), max([x1[1] for x1 in y])))

            # Pass 2. Sorting
            def compare_things(a, b):
                """
        Custom comparator for extlist sorting.
        Sorts back-to-front, bottom-to-top, | > \ > _, horizontal-to-vertical.
        """
                t1, t2 = a[1], b[1]  #
                if t1[1] > t2[1]:  # back-to-front
                    return 1
                if t1[1] < t2[1]:
                    return -1
                if t1[2] > t2[2]:  # bottom-to-top
                    return 1
                if t1[2] < t2[2]:
                    return -1
                if t1[0] < t2[0]:  # h-to-v
                    return 1
                if t1[0] > t2[0]:
                    return -1

                return cmp(
                    math.sin(
                        math.atan2(a[0][0][0] - a[0][1][0],
                                   a[0][0][0] - a[0][1][0])),
                    math.sin(
                        math.atan2(b[0][0][0] - b[0][1][0],
                                   b[0][0][0] - b[0][1][0])))
                print t1
                print t2

            extlist.sort(compare_things)

            # Pass 3. Rendering using painter's algorythm
            cr.set_dash([])
            for ply, prop, obj in extlist:
                if prop[0] == "v":
                    color = obj[1].get("extrude-face-color",
                                       obj[1].get("color", (0, 0, 0)))
                    cr.set_source_rgba(
                        color[0], color[1], color[2],
                        obj[1].get("extrude-face-opacity",
                                   obj[1].get("opacity", 1)))
                    poly(cr, ply)
                    color = obj[1].get("extrude-edge-color",
                                       obj[1].get("color", (0, 0, 0)))
                    cr.set_source_rgba(
                        color[0], color[1], color[2],
                        obj[1].get("extrude-edge-opacity",
                                   obj[1].get("opacity", 1)))
                    cr.set_line_width(.5)
                    line(cr, ply)
                if prop[0] == "h":
                    if "fill-color" in obj[1]:
                        color = obj[1]["fill-color"]
                        cr.set_source_rgba(
                            color[0], color[1], color[2],
                            obj[1].get("fill-opacity",
                                       obj[1].get("opacity", 1)))
                        poly(cr, ply)
                    color = obj[1].get("extrude-edge-color",
                                       obj[1].get("color", (0, 0, 0)))
                    cr.set_source_rgba(
                        color[0], color[1], color[2],
                        obj[1].get("extrude-edge-opacity",
                                   obj[1].get("opacity", 1)))
                    cr.set_line_width(1)
                    line(cr, ply)

                #cr.set_line_width (obj[1].get("width", 1))
                #color = obj[1].get("color", (0,0,0) )
                #cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("extrude-edge-opacity", obj[1].get("opacity", 1)))
                #line(cr,excoords)
                #if "fill-color" in obj[1]:
                #color = obj[1]["fill-color"]
                #cr.set_source_rgba(color[0], color[1], color[2], obj[1].get("fill-opacity", 1))
                #poly(cr,excoords)
            for obj in data:
                if "icon-image" in obj[1]:
                    image = style.cache["image"][obj[1]["icon-image"]]
                    if image:
                        dy = image.get_height() / 2
                        dx = image.get_width() / 2

                        where = self.lonlat2screen(
                            projections.transform(obj[0].center,
                                                  self.data.proj, self.proj))
                        cr.set_source_surface(image, where[0] - dx,
                                              where[1] - dy)
                        cr.paint()

            callback()
            # - render text labels
            texttimer = Timer("Text rendering")
            cr.set_line_join(
                1
            )  # setting linejoin to "round" to get less artifacts on halo render
            for obj in data:
                if "text" in obj[1]:

                    text = obj[1]["text"]
                    #cr.set_line_width (obj[1].get("width", 1))
                    #cr.set_font_size(float(obj[1].get("font-size", 9)))
                    ft_desc = pango.FontDescription()

                    ft_desc.set_family(obj[1].get('font-family', 'sans'))
                    ft_desc.set_size(pango.SCALE *
                                     int(obj[1].get('font-size', 9)))
                    fontstyle = obj[1].get('font-style', 'normal')
                    if fontstyle == 'italic':
                        fontstyle = pango.STYLE_ITALIC
                    else:
                        fontstyle = pango.STYLE_NORMAL
                    ft_desc.set_style(fontstyle)
                    fontweight = obj[1].get('font-weight', 400)
                    try:
                        fontweight = int(fontweight)
                    except ValueError:
                        if fontweight == 'bold':
                            fontweight = 700
                        else:
                            fontweight = 400
                    ft_desc.set_weight(fontweight)
                    if obj[1].get('text-transform', None) == 'uppercase':
                        text = text.upper()
                    p_ctx = pangocairo.CairoContext(cr)
                    p_layout = p_ctx.create_layout()
                    p_layout.set_font_description(ft_desc)
                    p_layout.set_text(text)
                    p_attrs = pango.AttrList()
                    decoration = obj[1].get('text-decoration', 'none')
                    if decoration == 'underline':
                        p_attrs.insert(
                            pango.AttrUnderline(pango.UNDERLINE_SINGLE,
                                                end_index=-1))
                    decoration = obj[1].get('font-variant', 'none')
                    if decoration == 'small-caps':
                        p_attrs.insert(
                            pango.AttrVariant(pango.VARIANT_SMALL_CAPS,
                                              start_index=0,
                                              end_index=-1))

                    p_layout.set_attributes(p_attrs)

                    if obj[1].get("text-position", "center") == "center":
                        where = self.lonlat2screen(
                            projections.transform(obj[0].center,
                                                  self.data.proj, self.proj))
                        for t in text_rendered_at:
                            if ((t[0] - where[0])**2 +
                                (t[1] - where[1])**2) < 15 * 15:
                                break
                        else:
                            text_rendered_at.add(where)
                            #debug ("drawing text: %s at %s"%(text, where))
                            if "text-halo-color" in obj[
                                    1] or "text-halo-radius" in obj[1]:
                                cr.new_path()
                                cr.move_to(where[0], where[1])
                                cr.set_line_width(obj[1].get(
                                    "text-halo-radius", 1))
                                color = obj[1].get("text-halo-color",
                                                   (1., 1., 1.))
                                cr.set_source_rgb(color[0], color[1], color[2])
                                cr.text_path(text)
                                cr.stroke()
                            cr.new_path()
                            cr.move_to(where[0], where[1])
                            cr.set_line_width(obj[1].get(
                                "text-halo-radius", 1))
                            color = obj[1].get("text-color", (0., 0., 0.))
                            cr.set_source_rgb(color[0], color[1], color[2])
                            cr.text_path(text)
                            cr.fill()
                    else:  ### render text along line
                        c = obj[0].cs
                        text = unicode(text, "utf-8")
                        # - calculate line length
                        length = reduce(
                            lambda x, y: (x[0] +
                                          ((y[0] - x[1])**2 +
                                           (y[1] - x[2])**2)**0.5, y[0], y[1]),
                            c, (0, c[0][0], c[0][1]))[0]
                        #print length, text, cr.text_extents(text)
                        if length > cr.text_extents(text)[2]:

                            # - function to get (x, y, normale) from (c, length_along_c)
                            def get_xy_from_len(c, length_along_c):
                                x0, y0 = c[0]

                                for x, y in c:
                                    seg_len = ((x - x0)**2 + (y - y0)**2)**0.5
                                    if length_along_c < seg_len:
                                        normed = length_along_c / seg_len
                                        return (x - x0) * normed + x0, (
                                            y - y0) * normed + y0, math.atan2(
                                                y - y0, x - x0)
                                    else:
                                        length_along_c -= seg_len
                                        x0, y0 = x, y
                                else:
                                    return None

                            da = 0
                            os = 1
                            z = length / 2 - cr.text_extents(text)[2] / 2
                            #  print get_xy_from_len(c,z)
                            if c[0][0] < c[1][0] and get_xy_from_len(
                                    c, z)[2] < math.pi / 2 and get_xy_from_len(
                                        c, z)[2] > -math.pi / 2:
                                da = 0
                                os = 1
                                z = length / 2 - cr.text_extents(text)[2] / 2
                            else:
                                da = math.pi
                                os = -1
                                z = length / 2 + cr.text_extents(text)[2] / 2
                            z1 = z
                            if "text-halo-color" in obj[
                                    1] or "text-halo-radius" in obj[1]:
                                cr.set_line_width(
                                    obj[1].get("text-halo-radius", 1.5) * 2)
                                color = obj[1].get("text-halo-color",
                                                   (1., 1., 1.))
                                cr.set_source_rgb(color[0], color[1], color[2])
                                xy = get_xy_from_len(c, z)
                                cr.save()
                                #cr.move_to(xy[0],xy[1])
                                p_ctx.translate(xy[0], xy[1])
                                cr.rotate(xy[2] + da)
                                #p_ctx.translate(x,y)
                                #p_ctx.show_layout(p_layout)
                                p_ctx.layout_path(p_layout)

                                cr.restore()
                                cr.stroke()
                                #for letter in text:
                                #cr.new_path()
                                #xy = get_xy_from_len(c,z)
                                ##print letter, cr.text_extents(letter)
                                #cr.move_to(xy[0],xy[1])
                                #cr.save()
                                #cr.rotate(xy[2]+da)
                                #cr.text_path(letter)
                                #cr.restore()
                                #cr.stroke()
                                #z += os*cr.text_extents(letter)[4]

                            color = obj[1].get("text-color", (0., 0., 0.))
                            cr.set_source_rgb(color[0], color[1], color[2])
                            z = z1
                            xy = get_xy_from_len(c, z)
                            cr.save()
                            #cr.move_to(xy[0],xy[1])
                            p_ctx.translate(xy[0], xy[1])
                            cr.rotate(xy[2] + da)
                            #p_ctx.translate(x,y)
                            p_ctx.show_layout(p_layout)
                            cr.restore()

                            #for letter in text:
                            #cr.new_path()
                            #xy = get_xy_from_len(c,z)
                            ##print letter, cr.text_extents(letter)
                            #cr.move_to(xy[0],xy[1])
                            #cr.save()
                            #cr.rotate(xy[2]+da)
                            #cr.text_path(letter)
                            #cr.restore()
                            #cr.fill()
                            #z += os*cr.text_extents(letter)[4]

            texttimer.stop()
            del data
        del layers

        timer.stop()
        rendertimer.stop()
        debug(self.bbox)
        callback(True)