示例#1
0
def render_page_number(ctx, page_number,
                       usable_area_width_pt, usable_area_height_pt, margin_pt,
                       transparent_background = True):
    """
    Render page number
    """
    ctx.save()
    x_offset = 0
    if page_number % 2:
        x_offset += commons.convert_pt_to_dots(usable_area_width_pt)\
                  - commons.convert_pt_to_dots(margin_pt)
    y_offset = commons.convert_pt_to_dots(usable_area_height_pt)\
             - commons.convert_pt_to_dots(margin_pt)
    ctx.translate(x_offset, y_offset)

    if transparent_background:
        ctx.set_source_rgba(1, 1, 1, 0.6)
    else:
        ctx.set_source_rgba(0.8, 0.8, 0.8, 0.6)
    ctx.rectangle(0, 0, commons.convert_pt_to_dots(margin_pt),
                  commons.convert_pt_to_dots(margin_pt))
    ctx.fill()

    ctx.set_source_rgba(0, 0, 0, 1)
    x_offset = commons.convert_pt_to_dots(margin_pt)/2
    y_offset = commons.convert_pt_to_dots(margin_pt)/2
    ctx.translate(x_offset, y_offset)
    draw_simpletext_center(ctx, unicode(page_number), 0, 0)
    ctx.restore()
示例#2
0
    def render(self, ctx, 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 (StreetIndexRenderingArea): the result from
                precompute_occupation_area().
            dpi (number): resolution of the target device.
        """

        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.CairoContext(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 = \
                self._create_layout_with_font(pc, header_fd)
        label_layout, label_fascent, label_fheight, label_em = \
                self._create_layout_with_font(pc, 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

            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 += header_fheight

            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))
        assert actual_n_cols <= rendering_area.n_cols
示例#3
0
    def render(self, dpi = UTILS.PT_PER_INCH):
        self.ctx.save()

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

        header_fd = pango.FontDescription("Georgia Bold 12")
        label_column_fd  = pango.FontDescription("DejaVu 8")

        header_layout, header_fascent, header_fheight, header_em = \
            self._create_layout_with_font(pc, header_fd)
        label_layout, label_fascent, label_fheight, label_em = \
            self._create_layout_with_font(pc, label_column_fd)
        column_layout, _, _, _ = \
            self._create_layout_with_font(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()