Skip to content
This repository has been archived by the owner on Dec 8, 2023. It is now read-only.

Commit

Permalink
优化字形栅格化迭代逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
TakWolf committed Jun 6, 2023
1 parent f02f786 commit 0ab53a2
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 91 deletions.
14 changes: 2 additions & 12 deletions src/nico_font_tool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,16 @@ def create_sheet(

sheet_data = [[_GLYPH_DATA_BORDER] for _ in range(font_rasterizer.adjusted_line_height)]
alphabet = []

for code_point in font_rasterizer.get_code_point_sequence():
c = chr(code_point)
if not c.isprintable():
continue

glyph_data, adjusted_advance_width = font_rasterizer.rasterize_glyph(code_point)
if glyph_data is None:
continue
logger.info(f'Rasterize glyph: {code_point} - {c} - {adjusted_advance_width}')

for c, glyph_data, adjusted_advance_width in font_rasterizer.rasterize_glyphs_in_order():
for y in range(font_rasterizer.adjusted_line_height):
for x in range(adjusted_advance_width):
if glyph_data[y][x] > 0:
sheet_data[y].append(_GLYPH_DATA_SOLID)
else:
sheet_data[y].append(_GLYPH_DATA_TRANSPARENT)
sheet_data[y].append(_GLYPH_DATA_BORDER)

alphabet.append(c)
logger.info(f'Rasterize glyph: {ord(c)} - {c} - {adjusted_advance_width}')

return sheet_data, alphabet

Expand Down
91 changes: 47 additions & 44 deletions src/nico_font_tool/bdf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from typing import Iterator

from bdffont import BdfFont

Expand Down Expand Up @@ -43,51 +44,53 @@ def __init__(
glyph_adjust_height,
)

def get_code_point_sequence(self) -> list[int]:
sequence = list(self.font.code_point_to_glyph.keys())
sequence.sort()
return sequence
def rasterize_glyphs_in_order(self) -> Iterator[tuple[str, list[list[int]], int]]:
code_points = list(self.font.code_point_to_glyph.keys())
code_points.sort()
for code_point in code_points:
c = chr(code_point)
if not c.isprintable():
continue

def rasterize_glyph(self, code_point: int) -> tuple[list[list[int]] | None, int | None]:
glyph = self.font.get_glyph(code_point)
advance_width = glyph.device_width_x
if advance_width <= 0:
return None, None
adjusted_advance_width = advance_width + self.glyph_adjust_width
if adjusted_advance_width <= 0:
return None, None
glyph = self.font.get_glyph(code_point)
advance_width = glyph.device_width_x
if advance_width <= 0:
continue
adjusted_advance_width = advance_width + self.glyph_adjust_width
if adjusted_advance_width <= 0:
continue

glyph_data = [[color for color in bitmap_row] for bitmap_row in glyph.bitmap]
# Bottom
append_bottom = glyph.bounding_box_offset_y - self.descent + self.glyph_adjust_height - self.glyph_offset_y
while append_bottom > 0:
append_bottom -= 1
glyph_data.append([])
while append_bottom < 0:
append_bottom += 1
if len(glyph_data) > 0:
glyph_data.pop()
# Top
while len(glyph_data) < self.adjusted_line_height:
glyph_data.insert(0, [])
while len(glyph_data) > self.adjusted_line_height:
glyph_data.pop(0)
# Left
append_left = glyph.bounding_box_offset_x + self.glyph_offset_x
while append_left > 0:
append_left -= 1
glyph_data = [[alpha for alpha in bitmap_row] for bitmap_row in glyph.bitmap]
# Bottom
append_bottom = glyph.bounding_box_offset_y - self.descent + self.glyph_adjust_height - self.glyph_offset_y
while append_bottom > 0:
append_bottom -= 1
glyph_data.append([])
while append_bottom < 0:
append_bottom += 1
if len(glyph_data) > 0:
glyph_data.pop()
# Top
while len(glyph_data) < self.adjusted_line_height:
glyph_data.insert(0, [])
while len(glyph_data) > self.adjusted_line_height:
glyph_data.pop(0)
# Left
append_left = glyph.bounding_box_offset_x + self.glyph_offset_x
while append_left > 0:
append_left -= 1
for glyph_data_row in glyph_data:
glyph_data_row.insert(0, 0)
while append_left < 0:
append_left += 1
for glyph_data_row in glyph_data:
if len(glyph_data_row) > 0:
glyph_data_row.pop(0)
# Right
for glyph_data_row in glyph_data:
glyph_data_row.insert(0, 0)
while append_left < 0:
append_left += 1
for glyph_data_row in glyph_data:
if len(glyph_data_row) > 0:
glyph_data_row.pop(0)
# Right
for glyph_data_row in glyph_data:
while len(glyph_data_row) < adjusted_advance_width:
glyph_data_row.append(0)
while len(glyph_data_row) > adjusted_advance_width:
glyph_data_row.pop()
while len(glyph_data_row) < adjusted_advance_width:
glyph_data_row.append(0)
while len(glyph_data_row) > adjusted_advance_width:
glyph_data_row.pop()

return glyph_data, adjusted_advance_width
yield c, glyph_data, adjusted_advance_width
7 changes: 3 additions & 4 deletions src/nico_font_tool/font.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Iterator


class FontRasterizer:
def __init__(
Expand All @@ -24,8 +26,5 @@ def line_height(self) -> int:
def adjusted_line_height(self) -> int:
return self.line_height + self.glyph_adjust_height

def get_code_point_sequence(self) -> list[int]:
raise NotImplementedError()

def rasterize_glyph(self, code_point: int) -> tuple[list[list[int]] | None, int | None]:
def rasterize_glyphs_in_order(self) -> Iterator[tuple[str, list[list[int]], int]]:
raise NotImplementedError()
64 changes: 33 additions & 31 deletions src/nico_font_tool/opentype.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import math
import os
from typing import Iterator

from PIL import ImageFont, Image, ImageDraw
from fontTools.ttLib import TTFont
Expand Down Expand Up @@ -33,37 +34,38 @@ def __init__(
glyph_adjust_height,
)

def get_code_point_sequence(self) -> list[int]:
sequence = list(self.font.getBestCmap().keys())
sequence.sort()
return sequence
def rasterize_glyphs_in_order(self) -> Iterator[tuple[str, list[list[int]], int]]:
code_points = list(self.font.getBestCmap().keys())
code_points.sort()
for code_point in code_points:
c = chr(code_point)
if not c.isprintable():
continue

def rasterize_glyph(self, code_point: int) -> tuple[list[list[int]] | None, int | None]:
glyph_name = self.font.getBestCmap()[code_point]
advance_width = math.ceil(self.font['hmtx'].metrics[glyph_name][0] / self.px_units)
if advance_width <= 0:
return None, None
adjusted_advance_width = advance_width + self.glyph_adjust_width
if adjusted_advance_width <= 0:
return None, None
glyph_name = self.font.getBestCmap()[code_point]
advance_width = math.ceil(self.font['hmtx'].metrics[glyph_name][0] / self.px_units)
if advance_width <= 0:
continue
adjusted_advance_width = advance_width + self.glyph_adjust_width
if adjusted_advance_width <= 0:
continue

glyph_image = Image.new('RGBA', (adjusted_advance_width, self.adjusted_line_height), (0, 0, 0, 0))
ImageDraw.Draw(glyph_image).text(
xy=(self.glyph_offset_x, self.glyph_offset_y),
text=chr(code_point),
fill=(0, 0, 0),
font=self.image_font,
)

glyph_data = []
for y in range(self.adjusted_line_height):
glyph_data_row = []
for x in range(adjusted_advance_width):
alpha = glyph_image.getpixel((x, y))[3]
if alpha > 127:
glyph_data_row.append(1)
else:
glyph_data_row.append(0)
glyph_data.append(glyph_data_row)
glyph_image = Image.new('RGBA', (adjusted_advance_width, self.adjusted_line_height), (0, 0, 0, 0))
ImageDraw.Draw(glyph_image).text(
xy=(self.glyph_offset_x, self.glyph_offset_y),
text=chr(code_point),
fill=(0, 0, 0),
font=self.image_font,
)
glyph_data = []
for y in range(self.adjusted_line_height):
glyph_data_row = []
for x in range(adjusted_advance_width):
alpha = glyph_image.getpixel((x, y))[3]
if alpha > 127:
glyph_data_row.append(1)
else:
glyph_data_row.append(0)
glyph_data.append(glyph_data_row)

return glyph_data, adjusted_advance_width
yield c, glyph_data, adjusted_advance_width

0 comments on commit 0ab53a2

Please sign in to comment.