Skip to content

Commit

Permalink
Speedup on Bold Variant
Browse files Browse the repository at this point in the history
  • Loading branch information
Dheatly23 committed Jun 19, 2023
1 parent 00037d8 commit dc7fc21
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 38 deletions.
38 changes: 32 additions & 6 deletions src/monocraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from generate_diacritics import generateDiacritics
from generate_examples import generateExamples
from polygonizer import PixelImage, generatePolygons
from generate_continuous_ligatures import generate_continuous_ligatures
from generate_continuous_ligatures import generate_continuous_ligatures

PIXEL_SIZE = 120

Expand Down Expand Up @@ -75,7 +75,6 @@ def generateFont():
fontList[1].generate(outputDir + "Monocraft-bold-no-ligatures.ttf")
fontList[2].generate(outputDir + "Monocraft-italic-no-ligatures.ttf")
for ligature in ligatures:
print(ligature["name"])
image, kw = generateImage(ligature)
createChar(fontList, -1, ligature["name"], image, width=PIXEL_SIZE * len(ligature["sequence"]) * 6, **kw)
for font in fontList:
Expand All @@ -87,7 +86,7 @@ def generateFont():
fontList[1].generate(outputDir + "Monocraft-bold.ttf")
fontList[1].generate(outputDir + "Monocraft-bold.otf")
fontList[2].generate(outputDir + "Monocraft-italic.ttf")
fontList[2].generate(outputDir + "Monocraft-italic.otf")
#fontList[2].generate(outputDir + "Monocraft-italic.otf")

def generateImage(character):
image = PixelImage()
Expand Down Expand Up @@ -144,7 +143,7 @@ def drawPolygon(poly, pen):
pen.lineTo(x, y)
pen.closePath()

BOLD_WEIGHT = 48
BOLD_DIST = 0.2
ITALIC_MAT = (1, 0, math.tan(math.radians(15)), 1, 0, 0)

def createChar(fontList, code, name, image=None, *, width=None, dx=0, dy=0):
Expand All @@ -157,9 +156,36 @@ def createChar(fontList, code, name, image=None, *, width=None, dx=0, dy=0):
char.width = width if width is not None else PIXEL_SIZE * 6
continue

drawPolygon(poly, char.glyphPen())
if font.macstyle & 1 != 0:
char.changeWeight(BOLD_WEIGHT, "CJK", 0, 1, "auto", True)
def f(p):
l = len(p)
for i, (x, y) in enumerate(p):
x_, y_ = x + dx, y + dy
px, py = p[i - 1]
if px < x:
y_ -= BOLD_DIST
elif px > x:
y_ += BOLD_DIST
elif py < y:
x_ += BOLD_DIST
else:
x_ -= BOLD_DIST
px, py = p[(i + 1) % l]
if px < x:
y_ += BOLD_DIST
elif px > x:
y_ -= BOLD_DIST
elif py < y:
x_ -= BOLD_DIST
else:
x_ += BOLD_DIST
yield (x_, y_)
drawPolygon(
[f(p) for p in generatePolygons(image, join_polygons=True)],
char.glyphPen(),
)
else:
drawPolygon(poly, char.glyphPen())
if font.macstyle & 2 != 0:
char.transform(ITALIC_MAT, ("round", ))
char.width = width if width is not None else PIXEL_SIZE * 6
Expand Down
65 changes: 33 additions & 32 deletions src/polygonizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def __getitem__(self, key):

def __setitem__(self, key, value):
''' Sets a pixel at (x, y).
Do nothing if out of bounds.
'''
x, y = key
Expand Down Expand Up @@ -188,9 +188,9 @@ def __or__(self, other):
return ret


def generatePolygons(image):
def generatePolygons(image, **kw):
for segment, start_pos in segmentize(image):
yield from polygonizeSegment(segment, start_pos)
yield from polygonizeSegment(segment, start_pos, **kw)


def segmentize(image):
Expand Down Expand Up @@ -322,7 +322,7 @@ def reverse(self):
return ret


def polygonizeSegment(image, start_pos):
def polygonizeSegment(image, start_pos, join_polygons=True):
x, y = start_pos

# Make sure position is top left
Expand Down Expand Up @@ -560,36 +560,37 @@ def find(l, x):
x, y = p

# Try to join polygons
for i in range(len(poly) - 1, -1, -1):
inner_poly, points_ = poly[i]

for v in points.values():
if len(v) > 1 and i in v:
j = min(v)
break
else:
continue

outer_poly, points__ = poly[j]
if join_polygons:
for i in range(len(poly) - 1, -1, -1):
inner_poly, points_ = poly[i]

for v in points.values():
if len(v) > 1 and i in v:
j = min(v)
break
else:
continue

for i_, p in enumerate(inner_poly):
j_ = points__.get(p)
if j_ is not None:
break
else:
raise RuntimeError(
f'Should not happened {inner_poly} {outer_poly}')

outer_poly[j_:j_] = [*inner_poly[i_:], *inner_poly[:i_]]
points__.update(
zip(
reversed(outer_poly),
range(len(outer_poly) - 1, -1, -1),
))
outer_poly, points__ = poly[j]

del poly[i]
for v in points.values():
v.discard(i)
for i_, p in enumerate(inner_poly):
j_ = points__.get(p)
if j_ is not None:
break
else:
raise RuntimeError(
f'Should not happened {inner_poly} {outer_poly}')

outer_poly[j_:j_] = [*inner_poly[i_:], *inner_poly[:i_]]
points__.update(
zip(
reversed(outer_poly),
range(len(outer_poly) - 1, -1, -1),
))

del poly[i]
for v in points.values():
v.discard(i)

# Emit polygons
for i, _ in poly:
Expand Down

0 comments on commit dc7fc21

Please sign in to comment.