%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()