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()
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
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)
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)
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()
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))
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()
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)