def on_draw(self, widget: Widget, context: cairo.Context): if not self.is_shape_set: self.layout(context) context.set_font_size(self.font_size) self.shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() shape = self.shape label = self.label if len(label) > 0 and label[-1] == ' ': label += '.' xb, yb, w, h, xa, ya = context.text_extents(label) context.rectangle(shape.start.x + self.padding, shape.start.y, shape.width - self.padding, shape.height) context.clip() context.move_to(shape.start.x + (shape.width - self.padding - w)/2, shape.start.y + shape.height - self.padding) context.show_text(self.label)
def _highlight_border(self, context: cairo.Context, row: int, col: int): width = self._total_width height = self._total_height line_width = 3 row_rectangles = [ Rectangle(Point(1, row * self.cell_height - line_width / 2), width - 2, line_width), Rectangle(Point(1, (row + 1) * self.cell_height - line_width / 2), width - 2, line_width) ] col_rectangles = [ Rectangle(Point(col * self.cell_width - line_width / 2, 1), line_width, height - 2), Rectangle(Point((col + 1) * self.cell_width - line_width / 2, 1), line_width, height - 2) ] context.save() r, g, b = self.highlight_color context.set_source_rgba(r, g, b, .6) for row_rectangle in row_rectangles: context.rectangle(row_rectangle.start.x, row_rectangle.start.y, row_rectangle.width, row_rectangle.height) context.fill() for col_rectangle in col_rectangles: context.rectangle(col_rectangle.start.x, col_rectangle.start.y, col_rectangle.width, col_rectangle.height) context.fill() context.restore()
def draw(self, wdg, ctx: cairo.Context, *args): if self.surface: ctx.fill() ctx.set_source_surface(self.surface, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() # Draw rectangles on the WTE image representing the selected WTU entries # Allows multiple selections active_rows: List[Gtk.TreePath] = self.builder.get_object( 'wtu_tree').get_selection().get_selected_rows()[ 1] # type: ignore store: Gtk.ListStore = self.builder.get_object( 'wtu_store') # type: ignore for x in active_rows: row = store[x.get_indices()[0]] ctx.set_line_width(4) ctx.set_source_rgba(1, 1, 1, 1) ctx.rectangle(int(row[0]), int(row[1]), int(row[2]), int(row[3])) ctx.stroke() ctx.set_line_width(2) ctx.set_source_rgba(0, 0, 0, 1) ctx.rectangle(int(row[0]), int(row[1]), int(row[2]), int(row[3])) ctx.stroke() return True
def draw(self, wdg, ctx: cairo.Context): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) # Background ctx.set_source_rgb(0, 0, 0) ctx.rectangle(0, 0, self.width, self.height) ctx.fill() matrix_x_flip = cairo.Matrix(-1, 0, 0, 1, BPC_TILE_DIM, 0) matrix_y_flip = cairo.Matrix(1, 0, 0, -1, 0, BPC_TILE_DIM) tiles_for_pals = self.animation_context.current() for i, mapping in enumerate(self.tile_mappings): tiles_for_frame = tiles_for_pals[mapping.pal_idx] tile_at_pos = mapping.idx if 0 < tile_at_pos < len(tiles_for_frame): tile = tiles_for_frame[tile_at_pos] if mapping.flip_x: ctx.transform(matrix_x_flip) if mapping.flip_y: ctx.transform(matrix_y_flip) ctx.set_source_surface(tile, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if mapping.flip_x: ctx.transform(matrix_x_flip) if mapping.flip_y: ctx.transform(matrix_y_flip) if (i + 1) % self.tiling_width == 0: # Move to beginning of next line ctx.translate(-BPC_TILE_DIM * (self.tiling_width - 1), BPC_TILE_DIM) else: # Move to next tile in line ctx.translate(BPC_TILE_DIM, 0)
def draw(self, wdg, ctx: cairo.Context, *args): if self.surface: wdg.set_size_request(self.surface.get_width(), self.surface.get_height()) ctx.fill() ctx.set_source_surface(self.surface, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() entry_tree: Gtk.TreeView = self.builder.get_object('entry_tree') active_rows: List[Gtk.TreePath] = entry_tree.get_selection( ).get_selected_rows()[1] for x in active_rows: prop = self.entries[x.get_indices()[0]].get_properties() if self.font.get_entry_image_size() > 12: ctx.set_line_width(4) ctx.set_source_rgba(0, 0, 0, 1) ctx.rectangle((prop["char"]%16)*self.font.get_entry_image_size()*IMAGE_ZOOM, \ (prop["char"]//16)*self.font.get_entry_image_size()*IMAGE_ZOOM, prop["width"]*IMAGE_ZOOM, self.font.get_entry_image_size()*IMAGE_ZOOM) ctx.stroke() ctx.set_line_width(2) if self.font.get_entry_image_size() > 12: ctx.set_source_rgba(1, 1, 1, 1) else: ctx.set_source_rgba(1, 0, 0, 1) ctx.rectangle((prop["char"]%16)*self.font.get_entry_image_size()*IMAGE_ZOOM, \ (prop["char"]//16)*self.font.get_entry_image_size()*IMAGE_ZOOM, prop["width"]*IMAGE_ZOOM, self.font.get_entry_image_size()*IMAGE_ZOOM) ctx.stroke() return True
def _handle_selection(self, ctx: cairo.Context): if self._selected is None: return if isinstance(self._selected, SsaActor): x, y, w, h = self.get_bb_actor(self._selected) elif isinstance(self._selected, SsaObject): x, y, w, h = self.get_bb_object(self._selected) elif isinstance(self._selected, SsaPerformer): x, y, w, h = self.get_bb_performer(self._selected) elif isinstance(self._selected, SsaEvent): x, y, w, h = self.get_bb_trigger(self._selected) elif isinstance(self._selected, SourceMapPositionMark): x, y, w, h = self.get_bb_pos_mark(self._selected) else: return padding = 2 x -= padding y -= padding w += padding * 2 h += padding * 2 ctx.set_source_rgba(*COLOR_LAYER_HIGHLIGHT) ctx.set_line_width(3) ctx.rectangle(x, y, w, h) ctx.set_dash([1.0]) ctx.stroke() ctx.set_dash([])
def outline(self, surface): border = Context(surface) border.rectangle(self.w / 64, self.w / 64, self.w - self.w / 32, self.h - self.w / 32 - 2) border.set_line_width(self.w / 32) border.set_source_rgb(0.1, 0.1, 0.1) border.set_line_join(rounded) border.stroke()
def background(self, cr: cairo.Context): linear = cairo.LinearGradient(0, 0, .25, 1) linear.add_color_stop_rgb(0.0, *colors[0]) linear.add_color_stop_rgb(0.4, *colors[5]) linear.add_color_stop_rgb(1.0, *colors[6]) cr.rectangle(0, 0, .5, 1) cr.set_source(linear) cr.fill() cr.rectangle(0.5, 0, 1, 1) linear = cairo.LinearGradient(1, 0, .75, 1) linear.add_color_stop_rgb(0.0, *colors[0]) linear.add_color_stop_rgb(0.4, *colors[5]) linear.add_color_stop_rgb(1.0, *colors[6]) cr.set_source(linear) cr.fill() cr.move_to(.5, 0) # lower left cr.rel_line_to(-.5, 1) cr.rel_line_to(1, 0) cr.close_path() radial = cairo.RadialGradient(0.5, 0.5, 0.1, 0.5, 0.5, 0.75) radial.add_color_stop_rgba(0, *colors[3], 0.7) radial.add_color_stop_rgba(.4, *colors[1], 0.5) radial.add_color_stop_rgba(1, *colors[2], 0.1) cr.set_source(radial) cr.fill()
def _draw_cell(self, context: cairo.Context, cell_value: CrucipixelCellValue, area: Rectangle): r, g, b = self.crucipixel_cell_value_to_color[cell_value] context.set_source_rgb(r, g, b) context.rectangle(area.start.x, area.start.y, area.width, area.height) context.fill() if not self.victory_screen and cell_value == CrucipixelCellValue.EMPTY: # draw the X r, g, b = self.crucipixel_cell_value_to_color[ CrucipixelCellValue.SELECTED ] context.set_source_rgb(r, g, b) context.set_line_cap(cairo.LINE_CAP_ROUND) delta_x = self.cell_width // 2.8 delta_y = self.cell_height // 2.8 context.move_to(area.start.x + area.width - delta_x, area.start.y + delta_y) context.line_to(area.start.x + delta_x, area.start.y + area.height - delta_y) context.move_to(area.start.x + area.width - delta_x, area.start.y + area.width - delta_y) context.line_to(area.start.x + delta_x, area.start.y + delta_y) context.stroke()
def selection_draw_callback(self, ctx: cairo.Context, x: int, y: int): if self.interaction_mode == DrawerInteraction.CHUNKS: # Draw a chunk chunks_at_frame = self.animation_context.current()[self.edited_layer] ctx.set_source_surface( chunks_at_frame[self.interaction_chunks_selected_id], x, y ) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() elif self.interaction_mode == DrawerInteraction.COL: # Draw collision if self.interaction_col_solid: ctx.set_source_rgba(1, 0, 0, 1) ctx.rectangle( x, y, BPC_TILE_DIM, BPC_TILE_DIM ) ctx.fill() elif self.interaction_mode == DrawerInteraction.DAT: # Draw data if self.interaction_dat_value > 0: ctx.select_font_face("monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(6) ctx.set_source_rgb(1, 1, 1) ctx.move_to(x, y + BPC_TILE_DIM - 2) ctx.show_text(f"{self.interaction_dat_value:02x}")
def draw(self, cr: cairo.Context) -> None: if self._extents is None: return extents = self._extents stroke_color = self._stroke_color stroke_width = self._stroke_width cr.rectangle(extents.x, extents.y, extents.w, extents.h) dx = 1 / cr.get_matrix().xx dy = 1 / cr.get_matrix().yy cr.save() if self._scale_strokes: stroke_scale = max(dx, dy) cr.identity_matrix() else: stroke_scale = 1.0 cr.set_line_width(stroke_width) cr.set_source_rgba(*stroke_color) cr.stroke() cr.restore() self._last_drawn_region = rectangle_stroke_region( extents, max(stroke_width * stroke_scale, dx, dy)) self._last_drawn_stroke_scale = stroke_scale
def create_surface(self): bw, bh = self.size old_backing = self._backing #should we honour self.depth here? self._backing = None if bw==0 or bh==0: #this can happen during cleanup return None backing = ImageSurface(FORMAT_ARGB32, bw, bh) self._backing = backing cr = Context(backing) if self._alpha_enabled: cr.set_operator(OPERATOR_CLEAR) cr.set_source_rgba(1, 1, 1, 0) else: cr.set_operator(OPERATOR_SOURCE) cr.set_source_rgba(1, 1, 1, 1) cr.rectangle(0, 0, bw, bh) cr.fill() if COPY_OLD_BACKING and old_backing is not None: oldw, oldh = old_backing.get_width(), old_backing.get_height() sx, sy, dx, dy, w, h = self.gravity_copy_coords(oldw, oldh, bw, bh) cr.translate(dx-sx, dy-sy) cr.rectangle(sx, sy, w, h) cr.clip() cr.set_operator(OPERATOR_SOURCE) cr.set_source_surface(old_backing, 0, 0) cr.paint() backing.flush() return cr
def render_picture(ctx: cairo.Context, picture: Picture) -> None: """ Render a picture at (0, 0) onto the supplied context (which should use mm units). """ ctx.save() # Load the picture image_surface = cairo.ImageSurface.create_for_data( picture.get_image_bytes(), cairo.FORMAT_ARGB32, picture.image_width, picture.image_height, ) # Scale and translate the picture according to the scale/crop mode in use. # # NB: Pattern matrix maps from page space to pixel space, hence the # apparently inverted transformation described here. ctx.set_source_surface(image_surface) pattern = ctx.get_source() m = pattern.get_matrix() m.scale(1 / picture.scale, 1 / picture.scale) m.translate(-picture.x_offset, -picture.y_offset) pattern.set_matrix(m) # Draw the picture (clipped) ctx.rectangle(0, 0, picture.width, picture.height) ctx.fill() ctx.restore()
def on_draw(self, widget: Gtk.Widget, cr: cairo.Context) -> bool: if self.frozen: return False if not self.row.valid(): if self.sig is not None: self.tw.disconnect(self.sig) self.sig = None return False path = self.row.get_path() color = self.stylecontext.get_background_color(Gtk.StateFlags.NORMAL) if not self.columns: self.columns = self.tw.get_columns() assert self.columns is not None for col in self.columns: rect = self.tw.get_background_area(path, col) cr.rectangle(rect.x, rect.y, rect.width, rect.height) cr.clip() cr.set_source_rgba(color.red, color.green, color.blue, 1.0 - self.get_state()) cr.set_operator(cairo.OPERATOR_OVER) cr.paint() return False
def draw_base(self, cr: cairo.Context): cr.identity_matrix() cr.set_matrix(self.matrix) cr.rectangle(-1, -1, 2, 2) cr.set_source_rgb(*colors[0]) cr.fill() if self.gtk_mode: cr.rectangle(-1, .65, .15, .35) cr.set_source_rgb(*colors[1]) cr.fill() cr.set_source_rgb(*colors[1]) cr.set_line_width(9e-3) cr.arc(0, 0, self.radius, 0, 2 * PI) # cr.stroke() for theta in np.linspace(0, 2 * PI, self.radio_button + 1): cr.move_to(0, 0) x, y = self.radius * np.cos(theta), self.radius * np.sin(theta) cr.line_to(x, y) if (x, y) not in self.inter_sections: self.inter_sections.append((x, y)) cr.stroke()
def draw_pieces(self): if not self.num_pieces: # Nothing to draw. return if (self.resized() or self.pieces != self.prev_pieces or self.pieces_overlay is None): # Need to recreate the cache drawing self.pieces_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) ctx = Context(self.pieces_overlay) if self.pieces: pieces = self.pieces elif self.num_pieces: # Completed torrents do not send any pieces so create list using 'completed' state. pieces = [COLOR_STATES.index('completed')] * self.num_pieces start_pos = 0 piece_width = self.width / len(pieces) pieces_colors = [[ color / 65535 for color in self.gtkui_config['pieces_color_%s' % state] ] for state in COLOR_STATES] for state in pieces: ctx.set_source_rgb(*pieces_colors[state]) ctx.rectangle(start_pos, 0, piece_width, self.height) ctx.fill() start_pos += piece_width self.cr.set_source_surface(self.pieces_overlay) self.cr.paint()
def _draw(self, widget: Gtk.Widget, ctx: Context): height = widget.get_allocated_height() ctx.scale(20, height) ctx.rectangle(0, 0, 1, 1) set_rgb(ctx, self.color) ctx.fill()
def on_draw(self, index: int, widget: Gtk.DrawingArea, ctx: cairo.Context): w16 = self._surfaces[index] ctx.set_source_rgb(0, 0, 0) ctx.rectangle(0, 0, *widget.get_size_request()) ctx.fill() ctx.set_source_surface(w16) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint()
def draw(self, wdg, ctx: cairo.Context, do_translates=True): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) chunk_width = self.tiling_width * DPCI_TILE_DIM chunk_height = self.tiling_height * DPCI_TILE_DIM # Background if not self.use_pink_bg: ctx.set_source_rgb(0, 0, 0) else: ctx.set_source_rgb(1.0, 0, 1.0) ctx.rectangle( 0, 0, self.width_in_chunks * self.tiling_width * DPCI_TILE_DIM, self.height_in_chunks * self.tiling_height * DPCI_TILE_DIM) ctx.fill() # Layers for chunks_at_frame in self.animation_context.current(): for i, chunk_at_pos in enumerate(self.mappings): if 0 < chunk_at_pos < len(chunks_at_frame): chunk = chunks_at_frame[chunk_at_pos] ctx.set_source_surface(chunk, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if (i + 1) % self.width_in_chunks == 0: # Move to beginning of next line if do_translates: ctx.translate( -chunk_width * (self.width_in_chunks - 1), chunk_height) else: # Move to next tile in line if do_translates: ctx.translate(chunk_width, 0) # Move back to beginning if do_translates: ctx.translate(0, -chunk_height * self.height_in_chunks) break size_w, size_h = self.draw_area.get_size_request() size_w /= self.scale size_h /= self.scale # Selection self.selection_plugin.set_size(self.tiling_width * DPCI_TILE_DIM, self.tiling_height * DPCI_TILE_DIM) self.selection_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) # Tile Grid if self.draw_tile_grid: self.tile_grid_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) # Chunk Grid if self.draw_chunk_grid: self.chunk_grid_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) return True
def draw_router_transmission(args, ld: Path, area, r, ctx: cairo.Context): ctx.rectangle(0, 0, area.x, area.y) ctx.set_source_rgba(*color_db(args)) ctx.fill() # transmitting circles for router in r: if not router.mm.visible: continue x, y = router.coordinates() if router.transmission_within_second: distance = \ max(router.interfaces.values(), key=lambda x: x['range'])[ 'range'] ctx.set_source_rgba(*color_transmission_circle(args)) ctx.move_to(x, y) ctx.arc(x, y, distance, 0, 2 * math.pi) ctx.fill() for router in r: if not router.mm.visible: continue x, y = router.coordinates() ctx.set_line_width(0.1) path_thickness = 6.0 # iterate over links for i, interface_name in enumerate(router.interfaces): range_ = router.interfaces[interface_name]['range'] # draw lines between links ctx.set_line_width(path_thickness) for r_id, r_obj in router.connections[interface_name].items(): if not r_obj.mm.visible: continue other_x, other_y = r_obj.coordinates() ctx.move_to(x, y) ctx.set_source_rgba(*color_tx_links(args)) ctx.line_to(other_x, other_y) ctx.stroke() path_thickness -= 4.0 if path_thickness < 2.0: path_thickness = 2.0 # draw dots over all for router in r: if not router.mm.visible: continue x, y = router.coordinates() ctx.set_line_width(0.0) ctx.set_source_rgba(*color_tx_links(args)) ctx.move_to(x, y) ctx.arc(x, y, 5, 0, 2 * math.pi) ctx.fill()
def draw(self, cr: Context, drawing_options: DrawingOptions): cr.set_source_rgb(*drawing_options.rail_color) cr.rectangle(-1, -1, 2, 2) cr.fill() cr.set_source_rgb( *(SENSOR_ACTIVATED if self.activated else SENSOR_NORMAL)) cr.arc(0, 0, 0.8, 0, math.tau) cr.fill()
def draw_squares(self, cr: cairo.Context, color=colors[2]): cr.set_line_width(self.lw) cr.set_source_rgba(*self.lc) nx, ny = self.normalize_coord(*np.where(self.M)) for x, y in zip(nx, ny): nx, ny = self.normalize_coord(x, y) cr.rectangle(x, y, self.norm_box_size[0], self.norm_box_size[1]) cr.stroke_preserve() cr.set_source_rgba(*color) cr.fill()
def draw(self, ctx: Context): with this_source_rgb(ctx, 1., 1., 1.): ctx.set_line_width(20) ctx.rectangle(0, 0, 894.0, 468.0) ctx.stroke() ctx.set_line_width(1) with this_source_rgb(ctx, 1., 0., 0.): ctx.rectangle(*self.top_left[:-1], *(self.top_left + self.size)[:-1]) ctx.stroke()
def create_image(context: cairo.Context, cells: CellBlock, cell_sizes: Dict[CellBlock, float]) -> None: context.rectangle(0, 0, WIDTH, HEIGHT) context.set_source_rgb(1, 1, 1) context.fill() context.set_source_rgb(0, 0, 0) for (x, y), cell_state in cells.items(): context.arc(x * 16, y * 16, cell_sizes[cell_state], 0, 2 * pi) context.fill()
def _handle_selection(self, ctx: cairo.Context): if self._selected is None: return if self._selected.level_id != self.level_id: return x, y = self._get_marker_xy(self._selected) x, y, w, h = (x - RAD * 2, y - RAD * 2, RAD * 4, RAD * 4) ctx.set_source_rgba(0, 0, 1, 0.6) ctx.rectangle(x, y, w, h) ctx.fill()
def on_draw(self, widget: Widget, context: cairo.Context): for child in self.list: if child.visible: context.save() context.transform(child.fromWidgetCoords) if child.is_clip_set(): rectangle = child.clip_rectangle context.rectangle(rectangle.start.x,rectangle.start.y, rectangle.width,rectangle.height) context.clip() child.on_draw(self,context) context.restore()
def on_draw(self, widget: Widget, context: cairo.Context): for child in self.list: if child.visible: context.save() context.transform(child.fromWidgetCoords) if child.is_clip_set(): rectangle = child.clip_rectangle context.rectangle(rectangle.start.x, rectangle.start.y, rectangle.width, rectangle.height) context.clip() child.on_draw(self, context) context.restore()
def _handle_layer_highlight(self, ctx: cairo.Context, layer: int, x: int, y: int, w: int, h: int): if layer == self._sector_highlighted: padding = 2 x -= padding y -= padding w += padding * 2 h += padding * 2 ctx.set_source_rgba(*COLOR_LAYER_HIGHLIGHT) ctx.set_line_width(1.5) ctx.rectangle(x, y, w, h) ctx.set_dash([1.0]) ctx.stroke() ctx.set_dash([])
def _draw_pos_mark(self, ctx: cairo.Context, pos_mark: SourceMapPositionMark, *bb_cords): # Outline ctx.set_source_rgba(*COLOR_POS_MARKS, 0.8) ctx.rectangle(*bb_cords) ctx.set_line_width(4.0) ctx.set_dash([1.0]) ctx.stroke() ctx.set_dash([]) # Inner ctx.rectangle(bb_cords[0] + BPC_TILE_DIM, bb_cords[1] + BPC_TILE_DIM, BPC_TILE_DIM, BPC_TILE_DIM) ctx.fill() # Label self._draw_name(ctx, COLOR_POS_MARKS, pos_mark.name, bb_cords[0], bb_cords[1], scale=2)
def on_draw(self, widget: "Widget", context: cairo.Context): translation = 10, 10 context.translate(*translation) self.contents.set_translate(*translation) self.navigator.set_translate(*translation) self.back_button.set_translate(*translation) up_margin = 4 down_margin = 6 left_margin = 4 right_margin = self.navigator.width navigator_margin = 4 base_x, base_y = self.fromWidgetCoords.transform_point(0, 0) base_x += translation[0] base_y += translation[1] width = self.container_size[0] - 2 * base_x - right_margin - 2 * navigator_margin height = self.container_size[1] - 2 * base_y - down_margin self.contents.set_max_size(width, height) self.contents.on_draw(widget, context) offset = self.contents.table_width + navigator_margin tot = len(self.contents.entries) if tot != 0: self.navigator.skip = self.contents.base / tot else: self.navigator.skip = 0 if tot != 0: self.navigator.fill = self.contents._shown / tot else: self.navigator.fill = 1 self.navigator.translate(offset, 0) context.translate(offset, 0) self.navigator.down_pos = self.contents.table_height self.navigator.on_draw(widget, context) context.translate(-offset, 0) rectangle_width = left_margin + offset + navigator_margin + right_margin rectangle_height = self.contents.table_height + up_margin + down_margin context.rectangle( -left_margin, -up_margin, rectangle_width, rectangle_height ) context.stroke() button_left = (rectangle_width - left_margin) / 2 button_left = 0 button_left = rectangle_width - left_margin button_up = rectangle_height + up_margin self.back_button.translate(button_left, button_up) context.translate(button_left, button_up) self.back_button.on_draw(self, context)
def drawcell(self, cairo_ctx: cairo.Context, i, j): """Draw the cell at i, j, using the supplied graphics context.""" tile = self.showboard[i + j * xsize] i = i * self.tilesize j = j * self.tilesize if (tile == "blank"): cairo_ctx.set_source_rgb(1, 1, 1) cairo_ctx.rectangle(i, j, self.tilesize, self.tilesize) cairo_ctx.fill() else: Gdk.cairo_set_source_pixbuf(cairo_ctx, self.get_image(tile), i, j) cairo_ctx.paint()
def _draw_marker(self, ctx: cairo.Context, marker: MapMarkerPlacement, x=None, y=None): x, y = self._get_marker_xy(marker, x, y) if (x, y) not in self.markers_at_pos: self.markers_at_pos[(x, y)] = [] self.markers_at_pos[(x, y)].append(marker) # Outline + Fill bb_cords = (x - RAD, y - RAD, RAD * 2, RAD * 2) ctx.rectangle(*bb_cords) ctx.set_line_width(1.0) ctx.set_source_rgb(0, 0, 0) ctx.stroke_preserve() ctx.set_source_rgba(*COLOR_MARKERS, 0.8) ctx.fill()
def _do_draw(self, cr: cairo.Context) -> None: extents = self.props.extents border_width = self.props.border_width border_color = self.props.border_color if extents is None: return cr.rectangle(*self._parent._widget_coord_from_canvas(extents.pos), *self._parent._widget_dist_from_canvas(extents.size)) cr.set_line_width(border_width) cr.set_source_rgb(*border_color) cr.stroke()
def on_draw(self, widget: Widget, context: cairo.Context): self.guide_line.set_shape_from_context(context) shape = self.guide_line.shape self.guide_line.set_translate(shape.width + 10, shape.height + 10) context.save() context.set_source_rgb(1, 1, 1) if self.guide_line.orientation == Orientation.HORIZONTAL: context.rectangle(10, shape.height + 10, shape.width, 20) else: context.rectangle(shape.width + 10, 10, 20, shape.height) context.fill() context.restore() super().on_draw(widget, context)
def _highlight_border(self, context: cairo.Context, row: int, col: int): width = self._total_width height = self._total_height line_width = 3 row_rectangles = [ Rectangle( Point(1, row * self.cell_height - line_width / 2), width - 2, line_width ), Rectangle( Point(1, (row + 1) * self.cell_height - line_width / 2), width - 2, line_width ) ] col_rectangles = [ Rectangle( Point(col * self.cell_width - line_width / 2, 1), line_width, height - 2 ), Rectangle( Point((col + 1) * self.cell_width - line_width / 2, 1), line_width, height - 2 ) ] context.save() r, g, b = self.highlight_color context.set_source_rgba(r, g, b, .6) for row_rectangle in row_rectangles: context.rectangle(row_rectangle.start.x, row_rectangle.start.y, row_rectangle.width, row_rectangle.height) context.fill() for col_rectangle in col_rectangles: context.rectangle(col_rectangle.start.x, col_rectangle.start.y, col_rectangle.width, col_rectangle.height) context.fill() context.restore()
def renderText(self, surface, text, y_offset, size, shade, w=(2,3), wrap=True): if len(text) < 1: return def setdesc(l, size): l.set_font_description( FontDescription( self.font + " " + str(size))) origin = Context(surface) origin.translate(self.w * (w[1] - w[0]) / (w[1] * 2), y_offset) box = CairoContext(origin) # Start laying out text layout = box.create_layout() setdesc(layout, size) width = self.w * w[0] / w[1] if wrap: layout.set_width(width * pango.SCALE) else: layout.set_width(-1) layout.set_alignment(pango.ALIGN_CENTER) layout.set_text(text) # Resize text to make sure it doesn't exceed width. wi, n = layout.get_pixel_size() if wi > width: s = size * width / wi setdesc(layout, s) layout.set_width(width * pango.SCALE) # Draw a transparent pane behind the text origin.set_source_rgba(1, 1, 1, 0.7) origin.rectangle(*layout.get_pixel_extents()[1]) origin.fill() # Draw text origin.set_source_rgb(shade, shade, shade) box.update_layout(layout) box.show_layout(layout)
ctx.paint() pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y L.flush() return L if __name__ == '__main__': from PIL import Image n_words = 200 H, W, dpi = 600, 800, 72.0 I = ImageSurface(FORMAT_A8, W, H) ctxI = Context(I) ctxI.rectangle(0,0,800,600) ctxI.set_source_rgba (0.9, 0.9, 0.9, 0) ctxI.fill() S = random.normal(0,1,n_words) S = (S-S.min())/(S.max()-S.min()) S = sort(1-sqrt(S))[::-1] sizes = (12 + S*48).astype(int).tolist() def spiral(): eccentricity = 1.5 radius = 8 step = 0.1 t = 0 while True: t += step yield eccentricity*radius*t*cos(t), radius*t*sin(t)
def _paint_panel(self, key, width, height, panel_h): self.db.IUD("update web_stat_panels set HEIGHT = %s where ID = %s" % (panel_h, key)) self.db.commit() color_x_line = (0.7, 0.7, 0.7) color_x_line_2 = (0.9, 0.9, 0.9) color_y_line = (0.9, 0.9, 0.9) color_y_line_date = (0.7, 0.7, 0.7) color_border = (0.5, 0.5, 0.5) left = 40 right = 10 bottom = 15 var_ids = "0" series = [0, 0, 0, 0] typ = 0 for row in self.db.select( "select SERIES_1, SERIES_2, SERIES_3, SERIES_4, TYP " " from web_stat_panels " " where ID = " + str(key) ): series = row var_ids = "%s, %s, %s, %s" % row[0:4] typ = row[4] width, height = int(width), int(height) if width <= 0: width = 300 if height <= 0: height = 150 interval = self.param("range") delta_x = 1 if interval == "-6 hour": delta_x = 6 * 3600 elif interval == "-12 hour": delta_x = 12 * 3600 elif interval == "-1 day": delta_x = 24 * 3600 elif interval == "-3 day": delta_x = 3 * 24 * 3600 elif interval == "-7 day": delta_x = 7 * 24 * 3600 elif interval == "-14 day": delta_x = 14 * 24 * 3600 elif interval == "-30 day": delta_x = 30 * 24 * 3600 elif interval == "-90 day": delta_x = 3 * 30 * 24 * 3600 elif interval == "-180 day": delta_x = 6 * 30 * 24 * 3600 elif interval == "-360 day": delta_x = 12 * 30 * 24 * 3600 min_x = int(self.param("start")) - delta_x // 2 max_x = min_x + delta_x min_x_q = min_x - delta_x # // 100 max_x_q = max_x + delta_x # // 100 max_y = -9999 min_y = 9999 # Делаем полную выборку данных. Выкидываем подозрительные точки и # собираем статистику. prev_vals = [-9999] * 4 chart_data = [[], [], [], []] zoom_step = delta_x / (width * 5) if zoom_step < 1 or typ != 0: zoom_step = 1 x_min_max_values = [] mi_x = max_x_q ma_x = min_x_q tt = -100 for row in self.db.select( "select UNIX_TIMESTAMP(CHANGE_DATE) D, MIN(VALUE) + (MAX(VALUE) - MIN(VALUE)) VALUE, VARIABLE_ID " " from core_variable_changes " " where VARIABLE_ID in (%s) " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " " group by 3, ROUND(UNIX_TIMESTAMP(CHANGE_DATE) / %s)" " order by 3, 1 " % (var_ids, min_x_q, max_x_q, zoom_step) ): ind = series.index(row[2]) chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) if tt == -100: tt = row[2] if tt != row[2]: v = [tt, mi_x, ma_x] x_min_max_values += [v] mi_x = max_x_q ma_x = min_x_q tt = row[2] if row[0] < mi_x: mi_x = row[0] if row[0] > ma_x: ma_x = row[0] if tt != -1: v = [tt, mi_x, ma_x] x_min_max_values += [v] # print(x_min_max_values) # print(series) """ for row in self.db.select("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)): """ """ try: self.db.IUD("set @rn := 0") sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)) for c in self.db.select("select count(*) c " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " % (min_x_q, max_x_q)): cou = c[0] ccc = 1000 * 4 if cou > ccc: sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, @rn := @rn + 1 rownum " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "having mod(rownum, %s) = 0 " "order by VARIABLE_ID, CHANGE_DATE " % (min_x_q, max_x_q, math.ceil(cou / ccc))) for row in self.db.select(sql): ind = series.index(row[2]) prev_vals[ind] = row[1] if abs(prev_vals[ind] - row[1]) < 10: chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) prev_vals[ind] = row[1] except: pass """ if min_y is None or max_y is None or min_y == 9999 or max_y == -9999 or min_y == max_y: max_y = 1 min_y = 0 min_y = math.floor(min_y) max_y = math.ceil(max_y) if typ == 2: if min_y < 0 and max_y < 0: max_y = 0 elif min_y > 0 and max_y > 0: min_y = 0 # Определяем цвета colors = [[1, 0, 0], [0, 0.65, 0.31], [0, 0, 1], [1, 0, 1]] off_y = (max_y - min_y) / 10 min_y -= off_y max_y += off_y try: kx = (max_x - min_x) / (width - left - right) ky = (max_y - min_y) / (height - bottom) if ky == 0: ky = 1 except: kx, ky = 1, 1 img = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(img) width -= right ctx.set_line_width(1) # Рисуем сетку ctx.set_font_size(12) try: b_w, b_h = ctx.text_extents("00-00-0000")[2:4] # Метки на оси Y count = math.ceil(max_y) - math.ceil(min_y) space_count = math.ceil(count / ((height - bottom) / (b_h * 1.5))) sc = 0 for i in range(math.ceil(min_y), math.ceil(max_y)): if sc == 0: y = height - bottom + (min_y - i) / ky ctx.set_source_rgb(*(color_x_line)) ctx.move_to(left, y) ctx.line_to(width, y) ctx.stroke() ctx.set_source_rgb(0, 0, 0) num = str(i) tw, th = ctx.text_extents(num)[2:4] ctx.move_to(left - 5 - tw, y + th // 2) ctx.show_text(num) sc = space_count sc -= 1 # Метки на оси Х x_step = 3600 if interval == "-6 hour" or interval == "-12 hour" or interval == "-1 day": # Дополнительно метки часов x_step = 3600 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step)): x = (i * x_step - min_x) / kx + left ctx.set_source_rgb(*(color_x_line_2)) ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() num = datetime.datetime.fromtimestamp(i * x_step).strftime("%H") tw, th = ctx.text_extents(num)[2:4] ctx.move_to(x + 2, height - bottom - 3) ctx.set_source_rgb(*(color_x_line)) ctx.show_text(num) x_step = 3600 * 24 space_count = 1 count = math.ceil(max_x / x_step) - math.ceil(min_x / x_step) try: if (width / count) < b_w: space_count = 2 except: pass sc = 0 tz = 3600 * 2 tx_prev = -100 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step) + 1): if sc == 0: d_i = datetime.datetime.fromtimestamp(i * x_step) x = (i * x_step - min_x - tz) / kx + left ctx.set_source_rgb(0, 0, 0) num = d_i.strftime("%d-%m-%Y %H") x -= (int(d_i.strftime("%H")) * 3600 - tz) / kx tw, th = ctx.text_extents(num)[2:4] tx = x - tw // 2 ctx.move_to(tx, height - bottom + th + 5) if tx - tx_prev > tw: ctx.show_text(num) tx_prev = tx ctx.set_source_rgb(*(color_y_line_date)) else: ctx.set_source_rgb(*(color_y_line)) if x >= left and x < width: ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() sc = space_count sc -= 1 except Exception as e: pass # Рисуем верхний и правый бордер ctx.set_source_rgb(*color_border) ctx.move_to(left, 0) ctx.line_to(width, 0) ctx.line_to(width, height - bottom) ctx.stroke() # Рисуем сами графики ctx.rectangle(left, 0, width - left, height) ctx.clip() is_first = True currVarID = -1 prevX = -1 if typ == 0: # Линейная for ind in range(4): """ if len(chart_data[ind]) > 0: for i in range(len(chart_data[ind]) - 1): chart_data[ind][i] = list(chart_data[ind][i]) r1 = chart_data[ind][i] r2 = chart_data[ind][i + 1] chart_data[ind][i][0] += (r2[0] - r1[0]) / 2 chart_data[ind][i][1] += (r2[1] - r1[1]) / 2 """ ctx.set_source_rgb(*colors[ind]) is_first = True for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: ctx.move_to(x, y) else: if row[0] - prevX > 10000: ctx.move_to(x, y) else: ctx.line_to(x, y) prevX = row[0] is_first = False ctx.stroke() elif typ == 1: # Точечная for ind in range(4): if chart_data[ind]: ctx.set_source_rgb(*colors[ind]) for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 3, y - 3, 6, 6) ctx.fill() elif typ == 2: # Столбчатая cy = height - bottom - (-min_y) / ky for ind in range(4): for row in chart_data[ind]: if currVarID != row[2]: ctx.fill() for i in range(4): if series[i] == row[2]: ctx.set_source_rgb(*colors[i]) x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 5, y, 10, cy - y) currVarID = row[2] ctx.fill() else: # Линейчастая # one_vals = self._get_one_val(series, min_x_q, max_x_q) one_vals = self._get_one_val(series, x_min_max_values, min_x_q, max_x_q) for ind in range(4): if series[ind]: is_now = True for r in one_vals[ind]: if r[4] == 1: chart_data[ind].insert(0, r) else: chart_data[ind] += [r] is_now = False if is_now: if len(chart_data[ind]) > 0: r = list(chart_data[ind][len(chart_data[ind]) - 1]) r[0] = datetime.datetime.now().timestamp() chart_data[ind] += [r] color = colors[ind] color_fill = color.copy() color_fill += [0.3] is_first = True y0 = height - bottom + min_y / ky for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: is_first = False else: ctx.set_source_rgb(*color) ctx.move_to(prevX, prevY) ctx.line_to(x, prevY) ctx.line_to(x, y) ctx.stroke() ctx.set_source_rgba(*color_fill) rx, ry, rw, rh = prevX, y0, x - prevX, prevY - y0 ctx.rectangle(rx, ry, rw, rh) ctx.fill() prevX, prevY = x, y # Рисуем оси ctx.set_source_rgb(0, 0, 0) ctx.move_to(left, 0) ctx.line_to(left, height - bottom) ctx.line_to(width, height - bottom) ctx.stroke() # --------------------------- del ctx byt = BytesIO() img.write_to_png(byt) byt.seek(0) return byt.read()
def on_draw(self, widget: Widget, context: cairo.Context): self.min_size = 200, 150 super().on_draw(widget, context) context.save() context.set_font_size(self.font_size) if self._table_extents is None: self._update_table_extents(context) skip = max(self.skip, 0) how_many = self.how_many table_extents = self._table_extents title_extents = self._table_extents.title_extents expected_height = title_extents.total_height + self.margin entries = self.entries base = skip up_to = skip over = False while up_to < len(entries) and not over: expected_height += table_extents[up_to].total_height over = expected_height >= self._max_height if not over: up_to += 1 while base > 0 and not over: expected_height += table_extents[base-1].total_height over = expected_height >= self._max_height if not over: base -= 1 how_many = up_to - base skip = base self.base = base entries = self.entries[skip:skip + how_many] def table_extents_iterator(): return table_extents.iter_over( skip, how_many ) start_x, start_y = context.get_current_point() start_y += title_extents.total_height h = title_extents.total_height self.title_height = h for (index, cell), data in zip(enumerate(title_extents), self.title): context.save() offset = title_extents.get_cell_data_left(index) context.rectangle(start_x + offset, start_y - h, cell.width, 2*h) context.clip() context.move_to( start_x + offset, start_y ) context.show_text(data) context.restore() # start_y += self.margin curr_x, curr_y = start_x, start_y# + title_extents.total_height for line_index, (line_extent, entry) in enumerate(zip(table_extents_iterator(), entries)): h = line_extent.total_height curr_y += h if curr_y + self.margin >= self._max_height: break for (cell_index, cell), data in zip(enumerate(line_extent), entry): context.save() offset = line_extent.get_cell_data_left(cell_index) context.rectangle(curr_x + offset, curr_y - h, cell.width, 2*h) context.clip() context.move_to( curr_x + offset, curr_y ) context.show_text(data) context.restore() curr_x = start_x end_x = table_extents.entries_width curr_y = start_y + self.margin end_y = table_extents.get_height_up_to(skip, how_many) + start_y + self.margin + 1 self.table_height = end_y self.table_width = end_x for line in table_extents_iterator(): context.move_to(curr_x, curr_y) context.line_to(end_x, curr_y) context.stroke() curr_y += line.total_height context.move_to(curr_x, curr_y) context.line_to(end_x, curr_y) context.stroke() curr_x = start_x curr_y = start_y - 1 + self.margin if self._how_many > 0: line = table_extents[0] for cell in line: context.move_to(curr_x, curr_y) context.line_to(curr_x, end_y) context.stroke() curr_x += cell.total_width + 2 * self.margin context.move_to(curr_x, curr_y) context.line_to(curr_x, end_y) context.stroke() if self._to_highlight is not None: r, g, b = global_constants.highlight context.set_source_rgba(r, g, b, .6) index = self._to_highlight base = start_y + table_extents.get_height_up_to(skip, index) + self.margin h = table_extents.get_height_of(skip, how_many, index) context.rectangle(start_x, base, table_extents.entries_width, h) context.fill() context.restore() self._shown = how_many
def do_draw(self, context: cairo.Context) -> bool: if not self.adjustment or self.adjustment.get_upper() <= 0: return False height = self.get_allocated_height() width = self.get_allocated_width() if width <= 0 or height <= 0: return False base_bg, base_outline, handle_overdraw, handle_outline = ( self.get_map_base_colors()) x0 = self.overdraw_padding + 0.5 x1 = width - 2 * x0 height_scale = height * self.get_height_scale() if self._cached_map is None: surface = cairo.Surface.create_similar( context.get_target(), cairo.CONTENT_COLOR_ALPHA, width, height) cache_ctx = cairo.Context(surface) cache_ctx.set_line_width(1) cache_ctx.rectangle(x0, -0.5, x1, height_scale + 0.5) cache_ctx.set_source_rgba(*base_bg) cache_ctx.fill() # We get drawing coordinates by tag to minimise our source # colour setting, and make this loop slightly cleaner. tagged_diffs = self.chunk_coords_by_tag() for tag, diffs in tagged_diffs.items(): cache_ctx.set_source_rgba(*self.fill_colors[tag]) for y0, y1 in diffs: y0 = round(y0 * height_scale) + 0.5 y1 = round(y1 * height_scale) - 0.5 cache_ctx.rectangle(x0, y0, x1, y1 - y0) cache_ctx.fill_preserve() cache_ctx.set_source_rgba(*self.line_colors[tag]) cache_ctx.stroke() cache_ctx.rectangle(x0, -0.5, x1, height_scale + 0.5) cache_ctx.set_source_rgba(*base_outline) cache_ctx.stroke() self._cached_map = surface context.set_source_surface(self._cached_map, 0, 0) context.paint() # Draw our scroll position indicator context.set_line_width(1) context.set_source_rgba(*handle_overdraw) adj_y = self.adjustment.get_value() / self.adjustment.get_upper() adj_h = self.adjustment.get_page_size() / self.adjustment.get_upper() context.rectangle( x0 - self.overdraw_padding, round(height_scale * adj_y) + 0.5, x1 + 2 * self.overdraw_padding, round(height_scale * adj_h) - 1, ) context.fill_preserve() context.set_source_rgba(*handle_outline) context.stroke() return True
def main(marker, paper, format, bbox, emergency, place, recipient, sender, text, sender_is_recipient, map_href): """ """ mark = Location(*marker) handle, filename = mkstemp(prefix='safetymap-', suffix='.pdf') close(handle) if paper == 'a4': surf = PDFSurface(filename, 210*ptpmm, 297*ptpmm) elif paper == 'letter': surf = PDFSurface(filename, 8.5*ptpin, 11*ptpin) ctx = Context(surf) ctx.scale(ptpmm, ptpmm) set_font_face_from_file(ctx, 'assets/HelveticaNeue.ttc') if paper == 'a4': draw_a4_master(ctx, format, map_href) ctx.translate(19, 24) elif paper == 'letter': draw_letter_master(ctx, format, map_href) ctx.translate(21, 18) ctx.set_line_width(.25 * mmppt) ctx.set_source_rgb(*md_gray) ctx.set_dash([3 * mmppt]) reps = {'4up': 4, '2up-fridge': 2, 'poster': 0} if reps[format]: card_img, mark_point = get_map_image(bbox, 84, 39, mark) for i in range(reps[format]): # dashed outlines ctx.move_to(0, 61) ctx.line_to(0, 0) ctx.line_to(173, 0) ctx.line_to(173, 61) #ctx.move_to(86, 0) #ctx.line_to(86, 61) ctx.stroke() # two card sides and contents draw_card_left(ctx, recipient, sender, text, sender_is_recipient) ctx.translate(86.5, 0) draw_card_right(ctx, card_img, mark_point, emergency, place) ctx.translate(-86.5, 61) if format == '4up': # bottom dashed outline ctx.move_to(0, 0) ctx.line_to(172, 0) ctx.stroke() elif format == '2up-fridge': # prepare to draw sideways ctx.translate(0, 122.5) ctx.rotate(-pi/2) ctx.rectangle(0, 0, 122.5, 173) ctx.stroke() poster_img, mark_point = get_map_image(bbox, 109, 77, mark) draw_small_poster(ctx, poster_img, mark_point, emergency, place, recipient, sender, text, sender_is_recipient) elif format == 'poster': ctx.rectangle(0, 0, 173, 245) ctx.stroke() poster_img, mark_point = get_map_image(bbox, 153, 108, mark) draw_large_poster(ctx, poster_img, mark_point, emergency, place, recipient, sender, text, sender_is_recipient) surf.finish() chmod(filename, 0644) return filename
widthZ, rowsZ, pitch = bitmap.width, bitmap.rows, bitmap.pitch Z = make_image_surface(bitmap) # Plain flags = FT_LOAD_RENDER face.load_char('S', flags) bitmap = face.glyph.bitmap widthF, rowsF, pitch = bitmap.width, bitmap.rows, bitmap.pitch F = make_image_surface(bitmap) # Draw surface = ImageSurface(FORMAT_ARGB32, 1200, 500) ctx = Context(surface) # fill background as gray ctx.rectangle(0,0,1200,500) ctx.set_source_rgb (0.5 , 0.5, 0.5) ctx.fill() # use the stroked font's size as scale, as it is likely slightly larger scale = 400.0 / rowsZ # draw bitmap first ctx.set_source_surface(F, 0, 0) patternF = ctx.get_source() SurfacePattern.set_filter(patternF, FILTER_BEST) scalematrix = Matrix() scalematrix.scale(1.0/scale,1.0/scale) scalematrix.translate(-(600.0 - widthF *scale /2.0 ), -50) patternF.set_matrix(scalematrix)