def cairo_paint_from_source(self, set_source_fn, source, x: int, y: int, iw: int, ih: int, width: int, height: int, options): """ must be called from UI thread """ backing = self._backing log("cairo_paint_surface%s backing=%s, paint box line width=%i", (set_source_fn, source, x, y, iw, ih, width, height, options), backing, self.paint_box_line_width) if not backing: return gc = Context(backing) if self.paint_box_line_width: gc.save() gc.rectangle(x, y, width, height) gc.clip() gc.set_operator(OPERATOR_CLEAR) gc.rectangle(x, y, width, height) gc.fill() gc.set_operator(OPERATOR_SOURCE) gc.translate(x, y) if iw != width or ih != height: gc.scale(width / iw, height / ih) gc.rectangle(0, 0, width, height) set_source_fn(gc, source, 0, 0) gc.paint() if self.paint_box_line_width: gc.restore() encoding = options.get("encoding") self.cairo_paint_box(gc, encoding, x, y, width, height)
def convert_to_png(input_file, output_file, width=None, height=None): """Convert svg to png.""" if width and height: handle = Rsvg.Handle() svg = handle.new_from_file(input_file) dim = svg.get_dimensions() img = ImageSurface( FORMAT_ARGB32, width, height) ctx = Context(img) ctx.scale(width / dim.width, height / dim.height) svg.render_cairo(ctx) png_io = BytesIO() img.write_to_png(png_io) with open(output_file, 'wb') as fout: fout.write(png_io.getvalue()) fout.close() svg.close() png_io.close() img.finish() else: with open(input_file, "r") as content_file: svg = content_file.read() content_file.close() fout = open(output_file, "wb") svg2png(bytestring=bytes(svg, "UTF-8"), write_to=fout) fout.close()
def convert_svg2png(infile, outfile, w, h): """ Converts svg files to png using Cairosvg or Inkscape @file_path : String; the svg file absolute path @dest_path : String; the png file absolute path """ if use_inkscape: cmd = Popen(["inkscape", "-z", "-f", infile, "-e", outfile, "-w", str(w), "-h", str(h)], stdout=PIPE, stderr=PIPE) cmd.communicate() else: handle = Rsvg.Handle() svg = handle.new_from_file(infile) dim = svg.get_dimensions() img = ImageSurface(FORMAT_ARGB32, w, h) ctx = Context(img) ctx.scale(w / dim.width, h / dim.height) svg.render_cairo(ctx) png_io = BytesIO() img.write_to_png(png_io) with open(outfile, 'wb') as fout: fout.write(png_io.getvalue()) svg.close() png_io.close() img.finish()
def write_text(self): if not self.text: # Nothing useful to draw, return now! return if self.resized( ) or self.text != self.prev_text or self.text_overlay is None: # Need to recreate the cache drawing self.text_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) ctx = Context(self.text_overlay) pg = CairoContext(ctx) pl = pg.create_layout() pl.set_font_description(self.text_font) pl.set_width(-1) # No text wrapping pl.set_text(self.text) plsize = pl.get_size() text_width = plsize[0] // SCALE text_height = plsize[1] // SCALE area_width_without_text = self.width - text_width area_height_without_text = self.height - text_height ctx.move_to(area_width_without_text // 2, area_height_without_text // 2) ctx.set_source_rgb(1, 1, 1) pg.update_layout(pl) pg.show_layout(pl) self.cr.set_source_surface(self.text_overlay) self.cr.paint()
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 export_svg(fn, paths, size, line_with=0.1, scale_factor=None): from cairo import SVGSurface, Context from .ddd import spatial_sort_2d as sort if not scale_factor: scale_factor = size s = SVGSurface(fn, size, size) c = Context(s) c.set_line_width(0.1) paths = sort(paths) for path in paths: path *= scale_factor c.new_path() c.move_to(*path[0, :]) for p in path[1:]: c.line_to(*p) c.stroke() c.save()
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 create_cairo_font_face_for_file(filename, faceindex=0, loadoptions=0): """ http://cairographics.org/freetypepython """ CAIRO_STATUS_SUCCESS = 0 FT_Err_Ok = 0 # find shared objects _freetype_so = ctypes.CDLL('libfreetype.so.6') _cairo_so = ctypes.CDLL('libcairo.so.2') _cairo_so.cairo_ft_font_face_create_for_ft_face.restype = ctypes.c_void_p _cairo_so.cairo_ft_font_face_create_for_ft_face.argtypes = [ ctypes.c_void_p, ctypes.c_int ] _cairo_so.cairo_set_font_face.argtypes = [ctypes.c_void_p, ctypes.c_void_p] _cairo_so.cairo_font_face_status.argtypes = [ctypes.c_void_p] _cairo_so.cairo_status.argtypes = [ctypes.c_void_p] # initialize freetype _ft_lib = ctypes.c_void_p() if FT_Err_Ok != _freetype_so.FT_Init_FreeType(ctypes.byref(_ft_lib)): raise "Error initialising FreeType library." class PycairoContext(ctypes.Structure): _fields_ = [("PyObject_HEAD", ctypes.c_byte * object.__basicsize__), ("ctx", ctypes.c_void_p), ("base", ctypes.c_void_p)] _surface = ImageSurface(FORMAT_A8, 0, 0) # create freetype face ft_face = ctypes.c_void_p() cairo_ctx = Context(_surface) cairo_t = PycairoContext.from_address(id(cairo_ctx)).ctx _cairo_so.cairo_ft_font_face_create_for_ft_face.restype = ctypes.c_void_p if FT_Err_Ok != _freetype_so.FT_New_Face(_ft_lib, filename, faceindex, ctypes.byref(ft_face)): raise Exception("Error creating FreeType font face for " + filename) # create cairo font face for freetype face cr_face = _cairo_so.cairo_ft_font_face_create_for_ft_face( ft_face, loadoptions) if CAIRO_STATUS_SUCCESS != _cairo_so.cairo_font_face_status(cr_face): raise Exception("Error creating cairo font face for " + filename) _cairo_so.cairo_set_font_face(cairo_t, cr_face) if CAIRO_STATUS_SUCCESS != _cairo_so.cairo_status(cairo_t): raise Exception("Error creating cairo font face for " + filename) face = cairo_ctx.get_font_face() return face
def setup_doc(name): ''' ''' doc = PDFSurface(name, sheet_width*ptpin, sheet_height*ptpin) ctx = Context(doc) ctx.scale(ptpin, ptpin) set_font_face_from_file(ctx, 'DejaVuSerifCondensed.ttf') return doc, ctx
def textwidth(text: str, fontSize: int, font: str): fn = abspath(gettempdir() + "/" + next(_get_candidate_names())) width = len(text) * fontSize with SVGSurface(fn, 1280, 720) as surface: cr = Context(surface) cr.select_font_face(font, FONT_SLANT_NORMAL, FONT_WEIGHT_BOLD) cr.set_font_size(fontSize) width = cr.text_extents(text)[2] remove(fn) return round(width, 1)
def __missing__(self, zoom): zoomfac = (1 + 2 * self._r) * zoom self[zoom] = SVGC = ImageSurface(FORMAT_ARGB32, ceil(zoomfac * self._h), ceil(zoomfac * self._k)) sccr = Context(SVGC) sccr.scale(zoom, zoom) sccr.translate(self._uh, self._uk) self._paint_function(sccr) return SVGC
def get_context_for_image(self, zoom): """Creates a temporary cairo context for the image surface :param zoom: The current scaling factor :return: Cairo context to draw on """ cairo_context = Context(self.__image) c = CairoContext(cairo_context) c.scale(zoom * self.multiplicator, zoom * self.multiplicator) return c
def extract_polygon_data(romset_dir, cinematic): global polygon_data, pdata_offset global cinematic_entries global cinematic_counter global video2_entries global game_level if cinematic: try: polygon_data = open(f"{romset_dir}/cinematic.rom", "rb").read() except: print("FIXME! Did not find a cinematic.rom file...") return entries = cinematic_entries level_path = f"{output_dir}/level_{game_level}" dirpath = f"{level_path}/cinematic/" makedir(level_path) else: try: polygon_data = open(f"{romset_dir}/video2.rom", "rb").read() except: print("FIXME! Did not find a video2.rom file...") return entries = video2_entries dirpath = f"{output_dir}/common_video/" game_level = 0 makedir(dirpath) for addr in entries.keys(): entry = entries[addr] s = SVGSurface(f"{dirpath}/{entry['label']}.svg", 320, 200) c = Context(s) zoom = entry["zoom"] x = entry["x"] y = entry["y"] if not isinstance(zoom, int): zoom = 0x40 #HACK! if not isinstance(x, int): x = 160 #HACK! if not isinstance(y, int): y = 100 #HACK! #print ("\ndecoding polygons at {}: {}".format(hex(addr), entry)) pdata_offset = addr readAndDrawPolygon(c, COLOR_BLACK, zoom, x, y) s.finish() # reset structures: cinematic_entries = {} cinematic_counter = 0
def extract_polygon_data(self, game_level, entries, cinematic): if cinematic: self.game_level = game_level else: self.game_level = 0 try: self.palette_data = open(f"{self.romset_dir}/palettes.rom", "rb").read() except: print("ERROR! Did not find a palettes.rom file...") return if cinematic: try: self.polygon_data = open(f"{self.romset_dir}/cinematic.rom", "rb").read() except: print("ERROR! Did not find a cinematic.rom file...") return level_path = f"{self.output_dir}/level_{game_level}" dirpath = f"{level_path}/cinematic/" makedir(level_path) else: try: self.polygon_data = open(f"{self.romset_dir}/video2.rom", "rb").read() except: print("ERROR! Did not find a video2.rom file...") return dirpath = f"{self.output_dir}/common_video/" makedir(dirpath) for addr in entries.keys(): entry = entries[addr] s = SVGSurface(f"{dirpath}/{entry['label']}.svg", 320, 200) ctx = Context(s) zoom = entry["zoom"] x = entry["x"] y = entry["y"] palette_number = entry["palette_number"] if not isinstance(zoom, int): zoom = 0x40 #HACK! if not isinstance(x, int): x = 160 #HACK! if not isinstance(y, int): y = 100 #HACK! #print ("\ndecoding polygons at {}: {}".format(hex(addr), entry)) self.readAndDrawPolygon(addr, ctx, palette_number, COLOR_BLACK, zoom, x, y) s.finish()
def _scale_down(self, handle, ratio): xsize, ysize = self.size if ratio >= 1.0: # Convert surface = ImageSurface(FORMAT_ARGB32, xsize, ysize) ctx = Context(surface) else: # Scale xsize, ysize = int(xsize * ratio), int(ysize * ratio) surface = ImageSurface(FORMAT_ARGB32, xsize, ysize) ctx = Context(surface) ctx.scale(ratio, ratio) # Render handle.render_cairo(ctx) # Transform to a PIL image for further manipulation size = (xsize, ysize) im = frombuffer('RGBA', size, surface.get_data(), 'raw', 'BGRA', 0, 1) surface.finish() return im, xsize, ysize
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 __init__(self, width: int, height: Optional[int] = None, *, normalise: bool = True): if height is None: height = width self._width = width self._height = height self._surface = ImageSurface(FORMAT_ARGB32, width, height) self._context = Context(self._surface) self._normalise = normalise if self._normalise: self.scale(self._width, self._height)
def draw_progress_overlay(self): if not self.text: # Nothing useful to draw, return now! return if (self.resized() or self.fraction != self.prev_fraction or self.progress_overlay is None): # Need to recreate the cache drawing self.progress_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) ctx = Context(self.progress_overlay) ctx.set_source_rgba(0.1, 0.1, 0.1, 0.3) # Transparent ctx.rectangle(0, 0, self.width * self.fraction, self.height) ctx.fill() self.cr.set_source_surface(self.progress_overlay) self.cr.paint()
def __init__(self, width, height): self.xform = lambda x, y: (x, y) self.img = ImageSurface(FORMAT_RGB24, width, height) self.ctx = Context(self.img) self.ctx.move_to(0, 0) self.ctx.line_to(width, 0) self.ctx.line_to(width, height) self.ctx.line_to(0, height) self.ctx.line_to(0, 0) self.ctx.set_source_rgb(1, 1, 1) self.ctx.fill() self.width = width self.height = height
def func(image, objects, *args, **kwargs): # Allow sending in a single object in every function. if not (isinstance(objects, list) or isinstance(objects, tuple)): objects = [objects] # Calculate the appropriate scaling for the markers. area = image.shape[1] * image.shape[0] for ref_area, scale in MARKER_SCALES: if area >= ref_area: break # TODO: Ideally, we would like to avoid having to create a copy of the # array just to add paddings to support the cairo format, but there's # no way to use a cairo surface with 24bpp. # TODO: Take into account endianness of the machine, as it's possible # it has to be concatenated in the other order in some machines. # We need to add an extra `alpha` layer, as cairo only supports 32 bits # per pixel formats, and our numpy array uses 24. This means creating # one copy before modifying and a second copy afterwards. with_alpha = np.concatenate([ image[..., ::-1], 255 * np.ones( (image.shape[0], image.shape[1], 1), dtype=np.uint8) ], axis=2) surface = ImageSurface.create_for_data(with_alpha, cairo.Format.RGB24, image.shape[1], image.shape[0]) ctx = Context(surface) # Set up the font. If not available, will default to a Sans Serif # font available in the system, so no need to have fallbacks. ctx.select_font_face("DejaVuSans-Bold", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(int(16 * scale)) vis_func(ctx, objects, scale=scale, *args, **kwargs) # Return the newly-drawn image, excluding the extra alpha channel # added. image = with_alpha[..., :-1][..., ::-1] return image
def export_svg(fn, paths, w, h, line_width=0.1): from cairo import SVGSurface, Context s = SVGSurface(fn, w, h) c = Context(s) c.set_line_width(line_width) for path in paths: c.new_path() c.move_to(*path[0, :]) for p in path[1:]: c.line_to(*p) c.stroke() c.save()
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 __init__(self, filename, width, height): """ """ self.filename = filename self.size = width, height handle, dummy_file = mkstemp(prefix='cairoutils-', suffix='.pdf') close(handle) surface = PDFSurface(dummy_file, width, height) self.context = Context(surface) self.commands = [] self.garbage = [dummy_file] self.page = [] self.point = Point(0, 0) self.stack = [(1, 0, 0, 0, -1, height)] self.affine = Affine(*self.stack[0])
def svg_to_png(filename, icondata, w=128, h=128): if not SVG_TO_PNG: return None Rsvg = load_Rsvg() log("svg_to_png%s Rsvg=%s", (filename, "%i bytes" % len(icondata), w, h), Rsvg) if not Rsvg: return None try: from cairo import ImageSurface, Context, FORMAT_ARGB32 #pylint: disable=no-name-in-module, import-outside-toplevel #'\sinkscape:[a-zA-Z]*=["a-zA-Z0-9]*' img = ImageSurface(FORMAT_ARGB32, w, h) ctx = Context(img) handle = Rsvg.Handle.new_from_data(icondata) dim = handle.get_dimensions() ctx.scale(w / dim.width, h / dim.height) handle.render_cairo(ctx) del handle img.flush() buf = BytesIO() img.write_to_png(buf) icondata = buf.getvalue() buf.close() img.finish() return icondata except Exception: log("svg_to_png%s", (icondata, w, h), exc_info=True) if re.findall(INKSCAPE_RE, icondata): #try again after stripping the bogus inkscape attributes #as some rsvg versions can't handle that (ie: Debian Bullseye) icondata = re.sub(INKSCAPE_RE, b"", icondata) return svg_to_png(filename, icondata, w, h) if icondata.find(INKSCAPE_BROKEN_SODIPODI_DTD) > 0: icondata = icondata.replace(INKSCAPE_BROKEN_SODIPODI_DTD, INKSCAPE_SODIPODI_DTD) return svg_to_png(filename, icondata, w, h) log.error("Error: failed to convert svg icon") if filename: log.error(" '%s':", filename) log.error(" %i bytes, %s", len(icondata), ellipsizer(icondata)) return None
def main(args, **argv): from dddUtils.ioOBJ import load_2d as load from cairo import SVGSurface, Context from numpy import array from glob import glob prefix = args.prefix size = args.size scale = args.scale one = 1.0/size steps = args.steps stride = args.stride skip = args.skip out = prefix + '.svg' print('making file: {:s}'.format(out)) s = SVGSurface(out, size, size) c = Context(s) c.set_line_width(0.1) c.set_source_rgba(*BLACK) for fn in sorted(glob(prefix + '*.2obj'))[skip:steps:stride]: print(fn) data = load(fn) vertices = data['vertices'] vertices *= scale*size edges = data['edges'] # make_random_line(c, vertices, edges) make_line(c, vertices, edges) c.save() return
def main(args, **argv): # from render.render import Render from dddUtils.ioOBJ import load_2d as load from cairo import SVGSurface, Context from numpy import array size = args.size scale = args.scale one = 1.0 / size data = load(args.fn) print(data) vertices = data['vertices'] faces = data['faces'] edges = data['edges'] out = '.'.join(args.fn.split('.')[:-1]) + '.svg' print('making file: {:s}'.format(out)) s = SVGSurface(out, size, size) c = Context(s) c.set_line_width(0.1) c.set_source_rgba(*BLACK) vertices -= get_mid(vertices) vertices *= scale vertices += array([[0.5, 0.5]]) vertices *= size make_triangles(c, vertices, faces, edges) # make_random_length_strips(c, vertices, faces, edges) c.save() return
def plugmap(w, s, e, n): west = open_df.long.min() south = open_df.lat.min() east = open_df.long.max() north = open_df.lat.max() zoom = 5 # tiles = list(mercantile.tiles(west, south, east, north, zoom)) print(tiles) tile_size = (256, 256) # создаем пустое изображение в которое как мозайку будем вставлять тайлы # для начала просто попробуем отобразить все четыре тайла в строчку map_image = ImageSurface(FORMAT_ARGB32, tile_size[0] * len(tiles), tile_size[1]) # создаем контекст для рисования ctx = Context(map_image) for idx, t in enumerate(tiles): server = random.choice(['a', 'b', 'c' ]) # у OSM три сервера, распределяем нагрузку url = 'http://{server}.tile.openstreetmap.org/{zoom}/{x}/{y}.png'.format( server=server, zoom=t.z, x=t.x, y=t.y) # запрашиваем изображение response = urllib.request.urlopen(url) # создаем cairo изображние img = ImageSurface.create_from_png(io.BytesIO(response.read())) # рисуем изображение, с правильным сдвигом по оси x ctx.set_source_surface(img, idx * tile_size[0], 0) ctx.paint() # сохраняем собраное изображение в файл with open("map.png", "wb") as f: map_image.write_to_png(f)
def _to_png(self, font, font_position=None, dst=None, limit=800, size=1500, tab_width=1500, padding_characters=""): """Use HB, FreeType and Cairo to produce a png for a table. Parameters ---------- font: DFont font_position: str Label indicating which font has been used. dst: str Path to output image. If no path is given, return in-memory """ # TODO (M Foley) better packaging for pycairo, freetype-py # and uharfbuzz. # Users should be able to pip install these bindings without needing # to install the correct libs. # A special mention to the individuals who maintain these packages. Using # these dependencies has sped up the process of creating diff images # significantly. It's an incredible age we live in. y_tab = int(1500 / 25) x_tab = int(tab_width / 64) width, height = 1024, 200 cells_per_row = int((width - x_tab) / x_tab) # Compute height of image x, y, baseline = x_tab, 0, 0 for idx, row in enumerate(self._data[:limit]): x += x_tab if idx % cells_per_row == 0: y += y_tab x = x_tab height += y height += 100 # draw image Z = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(Z) ctx.rectangle(0, 0, width, height) ctx.set_source_rgb(1, 1, 1) ctx.fill() # label image ctx.set_font_size(30) ctx.set_source_rgb(0.5, 0.5, 0.5) ctx.move_to(x_tab, 50) ctx.show_text("{}: {}".format(self.table_name, len(self._data))) ctx.move_to(x_tab, 100) if font_position: ctx.show_text("Font Set: {}".format(font_position)) if len(self._data) > limit: ctx.set_font_size(20) ctx.move_to(x_tab, 150) ctx.show_text( "Warning: {} different items. Only showing most serious {}". format(len(self._data), limit)) hb.ot_font_set_funcs(font.hbfont) # Draw glyphs x, y, baseline = x_tab, 200, 0 x_pos = x_tab y_pos = 200 for idx, row in enumerate(self._data[:limit]): string = "{}{}{}".format(padding_characters, row['string'], padding_characters) buf = self._shape_string(font, string, row['features']) char_info = buf.glyph_infos char_pos = buf.glyph_positions for info, pos in zip(char_info, char_pos): gid = info.codepoint font.ftfont.load_glyph(gid, flags=6) bitmap = font.ftslot.bitmap if bitmap.width > 0: ctx.set_source_rgb(0, 0, 0) glyph_surface = _make_image_surface( font.ftfont.glyph.bitmap, copy=False) ctx.set_source_surface( glyph_surface, x_pos + font.ftslot.bitmap_left + (pos.x_offset / 64.), y_pos - font.ftslot.bitmap_top - (pos.y_offset / 64.)) glyph_surface.flush() ctx.paint() x_pos += (pos.x_advance) / 64. y_pos += (pos.y_advance) / 64. x_pos += x_tab - (x_pos % x_tab) if idx % cells_per_row == 0: # add label if font_position: ctx.set_source_rgb(0.5, 0.5, 0.5) ctx.set_font_size(10) ctx.move_to(width - 20, y_pos) ctx.rotate(1.5708) ctx.show_text(font_position) ctx.set_source_rgb(0, 0, 0) ctx.rotate(-1.5708) # Start a new row y_pos += y_tab x_pos = x_tab Z.flush() if dst: Z.write_to_png(dst) else: img = StringIO() Z.write_to_png(img) return Image.open(img)
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
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 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