def draw_overlay(dst, lineseg, pxcoord): dims = [dst.shape[1], dst.shape[0]] surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, dims[0], dims[1]) ctx = cairo.Context(surface) ctx.scale(dims[0], dims[1]) ctx.set_line_width(0.005) # Stroke a path along lineseg ctx.set_source_rgba(1.0, 0.8, 0.8, 0.15) ctx.move_to(lineseg[0][0], lineseg[0][1]) ctx.line_to(lineseg[1][0], lineseg[1][1]) ctx.stroke() # Draw circle around pxcoord ctx.set_source_rgba(1.0, 0.8, 0.8, 0.15) ctx.save() ctx.translate(pxcoord[0], pxcoord[1]) ctx.scale(0.02, 0.02) ctx.arc(0., 0., 1., 0., 2 * np.pi) ctx.restore() ctx.stroke() if False: f = cairo.ToyFontFace("") ctx.move_to(.5, .5) ctx.show_text("Philip") # Perform composition buf = surface.get_data() rgb = np.ndarray(shape=dims[:2], dtype=np.uint32, buffer=buf) color = np.float32([(rgb >> 8) & 0xff, (rgb >> 16) & 0xff, (rgb >> 0) & 0xff]) color = color.swapaxes(0, 2).swapaxes(0, 1) a = np.float32((rgb >> 24) & 0xff) / 255.0 alpha = np.array([a, a, a]).swapaxes(0, 2).swapaxes(0, 1) np.copyto(dst, dst * (1 - alpha) + color)
def createScaledFont(family, size, slant=cairo.FONT_SLANT_NORMAL, weight=cairo.FONT_WEIGHT_NORMAL): face = cairo.ToyFontFace(family, slant, weight) return cairo.ScaledFont(face, cairo.Matrix(xx=size, yy=size), cairo.Matrix(), DEFAULT_FONT_OPTIONS)
def draw_label_on_screen(self, lab, point, size=16, color=(.35, .35, .35, 1.0), bold=False): ''' You'll never guess what this method does. :param lab: String with the text to draw. :param point: (x,y) tuple or other size-2 iterable. Where to draw it. :param size: Font size (default: 16) :param color: Color (RGBA tuple). Default is a light grey. :param bold: Boolean. :return: ''' oldm = self.ctx.get_matrix() oldfm = self.ctx.get_font_matrix() self.ctx.set_matrix(cairo.Matrix(1., 0., 0., 1., 0., 0.)) self.ctx.set_font_matrix( cairo.Matrix(float(size), 0., 0., float(size), 0., 0.)) oldf = self.ctx.get_font_face() if bold: self.ctx.set_font_face( cairo.ToyFontFace("sans-serif", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)) te = self.ctx.text_extents(lab) self.ctx.move_to(*point) self.ctx.rel_move_to(2, +te[3]) cr = (.35, .35, .35, 1.0) self.ctx.set_source_rgba(cr[0], cr[1], cr[2], cr[3]) self.ctx.show_text(lab) self.ctx.fill() self.ctx.set_matrix(oldm) self.ctx.set_font_matrix(oldfm) self.ctx.set_font_face(oldf)
def draw_text(self, context, string, x, y): if self.text_font: context.set_font_face( cairo.ToyFontFace(self.text_font, cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL)) context.set_font_size(self.text_size) xb, yb, w, h, dx, dy = context.text_extents(string) ho = (self.avatar_size / 2) - (h / 2) if self.align_right: context.move_to(0, 0) self.set_norm_col() context.rectangle(x - w - (self.text_pad * 2), y + ho - self.text_pad, w + (self.text_pad * 4), h + (self.text_pad * 2)) context.fill() self.set_text_col() context.move_to(x - w - self.text_pad, y + ho + h) context.show_text(string) else: context.move_to(0, 0) self.set_norm_col() context.rectangle(x - (self.text_pad * 2), y + ho - self.text_pad, w + (self.text_pad * 4), h + (self.text_pad * 2)) context.fill() self.set_text_col() context.move_to(x + self.text_pad, y + ho + h) context.show_text(string)
def _InitCairo(self): self.surface = cairo.PDFSurface( self.options['output_pdf'], self.width * self.POINTS_TO_MILLIMETERS_RATIO, self.height * self.POINTS_TO_MILLIMETERS_RATIO) self.fonts = dict() for slant in self.FONT_SLANTS: self.fonts[slant] = dict() for weight in self.FONT_WEIGHTS: self.fonts[slant][weight] = \ cairo.ToyFontFace("Monospace", slant, weight) self.context = cairo.Context(self.surface) self.context.scale(self.POINTS_TO_MILLIMETERS_RATIO, self.POINTS_TO_MILLIMETERS_RATIO) self.context.set_font_face( self.fonts[cairo.FONT_SLANT_NORMAL][cairo.FONT_WEIGHT_NORMAL]) self.context.set_font_size(1) self.font_ascent, self.font_descent, self.font_height, \ self.font_max_x_advance, self.font_max_y_advance = \ self.context.font_extents() font_scale_factor = \ self.column_width / (self.font_max_x_advance * self.characters_in_a_row) self.context.set_font_size(font_scale_factor) self.font_ascent, self.font_descent, self.font_height, \ self.font_max_x_advance, self.font_max_y_advance = \ self.context.font_extents() self.context.set_line_width(0.05)
def _get_font(font_spec, default): raw_font = default settings = _get_settings("org.gnome.desktop.interface") if settings: if font_spec in settings.list_keys(): raw_font = settings.get_string(font_spec) face = raw_font.rsplit(" ", 1)[0] return cairo.ToyFontFace(face)
def _build_csf(self): "Builds and caches a Cairo Scaled Font." fontFace = cr.ToyFontFace(self.name) identityMatrix = cr.Matrix() fontOptions = cr.FontOptions() # get defaults scaling = self.size * self._gschemScalingConstant scalingMatrix = cr.Matrix(xx = scaling, yy = scaling) self._csf = cr.ScaledFont(fontFace, scalingMatrix, identityMatrix, fontOptions)
def createScaledFont(family, size, slant=cairo.FONT_SLANT_NORMAL, weight=cairo.FONT_WEIGHT_NORMAL): """ Simple helper function to create a cairo ScaledFont. """ face = cairo.ToyFontFace(family, slant, weight) DEFAULT_FONT_OPTIONS = cairo.FontOptions() DEFAULT_FONT_OPTIONS.set_antialias(cairo.ANTIALIAS_SUBPIXEL) return cairo.ScaledFont(face, cairo.Matrix(xx=size, yy=size), cairo.Matrix(), DEFAULT_FONT_OPTIONS)
def drawRuler(self, cr): # FIXME use system defaults cr.set_font_face(cairo.ToyFontFace("Cantarell")) cr.set_font_size(13) textwidth = cr.text_extents(time_to_string(0))[2] for scale in self.scale: spacing = Zoomable.zoomratio * scale if spacing >= textwidth * 1.5: break offset = self.pixbuf_offset % spacing self.drawFrameBoundaries(cr) self.drawTicks(cr, offset, spacing, scale) self.drawTimes(cr, offset, spacing, scale)
def render_char(char, font_family, font_slant, font_weight, font_size, box_size, origin): font = cairo.ToyFontFace(font_family, {'n': cairo.FONT_SLANT_NORMAL}[font_slant], { 'n': cairo.FONT_WEIGHT_NORMAL, 'b': cairo.FONT_WEIGHT_BOLD }[font_weight]) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, box_size[0], box_size[1]) ctx = cairo.Context(surface) ctx.set_font_size(font_size) ctx.set_font_face(font) ctx.set_source_rgb(0, 0, 0) ctx.move_to( origin[0], origin[1] ) # NOTE that there seems to be a bug with move_to and show_text. It only renders to integer coordinates. :/ ctx.show_text(char) surface.write_to_png('%03d.png' % (ord(char), ))
def draw_text(self, context, string, pos_x, pos_y): """ Draw username & background at given position """ if self.text_font: context.set_font_face( cairo.ToyFontFace(self.text_font, cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL)) context.set_font_size(self.text_size) _xb, _yb, width, height, _dx, _dy = context.text_extents(string) height_offset = (self.avatar_size / 2) - (height / 2) if self.align_right: context.move_to(0, 0) self.set_norm_col() context.rectangle(pos_x - width - (self.text_pad * 2), pos_y + height_offset - self.text_pad, width + (self.text_pad * 4), height + (self.text_pad * 2)) context.fill() self.set_text_col() context.move_to(pos_x - width - self.text_pad, pos_y + height_offset + height) context.show_text(string) else: context.move_to(0, 0) self.set_norm_col() context.rectangle(pos_x - (self.text_pad * 2), pos_y + height_offset - self.text_pad, width + (self.text_pad * 4), height + (self.text_pad * 2)) context.fill() self.set_text_col() context.move_to(pos_x + self.text_pad, pos_y + height_offset + height) context.show_text(string)
import generate import cairo import time start_time = int(time.time()) W = (210 / 25.4) * 72 H = (297 / 25.4) * 72 surface = cairo.PDFSurface(f"output/cards_{start_time:d}.pdf", W, H) cx = cairo.Context(surface) pt_mm = 72 / 25.4 cx.scale(pt_mm, pt_mm) cx.set_source_rgba(0.0, 0.0, 0.0, 1.0) cx.set_line_width(0.3) cx.set_line_cap(cairo.LINE_CAP_ROUND) label_face = cairo.ToyFontFace("Fira Mono Medium", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) the_face = cairo.ToyFontFace("Fira Sans Book", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) top_margin = 25.0 left_margin = 16.0 col_shift = 9.0 row_shift = 10.0 card_shift = 45.0 bank_shift = 100.0 page_number_x = 98 page_number_y = 285 # ought to compute font metrics to do these properly! deltax = -1.5
def test_toy_font_get_weight(): font_face = cairo.ToyFontFace("") assert font_face.get_weight() == cairo.FontWeight.NORMAL assert isinstance(font_face.get_weight(), cairo.FontWeight)
def test_toy_font_get_slant(): font_face = cairo.ToyFontFace("") assert font_face.get_slant() == cairo.FontSlant.NORMAL assert isinstance(font_face.get_slant(), cairo.FontSlant)
def test_toy_font_get_family(): font_face = cairo.ToyFontFace("") assert isinstance(font_face.get_family(), str)
def test_toy_font_face(): with pytest.raises(TypeError): cairo.ToyFontFace(object())
def __new__(cls, *args, **kwargs): import cairo return cairo.ToyFontFace(*args, **kwargs)
def draw_tree(tree, outname): # get the layout of the tree structure = [{} for _ in range(len(tree))] i = 0 for level in tree: j = 0 curr = structure[i] for key in level.keys(): curr.update({key: j}) j += 1 i += 1 typecolors = { "": (150, 150, 150), "Other": (150, 150, 150), "unknown": (150, 150, 150) } typecolors.update({"Image": (230, 230, 20)}) typecolors.update({"Stylesheet": (20, 230, 100)}) typecolors.update({"Script": (255, 20, 20)}) typecolors.update({"EventSource": (20, 230, 100)}) typecolors.update({"Font": (20, 230, 100)}) typecolors.update({"Media": (255, 20, 20)}) typecolors.update({"Fetch": (230, 230, 20)}) typecolors.update({"Document": (230, 230, 20)}) typecolors.update({"XHR": (230, 230, 20)}) # get the height and max width # of the tree h = len(structure) w = 0 for level in structure: if len(level) > w: w = len(level) # picture parameters rad = 200 bufx = 100 bufy = 300 thck = 10 tsize = 50 tbuf = 6 # create a new image while True: try: # get the image size size = (bufx + w * (bufx + (2 * rad)), bufy + h * (bufy + (2 * rad))) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size[0], size[1]) break except cairo.Error: rad = int(rad / 2) bufx = int(bufx / 2) bufy = int(bufy / 2) thck = int(thck / 2) tsize = int(tsize / 2) tbuf = int(tbuf / 2) ctx = cairo.Context(surface) ctx.set_source_rgb(1, 1, 1) ctx.rectangle(0, 0, size[0], size[1]) ctx.fill() fnt = cairo.ToyFontFace("Menlo", cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL) opt = cairo.FontOptions() fnt = cairo.ScaledFont( fnt, cairo.Matrix(size[0] / 60, 0, 0, size[0] / 60, 0, 0), cairo.Matrix(1, 0, 0, 1, 0, 0), opt) ctx.set_scaled_font(fnt) nnt = str(num_nodes(tree)) net = str(num_ad_nodes(tree, True)) nit = str(num_ad_nodes(tree, False)) inf = str(nnt + "," + net + "," + nit) ext = fnt.text_extents(inf) ctx.move_to(0, ext.height) ctx.set_source_rgb(50 / 255, 20 / 255, 255 / 255) ctx.show_text(nnt) ctx.set_source_rgb(0, 0, 0) ctx.show_text(",") ctx.set_source_rgb(255 / 255, 20 / 255, 50 / 255) ctx.show_text(net) ctx.set_source_rgb(0, 0, 0) ctx.show_text(",") ctx.set_source_rgb(255 / 255, 20 / 255, 200 / 255) ctx.show_text(nit) ctx.stroke() fnt = cairo.ToyFontFace("Menlo", cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL) opt = cairo.FontOptions() fnt = cairo.ScaledFont(fnt, cairo.Matrix(tsize, 0, 0, tsize, 0, 0), cairo.Matrix(1, 0, 0, 1, 0, 0), opt) ctx.set_scaled_font(fnt) ctx.set_line_cap(cairo.LineCap.BUTT) ctx.set_line_join(cairo.LineJoin.ROUND) ctx.set_line_width(thck) # draw! plev = -1 c0xp = 0 c0yp = 0 slen = len(structure) # iterate through the levels of the tree for level in range(0, len(structure)): # get the width of the current level llen = len(structure[level]) # find the x center coordinate ctr = size[0] / 2 rng = llen * (2 * rad) + (llen - 1) * bufx c0x = ctr - (rng / 2) + rad # find the y center coordinate ctr = size[1] / 2 rng = slen * (2 * rad) + (slen - 1) * bufy c0y = ctr - (rng / 2) + rad cy = c0y + level * (2 * rad + bufy) # calculate number of unique parents puni = {} index = 0 for child in tree[level]: for parent in tree[level][child]["parents"]: if parent not in puni: puni.update({parent: index}) index += 1 for item in structure[level].keys(): if tree[level][item]["ad"] == "yes": color = (255 / 255, 20 / 255, 50 / 255) elif tree[level][item]["ad"] == "no": color = (50 / 255, 20 / 255, 255 / 255) else: color = (255 / 255, 20 / 255, 200 / 255) # since we are iterating "horizontally", we # need only update the x position cx = c0x + structure[level][item] * (2 * rad + bufx) # draw centered text try: sqtxt = str(tree[level][item]["squish"]) except KeyError: sqtxt = "" # draw the circle + text ctx.set_source_rgb(color[0], color[1], color[2]) ctx.arc(cx, cy, rad, 0, 2 * math.pi) ctx.fill() if "types" in tree[level][item]: ntypes = len(tree[level][item]["types"]) for idt, t in enumerate(tree[level][item]["types"]): try: color = typecolors[t] except KeyError: print(t) color = typecolors[""] ctx.set_source_rgb(color[0] / 255, color[1] / 255, color[2] / 255) ctx.arc(cx, cy, rad, idt * 2 * math.pi / ntypes, (idt + 1) * 2 * math.pi / ntypes) ctx.stroke() elif "type" in tree[level][item]: try: color = typecolors[tree[level][item]["type"]] except: print(tree[level][item]["type"]) color = typecolors[""] ctx.set_source_rgb(color[0] / 255, color[1] / 255, color[2] / 255) ctx.arc(cx, cy, rad, 0, 2 * math.pi) ctx.stroke() ctx.set_source_rgba(0, 0, 0, 1.0) ext = fnt.text_extents(get_url(item)) ctx.move_to(cx - ext.width / 2, cy - tbuf) ctx.show_text(get_url(item)) ext = fnt.text_extents(sqtxt) ctx.move_to(cx - ext.width / 2, cy + ext.height + tbuf) ctx.show_text(sqtxt) ctx.stroke() # if we aren't at the top level then # draw a line connecting it to its parent(s) if plev != -1: thisp = 0 thisptot = len(tree[level][item]["parents"]) # iterate through parents for parent in tree[level][item]["parents"].keys(): # get the index of the parent pindex = structure[level - 1][parent] cpx = c0xp + (pindex) * (2 * rad + bufx) cpy = c0yp # get the width of the parent layer plsize = len(puni) # calculate on offset so that lines dont intersect offy = int((puni[parent] + 2) * bufy / (plsize + 3)) ofrx = int((thck * (thisptot - 1)) + (2 * thck * (thisptot - 1))) of0x = int(-ofrx / 2) offx = int(of0x + thisp * ofrx / thisptot) # draw 3 lines to connect the parent and child ctx.move_to(cx + offx, cy - rad) ctx.line_to(cx + offx, cy - rad - offy) ctx.line_to(cpx, cy - rad - offy) ctx.line_to(cpx, cpy + rad) ctx.stroke() thisp += 1 # remember the parent level and center # of the circle at the beginning of the parent level plev = level c0xp = c0x c0yp = cy # save the image surface.write_to_png(outname)
def f(): self.cairo.set_font_face(cairo.ToyFontFace(fn)) self.cairo.set_font_size(sz)
def add_text(self, text, fontname, origin, size, color, positioning=FontPositioning.CENTER): ''' Add text with font of name fontname. If centered=True, then the origin denotes the center of the text to be drawn. Otherwise it respresents the top left corner. If target=FontSizing.WIDTH, then size represents the width in pixels for the target text. Similarly for height. Otherwise if target=FontSizing.SCALE the size represents the font size factor passed to cairo. ''' # get font try: font = self.fonts[fontname] except KeyError: font = cairo.ToyFontFace(fontname) self.fonts[fontname] = font # create options opt = cairo.FontOptions() # get size for width or height testfont = cairo.ScaledFont(font, cairo.Matrix(1, 0, 0, 1, 0, 0), cairo.Matrix(1, 0, 0, 1, 0, 0), opt) extents = testfont.text_extents(text) try: size = size / extents.height except ZeroDivisionError: return # create font for drawing usefont = cairo.ScaledFont(font, cairo.Matrix(size,0,0,size,0,0), cairo.Matrix(1,0,0,1,0,0), opt) if positioning == FontPositioning.CENTER: extents = usefont.text_extents(text) origin[0] += extents.height/2 origin[1] -= extents.width/2 origin[1] -= extents.x_bearing elif positioning == FontPositioning.TOP_LEFT: extents = usefont.text_extents(text) origin[0] += extents.height elif positioning == FontPositioning.TOP_RIGHT: extents = usefont.text_extents(text) origin[0] += extents.height origin[1] -= extents.width origin[1] -= extents.x_bearing elif positioning == FontPositioning.TOP_CENTER: extents = usefont.text_extents(text) origin[0] += extents.height origin[1] -= extents.width/2 origin[1] -= extents.x_bearing elif positioning == FontPositioning.BOTTOM_RIGHT: extents = usefont.text_extents(text) origin[1] -= extents.width origin[1] -= extents.x_bearing elif positioning == FontPositioning.BOTTOM_CENTER: extents = usefont.text_extents(text) origin[1] -= extents.width/2 origin[1] -= extents.x_bearing elif positioning == FontPositioning.RIGHT_CENTER: extents = usefont.text_extents(text) origin[0] += extents.height/2 origin[1] -= extents.width origin[1] -= extents.x_bearing elif positioning == FontPositioning.LEFT_CENTER: extents = usefont.text_extents(text) origin[0] += extents.height/2 self.context.set_source_rgb(color[0]/255, color[1]/255, color[2]/255) self.context.set_scaled_font(usefont) self.context.move_to(origin[1], origin[0]) self.context.show_text(str(text)) self.context.fill()
def font(family='', bold=False, italic=False): return cairo.ToyFontFace( family, cairo.FontSlant.ITALIC if italic else cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD if bold else cairo.FontWeight.NORMAL, )