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, 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() return True
def selection_draw_callback(self, ctx: cairo.Context, x: int, y: int): # Draw a chunk chunks_at_frame = self.animation_context.current()[0] ctx.set_source_surface( chunks_at_frame[self.interaction_chunks_selected_id], x, y) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint()
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 _draw_object_sprite(self, ctx: cairo.Context, obj: SsaObject, x, y): """Draws the sprite for an object""" sprite = self.sprite_provider.get_for_object(obj.object.name, lambda: GLib.idle_add(self._redraw))[0] ctx.translate(x, y) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.translate(-x, -y)
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() return True
def on_draw_icon_draw(self, widget: DrawingArea, ctx: cairo.Context): scale = 2 ctx.scale(scale, scale) ctx.set_source_surface(self.icon_surface) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.scale(1 / scale, 1 / scale) return True
def on_draw(self, _widget: Gtk.Widget, cr: cairo.Context) -> bool: if not self.frozen: cr.set_source_rgba(self.color.red, self.color.green, self.color.blue, self.color.alpha - self.get_state()) cr.set_operator(cairo.OPERATOR_OVER) cr.paint() return False
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 on_draw_example_placeholder_draw(self, widget: Gtk.DrawingArea, ctx: cairo.Context): sprite, x, y, w, h = self._sprite_provider.get_actor_placeholder( 9999, 0, lambda: GLib.idle_add(lambda: self.builder.get_object('draw_example_placeholder').queue_draw()) # type: ignore ) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if widget.get_size_request() != (w, h): widget.set_size_request(w, h)
def draw_background(ctx: cairo.Context, width: int, height: int): # TODO: Add noise/cracks/stains bg_color = RadialGradient([Color(0.84, 0.81, 0.74), Color(0.55, 0.50, 0.36)]) center_x = width / 2 center_y = height / 2 with source(ctx, bg_color.to_pattern(center_x, center_y, center_x)), operator( ctx, cairo.Operator.DARKEN ): ctx.paint()
def draw_icon(self, context: cairo.Context, icon: str, position: Tuple[int, int]): image = cairo.ImageSurface.create_from_png( os.path.join(os.path.dirname(__file__), "icons-7", f"{icon}.png") ) context.save() context.translate(*position) context.set_source_surface(image) context.paint() context.restore()
def _surface_place_actor(self, ctx: cairo.Context, x, y, w, h): ctx.set_line_width(1) sprite_surface = self.sprite_provider.get_monster_outline(1, 1)[0] ctx.translate(x, y) ctx.set_source_surface(sprite_surface) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() self._draw_plus(ctx) ctx.translate(-x, -y)
def draw(self, wdg, ctx: cairo.Context): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) chunks_at_frame = self.animation_context.current()[0] if 0 <= self.chunkidx < len(chunks_at_frame): chunk = chunks_at_frame[self.chunkidx] ctx.set_source_surface(chunk, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint()
def on_draw_sprite_draw(self, widget: Gtk.DrawingArea, ctx: cairo.Context): scale = 2 sprite, x, y, w, h = self._sprite_provider.get_for_item(self.item_p, lambda: GLib.idle_add(widget.queue_draw)) ctx.scale(scale, scale) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.scale(1 / scale, 1 / scale) if widget.get_size_request() != (w, h): widget.set_size_request(w * scale, h * scale) return True
def on_draw_portrait_draw(self, widget: Gtk.DrawingArea, ctx: cairo.Context): scale = 2 portrait = self._portrait_provider.get(self.entry.md_index - 1, 0, lambda: GLib.idle_add(widget.queue_draw), True) ctx.scale(scale, scale) ctx.set_source_surface(portrait) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.scale(1 / scale, 1 / scale) if widget.get_size_request() != (IMG_DIM * scale, IMG_DIM * scale): widget.set_size_request(IMG_DIM * scale, IMG_DIM * scale) return True
def on_draw_sprite_draw(self, widget: Gtk.DrawingArea, ctx: cairo.Context): if self.entry.entid > 0: sprite, x, y, w, h = self._sprite_provider.get_monster(self.entry.md_index, 0, lambda: GLib.idle_add(widget.queue_draw)) else: sprite, x, y, w, h = self._sprite_provider.get_error() ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if widget.get_size_request() != (w, h): widget.set_size_request(w, h) return True
def draw(self, da, ctx:cairo.Context): self.ctx = ctx print('ok') print(pixbuf) Gdk.cairo_set_source_pixbuf(ctx, pixbuf, 0, 0) ctx.paint() ctx.set_source_rgb(255, 0, 0) ctx.set_line_width(SIZE / 4) ctx.set_tolerance(0.1) ctx.set_line_join(cairo.LINE_JOIN_ROUND) ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) self.stroke_shapes(ctx, 0, 0)
def draw(self, da, ctx: cairo.Context): print('ok') print(pixbuf) Gdk.cairo_set_source_pixbuf(ctx, pixbuf, 0, 0) ctx.paint() ctx.set_source_rgb(255, 0, 0) ctx.set_line_width(SIZE / 4) ctx.set_tolerance(0.1) ctx.set_line_join(cairo.LINE_JOIN_ROUND) ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) self.stroke_shapes(ctx, 0, 0) ctx.get_target().write_to_png('./a.png') return True
def load_image_at_size(name, width, height): """Loads an image file at the specified size. Does NOT handle exceptions!""" from gi.repository import GdkPixbuf, Gdk from cairo import ImageSurface, FORMAT_ARGB32, Context pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(name, width, height) surface = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(surface) Gdk.cairo_set_source_pixbuf(ctx, pixbuf, 0, 0) ctx.paint() return surface
def on_draw_sprite_draw(self, widget: Gtk.DrawingArea, ctx: cairo.Context): if not self._drawing_is_active: return True scale = 4 sprite, x, y, w, h = self._get_sprite_anim() ctx.scale(scale, scale) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ww, wh = widget.get_size_request() if ww < w or wh < h: widget.set_size_request(w * scale, h * scale) ctx.scale(1 / scale, 1 / scale) return True
def _draw_actor_sprite(self, ctx: cairo.Context, actor: SsaActor, x, y): """Draws the sprite for an actor""" if actor.actor.entid == 0: sprite = self.sprite_provider.get_actor_placeholder( actor.actor.id, actor.pos.direction.id, self._redraw)[0] else: sprite = self.sprite_provider.get_monster( actor.actor.entid, actor.pos.direction.id, lambda: GLib.idle_add(self._redraw))[0] ctx.translate(x, y) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.translate(-x, -y)
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 do_draw(self, cr: cairo.Context, width: int = 0, height: int = 0) -> bool: if not self._model: return False if not self._back_buffer: return False cr.set_source_surface(self._back_buffer, 0, 0) cr.paint() return False
def on_draw(self, subindex: int, widget: Gtk.DrawingArea, ctx: cairo.Context): scale = 2 portrait = self._portrait_provider.get( self.item_id, subindex, lambda: GLib.idle_add(widget.queue_draw), False) ctx.set_source_rgb(1, 1, 1) ctx.rectangle(0, 0, *widget.get_size_request()) ctx.fill() ctx.scale(scale, scale) ctx.set_source_surface(portrait) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.scale(1 / scale, 1 / scale) return True
def _do_draw(self, cr: cairo.Context) -> None: pixbuf = self.props.pixbuf if pixbuf is None: return scale = self._parent._widget_dist_from_canvas((1, 1)) offset = self._parent._widget_coord_from_canvas((0, 0)) with cairo_saved(cr): cr.translate(*offset) cr.scale(*scale) Gdk.cairo_set_source_pixbuf(cr, pixbuf, pixbuf_x=0, pixbuf_y=0) cr.get_source().set_filter(cairo.Filter.FAST) cr.paint()
class MapSurface(object): """wrapper to render the map to svg/png""" def __init__(self, hexmap=None, filename=None, width=None, height=None, size=None): self.hexmap = hexmap if self.hexmap is None: raise ValueError("No map was passed to {}".format(self.__class__.__name__)) self.surface_name = filename or "test.svg" self.size = size or 32.0 self.surface_width = width if self.surface_width is None: self.surface_width = (self.hexmap.map.cols + .5) * self.size * SQRT3 self.surface_height = height if self.surface_height is None: self.surface_height = (self.hexmap.map.rows * 1.5 + .25) * self.size self.layer = [] # build base map self.surface = SVGSurface(self.surface_name + ".svg", self.surface_width, self.surface_height) self.context = Context(self.surface) # background: magenta self.context.save() self.context.set_source_rgb(1.0, 0.0, 1.0) self.context.paint() self.context.restore() def add_layer(self, renderer_cls, position=None): if not position: self.layer.append(renderer_cls(self)) else: self.layer.insert(position, renderer_cls(self)) def render(self): print "Rendering {} ({}x{})".format(self.surface_name, self.surface_width, self.surface_height) for renderer in self.layer: renderer.render() def finalise(self, with_png=False): print "finalising:" if with_png is True: print "PNG" self.surface.write_to_png(self.surface_name + ".png") print "SVG" self.surface.finish() print "DONE!"
def draw(self, wdg, ctx: cairo.Context): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) # Background if self.map_bg is not None: if self.level_id == WORLD_MAP_DEFAULT_ID: # We display the bottom right of the map. ctx.set_source_surface(self.map_bg, -504, -1008) else: ctx.set_source_surface(self.map_bg, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() size_w, size_h = self.draw_area.get_size_request() size_w /= self.scale size_h /= self.scale # Tile Grid if self.draw_tile_grid: self.tile_grid_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) # Selection self._handle_selection(ctx) # RENDER MARKERS self.markers_at_pos = {} for i, marker in enumerate(self.markers): if marker != self._editing and marker != self._hide and marker.level_id == self.level_id and marker.reference_id <= -1: self._draw_marker(ctx, marker) if self._editing: # Black out ctx.set_source_rgba(0, 0, 0, 0.5) ctx.rectangle(0, 0, size_w, size_h) ctx.fill() # Render editing marker self._draw_marker(ctx, self._editing) # nah, too crowded. #for (x, y), list_of_markers in self.markers_at_pos.items(): # ms = [self.markers.index(m) for m in list_of_markers] # self._draw_name(ctx, ms, x, y) return True
def paint_image(self, img, x, y, w, h): #roundtrip via png (yuk) from io import BytesIO png = BytesIO() img.save(png, format="PNG") reader = BytesIO(png.getvalue()) png.close() img = ImageSurface.create_from_png(reader) gc = Context(self.backing) gc.rectangle(x, y, w, h) gc.clip() gc.set_operator(OPERATOR_CLEAR) gc.rectangle(x, y, w, h) gc.fill() gc.set_operator(OPERATOR_SOURCE) gc.translate(x, y) gc.rectangle(0, 0, w, h) gc.set_source_surface(img, x, y) gc.paint()
def screen(self, base_w, base_h, ctx: cairo.Context, display_id: int): if display_id == 0: self.decode_screen() ctx.translate(base_w * self._scale / 2, base_h * self._scale / 2) ctx.rotate(-radians(self._screen_rotation_degrees)) if self._screen_rotation_degrees == 90 or self._screen_rotation_degrees == 270: ctx.translate(-base_h * self._scale / 2, -base_w * self._scale / 2) else: ctx.translate(-base_w * self._scale / 2, -base_h * self._scale / 2) ctx.scale(self._scale, self._scale) if display_id == 0: ctx.set_source_surface(self._upper_image) else: ctx.set_source_surface(self._lower_image) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if self._after_render_hook: self._after_render_hook(ctx, display_id)
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 make_label(text, filename, size=12, angle=0): ''' Parameters: ----------- text : string Text to be displayed filename : string Path to a font size : int Font size in 1/64th points angle : float Text angle in degrees ''' face = Face(filename) face.set_char_size( size*64 ) # FT_Angle is a 16.16 fixed-point value expressed in degrees. angle = FT_Angle(angle * 65536) matrix = FT_Matrix( FT_Cos( angle ), - FT_Sin( angle ), FT_Sin( angle ) , FT_Cos( angle ) ) flags = FT_LOAD_RENDER pen = FT_Vector(0,0) FT_Set_Transform( face._FT_Face, byref(matrix), byref(pen) ) previous = 0 xmin, xmax = 0, 0 ymin, ymax = 0, 0 for c in text: face.load_char(c, flags) kerning = face.get_kerning(previous, c) previous = c bitmap = face.glyph.bitmap pitch = face.glyph.bitmap.pitch width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows top = face.glyph.bitmap_top left = face.glyph.bitmap_left pen.x += kerning.x x0 = (pen.x >> 6) + left x1 = x0 + width y0 = (pen.y >> 6) - (rows - top) y1 = y0 + rows xmin, xmax = min(xmin, x0), max(xmax, x1) ymin, ymax = min(ymin, y0), max(ymax, y1) pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y L = ImageSurface(FORMAT_A8, xmax-xmin, ymax-ymin) previous = 0 pen.x, pen.y = 0, 0 ctx = Context(L) for c in text: face.load_char(c, flags) kerning = face.get_kerning(previous, c) previous = c bitmap = face.glyph.bitmap pitch = face.glyph.bitmap.pitch width = face.glyph.bitmap.width rows = face.glyph.bitmap.rows top = face.glyph.bitmap_top left = face.glyph.bitmap_left pen.x += kerning.x x = (pen.x >> 6) - xmin + left y = - (pen.y >> 6) + ymax - top if (width > 0): glyph_surface = make_image_surface(face.glyph.bitmap) ctx.set_source_surface(glyph_surface, x, y) ctx.paint() pen.x += face.glyph.advance.x pen.y += face.glyph.advance.y L.flush() return L
def generateOverlay(text, font, showFlumotion, showCC, showXiph, width, height): """Generate an transparent image with text + logotypes rendered on top of it suitable for mixing into a video stream @param text: text to put in the top left corner @type text: str @param font: font description used to render the text @type: str @param showFlumotion: if we should show the flumotion logo @type showFlumotion: bool @param showCC: if we should show the Creative Common logo @type showCC: bool @param showXiph: if we should show the xiph logo @type showXiph: bool @param width: width of the image to generate @type width: int @param height: height of the image to generate @type height: int @returns: raw image and if images or if text overflowed @rtype: 3 sized tuple of string and 2 booleans """ from cairo import ImageSurface from cairo import Context image = ImageSurface(cairo.FORMAT_ARGB32, width, height) context = Context(image) subImages = [] if showXiph: subImages.append(os.path.join(configure.imagedir, '36x36', 'xiph.png')) if showCC: subImages.append(os.path.join(configure.imagedir, '36x36', 'cc.png')) if showFlumotion: subImages.append(os.path.join(configure.imagedir, '36x36', 'fluendo.png')) imagesOverflowed = False offsetX = BORDER for subPath in subImages: sub = ImageSurface.create_from_png(subPath) subX = sub.get_width() subY = sub.get_height() offsetY = height - subY - BORDER context.set_source_surface(sub, offsetX, offsetY) context.paint() if (offsetX + subX) > width: imagesOverflowed = True offsetX += subX + BORDER textOverflowed = False if text: pcContext = pangocairo.CairoContext(context) pangoLayout = pcContext.create_layout() if font is not None: font = pango.FontDescription(font) if not font.get_family() or \ not font.get_family().lower() in [family.get_name().lower() for family in pangoLayout.get_context().list_families()]: font.set_family(FONT) if font.get_size() == 0: font.set_size(FONT_SIZE) else: font = pango.FontDescription('%s %s' % (FONT, FONT_PROPS)) pangoLayout.set_font_description(font) context.move_to(TEXT_XOFFSET+2, TEXT_YOFFSET+2) pangoLayout.set_markup('<span foreground="black" >%s</span>' % text) pcContext.show_layout(pangoLayout) context.move_to(TEXT_XOFFSET, TEXT_YOFFSET) pangoLayout.set_markup('<span foreground="white" >%s</span>' % text) pcContext.show_layout(pangoLayout) textWidth, textHeight = pangoLayout.get_pixel_size() if textWidth > width: textOverflowed = True if cairo.version < '1.2.6': buf = image.get_data_as_rgba() else: buf = image.get_data() return buf, imagesOverflowed, textOverflowed
raise RuntimeError('pitch != width * 4 for color bitmap: Please report this.') bitmap = np.array(bitmap.buffer, dtype=np.uint8).reshape((bitmap.rows,bitmap.width,4)) I = ImageSurface(FORMAT_ARGB32, width, rows) try: ndI = np.ndarray(shape=(rows,width), buffer=I.get_data(), dtype=np.uint32, order='C', strides=[I.get_stride(), 4]) except NotImplementedError: raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)") # Although both are 32-bit, cairo is host-order while # freetype is small endian. ndI[:,:] = bitmap[:,:,3] * 2**24 + bitmap[:,:,2] * 2**16 + bitmap[:,:,1] * 2**8 + bitmap[:,:,0] I.mark_dirty() surface = ImageSurface(FORMAT_ARGB32, 2*width, rows) ctx = Context(surface) ctx.set_source_surface(I, 0, 0) ctx.paint() ctx.set_source_surface(I, width/2, 0) ctx.paint() ctx.set_source_surface(I, width , 0) ctx.paint() surface.write_to_png("emoji-color-cairo.png") Image.open("emoji-color-cairo.png").show()