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