%PDF- %PDF-
Direktori : /usr/share/doc/python3-freetype/examples/ |
Current File : //usr/share/doc/python3-freetype/examples/wordle-cairo.py |
#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # pycairo/cairocffi-based wordle example - Copyright 2017 Hin-Tak Leung # Distributed under the terms of the new BSD license. # # rewrite of the numply,matplotlib-based example from Nicolas P. Rougier # - Cairo can paint partly off-screen, so this example does! # # This example behaves differently under pycairo 1.11+ (released in 2017-04-09). # Auto-checked. On older pycairo, it does not draw partial patterns at the edges. # Also, Suface.get_data() is not in the "python 3, pycairo < 1.11" combination. # # ----------------------------------------------------------------------------- from math import cos, sin from numpy import random, sort, sqrt, ndarray, ubyte from freetype import * try: # pycairo 1.11+: from cairo import Region, RectangleInt, REGION_OVERLAP_OUT except ImportError: # stubs for pycairo < 1.11: class Region: def __init__(self): return def union(self, rec): return def contains_rectangle(self, rec): # inhibit drawing return True class RectangleInt: def __init__(self, x, y, w, h): return REGION_OVERLAP_OUT = False from cairo import Context, ImageSurface, FORMAT_A8, FORMAT_ARGB32, Matrix from bitmap_to_surface import make_image_surface 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 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) drawn_regions = Region() for size in sizes: angle = random.randint(-25,25) try: L = make_label('Hello', './Vera.ttf', size, angle=angle) except NotImplementedError: raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)") h = L.get_height() w = L.get_width() if h < H and w < W: x0 = W//2 + (random.uniform()-.1)*50 y0 = H//2 + (random.uniform()-.1)*50 for dx,dy in spiral(): c = .25+.75*random.random() x = int(x0+dx) y = int(y0+dy) checked = False I.flush() if not (x <= w//2 or y <= h//2 or x >= (W-w//2) or y >= (H-h//2)): ndI = ndarray(shape=(h,w), buffer=I.get_data(), dtype=ubyte, order='C', offset=(x-w//2) + I.get_stride() * (y-h//2), strides=[I.get_stride(), 1]) ndL = ndarray(shape=(h,w), buffer=L.get_data(), dtype=ubyte, order='C', strides=[L.get_stride(), 1]) if ((ndI * ndL).sum() == 0): checked = True new_region = RectangleInt(x-w//2, y-h//2, w, h) if (checked or ( drawn_regions.contains_rectangle(new_region) == REGION_OVERLAP_OUT )): ctxI.set_source_surface(L, 0, 0) pattern = ctxI.get_source() scalematrix = Matrix() scalematrix.scale(1.0,1.0) scalematrix.translate(w//2 - x, h//2 - y) pattern.set_matrix(scalematrix) ctxI.set_source_rgba(c,c,c,c) ctxI.mask(pattern) drawn_regions.union(new_region) break I.flush() I.write_to_png("wordle-cairo.png") Image.open("wordle-cairo.png").show()