Пример #1
0
 def do_draw(self, gpsmap, ctx):
     """
     Draw all the messages
     """
     ctx.save()
     #font_size = "%s %d" % (self.font, self.size)
     #font = Pango.FontDescription(font_size)
     descr = Pango.font_description_from_string(self.font)
     descr.set_size(self.size * Pango.SCALE)
     color = Gdk.color_parse(self.color)
     ctx.set_source_rgba(float(color.red / 65535.0),
                         float(color.green / 65535.0),
                         float(color.blue / 65535.0), 0.9)  # transparency
     d_width = gpsmap.get_allocation().width
     d_width -= 100
     ctx.restore()
     ctx.save()
     ctx.move_to(100, 5)
     layout = PangoCairo.create_layout(ctx)
     if is_quartz():
         PangoCairo.context_set_resolution(layout.get_context(), 72)
     layout.set_font_description(descr)
     layout.set_indent(Pango.SCALE * 0)
     layout.set_alignment(Pango.Alignment.LEFT)
     layout.set_wrap(Pango.WrapMode.WORD_CHAR)
     layout.set_spacing(Pango.SCALE * 3)
     layout.set_width(d_width * Pango.SCALE)
     layout.set_text(self.message, -1)
     PangoCairo.show_layout(ctx, layout)
     ctx.restore()
     ctx.stroke()
Пример #2
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
Пример #3
0
    def snapshot(self,
                 snapshot: Gtk.Snapshot,
                 bounds: Graphene.Rect,
                 fgcolor: Gdk.RGBA, scale: float):
        if (self._cached_texture_scale < scale
                or not self._fgcolor.equal(fgcolor)):
            PangoCairo.context_set_resolution(
                _text_texture_pango_ctx, 96 * scale)
            layout = Pango.Layout.new(_text_texture_pango_ctx)
            layout.set_text(self._text)
            layout.set_font_description(FONT_NORMAL)
            layout_width, layout_height = layout.get_pixel_size()

            scaled_w = int(WIDTH * scale)
            scaled_h = int(HEIGHT * scale)

            cr = cairo.ImageSurface(
                cairo.Format.ARGB32,
                scaled_w, scaled_h)
            ctx = cairo.Context(cr)
            Gdk.cairo_set_source_rgba(ctx, fgcolor)

            x = int(scaled_w / 2 - layout_width / 2)
            y = int(scaled_h / 2 - layout_height / 2)
            ctx.move_to(x, y)

            PangoCairo.show_layout(ctx, layout)

            pixbuf = Gdk.pixbuf_get_from_surface(
                cr, 0, 0, scaled_w, scaled_h)

            del self._cached_texture
            self._cached_texture = Gdk.Texture.new_for_pixbuf(pixbuf)
            self._cached_texture_scale = scale
            self._fgcolor = fgcolor

        snapshot.append_texture(self._cached_texture, bounds)
Пример #4
0
    def run(self):
        """Create the output file.
        The derived class overrides EXT and create_cairo_surface
        """
        # get paper dimensions
        paper_width = self.paper.get_size().get_width() * DPI / 2.54
        paper_height = self.paper.get_size().get_height() * DPI / 2.54
        page_width = round(self.paper.get_usable_width() * DPI / 2.54)
        page_height = round(self.paper.get_usable_height() * DPI / 2.54)
        left_margin = self.paper.get_left_margin() * DPI / 2.54
        top_margin = self.paper.get_top_margin() * DPI / 2.54

        # create cairo context and pango layout
        filename = self._backend.filename
        # Cairo can't reliably handle unicode filenames on Linux or
        # Windows, so open the file for it.
        with open(filename, 'wb') as fd:
            try:
                surface = self.create_cairo_surface(fd, paper_width,
                                                    paper_height)
                surface.set_fallback_resolution(300, 300)
                cr = cairo.Context(surface)
                fontmap = PangoCairo.font_map_new()
                fontmap.set_resolution(DPI)
                pango_context = fontmap.create_context()
                options = cairo.FontOptions()
                options.set_hint_metrics(cairo.HINT_METRICS_OFF)
                if is_quartz():
                    PangoCairo.context_set_resolution(pango_context, 72)
                PangoCairo.context_set_font_options(pango_context, options)
                layout = Pango.Layout(pango_context)
                PangoCairo.update_context(cr, pango_context)
                # paginate the document
                self.paginate_document(layout, page_width, page_height, DPI,
                                       DPI)
                body_pages = self._pages

                # build the table of contents and alphabetical index
                toc_page = None
                index_page = None
                toc = []
                index = {}
                for page_nr, page in enumerate(body_pages):
                    if page.has_toc():
                        toc_page = page_nr
                    if page.has_index():
                        index_page = page_nr
                    for mark in page.get_marks():
                        if mark.type == INDEX_TYPE_ALP:
                            if mark.key in index:
                                if page_nr + 1 not in index[mark.key]:
                                    index[mark.key].append(page_nr + 1)
                            else:
                                index[mark.key] = [page_nr + 1]
                        elif mark.type == INDEX_TYPE_TOC:
                            toc.append([mark, page_nr + 1])

                # paginate the table of contents
                rebuild_required = False
                if toc_page is not None:
                    toc_pages = self.__generate_toc(layout, page_width,
                                                    page_height, toc)
                    offset = len(toc_pages) - 1
                    if offset > 0:
                        self.__increment_pages(toc, index, toc_page, offset)
                        rebuild_required = True
                    if index_page and toc_page < index_page:
                        index_page += offset
                else:
                    toc_pages = []

                # paginate the index
                if index_page is not None:
                    index_pages = self.__generate_index(
                        layout, page_width, page_height, index)
                    offset = len(index_pages) - 1
                    if offset > 0:
                        self.__increment_pages(toc, index, index_page, offset)
                        rebuild_required = True
                    if toc_page and toc_page > index_page:
                        toc_page += offset
                else:
                    index_pages = []

                # rebuild the table of contents and index if required
                if rebuild_required:
                    if toc_page is not None:
                        toc_pages = self.__generate_toc(
                            layout, page_width, page_height, toc)
                    if index_page is not None:
                        index_pages = self.__generate_index(
                            layout, page_width, page_height, index)

                # render the pages
                if toc_page is not None:
                    body_pages = body_pages[:toc_page] + toc_pages + \
                                 body_pages[toc_page+1:]
                if index_page is not None:
                    body_pages = body_pages[:index_page] + index_pages + \
                                 body_pages[index_page+1:]
                self._pages = body_pages
                for page_nr, page in enumerate(self._pages):
                    cr.save()
                    cr.translate(left_margin, top_margin)
                    self.draw_page(page_nr, cr, layout, page_width,
                                   page_height, DPI, DPI)
                    cr.show_page()
                    cr.restore()

                # close the surface (file)
                surface.finish()

            except IOError as msg:
                errmsg = "%s\n%s" % (_("Could not create %s") % filename, msg)
                raise ReportError(errmsg)
            except Exception as err:
                errmsg = "%s\n%s" % (_("Could not create %s") % filename, err)
                raise ReportError(errmsg)
    def on_draw(self, widget, cr):

        layout = PangoCairo.create_layout(cr)
        if is_quartz():
            PangoCairo.context_set_resolution(layout.get_context(), 72)
        layout.set_font_description(self.get_style().font_desc)
        layout.set_markup(TEXT, -1)

        fontw, fonth = layout.get_pixel_size()
        xmin = fontw + BORDER_WIDTH
        ymin = fonth + BORDER_WIDTH
        self.set_size_request(xmin, ymin)

        # time

        hours = time.localtime().tm_hour
        minutes = time.localtime().tm_min
        secs = time.localtime().tm_sec
        second_arc = (2 * math.pi / 60) * secs
        minute_arc = (2 * math.pi / 60) * minutes
        if hours > 12:
            hours = hours - 12
        hour_arc = (2 * math.pi / 12) * hours + minute_arc / 12

        # clock background

        alloc = self.get_allocation()
        x = alloc.x
        y = alloc.y
        w = alloc.width
        h = alloc.height
        cr.set_source_rgba(1, 0.2, 0.2, 0.6)
        cr.arc(w / 2, h / 2, min(w, h) / 2 - 8, 0, 2 * 3.14)
        cr.fill()
        cr.stroke()

        # center arc

        cr.set_source_rgb(0, 0, 0)
        cr.arc(w / 2, h / 2, (min(w, h) / 2 - 20) / 5, 0, 2 * math.pi)
        cr.fill()
        cr.line_to(w / 2, h / 2)
        cr.stroke()

        # pointer hour

        cr.set_source_rgba(0.5, 0.5, 0.5, 0.5)
        cr.set_line_width((min(w, h) / 2 - 20) / 6)
        cr.move_to(w / 2, h / 2)
        cr.line_to(
            w / 2 +
            (min(w, h) / 2 - 20) * 0.6 * math.cos(hour_arc - math.pi / 2),
            h / 2 +
            (min(w, h) / 2 - 20) * 0.6 * math.sin(hour_arc - math.pi / 2))
        cr.stroke()

        # pointer minute

        cr.set_source_rgba(0.5, 0.5, 0.5, 0.5)
        cr.set_line_width((min(w, h) / 2 - 20) / 6 * 0.8)
        cr.move_to(w / 2, h / 2)
        cr.line_to(
            w / 2 +
            (min(w, h) / 2 - 20) * 0.8 * math.cos(minute_arc - math.pi / 2),
            h / 2 +
            (min(w, h) / 2 - 20) * 0.8 * math.sin(minute_arc - math.pi / 2))
        cr.stroke()

        # pointer second

        cr.set_source_rgba(0.5, 0.5, 0.5, 0.5)
        cr.set_line_width((min(w, h) / 2 - 20) / 6 * 0.4)
        cr.move_to(w / 2, h / 2)
        cr.line_to(
            w / 2 + (min(w, h) / 2 - 20) * math.cos(second_arc - math.pi / 2),
            h / 2 + (min(w, h) / 2 - 20) * math.sin(second_arc - math.pi / 2))
        cr.stroke()

        # pango layout

        cr.move_to((w - fontw - 4), (h - fonth))
        PangoCairo.show_layout(cr, layout)
Пример #6
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()
Пример #7
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))
Пример #8
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()
Пример #9
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)