I started exploring the freetype-py library and the vector information available for glyphs. As part of the exploration I found this great unicode characters table. In addition to the character code and the writing system it belongs to, this table also shows the areas of the world where the writing system is used. This can be very useful to the third layer of the visualization regarding the history / geography of writing systems.
I started by looking at the glyph-vector example provided with the library. Note that this example uses matplotlib to plot the glyph. The glyph information is initially divided into closed contours - closed lines, for example the letter O has two contours, the outer circle and the inner circle while the letter S has only one contour. The closed contours are in turn divided into segments that can be either a straight line or a quadratic Bezier curve (or curves). A clear and concise description of the outlines and how the control points define the line in TrueType can be found here.
Below are a few examples of characters from different writing systems with their control lines (dashed). These are of course just single characters and therefore do not represent the entire writing system to which they belong. This is only meant to show the type of information available, the great variance between the writing systems and how these parameters can be used to asses similarity.
These are characters from the Chinese character set, Latin, Hebrew and Tibetan (from left to right respectively). The statistics for each character is as follows:
I started by looking at the glyph-vector example provided with the library. Note that this example uses matplotlib to plot the glyph. The glyph information is initially divided into closed contours - closed lines, for example the letter O has two contours, the outer circle and the inner circle while the letter S has only one contour. The closed contours are in turn divided into segments that can be either a straight line or a quadratic Bezier curve (or curves). A clear and concise description of the outlines and how the control points define the line in TrueType can be found here.
Below are a few examples of characters from different writing systems with their control lines (dashed). These are of course just single characters and therefore do not represent the entire writing system to which they belong. This is only meant to show the type of information available, the great variance between the writing systems and how these parameters can be used to asses similarity.
These are characters from the Chinese character set, Latin, Hebrew and Tibetan (from left to right respectively). The statistics for each character is as follows:
Writing System
|
Chinese
|
English
|
Hebrew
|
Tibetan
|
|---|---|---|---|---|
Closed contours
|
7 | 2 | 1 | 9 |
Total segments
|
57 | 17 | 12 | 58 |
Straight lines
|
47 | 11 | 8 | 9 |
Curves
|
9 | 6 | 4 | 49 |
The code is below. Note that it relies on having matplotlib and the path to the ttf file.
# coding=UTF8
# -----------------------------------------------------------------------------
#
# FreeType high-level python API - Copyright 2011 Nicolas P. Rougier
# Distributed under the terms of the new BSD license.
#
# -----------------------------------------------------------------------------
'''
Show how to access glyph outline description.
'''
from freetype import *
if __name__ == '__main__':
import numpy
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
face = Face('path/to/file/Arial Unicode.ttf')
face.set_char_size( 48*64 )
face.load_char(u'\u0F03')
slot = face.glyph
outline = slot.outline
points = numpy.array(outline.points, dtype=[('x',float), ('y',float)])
x, y = points['x'], points['y']
figure = plt.figure(figsize=(8,10))
axis = figure.add_subplot(111)
#axis.scatter(points['x'], points['y'], alpha=.25)
start, end = 0, 0
lines, curves1, curves2 = 0, 0, 0
VERTS, CODES = [], []
# Iterate over each contour
for i in range(len(outline.contours)):
end = outline.contours[i]
points = outline.points[start:end+1]
points.append(points[0])
tags = outline.tags[start:end+1]
tags.append(tags[0])
segments = [ [points[0],], ]
for j in range(1, len(points) ):
segments[-1].append(points[j])
if tags[j] & (1 << 0) and j < (len(points)-1):
segments.append( [points[j],] )
verts = [points[0], ]
codes = [Path.MOVETO,]
for segment in segments:
if len(segment) == 2:
verts.extend(segment[1:])
codes.extend([Path.LINETO])
lines+=1
elif len(segment) == 3:
verts.extend(segment[1:])
codes.extend([Path.CURVE3, Path.CURVE3])
curves1+=1
else:
verts.append(segment[1])
codes.append(Path.CURVE3)
for i in range(1,len(segment)-2):
A,B = segment[i], segment[i+1]
C = ((A[0]+B[0])/2.0, (A[1]+B[1])/2.0)
verts.extend([ C, B ])
codes.extend([ Path.CURVE3, Path.CURVE3])
verts.append(segment[-1])
codes.append(Path.CURVE3)
curves2+=1
VERTS.extend(verts)
CODES.extend(codes)
start = end+1
print 'segments: ', len(outline.contours)
print 'lines: ', lines
print 'curves: ', curves1+curves2
# Draw glyph lines
path = Path(VERTS, CODES)
glyph = patches.PathPatch(path, facecolor='.75', fill=False, lw=1)
# Draw "control" lines
for i, code in enumerate(CODES):
if code == Path.CURVE3:
CODES[i] = Path.LINETO
path = Path(VERTS, CODES)
patch = patches.PathPatch(path, ec='.5', fill=False, ls='dashed', lw=1 )
axis.add_patch(patch)
axis.add_patch(glyph)
axis.set_xlim(x.min()-100, x.max()+100)
plt.xticks([])
axis.set_ylim(y.min()-100, y.max()+100)
plt.yticks([])
plt.show()




No comments:
Post a Comment