Пример #1
0
    def _pre_render(self):
        #we use a new CairoContext to pre render the text
        rs = cairo.RecordingSurface(cairo.CONTENT_ALPHA, None)
        cr = cairo.Context(rs)

        if GI:
            cr = _UNSAFE_cairocffi_context_to_pycairo(cr)
        self._pang_ctx = PangoCairo.create_context(cr)
        self.layout = PangoCairo.create_layout(cr)
        # layout line spacing
        # TODO: the behaviour is not the same as nodebox yet
        ## self.layout.set_spacing(int(((self._lineheight-1)*self._fontsize)*Pango.SCALE)) #pango requires an int casting
        # we pass pango font description and the text to the pango layout
        self.layout.set_font_description(self._fontface)
        self.layout.set_text(self.text, -1)
        # check if max text width is set and pass it to pango layout
        # text will wrap, meanwhile it checks if and indent has to be applied
        # indent is subordinated to width because it makes no sense on a single-line text block
        if self.width:
            self.layout.set_width(int(self.width)*Pango.SCALE)
            if self._indent:
                self.layout.set_indent(self._indent*Pango.SCALE)                
        # set text alignment    
        if self._align == "right":
            self.layout.set_alignment(Pango.Alignment.RIGHT)
        elif self._align == "center":
            self.layout.set_alignment(Pango.Alignment.CENTER)
        elif self._align == "justify":
            self.layout.set_alignment(Pango.Alignment.LEFT)
            self.layout.set_justify(True)
        else:
            self.layout.set_alignment(Pango.Alignment.LEFT)
Пример #2
0
    def _draw_time(self):
        """Draw the time in colors (digital display).
        """
        # TRANS: The format used to display the time for digital clock
        # You can add AM/PM indicator or use 12/24 format, for example
        # "%I:%M:%S %p".  See
        # http://docs.python.org/lib/module-time.html for available
        # strftime formats If the display of the time is moving
        # horizontally, it means that the glyphs of the digits used in
        # the font don't have the same width. Try to use a Monospace
        # font.  xgettext:no-python-format
        markup = _('<markup>\
<span lang="en" font_desc="Sans,Monospace Bold 96">\
<span foreground="#005FE4">%I</span>:\
<span foreground="#00B20D">%M</span>:\
<span foreground="#E6000A">%S</span>%p</span></markup>')
        # BUG: The following line kills Python 2.5 but is valid in 2.4
        markup_time = self._time.strftime(markup)
        # markup_time = time.strftime(markup)

        cr = self.window.cairo_create()
        cr.set_source_rgba(*style.Color(self._COLOR_BLACK).get_rgba())
        pango_layout = PangoCairo.create_layout(
            PangoCairo.create_context(cr))
        d = int(self._center_y + 0.3 * self._radius)
        pango_layout.set_markup(markup_time)
        dx, dy = pango_layout.get_pixel_size()
        pango_layout.set_alignment(Pango.Alignment.CENTER)
        cr.translate(self._center_x - dx / 2.0, d - dy / 2.0)
        PangoCairo.show_layout(cr, pango_layout)
Пример #3
0
def write(c, text, name, size, centered=False, at_top=False):
    pc = PangoCairo.create_context(c)

    font = Pango.FontDescription(name)
    font.set_size(int(round(size * Pango.SCALE)))
    lo = PangoCairo.create_layout(pc)
    lo.set_font_description(font)
    lo.set_text('X', -1)
    baseline_offset = lo.get_baseline() / Pango.SCALE
    if not at_top:
        c.rel_move_to(0, -baseline_offset)

    lo.set_font_description(font)
    lo.set_text(text, -1)
    if hasattr(lo, 'get_logical_extents'):
        extents = lo.get_logical_extents()
        ex = extents.get_width() / Pango.SCALE
    else:
        ex = size
        ex *= len(text)

    if centered:
        c.rel_move_to(-ex / 2, 0)
    PangoCairo.update_layout(c, lo)
    PangoCairo.show_layout(c, lo)
    c.rel_move_to(ex, 0)

    if not at_top:
        c.rel_move_to(0, -baseline_offset)
Пример #4
0
    def _render(self, ctx=None):
        if not self._doRender:
            return
        ctx = ctx or self._get_context()
        if GI:
            ctx = _UNSAFE_cairocffi_context_to_pycairo(ctx)
        # we build a PangoCairo context linked to cairo context
        # then we create a pango layout
        
        # we update the context as we already used a null one on the pre-rendering
        # supposedly there should not be a big performance penalty
        self._pang_ctx = PangoCairo.create_context(ctx)

        if self._fillcolor is not None:
            # Go to initial point (CORNER or CENTER):
            transform = self._call_transform_mode(self._transform)
            if GI:
                transform = pycairo.Matrix(*transform.as_tuple())
            ctx.set_matrix(transform)

            ctx.translate(self.x, self.y-self.baseline)
            
            if self._outline is False:
                ctx.set_source_rgba(*self._fillcolor)
            PangoCairo.show_layout(ctx, self.layout)
            PangoCairo.update_layout(ctx, self.layout)
Пример #5
0
    def _pre_render(self):
        # we use a new CairoContext to pre render the text
        rs = cairo.RecordingSurface(cairo.CONTENT_ALPHA, None)
        cr = cairo.Context(rs)

        if GI:
            cr = _UNSAFE_cairocffi_context_to_pycairo(cr)
        self._pang_ctx = PangoCairo.create_context(cr)
        self.layout = PangoCairo.create_layout(cr)
        # layout line spacing
        # TODO: the behaviour is not the same as nodebox yet
        # self.layout.set_spacing(int(((self._lineheight-1)*self._fontsize)*Pango.SCALE)) #pango requires an int casting
        # we pass pango font description and the text to the pango layout
        self.layout.set_font_description(self._fontface)
        self.layout.set_text(self.text, -1)
        # check if max text width is set and pass it to pango layout
        # text will wrap, meanwhile it checks if and indent has to be applied
        # indent is subordinated to width because it makes no sense on a single-line text block
        if self.width:
            self.layout.set_width(int(self.width) * Pango.SCALE)
            if self._indent:
                self.layout.set_indent(self._indent * Pango.SCALE)
        # set text alignment
        if self._align == "right":
            self.layout.set_alignment(Pango.Alignment.RIGHT)
        elif self._align == "center":
            self.layout.set_alignment(Pango.Alignment.CENTER)
        elif self._align == "justify":
            self.layout.set_alignment(Pango.Alignment.LEFT)
            self.layout.set_justify(True)
        else:
            self.layout.set_alignment(Pango.Alignment.LEFT)
Пример #6
0
	def draw(self,sender, c, data=None):
		c.set_source_rgb(0,0,0)
		self.drawBackground(c)
				
		pc = PangoCairo.create_context(c)
		#c.set_antialias( cairo.Antialias.SUBPIXEL )
		l = Pango.Layout(pc)
		l.set_font_description( Pango.FontDescription(self.font))
		l.set_text( self.text, -1)
		
		l.set_alignment( Pango.Alignment.CENTER )
		l.set_wrap( Pango.WrapMode.WORD )
		l.set_width( (self.width-5) * Pango.SCALE )
		l.set_height( (self.height-5) * Pango.SCALE )
		l.set_ellipsize( Pango.EllipsizeMode.END )
		
		w = 0
		h = 0
		w,h = l.get_pixel_size()
		c.move_to( 0, (self.height/2) - (h/2) )
		
		c.set_source_rgb(0, 0, 0)
		PangoCairo.update_layout(c, l)
		PangoCairo.show_layout(c, l)
		
		import storage
		if(storage.window.focusedItem == self):
			c.set_source_rgb(0,0,200)
			c.move_to(0,0)
			c.rectangle(0,0,self.width-1,self.height-1)
			c.stroke()
		
		return False
Пример #7
0
    def _render(self, ctx=None):
        if not self._doRender:
            return
        ctx = ctx or self._get_context()
        if GI:
            ctx = _UNSAFE_cairocffi_context_to_pycairo(ctx)
        # we build a PangoCairo context linked to cairo context
        # then we create a pango layout

        # we update the context as we already used a null one on the pre-rendering
        # supposedly there should not be a big performance penalty
        self._pang_ctx = PangoCairo.create_context(ctx)

        if self._fillcolor is not None:
            # Go to initial point (CORNER or CENTER):
            transform = self._call_transform_mode(self._transform)
            if GI:
                transform = pycairo.Matrix(*transform.as_tuple())
            ctx.set_matrix(transform)

            ctx.translate(self.x, self.y - self.baseline)

            if self._outline is False:
                ctx.set_source_rgba(*self._fillcolor)
            PangoCairo.show_layout(ctx, self.layout)
            PangoCairo.update_layout(ctx, self.layout)
Пример #8
0
 def create_params(self):
     self.surface = cairo.ImageSurface(cairo.FORMAT_A8, self.width, self.height)
     self.context = cairo.Context(self.surface)
     self.pc = PangoCairo.create_context(self.context)
     self.layout = PangoCairo.create_layout(self.context)
     
     self.layout.set_font_description(Pango.FontDescription(self.font))
     self.font_desc = Pango.font_description_from_string(self.font)
Пример #9
0
    def printPage(self, operation, context, page_nr):
        self.pangolayout = context.create_pango_layout()
        self.cairo_context = context.get_cairo_context()

        self.pangolayout.set_width(-1)
        self.PangoCairo = PangoCairo.create_context(self.cairo_context)

        getattr(self, self.drawfunction)(page_nr)
Пример #10
0
def draw_text_adjusted(ctx, text, x, y, width, height, max_char_number=None,
                       text_color=(0, 0, 0, 1), align=Pango.Alignment.CENTER,
                       width_adjust=0.7, height_adjust=0.8):
    """
    Draw a text adjusted to a maximum character number

    Args:
       ctx (cairo.Context): The cairo context to use to draw.
       text (str): the text to draw.
       x/y (numbers): The position on the canvas.
       width/height (numbers): The area we want to
           write into (cairo units).
       max_char_number (number): If set a maximum character number.
    """
    pc = PangoCairo.create_context(ctx)
    layout = PangoCairo.create_layout(ctx)
    layout.set_width(int(width_adjust * width * Pango.SCALE))
    layout.set_alignment(align)
    fd = Pango.FontDescription("Georgia Bold")
    fd.set_size(Pango.SCALE)
    layout.set_font_description(fd)

    if max_char_number:
        # adjust size with the max character number
        layout.set_text('0'*max_char_number, -1)
        adjust_font_size(layout, fd, width_adjust*width, height_adjust*height)

    # set the real text
    layout.set_text(text, -1)
    if not max_char_number:
        adjust_font_size(layout, fd, width_adjust*width, height_adjust*height)

    # draw
    ink, logical = layout.get_extents()
    ctx.save()
    ctx.set_source_rgba(*text_color)
    if align == Pango.Alignment.CENTER:
        x = x - (ink.width/2.0)/Pango.SCALE - int(float(ink.x)/Pango.SCALE)
        y = y - (ink.height/2.0)/Pango.SCALE - int(float(ink.y)/Pango.SCALE)
    else:
        y = y - (ink.height/2.0)/Pango.SCALE - ink.y/Pango.SCALE
    ctx.translate(x, y)

    if align == Pango.Alignment.LEFT:
        # Hack to workaround what appears to be a Cairo bug: without
        # drawing a rectangle here, the translation above is not taken
        # into account for rendering the text.
        ctx.rectangle(0, 0, 0, 0)
    PangoCairo.update_layout(ctx, layout)
    PangoCairo.show_layout(ctx, layout)
    ctx.restore()
Пример #11
0
    def canvas_draw(self, widget, cr):
        """
        draw the word centered in the window.
        """
        w, h = self.draw_size

        # center of the text
        cx, cy = w/2., h/2.

        # circle
        cr.set_line_width(9)
        cr.set_source_rgb(1.0, 1.0, 1.0)

        ctx = pangocairo.create_context(cr)
        layout = pango.Layout.new(ctx)
        prefixlayout = pango.Layout.new(ctx)

        desc = pango.font_description_from_string(self.font)
        for l in (layout, prefixlayout):
            l.set_font_description(desc)

        txt = self.current_word

        center = self.current_center
        if len(txt) > 0:
            markup = "%s<span foreground='red'>%s</span>%s" % tuple(
                t.replace("<", "&lt;").replace(">", "&gt;")
                for t in (txt[:center],
                          txt[center],
                          txt[center+1:]))
            prefix = txt[:center]
        else:
            markup = ""
            prefix = ""

        e, attr, txt, accel = pango.parse_markup(markup, -1, '\x00')
        layout.set_text(txt, -1)
        layout.set_attributes(attr)
        prefixlayout.set_text(prefix, -1)

        pangocairo.update_layout(cr, layout)
        pangocairo.update_layout(cr, prefixlayout)

        # text metrics
        _, txth = (x/1024. for x in layout.get_size())
        prew, _ = (x/1024. for x in prefixlayout.get_size())

        cr.move_to(cx - (prew), cy - txth/2)

        # render the text
        pangocairo.show_layout(cr, layout)
Пример #12
0
def pangocairo_create_context(cr):
    """
    If python-gi-cairo is not installed, using PangoCairo.create_context
    dies with an unhelpful KeyError, check for that and output somethig
    useful.
    """
    # TODO move this to core.backend
    try:
        return PangoCairo.create_context(cr)
    except KeyError as e:
        if e.args == ('could not find foreign type Context',):
            raise ShoebotInstallError("Error creating PangoCairo missing dependency: python-gi-cairo")
        else:
            raise
Пример #13
0
def pangocairo_create_context(cr):
    """
    If python-gi-cairo is not installed, using PangoCairo.create_context
    dies with an unhelpful KeyError, check for that and output somethig
    useful.
    """
    # TODO move this to core.backend
    try:
        return PangoCairo.create_context(cr)
    except KeyError as e:
        if e.args == ('could not find foreign type Context',):
            raise ShoebotInstallError("Error creating PangoCairo missing dependency: python-gi-cairo")
        else:
            raise
Пример #14
0
    def canvas_draw(self, widget, cr):
        """
        draw the word centered in the window.
        """
        w, h = self.draw_size

        # center of the text
        cx, cy = w / 2., h / 2.

        # circle
        cr.set_line_width(9)
        cr.set_source_rgb(1.0, 1.0, 1.0)

        ctx = pangocairo.create_context(cr)
        layout = pango.Layout.new(ctx)
        prefixlayout = pango.Layout.new(ctx)

        desc = pango.font_description_from_string(self.font)
        for l in (layout, prefixlayout):
            l.set_font_description(desc)

        txt = self.current_word

        center = self.current_center
        if len(txt) > 0:
            markup = "%s<span foreground='red'>%s</span>%s" % tuple(
                t.replace("<", "&lt;").replace(">", "&gt;")
                for t in (txt[:center], txt[center], txt[center + 1:]))
            prefix = txt[:center]
        else:
            markup = ""
            prefix = ""

        e, attr, txt, accel = pango.parse_markup(markup, -1, '\x00')
        layout.set_text(txt, -1)
        layout.set_attributes(attr)
        prefixlayout.set_text(prefix, -1)

        pangocairo.update_layout(cr, layout)
        pangocairo.update_layout(cr, prefixlayout)

        # text metrics
        _, txth = (x / 1024. for x in layout.get_size())
        prew, _ = (x / 1024. for x in prefixlayout.get_size())

        cr.move_to(cx - (prew), cy - txth / 2)

        # render the text
        pangocairo.show_layout(cr, layout)
Пример #15
0
def pangocairo_create_context(cr):
    """
    Create a PangoCairo context from a given pycairo context.

    If python-gi-cairo is not installed PangoCairo.create_context dies
    with an unhelpful KeyError, output a better error if that happens.
    """
    # TODO move this to core.backend
    try:
        return PangoCairo.create_context(cr)
    except KeyError as e:
        if e.args == ("could not find foreign type Context", ):
            raise ShoebotInstallError(
                "Error creating PangoCairo missing dependency: python-gi-cairo"
            )
    raise
Пример #16
0
    def _marker(self, color, txt, lat, lon, ctx, dpi):

        marker_path = os.path.abspath(
            os.path.join(os.path.dirname(__file__), '..', '..', 'images',
                         'marker.svg'))

        fp = open(marker_path, 'r')
        data = fp.read()
        fp.close()

        if color[0] != '#':
            c = Color(color)
            color = c.hex_l

        data = data.replace('#000000', color)

        rsvg = Rsvg.Handle()
        svg = rsvg.new_from_data(data.encode())

        x, y = self._latlon2xy(lat, lon, dpi)

        scale = (50.0 / svg.props.height) * (dpi / 72.0)

        x -= svg.props.width * scale / 2
        y -= svg.props.height * scale

        ctx.save()
        ctx.translate(x, y)

        ctx.scale(scale, scale)
        svg.render_cairo(ctx)

        pc = PangoCairo.create_context(ctx)
        layout = PangoCairo.create_layout(ctx)
        fd = Pango.FontDescription('Droid Sans')
        fd.set_size(Pango.SCALE)
        layout.set_font_description(fd)
        layout.set_text(txt, -1)
        draw_utils.adjust_font_size(layout, fd, svg.props.width / 3,
                                    svg.props.width / 3)
        ink, logical = layout.get_extents()
        ctx.translate(svg.props.width / 2 - logical.width / svg.props.height,
                      svg.props.height / 5)
        PangoCairo.update_layout(ctx, layout)
        PangoCairo.show_layout(ctx, layout)

        ctx.restore()
Пример #17
0
    def __init__(self, font_family, font_size,
            weight=Pango.Weight.NORMAL,
            export_dir=None):
        font_descr = Pango.FontDescription()
        font_descr.set_family(font_family)
        font_descr.set_size(font_size * Pango.SCALE)
        font_descr.set_weight(weight)

        self._nullbuffer = bytearray(self.WIDTH*self.HEIGHT)
        self._buffer = bytearray(self.WIDTH*self.HEIGHT)
        self._surface = cairo.ImageSurface.create_for_data(
            self._buffer, cairo.FORMAT_A8, self.WIDTH, self.HEIGHT,
            self.WIDTH)
        self._cairo = cairo.Context(self._surface)
        self._pango = PangoCairo.create_context(self._cairo)
        PangoCairo.context_set_resolution(self._pango, 72)
        # self._pango.set_resolution(72.)
        self._layout = Pango.Layout(self._pango)
        self._layout.set_font_description(font_descr)

        self._export_dir = export_dir
Пример #18
0
def cairo_draws(widget, mything):  # mything is the Cairo context.
    width = widget.get_allocated_width()

    mything.set_source_rgba(0, 0, 0, 1)  # Sets the text colour.
    if rotation == 1:
        mything.translate(width - 2, 20)
        mything.rotate(math.radians(90))
    else:
        mything.translate(10, 2)

    mypc = PangoCairo.create_context(mything)
    mypc.set_base_gravity(
        4
    )  # Pango gravity. South = 0, East = 1, North = 2, West = 3, Auto = 4.

    mylayout = Pango.Layout.new(mypc)
    mylayout.set_font_description(
        Pango.FontDescription("%s %s %s" % (font, fontstyle, fontsize)))
    mylayout.set_text(usertext, -1)

    PangoCairo.show_layout(mything, mylayout)
Пример #19
0
    def use_pango_font(font, start, count, will_call_prepost=False):
        import gi
        gi.require_version('Pango', '1.0')
        gi.require_version('PangoCairo', '1.0')
        from gi.repository import Pango
        from gi.repository import PangoCairo
        #from gi.repository import Cairo as cairo
        import cairo

        fontDesc = Pango.FontDescription(font)
        a = array.array('b', itertools.repeat(0, 256 * 256))
        surface = cairo.ImageSurface.create_for_data(a, cairo.FORMAT_A8, 256,
                                                     256)
        context = cairo.Context(surface)
        pango_context = PangoCairo.create_context(context)
        layout = PangoCairo.create_layout(context)
        fontmap = PangoCairo.font_map_get_default()
        font = fontmap.load_font(fontmap.create_context(), fontDesc)
        layout.set_font_description(fontDesc)
        metrics = font.get_metrics()
        descent = metrics.get_descent()
        d = descent / Pango.SCALE
        linespace = metrics.get_ascent() + metrics.get_descent()
        width = metrics.get_approximate_char_width()

        glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT)
        glPixelStorei(GL_UNPACK_SWAP_BYTES, 0)
        glPixelStorei(GL_UNPACK_LSB_FIRST, 1)
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 256)
        glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 256)
        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0)
        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0)
        glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glPixelZoom(1, -1)

        base = glGenLists(count)
        for i in range(count):
            ch = chr(start + i)
            layout.set_text(ch, -1)
            w, h = layout.get_size()
            context.save()
            context.new_path()
            context.rectangle(0, 0, 256, 256)
            context.set_source_rgba(0., 0., 0., 0.)
            context.set_operator(cairo.OPERATOR_SOURCE)
            context.paint()
            context.restore()

            context.save()
            context.set_source_rgba(1., 1., 1., 1.)
            context.set_operator(cairo.OPERATOR_SOURCE)
            context.move_to(0, 0)
            PangoCairo.update_context(context, pango_context)
            PangoCairo.show_layout(context, layout)
            context.restore()
            w, h = int(w / Pango.SCALE), int(h / Pango.SCALE)
            glNewList(base + i, GL_COMPILE)
            glBitmap(0, 0, 0, 0, 0, h - d, ''.encode())
            #glDrawPixels(0, 0, 0, 0, 0, h-d, '');
            if not will_call_prepost:
                pango_font_pre()
            if w and h:
                try:
                    pass
                    glDrawPixels(w, h, GL_LUMINANCE, GL_UNSIGNED_BYTE,
                                 a.tostring())
                except Exception as e:
                    print("glnav Exception ", e)

            glBitmap(0, 0, 0, 0, w, -h + d, ''.encode())
            if not will_call_prepost:
                pango_font_post()
            glEndList()

        glPopClientAttrib()
        return base, int(width / Pango.SCALE), int(linespace / Pango.SCALE)
Пример #20
0
    def render(self, dpi=UTILS.PT_PER_INCH):
        self.ctx.save()

        # Create a PangoCairo context for drawing to Cairo
        pc = PangoCairo.create_context(self.ctx)

        city_fd = Pango.FontDescription("DejaVu Sans Condensed Bold 18")
        header_fd = Pango.FontDescription("DejaVu Sans Condensed Bold 12")
        label_column_fd = Pango.FontDescription("DejaVu 6")

        city_layout, city_fascent, city_fheight, city_em = \
            self._create_layout_with_font(self.ctx, pc, city_fd)
        header_layout, header_fascent, header_fheight, header_em = \
            self._create_layout_with_font(self.ctx, pc, header_fd)
        label_layout, label_fascent, label_fheight, label_em = \
            self._create_layout_with_font(self.ctx, pc, label_column_fd)
        column_layout, _, _, _ = \
            self._create_layout_with_font(self.ctx, pc, label_column_fd)

        # By OCitysmap's convention, the default resolution is 72 dpi,
        # which maps to the default pangocairo resolution (96 dpi
        # according to pangocairo docs). If we want to render with
        # another resolution (different from 72), we have to scale the
        # pangocairo resolution accordingly:
        PangoCairo.context_set_resolution(city_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        PangoCairo.context_set_resolution(column_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        PangoCairo.context_set_resolution(label_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        PangoCairo.context_set_resolution(header_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)

        margin = label_em
        cityBlockHeight = city_fheight * 2

        index_area_w_pt = self.rendering_area_w - 2 * self.print_bleed_pt - self.margin_inside_pt - self.margin_outside_pt
        city_layout.set_width(
            int(UTILS.convert_pt_to_dots((index_area_w_pt) * Pango.SCALE,
                                         dpi)))

        self._draw_page_stroke()
        self._draw_page_content_stroke()

        citiesWithEntries = {
            k: v
            for k, v in self.index_categories.items() if len(v) > 0
        }  # print only cities with entries
        cities = list(citiesWithEntries.keys())
        cities.sort()

        margin_top = self.print_bleed_pt + self.margin_top_bottom_pt
        margin_top_page = margin_top
        offset_y = margin_top_page
        max_drawing_height = 0
        city_index = -1
        LOG.debug(
            "%f print_bleed_pt, %f print_safe_margin_pt, %f margin_top_bottom_pt, %f margin_top"
            % (self.print_bleed_pt, self.print_safe_margin_pt,
               self.margin_top_bottom_pt, margin_top))
        page_full_available_h = self.rendering_area_h - 2 * self.print_bleed_pt - 2 * self.margin_top_bottom_pt

        content_width = self.rendering_area_w - 2 * Renderer.PRINT_BLEED_PT
        content_height = self.rendering_area_h - 2 * Renderer.PRINT_BLEED_PT
        margin_x = self.print_bleed_pt
        margin_y = self.print_bleed_pt

        if Renderer.DEBUG:  # red stroke dash1: show area excluding bleed-difference
            self.ctx.save()
            self.ctx.set_source_rgba(1, 0.4, 0.4, .75)
            self.ctx.set_dash([1.0, 1.0], 1.0 / 2.0)
            self.ctx.rectangle(margin_x, margin_y, content_width,
                               content_height)
            self.ctx.stroke()
            self.ctx.restore()

        content_width -= self.margin_inside_pt + self.margin_outside_pt
        content_height -= 2 * self.margin_top_bottom_pt
        margin_x += (self.margin_inside_pt if
                     (self.index_page_num + self.page_offset) %
                     2 else self.margin_outside_pt)
        margin_y += self.margin_top_bottom_pt

        #LOG.debug(list(filter(lambda x: len(self.index_categories[cities[x]]) > 0, cities)))
        for city in cities:
            city_index = city_index + 1

            margin_top_page += max_drawing_height  # add max drawing height of previous city
            index_area_h_pt = self.rendering_area_h - self.print_bleed_pt - self.margin_top_bottom_pt - margin_top_page
            LOG.debug("============")
            LOG.debug(
                "printing index for city '%s'. available area: %f x %f, margin_top_page: %f"
                % (city, index_area_w_pt, index_area_h_pt, margin_top_page))

            if (margin_top_page > (page_full_available_h * 4 / 5)):
                LOG.debug("NEW PAGE: margin_top_page (%f) > %f" %
                          (margin_top_page, page_full_available_h * 4 / 5))
                self._new_page()
                self._draw_page_stroke()
                self._draw_page_content_stroke()
                margin_top = self.print_bleed_pt + self.margin_top_bottom_pt
                margin_top_page = margin_top
                index_area_h_pt = self.rendering_area_h - self.print_bleed_pt - self.margin_top_bottom_pt - margin_top_page  # full page height available now with this new page.

            city_header_height = 0
            if len(cities) > 1:
                city_header_height = self._draw_page_header(
                    self._i18n.isrtl(),
                    self.ctx,
                    pc,
                    city_layout,
                    UTILS.convert_pt_to_dots(city_fascent, dpi),
                    UTILS.convert_pt_to_dots(cityBlockHeight, dpi),
                    UTILS.convert_pt_to_dots(
                        self.rendering_area_x + self.print_bleed_pt +
                        (self.margin_inside_pt if
                         (self.index_page_num + self.page_offset) %
                         2 else self.margin_outside_pt), dpi),
                    UTILS.convert_pt_to_dots(
                        margin_top_page + header_fascent / 2, dpi
                    ),  # baseline_y, original: self.rendering_area_y + header_fascent
                    margin_top_page,  #margin_top
                    city)
                index_area_h_pt -= city_header_height
                margin_top_page += city_header_height

            # find largest label and location
            max_label_drawing_width = 0.0
            max_location_drawing_width = 0.0

            if False:
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])
                self.index_categories[city].append(
                    self.index_categories[city][0])

            if False:
                # Alle Kategorien, bis auf 1 entfernen
                while len(self.index_categories[city]) > 1:
                    self.index_categories[city].pop(1)

                # Alle Einträge, bis auf 1, dieser Kategorie entferne
                #while len(self.index_categories[city][0].items)>4:
                #    self.index_categories[city][0].items.pop(1)

                # Bei dieser Kategorie weitere Einträge hinzufügen
                for i in range(40):
                    self.index_categories[city][0].items.append(
                        self.index_categories[city][0].items[3])

            # calculate height of categories
            #LOG.debug("number of categories: %d" % len(self.index_categories[city]))
            #LOG.debug("number of entries in first category: %d" % len(self.index_categories[city][0].items))
            sum_height = 0
            for category in self.index_categories[city]:
                sum_height += category.label_drawing_height(header_layout)
                #LOG.debug("adding height %f for category %s" % (category.label_drawing_height(header_layout), category.name))
                for street in category.items:
                    #LOG.debug("label_drawing_height of %s: %f" % (street.label, street.label_drawing_height(label_layout)))
                    sum_height += street.label_drawing_height(label_layout)

                    w = street.label_drawing_width(label_layout)
                    if w > max_label_drawing_width:
                        max_label_drawing_width = w
                        #LOG.debug("new max_label_drawing_width: %f (%s)" % (max_label_drawing_width, street.label))

                    w = street.location_drawing_width(label_layout)
                    if w > max_location_drawing_width:
                        max_location_drawing_width = w
                        #LOG.debug("new max_location_drawing_width: %f (%s)" % (max_location_drawing_width, street.location_str))
            col_max_height = math.ceil(float(sum_height) / 4) + 40
            LOG.debug(
                "sum_height: %f, %f per column (4) => col_max_height: %d" %
                (sum_height, float(sum_height) / 4, col_max_height))

            # No street to render, bail out
            if max_label_drawing_width == 0.0:
                return

            #LOG.debug("max_label_drawing_width: %f" % max_label_drawing_width)
            #LOG.debug("max_location_drawing_width: %f" % max_location_drawing_width)

            # Find best number of columns
            # max_drawing_width = max_label_drawing_width + max_location_drawing_width + 2 * margin
            max_drawing_height = col_max_height
            needed_drawing_height = max_drawing_height
            if (index_area_h_pt < max_drawing_height):
                LOG.debug(
                    "more height neededed (max_drawing_height: %f), than there is available on this page left (index_area_h_pt: %f). Setting max_drawing_height to index_area_h_pt"
                    % (max_drawing_height, index_area_h_pt))
                max_drawing_height = index_area_h_pt

            if Renderer.DEBUG:  # green stroke dash3: show printable page area (after header)
                LOG.debug("Index - printable area (after header): %f x %f" %
                          (index_area_w_pt, max_drawing_height))
                self.ctx.save()
                self.ctx.set_source_rgba(0, 1, 0, .75)
                self.ctx.set_dash([3.0, 3.0], 3.0 / 2.0)
                self.ctx.rectangle(
                    self.print_bleed_pt +
                    (self.margin_inside_pt if
                     (self.index_page_num + self.page_offset) %
                     2 else self.margin_outside_pt), margin_top_page,
                    index_area_w_pt, max_drawing_height)
                self.ctx.stroke()
                self.ctx.restore()

            #LOG.debug("max_drawing_width: %f" % max_drawing_width)

            #columns_count = int(math.ceil(index_area_w_pt / max_drawing_width))
            # following test should not be needed. No time to prove it. ;-)
            #if columns_count == 0:
            #    columns_count = 1

            #LOG.debug("number of columns: %d" % columns_count)

            columns_count = 4  # Gerald: fixed to 4.
            # We have now have several columns
            column_width = index_area_w_pt / columns_count
            #LOG.debug("column_width: %d" % column_width)

            column_layout.set_width(
                int(
                    UTILS.convert_pt_to_dots(
                        (column_width - margin - 5) * Pango.SCALE, dpi)))
            label_layout.set_width(
                int(
                    UTILS.convert_pt_to_dots(
                        (column_width - margin - max_location_drawing_width -
                         2 * label_em) * Pango.SCALE, dpi)))
            header_layout.set_width(
                int(
                    UTILS.convert_pt_to_dots(
                        (column_width - margin) * Pango.SCALE, dpi)))

            if not self._i18n.isrtl():
                orig_offset_x = offset_x = margin / 2.
                orig_delta_x = delta_x = column_width
            else:
                orig_offset_x = offset_x = index_area_w_pt - column_width + margin / 2.
                orig_delta_x = delta_x = -column_width

            actual_n_cols = 0

            # page number of first page
            self._draw_page_number()

            if Renderer.DEBUG:  # light pink stroke dash 4: full column
                # temp: show index-area (inside grayed margin)
                LOG.debug(
                    "pink: %f w -> index_area_w_pt, %f h -> index_area_h_pt" %
                    (index_area_w_pt, index_area_h_pt))
                self.ctx.save()
                self.ctx.set_source_rgba(.85, .25, .85, .75)
                self.ctx.set_dash([4.0, 4.0], 4.0 / 2.0)
                self.ctx.rectangle(
                    self.print_bleed_pt +
                    (self.margin_inside_pt if
                     (self.index_page_num + self.page_offset) %
                     2 else self.margin_outside_pt) +
                    (city_index % 4) * column_width, margin_top_page,
                    column_width, max_drawing_height)
                self.ctx.stroke()
                self.ctx.restore()

            offset_y = margin_top_page  # each city/category starts on the corresponding margin
            for category in self.index_categories[city]:
                if (offset_y + header_fheight + label_fheight + margin / 2. >
                    (max_drawing_height + margin_top_page)):
                    offset_y = margin_top_page
                    offset_x += delta_x
                    actual_n_cols += 1

                    if actual_n_cols == columns_count:
                        self._new_page()
                        self._draw_page_stroke()
                        self._draw_page_content_stroke()
                        actual_n_cols = 0
                        city_header_height = 0  # no city-header on the additional city-pages
                        margin_top_page = margin_top
                        offset_y = margin_top_page
                        offset_x = orig_offset_x
                        delta_x = orig_delta_x
                        max_drawing_height = needed_drawing_height - max_drawing_height + margin_top_page  # OR index_area_h_pt => its a new page, full index_area_h_pt is available now #
                        LOG.debug(
                            "NEW PAGE (before category %s). actual_n_cols == columns_count (%d). needed_drawing_height %d, max_drawing_height %d"
                            % (category.name, columns_count,
                               needed_drawing_height, max_drawing_height))

                        if Renderer.DEBUG:
                            self.ctx.save()
                            self.ctx.set_source_rgba(1, 0, 0, .75)
                            self.ctx.set_dash([8.0, 8.0], 8.0 / 2.0)
                            self.ctx.rectangle(
                                self.rendering_area_x +
                                (self.margin_inside_pt if
                                 (self.index_page_num + self.page_offset) %
                                 2 else self.margin_outside_pt) + offset_x,
                                offset_y, column_width, max_drawing_height)
                            self.ctx.stroke()
                            self.ctx.restore()

                category_height = category.label_drawing_height(header_layout)
                #LOG.debug("category %s, height draw %d | %d | %d | %d" % (category.name, category_height, header_fascent, UTILS.convert_pt_to_dots(header_fascent, dpi), header_fheight))
                category.draw(
                    self._i18n.isrtl(), self.ctx, pc, header_layout,
                    UTILS.convert_pt_to_dots(header_fascent, dpi),
                    UTILS.convert_pt_to_dots(header_fheight, dpi),
                    UTILS.convert_pt_to_dots(
                        self.rendering_area_x +
                        (self.margin_inside_pt if
                         (self.index_page_num + self.page_offset) %
                         2 else self.margin_outside_pt) + offset_x, dpi),
                    UTILS.convert_pt_to_dots(
                        self.rendering_area_y + offset_y + header_fascent,
                        dpi))

                offset_y += category_height

                for street in category.items:
                    label_height = street.label_drawing_height(label_layout)
                    if (offset_y + label_height + margin / 2. >
                        (max_drawing_height + margin_top_page)):
                        offset_y = margin_top_page
                        offset_x += delta_x
                        actual_n_cols += 1

                        if actual_n_cols == columns_count:
                            LOG.debug(
                                "NEW PAGE (before street %s). actual_n_cols %d == columns_count %d"
                                % (street.label, actual_n_cols, columns_count))
                            self._new_page()
                            self._draw_page_stroke()
                            self._draw_page_content_stroke()
                            actual_n_cols = 0
                            city_header_height = 0
                            margin_top_page = margin_top
                            offset_y = margin_top_page
                            offset_x = orig_offset_x
                            delta_x = orig_delta_x
                            max_drawing_height = needed_drawing_height - max_drawing_height + margin_top_page

                            if Renderer.DEBUG:
                                self.ctx.save()
                                self.ctx.set_source_rgba(1, 0, 0, .75)
                                self.ctx.set_dash([8.0, 8.0], 8.0 / 2.0)
                                self.ctx.rectangle(
                                    self.rendering_area_x +
                                    (self.margin_inside_pt if
                                     (self.index_page_num + self.page_offset) %
                                     2 else self.margin_outside_pt) + offset_x,
                                    offset_y, column_width, max_drawing_height)
                                self.ctx.stroke()
                                self.ctx.restore()

                    self.ctx.set_source_rgb(0, 0, 0)

                    if (street.color is None):
                        self.ctx.set_source_rgb(0, 0, 0)
                    else:
                        color = tuple(
                            int(street.color.lstrip('#')[i:i + 2], 16) / 255.
                            for i in (0, 2, 4))

                        # draw colorized rectangle next to street
                        self.ctx.save()
                        self.ctx.set_source_rgb(color[0], color[1], color[2])
                        self.ctx.rectangle(
                            self.rendering_area_x +
                            (self.margin_inside_pt if
                             (self.index_page_num + self.page_offset) %
                             2 else self.margin_outside_pt) + offset_x,
                            self.rendering_area_y + offset_y, 5, label_height)
                        self.ctx.fill()
                        self.ctx.restore()
                        # alternative: colorize street-text:
                        # self.ctx.set_source_rgb(color[0],color[1],color[2])

                    street.draw(
                        self._i18n.isrtl(), self.ctx, pc, column_layout,
                        UTILS.convert_pt_to_dots(label_fascent, dpi),
                        UTILS.convert_pt_to_dots(label_fheight, dpi),
                        UTILS.convert_pt_to_dots(
                            self.rendering_area_x + 5 +
                            (self.margin_inside_pt if
                             (self.index_page_num + self.page_offset) %
                             2 else self.margin_outside_pt) + offset_x, dpi),
                        UTILS.convert_pt_to_dots(
                            self.rendering_area_y + offset_y + label_fascent,
                            dpi), label_layout,
                        UTILS.convert_pt_to_dots(label_height, dpi),
                        UTILS.convert_pt_to_dots(max_location_drawing_width,
                                                 dpi))

                    offset_y += label_height

        self.ctx.restore()
Пример #21
0
    def render_text(self, ctx):
        """ Add legion height to a Cairo surface
        """
        if not self.show_height:
            return
        ctx.identity_matrix()
        ctx.scale\
            ( ctx.get_target().get_width()
            , ctx.get_target().get_height()
            )
        ctx.set_source_rgb(*self.font_bg_color)
        ctx.rectangle\
            ( self.font_fg.location.x
            , self.font_fg.location.y
            , self.font_fg.width
            , self.font_fg.height
            )
        ctx.fill()


        print("-----------------------------------")


        cairo_fontoptions = cairo.FontOptions()
        cairo_fontoptions.set_hint_metrics(cairo.HINT_METRICS_OFF)
        cairo_fontoptions.set_hint_style(cairo.HINT_STYLE_NONE)



        ctx.set_font_options(cairo_fontoptions)
        ctx.identity_matrix()
        pango_context = PangoCairo.create_context(ctx)

        l1 = Pango.Layout(pango_context)
        l1.set_font_description(self.font_description)
        l1.set_text("8",1)
        e1 = l1.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)

        PangoCairo.context_set_resolution(pango_context, 192)
        l1 = Pango.Layout(pango_context)
        l1.set_font_description(self.font_description)
        l1.set_text("8",1)
        e1 = l1.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)

        PangoCairo.context_set_resolution(pango_context, 48)
        l1 = Pango.Layout(pango_context)
        l1.set_font_description(self.font_description)
        l1.set_text("8",1)
        e1 = l1.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)

        PangoCairo.context_set_resolution(pango_context, 5)
        l1 = Pango.Layout(pango_context)
        l1.set_font_description(self.font_description)
        l1.set_text("8",1)
        e1 = l1.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)

        PangoCairo.context_set_resolution(pango_context, 96)
        l1 = Pango.Layout(pango_context)
        l1.set_font_description(self.font_description)
        l1.set_text("8",1)
        e1 = l1.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)


        print("-----------------------------------")


        ctx.set_font_options(cairo_fontoptions)

        ctx.identity_matrix()
        ctx.scale(*(1,)*2)
        layout = PangoCairo.create_layout(ctx)
        layout.set_font_description(self.font_description)
        layout.set_text("8",1)
        e1 = layout.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)

        ctx.identity_matrix()
        ctx.scale(*(10,)*2)
        layout = PangoCairo.create_layout(ctx)
        layout.set_font_description(self.font_description)
        layout.set_text("8",1)
        e1 = layout.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)

        ctx.identity_matrix()
        ctx.scale(*(1/25,)*2)
        layout = PangoCairo.create_layout(ctx)
        layout.set_font_description(self.font_description)
        layout.set_text("8",1)
        e1 = layout.get_extents()[0]
        print(e1.x / Pango.SCALE, e1.y / Pango.SCALE, e1.width / Pango.SCALE, e1.height / Pango.SCALE)


        print("-----------------------------------")


        ctx.identity_matrix()
        pango_context = PangoCairo.create_context(ctx)
        PangoCairo.context_set_resolution(pango_context, self.font_scale * 96)
        #layout = PangoCairo.create_layout(ctx)
        layout = Pango.Layout.new(pango_context)
        layout.set_font_description(self.font_description)
        layout.set_text(str(len(self.legion)), 1)
        #dimensions = get_max_device_ink_size("0123456789", PangoCairo.create_context(ctx))
        #r1 = Rectangle((0,0), dimensions)
        #r1.scale_inscribe(self.font_limits)
        #r1[1:1] = self.font_limits[1:1]
        #print(r1)
        r = layout.get_extents()[0]
        rx = r.x / Pango.SCALE
        ry = r.y / Pango.SCALE
        rw = r.width / Pango.SCALE
        rh = r.height / Pango.SCALE
        print(rx, ry, rw, rh)
        print(self.font_fg, self.font_fg / self.font_scale)
        print(self.font_limits)
        ctx.move_to(self.font_fg.location.x*135, self.font_fg.location.y*135)
        #ctx.scale(self.font_scale, self.font_scale)
        ctx.set_source_rgb(*self.font_fg_color)
        PangoCairo.show_layout(ctx, layout)
Пример #22
0
 def set_canvas(self, canvas):
     G15Text.set_canvas(self, canvas)
     self.__pango_cairo_context = pangocairo.create_context(self.canvas)
Пример #23
0
def renderText( text, font, variation ):
    """Render a unicode text into 32xH image and return a numpy array"""

    #  global stats
    text = choice( leftPaddingChoices ) + text
    #  print("'"+text+"'")
    surface = cairo.ImageSurface(cairo.FORMAT_A8, canvasWidth, imageHeight )
    context = cairo.Context(surface)
    pc = PangoCairo.create_context(context)
    layout = PangoCairo.create_layout(context)
    if( font in fontDescCache ):
        fontDesc = fontDescCache[font]
    else:
        fontDesc = fontDescCache[font] = Pango.font_description_from_string( font )
    layout.set_font_description(Pango.FontDescription( font ))
    layout.set_markup( '<span>' +  text +'</span>', -1 );

    inkRect, _ = layout.get_pixel_extents()
    actualW = inkRect.width; actualH = inkRect.height

    if( variation == VARIATIONS.fit_height ):
        #  stats['fit'] +=1
        #  Fit-height is done by varying font size
        fontDesc = layout.get_font_description()
        fontDesc.set_size( int(fontDesc.get_size() * 0.9 * imageHeight/ actualH ) )
        layout.set_font_description( fontDesc )
        inkRect, _ = layout.get_pixel_extents()
        actualW = inkRect.width; actualH = inkRect.height
    elif( variation ==  VARIATIONS.random):
        #  stats['tw'] +=1
        # Random alignment means random rotation
        twist = choice( TWIST_CHOICES )
        context.rotate( twist * math.atan( ( imageHeight - actualH  )/ actualW  ) )
        if twist < 0:
            context.translate(0, imageHeight - actualH )
    elif( variation == VARIATIONS.alighn_top ):
        #  stats['top'] +=1
        context.translate(0, -2)
        # Random alignment means random rotation
        #  context.translate(0, imageHeight - actualH )
    elif( variation == VARIATIONS.alighn_bottom ):
        #  stats['bot'] +=1
        # Random alignment means random rotation
        context.translate(0, imageHeight - actualH )



    PangoCairo.show_layout(context, layout)
    data = surface.get_data()
    #  import ipdb; ipdb.set_trace()

    if( actualW > targetW ):
        #  print(' actualW > targetW ')
        #  Resize image by shrinking the width of image
        data = np.frombuffer(data, dtype=np.uint8).reshape(( imageHeight, canvasWidth ))[:, :actualW + 10]
        data = Image.fromarray( data ).resize( ( targetW, imageHeight ), Image.BILINEAR )
        data = np.array( data )
    else:
        data = np.frombuffer(data, dtype=np.uint8).reshape(( imageHeight, canvasWidth ))[:, :targetW]

    data = np.invert( data ) # becuase pango will render white text on black
    bg = choice( bgChoices )
    data = (data*bg).astype( np.uint8 )

    # Add create a noise layer and merge with image
    ncc = choice(noiseSDChoices)
    #  ncc = noiseSDChoices[ i % len( noiseSDChoices )  ]
    #  print( ncc )
    data = np.clip( data - random.normal(  *ncc, data.shape ), 0, 255 ).astype(np.uint8)
    #  import ipdb; ipdb.set_trace()
    #  data = np.clip( data - random.multivariate_normal( [ ncc[0] ], [[ ncc[1]]], data.shape ).squeeze(), 0, 255 ).astype(np.uint8)
    return data
Пример #24
0
    def do_tool_operation(self, operation):
        cairo_context = self.start_tool_operation(operation)

        font_fam = operation['font_fam']
        font_size = operation['font_size'] * 2
        entire_text = operation['text']
        background_color = operation['rgba2']
        text_x = operation['x']
        text_y = operation['y']

        font_description_string = font_fam
        if operation['is_italic']:
            font_description_string += " Italic"
        if operation['is_bold']:
            font_description_string += " Bold"
        font_description_string += " " + str(font_size)
        font = Pango.FontDescription(font_description_string)

        p_context = PangoCairo.create_context(cairo_context)
        layout = Pango.Layout(p_context)
        layout.set_font_description(font)

        if not operation['antialias']:
            font_options = cairo.FontOptions()
            font_options.set_antialias(cairo.Antialias.NONE)
            font_options.set_hint_metrics(cairo.HintMetrics.OFF)
            font_options.set_hint_style(cairo.HintStyle.FULL)
            PangoCairo.context_set_font_options(p_context, font_options)

        ########################################################################
        # Draw background ######################################################

        if operation['background'] == 'rectangle':
            lines = entire_text.split('\n')
            line_y = text_y
            for line_text in lines:
                line_y = self._op_bg_rectangle(cairo_context, layout, \
                                    background_color, text_x, line_y, line_text)
        elif operation['background'] == 'shadow':
            dist = max(min(int(font_size / 16), 4), 1)
            cairo_context.set_source_rgba(*background_color)
            self._show_text_at_coords(cairo_context, layout, entire_text, \
                                                   text_x + dist, text_y + dist)
        elif operation['background'] == 'thin-outline':
            cairo_context.set_source_rgba(*background_color)
            dist = min(int(font_size / 16), 10)
            dist = max(dist, 2)
            for dx in range(-dist, dist):
                for dy in range(-dist, dist):
                    if abs(dx) + abs(dy) <= dist * 1.5:
                        self._show_text_at_coords(cairo_context, layout, \
                                          entire_text, text_x + dx, text_y + dy)
            # these `for`s and this `if` should outline with an octogonal shape,
            # which is close enough to a smooth round outline imho.
        elif operation['background'] == 'thick-outline':
            cairo_context.set_source_rgba(*background_color)
            dist = int(font_size / 10)
            dist = max(dist, 2)
            for dx in range(-dist, dist):
                for dy in range(-dist, dist):
                    if abs(dx) + abs(dy) <= dist * 1.5:
                        self._show_text_at_coords(cairo_context, layout, \
                                          entire_text, text_x + dx, text_y + dy)
            # looks better, but so much computation for bullshit...

        ########################################################################
        # Draw text ############################################################

        cairo_context.set_source_rgba(*operation['rgba1'])
        self._show_text_at_coords(cairo_context, layout, entire_text, \
                                                                 text_x, text_y)

        self.non_destructive_show_modif()
Пример #25
0
    def render(self, ctx, p_rendering_area, dpi=UTILS.PT_PER_INCH):
        """
        Render the street and amenities index at the given (x,y)
        coordinates into the provided Cairo surface. The index must
        not be larger than the provided surface (use
        precompute_occupation_area() to adjust it).

        Args:
            ctx (cairo.Context): the cairo context to use for the rendering.
            rendering_area (IndexRenderingArea): the result from
                precompute_occupation_area().
            dpi (number): resolution of the target device.
        """

        rendering_area = p_rendering_area
        rendering_area.x = rendering_area.x + 1
        rendering_area.y = rendering_area.y + 1
        rendering_area.w = rendering_area.w - 2
        rendering_area.h = rendering_area.h - 2

        if not self._index_categories:
            raise commons.IndexEmptyError

        LOG.debug("Rendering the street index within %s at %sdpi..." %
                  (rendering_area, dpi))

        ##
        ## In the following, the algorithm only manipulates values
        ## expressed in 'pt'. Only the drawing-related functions will
        ## translate them to cairo units
        ##

        ctx.save()
        ctx.move_to(UTILS.convert_pt_to_dots(rendering_area.x, dpi),
                    UTILS.convert_pt_to_dots(rendering_area.y, dpi))

        # Create a PangoCairo context for drawing to Cairo
        pc = PangoCairo.create_context(ctx)

        header_fd = Pango.FontDescription(
            rendering_area.rendering_style.header_font_spec)
        label_fd = Pango.FontDescription(
            rendering_area.rendering_style.label_font_spec)

        header_layout, header_fascent, header_fheight, header_em = \
                draw_utils.create_layout_with_font(ctx, header_fd)
        label_layout, label_fascent, label_fheight, label_em = \
                draw_utils.create_layout_with_font(ctx, label_fd)

        #print "RENDER", header_layout, header_fascent, header_fheight, header_em
        #print "RENDER", label_layout, label_fascent, label_fheight, label_em

        # By OCitysmap's convention, the default resolution is 72 dpi,
        # which maps to the default pangocairo resolution (96 dpi
        # according to pangocairo docs). If we want to render with
        # another resolution (different from 72), we have to scale the
        # pangocairo resolution accordingly:
        PangoCairo.context_set_resolution(label_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        PangoCairo.context_set_resolution(header_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        # All this is because we want pango to have the exact same
        # behavior as with the default 72dpi resolution. If we instead
        # decided to call cairo::scale, then pango might choose
        # different font metrics which don't fit in the prepared
        # layout anymore...

        margin = label_em
        column_width = int(rendering_area.w / rendering_area.n_cols)

        label_layout.set_width(
            int(
                UTILS.convert_pt_to_dots((column_width - margin) * Pango.SCALE,
                                         dpi)))
        header_layout.set_width(
            int(
                UTILS.convert_pt_to_dots((column_width - margin) * Pango.SCALE,
                                         dpi)))

        if not self._i18n.isrtl():
            offset_x = margin / 2.
            delta_x = column_width
        else:
            offset_x = rendering_area.w - column_width + margin / 2.
            delta_x = -column_width

        actual_n_cols = 1
        offset_y = margin / 2.
        for category in self._index_categories:
            if (offset_y + header_fheight + label_fheight + margin / 2. >
                    rendering_area.h):
                offset_y = margin / 2.
                offset_x += delta_x
                actual_n_cols += 1

            height = category.draw(
                self._i18n.isrtl(), ctx, pc, header_layout,
                UTILS.convert_pt_to_dots(header_fascent, dpi),
                UTILS.convert_pt_to_dots(header_fheight, dpi),
                UTILS.convert_pt_to_dots(rendering_area.x + offset_x, dpi),
                UTILS.convert_pt_to_dots(
                    rendering_area.y + offset_y + header_fascent, dpi))

            offset_y += height * 72.0 / dpi

            for street in category.items:
                if (offset_y + label_fheight + margin / 2. > rendering_area.h):
                    offset_y = margin / 2.
                    offset_x += delta_x
                    actual_n_cols += 1

                street.draw(
                    self._i18n.isrtl(), ctx, pc, label_layout,
                    UTILS.convert_pt_to_dots(label_fascent, dpi),
                    UTILS.convert_pt_to_dots(label_fheight, dpi),
                    UTILS.convert_pt_to_dots(rendering_area.x + offset_x, dpi),
                    UTILS.convert_pt_to_dots(
                        rendering_area.y + offset_y + label_fascent, dpi))

                offset_y += label_fheight

        # Restore original context
        ctx.restore()

        # Simple verification...
        if actual_n_cols < rendering_area.n_cols:
            LOG.warning(
                "Rounding/security margin lost some space (%d actual cols vs. allocated %d"
                % (actual_n_cols, rendering_area.n_cols))
        if actual_n_cols > rendering_area.n_cols:
            LOG.warning(
                "Rounding/security margin used more space (%d actual cols vs. allocated %d"
                % (actual_n_cols, rendering_area.n_cols))
Пример #26
0
    def render(self, dpi=UTILS.PT_PER_INCH):
        self.ctx.save()

        # Create a PangoCairo context for drawing to Cairo
        pc = PangoCairo.create_context(self.ctx)

        header_fd = Pango.FontDescription("Georgia Bold 12")
        label_column_fd = Pango.FontDescription("DejaVu 6")

        header_layout, header_fascent, header_fheight, header_em = \
            self._create_layout_with_font(self.ctx, pc, header_fd)
        label_layout, label_fascent, label_fheight, label_em = \
            self._create_layout_with_font(self.ctx, pc, label_column_fd)
        column_layout, _, _, _ = \
            self._create_layout_with_font(self.ctx, pc, label_column_fd)

        # By OCitysmap's convention, the default resolution is 72 dpi,
        # which maps to the default pangocairo resolution (96 dpi
        # according to pangocairo docs). If we want to render with
        # another resolution (different from 72), we have to scale the
        # pangocairo resolution accordingly:
        PangoCairo.context_set_resolution(column_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        PangoCairo.context_set_resolution(label_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)
        PangoCairo.context_set_resolution(header_layout.get_context(),
                                          96. * dpi / UTILS.PT_PER_INCH)

        margin = label_em

        # find largest label and location
        max_label_drawing_width = 0.0
        max_location_drawing_width = 0.0
        for category in self.index_categories:
            for street in category.items:
                w = street.label_drawing_width(label_layout)
                if w > max_label_drawing_width:
                    max_label_drawing_width = w

                w = street.location_drawing_width(label_layout)
                if w > max_location_drawing_width:
                    max_location_drawing_width = w

        # No street to render, bail out
        if max_label_drawing_width == 0.0:
            return

        # Find best number of columns
        max_drawing_width = \
            max_label_drawing_width + max_location_drawing_width + 2 * margin
        max_drawing_height = self.rendering_area_h - PAGE_NUMBER_MARGIN_PT

        columns_count = int(
            math.ceil(self.rendering_area_w / max_drawing_width))
        # following test should not be needed. No time to prove it. ;-)
        if columns_count == 0:
            columns_count = 1

        # We have now have several columns
        column_width = self.rendering_area_w / columns_count

        column_layout.set_width(
            int(
                UTILS.convert_pt_to_dots((column_width - margin) * Pango.SCALE,
                                         dpi)))
        label_layout.set_width(
            int(
                UTILS.convert_pt_to_dots(
                    (column_width - margin - max_location_drawing_width -
                     2 * label_em) * Pango.SCALE, dpi)))
        header_layout.set_width(
            int(
                UTILS.convert_pt_to_dots((column_width - margin) * Pango.SCALE,
                                         dpi)))

        if not self._i18n.isrtl():
            orig_offset_x = offset_x = margin / 2.
            orig_delta_x = delta_x = column_width
        else:
            orig_offset_x = offset_x = \
                self.rendering_area_w - column_width + margin/2.
            orig_delta_x = delta_x = -column_width

        actual_n_cols = 0
        offset_y = margin / 2.

        # page number of first page
        self._draw_page_number()

        for category in self.index_categories:
            if (offset_y + header_fheight + label_fheight + margin / 2. >
                    max_drawing_height):
                offset_y = margin / 2.
                offset_x += delta_x
                actual_n_cols += 1

                if actual_n_cols == columns_count:
                    self._new_page()
                    actual_n_cols = 0
                    offset_y = margin / 2.
                    offset_x = orig_offset_x
                    delta_x = orig_delta_x

            category.draw(
                self._i18n.isrtl(), self.ctx, pc, header_layout,
                UTILS.convert_pt_to_dots(header_fascent, dpi),
                UTILS.convert_pt_to_dots(header_fheight, dpi),
                UTILS.convert_pt_to_dots(self.rendering_area_x + offset_x,
                                         dpi),
                UTILS.convert_pt_to_dots(
                    self.rendering_area_y + offset_y + header_fascent, dpi))

            offset_y += header_fheight

            for street in category.items:
                label_height = street.label_drawing_height(label_layout)
                if (offset_y + label_height + margin / 2. >
                        max_drawing_height):
                    offset_y = margin / 2.
                    offset_x += delta_x
                    actual_n_cols += 1

                    if actual_n_cols == columns_count:
                        self._new_page()
                        actual_n_cols = 0
                        offset_y = margin / 2.
                        offset_x = orig_offset_x
                        delta_x = orig_delta_x

                street.draw(
                    self._i18n.isrtl(), self.ctx, pc, column_layout,
                    UTILS.convert_pt_to_dots(label_fascent, dpi),
                    UTILS.convert_pt_to_dots(label_fheight, dpi),
                    UTILS.convert_pt_to_dots(self.rendering_area_x + offset_x,
                                             dpi),
                    UTILS.convert_pt_to_dots(
                        self.rendering_area_y + offset_y + label_fascent, dpi),
                    label_layout, UTILS.convert_pt_to_dots(label_height, dpi),
                    UTILS.convert_pt_to_dots(max_location_drawing_width, dpi))

                offset_y += label_height

        self.ctx.restore()
Пример #27
0
    def _draw_copyright_notice(self, ctx, w_dots, h_dots, notice=None,
                               osm_date=None):
        """
        Draw a copyright notice at current location and within the
        given w_dots*h_dots rectangle.

        Args:
           ctx (cairo.Context): The Cairo context to use to draw.
           w_dots,h_dots (number): Rectangle dimension (ciaro units).
           font_face (str): Pango font specification.
           notice (str): Optional notice to replace the default.
        """

        today = datetime.date.today()
        if notice is None: 
            notice = _(u'Copyright © %(year)d MapOSMatic/OCitySMap developers.')
            notice+= ' '
            notice+= _(u'Map data © %(year)d OpenStreetMap contributors (see http://osm.org/copyright)')
            notice+= '\n'

            annotations = []
            if self.rc.stylesheet.annotation != '':
                annotations.append(self.rc.stylesheet.annotation)
            for overlay in self._overlays:
                if overlay.annotation != '':
                    annotations.append(overlay.annotation)
            if len(annotations) > 0:
                notice+= _(u'Map styles:')
                notice+= ' ' + '; '.join(annotations) + '\n'

            datasources = set()
            if self.rc.stylesheet.datasource != '':
                datasources.add(self.rc.stylesheet.datasource)
            for overlay in self._overlays:
                if overlay.datasource != '':
                    datasources.add(overlay.datasource)
            if len(datasources) > 0:
                notice+= _(u'Additional data sources:')
                notice+= ' ' + '; '.join(list(datasources)) + '\n'

            notice+= _(u'Map rendered on: %(date)s. OSM data updated on: %(osmdate)s.')
            notice+= ' '
            notice+= _(u'The map may be incomplete or inaccurate.')

        # We need the correct locale to be set for strftime().
        prev_locale = locale.getlocale(locale.LC_TIME)
        try:
            locale.setlocale(locale.LC_TIME, self.rc.i18n.language_code())
        except Exception:
            LOG.warning('error while setting LC_COLLATE to "%s"' % self.rc.i18n.language_code())

        try:
            if osm_date is None:
                osm_date_str = _(u'unknown')
            else:
                osm_date_str = osm_date.strftime("%d %B %Y %H:%M")

            notice = notice % {'year': today.year,
                               'date': today.strftime("%d %B %Y"),
                               'osmdate': osm_date_str}
        finally:
            locale.setlocale(locale.LC_TIME, prev_locale)

        ctx.save()
        pc = PangoCairo.create_context(ctx)
        fd = Pango.FontDescription('DejaVu')
        fd.set_size(Pango.SCALE)
        layout = PangoCairo.create_layout(ctx)
        layout.set_font_description(fd)
        layout.set_text(notice, -1)
        draw_utils.adjust_font_size(layout, fd, w_dots, h_dots)
        PangoCairo.update_layout(ctx, layout)
        PangoCairo.show_layout(ctx, layout)
        ctx.restore()
Пример #28
0
    def _draw_title(self, ctx, w_dots, h_dots, font_face):
        """
        Draw the title at the current position inside a
        w_dots*h_dots rectangle.

        Args:
           ctx (cairo.Context): The Cairo context to use to draw.
           w_dots,h_dots (number): Rectangle dimension (ciaro units)
           font_face (str): Pango font specification.
        """

        # Title background
        ctx.save()
        ctx.set_source_rgb(0.8, 0.9, 0.96) # TODO: make title bar color configurable?
        ctx.rectangle(0, 0, w_dots, h_dots)
        ctx.fill()
        ctx.restore()

        # Retrieve and paint the OSM logo
        ctx.save()
        grp, logo_width = self._get_osm_logo(ctx, 0.8*h_dots)
        if grp:
            ctx.translate(w_dots - logo_width - 0.1*h_dots, 0.1*h_dots)
            ctx.set_source(grp)
            ctx.paint_with_alpha(0.5)
        else:
            LOG.warning("OSM Logo not available.")
            logo_width = 0
        ctx.restore()

        # Retrieve and paint the extra logo
        # TODO: 
        logo_width2 = 0
        if self.rc.poi_file:
            ctx.save()
            grp, logo_width2 = self._get_extra_logo(ctx, 0.8*h_dots)
            if grp:
                ctx.translate(0.4*h_dots, 0.1*h_dots)
                ctx.set_source(grp)
                ctx.paint_with_alpha(0.5)
                logo_width2 += 0.4*h_dots
            else:
                LOG.warning("Extra Logo not available.")
                logo_width2 = 0
            ctx.restore()

        # Prepare the title
        pc = PangoCairo.create_context(ctx)
        layout = PangoCairo.create_layout(ctx)
        layout.set_width(int((w_dots - 0.1*w_dots - logo_width - logo_width2) * Pango.SCALE))
        if not self.rc.i18n.isrtl():
            layout.set_alignment(Pango.Alignment.LEFT)
        else:
            layout.set_alignment(Pango.Alignment.RIGHT)
        fd = Pango.FontDescription(font_face)
        fd.set_size(Pango.SCALE)
        layout.set_font_description(fd)
        layout.set_text(self.rc.title, -1)
        draw_utils.adjust_font_size(layout, fd, layout.get_width(), 0.8*h_dots)

        # Draw the title
        ctx.save()
        ctx.set_line_width(1)
        ctx.rectangle(0, 0, w_dots, h_dots)
        ctx.stroke()
        ctx.translate(0.4*h_dots + logo_width2,
                      (h_dots -
                       (layout.get_size()[1] / Pango.SCALE)) / 2.0)
        PangoCairo.update_layout(ctx, layout)
        PangoCairo.show_layout(ctx, layout)
        ctx.restore()
Пример #29
0
                self.location_str = "%d, %s" % (self.page_number,
                                                self.location_str)





if __name__ == "__main__":
    import cairo
    gi.require_version('PangoCairo', '1.0')
    from gi.repository import PangoCairo

    surface = cairo.PDFSurface('/tmp/idx_commons.pdf', 1000, 1000)

    ctx = cairo.Context(surface)
    pc = PangoCairo.create_context(ctx)

    font_desc = Pango.FontDescription('DejaVu')
    font_desc.set_size(12 * Pango.SCALE)

    layout = PangoCairo.create_layout(ctx)
    layout.set_font_description(font_desc)
    layout.set_width(200 * Pango.SCALE)

    font = layout.get_context().load_font(font_desc)
    font_metric = font.get_metrics()

    fascent = font_metric.get_ascent() / Pango.SCALE
    fheight = ((font_metric.get_ascent() + font_metric.get_descent())
               / Pango.SCALE)
Пример #30
0
    def precompute_occupation_area(self, surface, x, y, w, h,
                                   freedom_direction, alignment):
        """Prepare to render the street and amenities index at the
        given (x,y) coordinates into the provided Cairo surface. The
        index must not be larger than the provided width and height
        (in pixels). Nothing will be drawn on surface.

        Parameters
        ----------
            surface : cairo.Surface
                The cairo surface to render into.
            x : int
                Horizontal origin position, in pixels.
            y : int
                Vertical origin position, in pixels.
            w : int
                Maximum usable width for the index, in dots (Cairo unit).
            h : int
                Maximum usable height for the index, in dots (Cairo unit).
            freedom_direction : str
                 Freedom direction, can be 'width' or
                'height'. See _compute_columns_split for more details.
            alignment : str
                'top' or 'bottom' for a freedom_direction of
                'height', 'left' or 'right' for 'width'.
                Tells which side to stick the index to.

        Returns
        -------
        Returns the actual graphical IndexRenderingArea defining
        how and where the index should be rendered. Raise
        IndexDoesNotFitError when the provided area's surface is not
        enough to hold the index.
        """
        if ((freedom_direction == 'height'
             and alignment not in ('top', 'bottom'))
                or (freedom_direction == 'width'
                    and alignment not in ('left', 'right'))):
            raise ValueError('Incompatible freedom direction and alignment!')

        if not self._index_categories:
            raise commons.IndexEmptyError

        LOG.debug(
            "Determining index area within %dx%d+%d+%d aligned %s/%s..." %
            (w, h, x, y, alignment, freedom_direction))

        # Create a PangoCairo context for drawing to Cairo
        ctx = cairo.Context(surface)
        pc = PangoCairo.create_context(ctx)

        # Iterate over the rendering_styles until we find a suitable layout
        rendering_style = None
        for rs in self._rendering_styles:
            LOG.debug("Trying index fit using %s..." % rs)
            try:
                n_cols, min_dimension \
                    = self._compute_columns_split(ctx, pc, rs, w, h,
                                                  freedom_direction)

                # Great: index did fit OK !
                rendering_style = rs
                break

            except IndexDoesNotFitError:
                # Index did not fit => try smaller...
                LOG.debug("Index %s too large: should try a smaller one." % rs)
                continue

        # Index really did not fit with any of the rendering styles ?
        if not rendering_style:
            raise IndexDoesNotFitError("Index does not fit in area")

        # Realign at bottom/top left/right
        if freedom_direction == 'height':
            index_width = w
            index_height = min_dimension
        elif freedom_direction == 'width':
            index_width = min_dimension
            index_height = h

        base_offset_x = 0
        base_offset_y = 0
        if alignment == 'bottom':
            base_offset_y = h - index_height
        if alignment == 'right':
            base_offset_x = w - index_width

        area = IndexRenderingArea(rendering_style, x + base_offset_x,
                                  y + base_offset_y, index_width, index_height,
                                  n_cols)
        LOG.debug("Will be able to render index in %s" % area)
        return area