Skip to content

Commit

Permalink
Merge pull request #103 from IdreesInc/88-a-small-break-between-pixels
Browse files Browse the repository at this point in the history
88 Merge adjacent pixels into combined shapes
  • Loading branch information
IdreesInc committed Feb 5, 2023
2 parents e1c44cf + 5362273 commit 6895837
Show file tree
Hide file tree
Showing 2 changed files with 659 additions and 36 deletions.
89 changes: 53 additions & 36 deletions src/monocraft.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Monocraft, a monospaced font for developers who like Minecraft a bit too much.
# Copyright (C) 2022 Idrees Hassan
# Copyright (C) 2022-2023 Idrees Hassan
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
Expand All @@ -18,6 +18,7 @@
import json
from generate_diacritics import generateDiacritics
from generate_examples import generateExamples
from polygonizer import PixelImage, generatePolygons

PIXEL_SIZE = 120

Expand All @@ -35,7 +36,7 @@ def generateFont():
monocraft.fullname = "Monocraft"
monocraft.copyright = "Idrees Hassan, https://github.com/IdreesInc/Monocraft"
monocraft.encoding = "UnicodeFull"
monocraft.version = "2.3"
monocraft.version = "2.4"
monocraft.weight = "Regular"
monocraft.ascent = PIXEL_SIZE * 8
monocraft.descent = PIXEL_SIZE
Expand All @@ -50,16 +51,8 @@ def generateFont():
pen = monocraft[character["name"]].glyphPen()
top = 0
drawn = character
if "pixels" in character:
top = drawCharacter(character, pen)
elif "reference" in character:
drawn = charactersByCodepoint[character["reference"]]
top = drawCharacter(drawn, pen)
if "diacritic" in character:
diacritic = diacritics[character["diacritic"]]
if "diacriticSpace" in character:
top += PIXEL_SIZE * character["diacriticSpace"]
drawGlyph(diacritic["pixels"], pen, getLeftMargin(drawn), top)

drawImage(generateImage(character), pen)
monocraft[character["name"]].width = PIXEL_SIZE * 6
print(f"Generated {len(characters)} characters")

Expand All @@ -72,37 +65,61 @@ def generateFont():
for ligature in ligatures:
lig = monocraft.createChar(-1, ligature["name"])
pen = monocraft[ligature["name"]].glyphPen()
drawCharacter(ligature, pen)
drawImage(generateImage(ligature), pen)
monocraft[ligature["name"]].width = PIXEL_SIZE * len(ligature["sequence"]) * 6
lig.addPosSub("ligatures-subtable", tuple(map(lambda codepoint: charactersByCodepoint[codepoint]["name"], ligature["sequence"])))
print(f"Generated {len(ligatures)} ligatures")

monocraft.generate(outputDir + "Monocraft.ttf")
monocraft.generate(outputDir + "Monocraft.otf")

def getLeftMargin(character):
return PIXEL_SIZE * character["leftMargin"] if "leftMargin" in character else 0

def drawCharacter(character, pen):
if "reference" in character: return drawCharacter(charactersByCodepoint[character["reference"]],pen)
leftMargin = getLeftMargin(character)
floor = -PIXEL_SIZE * character["descent"] if "descent" in character else 0
return drawGlyph(character["pixels"], pen, leftMargin, floor)

def drawGlyph(pixels, pen, startingX, startingY):
top = 0 # The highest point of the character
for rowIndex in range(len(pixels)):
row = pixels[-(rowIndex + 1)]
for columnIndex in range(len(row)):
if row[columnIndex] == 0:
continue
pen.moveTo((columnIndex * PIXEL_SIZE + startingX, rowIndex * PIXEL_SIZE + startingY)) # Bottom left
pen.lineTo((columnIndex * PIXEL_SIZE + startingX, (rowIndex + 1) * PIXEL_SIZE + startingY))
pen.lineTo(((columnIndex + 1) * PIXEL_SIZE + startingX, (rowIndex + 1) * PIXEL_SIZE + startingY))
pen.lineTo(((columnIndex + 1) * PIXEL_SIZE + startingX, rowIndex * PIXEL_SIZE + startingY))
pen.closePath()
top = (rowIndex + 1) * PIXEL_SIZE + startingY
return top
def generateImage(character):
image = PixelImage()
if "pixels" in character:
arr = character["pixels"]
x = int(character["leftMargin"]) if "leftMargin" in character else 0
y = int(-character["descent"]) if "descent" in character else 0
image = image | imageFromArray(arr, x, y)
if "reference" in character:
image = image | generateImage(charactersByCodepoint[character["reference"]])
if "diacritic" in character:
diacritic = diacritics[character["diacritic"]]
arr = diacritic["pixels"]
x = image.x
y = findHighestY(image) + 1
if "diacriticSpace" in character:
y += int(character["diacriticSpace"])
image = image | imageFromArray(arr, x, y)
return image

def findHighestY(image):
for y in range(image.y_end - 1, image.y, -1):
for x in range(image.x, image.x_end):
if image[x, y]:
return y
return image.y

def imageFromArray(arr, x=0, y=0):
return PixelImage(
x=x,
y=y,
width=len(arr[0]),
height=len(arr),
data=bytes(x for a in reversed(arr) for x in a),
)

def drawImage(image, pen):
for polygon in generatePolygons(image):
start = True
for x, y in polygon:
x *= PIXEL_SIZE
y *= PIXEL_SIZE
if start:
pen.moveTo(x, y)
start = False
else:
pen.lineTo(x, y)
pen.closePath()

generateFont()
generateExamples(characters, ligatures, charactersByCodepoint)
Loading

0 comments on commit 6895837

Please sign in to comment.