Skip to content

Instantly share code, notes, and snippets.

@gferreira
Last active August 19, 2017 14:46
Show Gist options
  • Save gferreira/248d4cfce311c688bad29b11786781b6 to your computer and use it in GitHub Desktop.
Save gferreira/248d4cfce311c688bad29b11786781b6 to your computer and use it in GitHub Desktop.
fontParts object map
# fontParts object map
from grapefruit import Color
from collections import OrderedDict
class FontPartsMap(object):
colors = OrderedDict([
('font' , (80, 0.50, 0.49)),
('font_lib' , (136, 0.42, 0.55)),
('info' , (176, 0.9, 0.36)),
('kerning' , (183, 0.9, 0.44)),
('features' , (203, 0.7, 0.57)),
('layer' , (417, 0.5, 0.49)),
('glyph' , (38, 0.91, 0.69)),
('glyph_lib' , (22, 0.85, 0.59)),
('anchor' , (21, 0.68, 0.50)),
('component' , (25, 0.69, 0.51)),
('image' , (20, 0.59, 0.51)),
('guideline' , (11, 0.65, 0.52)),
('contour' , (4, 0.55, 0.52)),
('point' , (347, 0.66, 0.52)),
('bPoint' , (333, 0.67, 0.48)),
('segment' , (324, 0.67, 0.42)),
])
lines = [
('font', 'info'),
('font', 'font_lib'),
('font', 'kerning'),
('font', 'features'),
('font', 'layer'),
('layer', 'glyph'),
('glyph', 'glyph_lib'),
('glyph', 'anchor'),
('glyph', 'component'),
('glyph', 'image'),
('glyph', 'guideline'),
('glyph', 'contour'),
('contour', 'point'),
('contour', 'bPoint'),
('contour', 'segment')
]
positions = {}
radius_1 = 50
radius_2 = 70
length_1 = 160
length_2 = 200
length_3 = 170
font = 'Menlo-Bold'
font_size_1 = 18
font_size_2 = 32
lines_stroke_color = 0.6,
lines_stroke_width = 4
lines_dash = 3, 7
circles_stroke_color = 0,
circles_stroke_width = 3
rand_range = 0
landscape = True
def make_positions(self, (x, y)):
x0, y0 = x, y
a1 = 180/3 # font
a2 = 180/4 # glyph
a3 = 180/3.5 # contour
# font
self.positions['font'] = x0, y0
# font lib
x1 = x0 + self.length_1
y1 = y0
self.positions['font_lib'] = x1, y1
# info
x2 = x0 + cos(radians(a1)) * self.length_1
y2 = y0 + sin(radians(a1)) * self.length_1
self.positions['info'] = x2, y2
# kerning
i = 2
x3 = x0 + cos(radians(a1*i)) * self.length_1
y3 = y0 + sin(radians(a1*i)) * self.length_1
self.positions['kerning'] = x3, y3
# features
i = 3
x4 = x0 + cos(radians(a1*i)) * self.length_1
y4 = y0 + sin(radians(a1*i)) * self.length_1
self.positions['features'] = x4, y4
# layer
x5 = x0
y5 = y0 - self.length_2
self.positions['layer'] = x5, y5
# glyph
x6 = x0
y6 = y5 - self.length_2
self.positions['glyph'] = x6, y6
# glyph_lib
i = -5
x7 = x6 + cos(radians(a2*i)) * self.length_2
y7 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['glyph_lib'] = x7, y7
# anchor
i = -4
x8 = x6 + cos(radians(a2*i)) * self.length_2
y8 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['anchor'] = x8, y8
# component
i = -3
x9 = x6 + cos(radians(a2*i)) * self.length_2
y9 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['component'] = x9, y9
# image
i = -2
x10 = x6 + cos(radians(a2*i)) * self.length_2
y10 = y6 + sin(radians(a2*i)) * self.length_2
line((x6, y6), (x10, y10))
self.positions['image'] = x10, y10
# guideline
i = -1
x11 = x6 + cos(radians(a2*i)) * self.length_2
y11 = y6 + sin(radians(a2*i)) * self.length_2
line((x6, y6), (x11, y11))
self.positions['guideline'] = x11, y11
# contour
i = 0
x12 = x6 + cos(radians(a2*i)) * self.length_2
y12 = y6 + sin(radians(a2*i)) * self.length_1
self.positions['contour'] = x12, y12
# point
a3_ = 0
i = 2
x13 = x12 + cos(radians(a3_+a3*i)) * self.length_3
y13 = y12 + sin(radians(a3_+a3*i)) * self.length_3
self.positions['point'] = x13, y13
# bPoint
i = 1
x14 = x12 + cos(radians(a3_+a3*i)) * self.length_3
y14 = y12 + sin(radians(a3_+a3*i)) * self.length_3
self.positions['bPoint'] = x14, y14
# segment
i = 0
x15 = x12 + cos(radians(a3_+a3*i)) * self.length_3
y15 = y12 + sin(radians(a3_+a3*i)) * self.length_3
self.positions['segment'] = x15, y15
# randomize positions
if self.rand_range != 0:
for obj, (x, y) in self.positions.items():
x += randint(-self.rand_range, self.rand_range)
y += randint(-self.rand_range, self.rand_range)
self.positions[obj] = x, y
def make_positions_landscape(self, (x, y)):
x0, y0 = x, y
a1 = 180/4 # font
a2 = 180/4 # glyph
a3 = 180/3.5 # contour
# font
self.positions['font'] = x0, y0
# font lib
i = 2.0
x1 = x0 + cos(radians(a1*i)) * self.length_2
y1 = y0 + sin(radians(a1*i)) * self.length_2
self.positions['font_lib'] = x1, y1
# info
i += 1
x2 = x0 + cos(radians(a1*i)) * self.length_2
y2 = y0 + sin(radians(a1*i)) * self.length_2
self.positions['info'] = x2, y2
# kerning
i += 1
x3 = x0 + cos(radians(a1*i)) * self.length_2
y3 = y0 + sin(radians(a1*i)) * self.length_2
self.positions['kerning'] = x3, y3
# features
i += 1
x4 = x0 + cos(radians(a1*i)) * self.length_2
y4 = y0 + sin(radians(a1*i)) * self.length_2
self.positions['features'] = x4, y4
# layer
x5 = x0 + self.length_1
y5 = y0
self.positions['layer'] = x5, y5
# glyph
x6 = x5 + self.length_1
y6 = y5 #- self.length_2
self.positions['glyph'] = x6, y6
# glyph_lib
i = 2.5
x7 = x6 + cos(radians(a2*i)) * self.length_2
y7 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['glyph_lib'] = x7, y7
# anchor
i = 1.5
x8 = x6 + cos(radians(a2*i)) * self.length_2
y8 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['anchor'] = x8, y8
# component
i = 0.5
x9 = x6 + cos(radians(a2*i)) * self.length_2
y9 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['component'] = x9, y9
# image
i = -0.5
x10 = x6 + cos(radians(a2*i)) * self.length_2
y10 = y6 + sin(radians(a2*i)) * self.length_2
line((x6, y6), (x10, y10))
self.positions['image'] = x10, y10
# guideline
i = -1.5
x11 = x6 + cos(radians(a2*i)) * self.length_2
y11 = y6 + sin(radians(a2*i)) * self.length_2
line((x6, y6), (x11, y11))
self.positions['guideline'] = x11, y11
# contour
i = -2.5
x12 = x6 + cos(radians(a2*i)) * self.length_2
y12 = y6 + sin(radians(a2*i)) * self.length_2
self.positions['contour'] = x12, y12
# point
a3_ = -77
i = -2
x13 = x12 + cos(radians(a3_+a3*i)) * self.length_3
y13 = y12 + sin(radians(a3_+a3*i)) * self.length_3
self.positions['point'] = x13, y13
# bPoint
i += 1
x14 = x12 + cos(radians(a3_+a3*i)) * self.length_3
y14 = y12 + sin(radians(a3_+a3*i)) * self.length_3
self.positions['bPoint'] = x14, y14
# segment
i += 1
x15 = x12 + cos(radians(a3_+a3*i)) * self.length_3
y15 = y12 + sin(radians(a3_+a3*i)) * self.length_3
self.positions['segment'] = x15, y15
# randomize positions
if self.rand_range != 0:
for obj, (x, y) in self.positions.items():
x += randint(-self.rand_range, self.rand_range)
y += randint(-self.rand_range, self.rand_range)
self.positions[obj] = x, y
def draw_lines(self):
save()
stroke(*self.lines_stroke_color)
strokeWidth(self.lines_stroke_width)
lineDash(self.lines_dash)
lineCap('round')
for obj_1, obj_2 in self.lines:
line(self.positions[obj_1], self.positions[obj_2])
restore()
def draw_circles(self):
save()
stroke(*self.circles_stroke_color)
strokeWidth(self.circles_stroke_width)
shadow((2, -5), blur=15, color=(0, 0.25))
for obj, pos in self.positions.items():
if obj not in ['font', 'glyph']:
r = self.radius_1
else:
r = self.radius_2
x = pos[0] - r
y = pos[1] - r
# c = Color.NewFromHsl(*self.colors[obj])
c = self.colors[obj]
fill(*c.rgb)
oval(x, y, r*2, r*2)
restore()
def draw_captions(self):
fill(1)
shadow((2, -2), blur=5, color=(0, 0.3))
font(self.font)
for obj in self.positions.keys():
x, y = self.positions[obj]
if obj not in ['font', 'glyph']:
r = self.radius_1
fontSize(self.font_size_1)
h = r-self.font_size_1*-0.6
else:
r = self.radius_2
fontSize(self.font_size_2)
h = r-self.font_size_2*-0.65
if len(obj.split('_')) > 1:
obj = obj.split('_')[-1]
textBox(obj, (x-r, y-r, r*2, h), align='center')
def draw(self, (x, y)):
if not self.landscape:
self.make_positions((x, y))
else:
self.make_positions_landscape((x, y))
self.draw_lines()
self.draw_circles()
self.draw_captions()
Variable([
dict(name="radius_1", ui="Slider", args=dict(value=60, minValue=30, maxValue=100)),
dict(name="radius_2", ui="Slider", args=dict(value=120, minValue=50, maxValue=200)),
dict(name="length_1", ui="Slider", args=dict(value=190, minValue=80, maxValue=300)),
dict(name="length_2", ui="Slider", args=dict(value=210, minValue=80, maxValue=300)),
dict(name="length_3", ui="Slider", args=dict(value=190, minValue=80, maxValue=300)),
dict(name="randomness", ui="Slider", args=dict(value=0, minValue=0, maxValue=20)),
dict(name="landscape", ui="CheckBox", args=dict(value=False)),
dict(name="draw_swatches", ui="CheckBox", args=dict(value=False)),
], globals())
M = FontPartsMap()
M.radius_1 = radius_1
M.radius_2 = radius_2
M.length_1 = length_1
M.length_2 = length_2
M.length_3 = length_3
M.landscape = landscape
M.lines_stroke_color = 0.7,
M.lines_stroke_width = 4
M.lines_dash = 2, 7
M.circles_stroke_color = 0,
M.circles_stroke_width = 0
M.rand_range = int(randomness)
if landscape:
newPage('A4Landscape')
else:
newPage('A4')
fill(1)
rect(0, 0, width(), height())
#---------------
# color palette
#---------------
colors = [
M.colors.keys()[:5],
M.colors.keys()[6:13],
M.colors.keys()[12:],
[M.colors.keys()[0], M.colors.keys()[5], M.colors.keys()[6]],
]
colors_new = OrderedDict()
colors_new['font'] = Color.NewFromHsl(*M.colors['font'])
colors_new['glyph'] = Color.NewFromHsl(*M.colors['glyph'])
c1 = colors_new['font']
c2 = colors_new['glyph']
for i, obj in enumerate(colors[0][1:]):
color = c1.ColorWithHue(c1.hue + (i+1)*25)
colors_new[obj] = color
for i, obj in enumerate(colors[1][1:]):
color = c2.ColorWithHue(c2.hue - (i+1)*15)
colors_new[obj] = color
c3 = colors_new['contour']
for i, obj in enumerate(colors[2][1:]):
color = c3.ColorWithHue(c3.hue - (i+1)*20)
colors_new[obj] = color
colors_new['layer'] = c1.Blend(c2, percent=0.5)
if draw_swatches:
x, y = 20, 130
s = 30
m = 4
shadow(None)
save()
translate(x, y)
for i, color_set in enumerate(colors):
save()
for obj in color_set:
c = colors_new[obj]
fill(*c.rgb)
rect(0, 0, s, s)
translate(s+m, 0)
restore()
translate(0, -s-m)
if i == len(colors)-2:
translate(0, -m*2)
restore()
M.colors = colors_new
if landscape:
scale(0.76)
x, y = 336, 470
else:
scale(0.76)
x, y = 299, 800
M.draw((x, y))
# save image
import os
folder = os.getcwd()
img_paths = [
os.path.join(folder, 'fontparts-map.svg'),
os.path.join(folder, 'fontparts-map.png'),
]
saveImage(img_paths)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment