Compare commits

...

30 commits

Author SHA1 Message Date
7da4b31e17 run black 2021-01-05 08:59:06 -06:00
1724754e9c pcf: Support vewwy big letters
When glyphs lie entirely within 127 pixels of the glyph origin,
they get "compressed metrics".  Otherwise, they get "uncompressed
metrics".  Some of the calculations for "uncompressed metrics"
were wrong.  This only affects extremely unusual or large
point-size fonts, which is why it wasn't found initially.

Testing performed: rendered the letter 'a' at 200 points from
pcf.
2021-01-05 08:56:40 -06:00
Limor "Ladyada" Fried
d96e66fb37
Merge pull request #33 from FoamyGuy/pcf_examples
Adding pcf font files to example scripts. Few other fixes
2020-12-12 13:38:24 -05:00
foamyguy
97c0318e15 create fonts section in readme 2020-12-12 11:48:11 -06:00
foamyguy
2c6529dc45 add pcf filenames in examples. display variable in displayio simpletest. 2020-12-12 11:39:29 -06:00
foamyguy
af282529b9 fix readme example code block. update supported types for pcf in readme. 2020-12-12 10:26:51 -06:00
Jeff Epler
da4fa0b415
Merge pull request #32 from jepler/pcf
Implement PCF font loading
2020-12-08 20:28:14 -06:00
6e57a8b9e9 bitmap_font: Remove use of f-string, not compatible with 5.x mpy-cross 2020-12-08 14:03:33 -06:00
d379f1962e pcf: Remove use of f-string, not compatible with 5.x mpy-cross 2020-12-08 14:02:53 -06:00
383fc039c5 ttf: fix lint error 2020-12-08 13:47:58 -06:00
ceed4c2a88 pcf: black & lint 2020-12-08 11:16:37 -06:00
Jeff Epler
6ae6e07484 bdf: Add ascent, descent properties
This will be used by a future version of adafruit_display_text to avoid
needing to load glyphs from the font to guess these values.
2020-12-08 11:16:37 -06:00
e15c7d1f5c pcf: Optimize memory allocations 2020-12-08 10:59:08 -06:00
84bf5208bb Optimize bitmap fill 2020-12-08 10:49:18 -06:00
e1634e1a59 Fix off by 1 error in encoding index calculation 2020-12-08 10:49:18 -06:00
7dcd40828e Allow alternate specimens 2020-12-08 10:49:18 -06:00
e5d0839aca Add font with kana glyphs for testing 2020-12-08 10:49:18 -06:00
7869ef43be pcf: handle missing glyphs (mapped like code point 0xffff) 2020-12-07 21:57:02 -06:00
3c31cff165 run black 2020-12-07 19:08:24 -06:00
7658511786 Fix number of characters in this font
This font was probably manually trimmed from one with a larger repertoire of code points.

This was fine, except that bdftopcf didn't like it.
2020-12-07 19:07:12 -06:00
2bef623710 Implement loading pcf fonts
A pcf font can be generated from a bdf font using `bdftopcf` from debian/ubuntu package fonts-utils
2020-12-07 19:06:25 -06:00
27648e7ab7 bitmap_font: fix imports, give better error 2020-12-07 19:05:24 -06:00
Scott Shawcroft
51e9a1fa2e
Merge pull request #30 from FoamyGuy/magtag_example
adding MagTag example
2020-11-23 15:16:04 -08:00
foamyguy
8c1fa9b684 a few comments in magtag example 2020-11-22 15:04:12 -06:00
foamyguy
c38baeb932 adding magtag example 2020-11-22 15:01:06 -06:00
foamyguy
7e153547f5
Merge pull request #29 from adafruit/tannewt-patch-1
Fix 2.6.0 lint
2020-09-03 19:33:27 -05:00
Scott Shawcroft
ca48d4afde
Merge pull request #28 from ronfischler/set-changed-during-iteration-fix
Make a copy of the set to iterate over, not the original set we will …
2020-09-02 16:57:41 -07:00
Scott Shawcroft
1f46cc3a68
reorder imports 2020-09-02 16:46:51 -07:00
Scott Shawcroft
977edcbd88
Reorder imports 2020-09-02 16:43:09 -07:00
ronfischler
2501072843 Make a copy of the set to iterate over, not the original set we will be removing items from 2020-09-02 12:06:32 -07:00
13 changed files with 30838 additions and 124 deletions

1
.gitignore vendored
View file

@ -9,5 +9,4 @@ bundles
.eggs .eggs
dist dist
**/*.egg-info **/*.egg-info
*.pcf
*.ttf *.ttf

View file

@ -13,7 +13,7 @@ Introduction
:target: https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font/actions/ :target: https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font/actions/
:alt: Build Status :alt: Build Status
Loads bitmap fonts into CircuitPython's displayio. BDF files are well supported. PCF and TTF Loads bitmap fonts into CircuitPython's displayio. BDF and PCF files are well supported. TTF
support is not yet complete. support is not yet complete.
Dependencies Dependencies
@ -53,14 +53,23 @@ To install in a virtual environment in your current project:
Usage Example Usage Example
============= =============
.. code-block::python .. code-block:: python
from adafruit_bitmap_font import bitmap_font from adafruit_bitmap_font import bitmap_font
from displayio import Bitmap from displayio import Bitmap
font = bitmap_font.load_font("scientifica-11.bdf", Bitmap) font = bitmap_font.load_font("fonts/Arial-16.bdf", Bitmap)
print(font.get_glyph(ord("A"))) print(font.get_glyph(ord("A")))
Creating Fonts
==============
See `this learn guide <https://learn.adafruit.com/custom-fonts-for-pyportal-circuitpython-display>`_ for more information about building custom fornt files
The command line tool :code:`otf2bdf` can be used make bdf files for use with this library.
The command line tool :code:`bdftopcf` can be used make pcf files for use with this library.
Contributing Contributing
============ ============

View file

@ -63,6 +63,41 @@ class BDF(GlyphCache):
self.point_size = None self.point_size = None
self.x_resolution = None self.x_resolution = None
self.y_resolution = None self.y_resolution = None
self._ascent = None
self._descent = None
@property
def descent(self):
"""The number of pixels below the baseline of a typical descender"""
if self._descent is None:
self.file.seek(0)
while True:
line = self.file.readline()
if not line:
break
if line.startswith(b"FONT_DESCENT "):
self._descent = int(line.split()[1])
break
return self._descent
@property
def ascent(self):
"""The number of pixels above the baseline of a typical ascender"""
if self._ascent is None:
self.file.seek(0)
while True:
line = self.file.readline()
line = str(line, "utf-8")
if not line:
break
if line.startswith("FONT_ASCENT "):
self._ascent = int(line.split()[1])
break
return self._ascent
def get_bounding_box(self): def get_bounding_box(self):
"""Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset""" """Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset"""
@ -97,7 +132,7 @@ class BDF(GlyphCache):
remaining = code_points remaining = code_points
else: else:
remaining = set(code_points) remaining = set(code_points)
for code_point in remaining: for code_point in remaining.copy():
if code_point in self._glyphs and self._glyphs[code_point]: if code_point in self._glyphs and self._glyphs[code_point]:
remaining.remove(code_point) remaining.remove(code_point)
if not remaining: if not remaining:

View file

@ -57,11 +57,12 @@ def load_font(filename, bitmap=None):
return bdf.BDF(font_file, bitmap) return bdf.BDF(font_file, bitmap)
if filename.endswith("pcf") and first_four == b"\x01fcp": if filename.endswith("pcf") and first_four == b"\x01fcp":
import pcf from . import pcf
return pcf.PCF(font_file) return pcf.PCF(font_file, bitmap)
if filename.endswith("ttf") and first_four == b"\x00\x01\x00\x00": if filename.endswith("ttf") and first_four == b"\x00\x01\x00\x00":
import ttf from . import ttf
return ttf.TTF(font_file) return ttf.TTF(font_file, bitmap)
return None
raise ValueError("Unknown magic number %r" % first_four)

View file

@ -1,10 +1,51 @@
# pylint: skip-file # The MIT License (MIT)
# Remove the above when PCF is actually supported. #
# Copyright © 2020 Jeff Epler for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_bitmap_font.pcf`
====================================================
from .glyph_cache import GlyphCache Loads PCF format fonts.
import displayio
* Author(s): Jeff Epler
Implementation Notes
--------------------
**Hardware:**
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://github.com/adafruit/circuitpython/releases
"""
from collections import namedtuple
import gc
import struct import struct
from fontio import Glyph
from .glyph_cache import GlyphCache
_PCF_PROPERTIES = 1 << 0 _PCF_PROPERTIES = 1 << 0
_PCF_ACCELERATORS = 1 << 1 _PCF_ACCELERATORS = 1 << 1
_PCF_METRICS = 1 << 2 _PCF_METRICS = 1 << 2
@ -25,139 +66,345 @@ _PCF_BYTE_MASK = 1 << 2 # If set then Most Sig Byte First */
_PCF_BIT_MASK = 1 << 3 # If set then Most Sig Bit First */ _PCF_BIT_MASK = 1 << 3 # If set then Most Sig Bit First */
_PCF_SCAN_UNIT_MASK = 3 << 4 _PCF_SCAN_UNIT_MASK = 3 << 4
# https://fontforge.github.io/en-US/documentation/reference/pcf-format/ # https://fontforge.org/docs/techref/pcf-format.html
Table = namedtuple("Table", ("format", "size", "offset"))
Metrics = namedtuple(
"Metrics",
(
"left_side_bearing",
"right_side_bearing",
"character_width",
"character_ascent",
"character_descent",
"character_attributes",
),
)
Accelerators = namedtuple(
"Accelerators",
(
"no_overlap",
"constant_metrics",
"terminal_font",
"constant_width",
"ink_inside",
"ink_metrics",
"draw_direction",
"font_ascent",
"font_descent",
"max_overlap",
"minbounds",
"maxbounds",
"ink_minbounds",
"ink_maxbounds",
),
)
Encoding = namedtuple(
"Encoding", ("min_byte2", "max_byte2", "min_byte1", "max_byte1", "default_char")
)
Bitmap = namedtuple("Bitmap", ("glyph_count", "bitmap_sizes"))
class PCF(GlyphCache): class PCF(GlyphCache):
def __init__(self, f): """Loads glyphs from a PCF file in the given bitmap_class."""
def __init__(self, f, bitmap_class):
super().__init__() super().__init__()
self.file = f self.file = f
self.name = f self.name = f
f.seek(0) f.seek(0)
header, table_count = self.read("<4sI") self.buffer = bytearray(1)
self.bitmap_class = bitmap_class
_, table_count = self._read("<4sI")
self.tables = {} self.tables = {}
for _ in range(table_count): for _ in range(table_count):
type, format, size, offset = self.read("<IIII") type_, format_, size, offset = self._read("<IIII")
self.tables[type] = {"format": format, "size": size, "offset": offset} self.tables[type_] = Table(format_, size, offset)
print(type)
def read(self, format): bitmap_format = self.tables[_PCF_BITMAPS].format
s = struct.calcsize(format) if bitmap_format != 0xE:
return struct.unpack_from(format, self.file.read(s)) raise NotImplementedError("Unsupported format %s" % bitmap_format)
self._accel = self._read_accelerator_tables()
self._encoding = self._read_encoding_table()
self._bitmaps = self._read_bitmap_table()
self._ascent = self._accel.font_ascent
self._descent = self._accel.font_descent
minbounds = self._accel.ink_minbounds
maxbounds = self._accel.ink_maxbounds
width = maxbounds.right_side_bearing - minbounds.left_side_bearing
height = maxbounds.character_ascent + maxbounds.character_descent
self._bounding_box = (
width,
height,
minbounds.left_side_bearing,
-maxbounds.character_descent,
)
@property
def ascent(self):
"""The number of pixels above the baseline of a typical ascender"""
return self._ascent
@property
def descent(self):
"""The number of pixels below the baseline of a typical descender"""
return self._descent
def get_bounding_box(self): def get_bounding_box(self):
"""Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset"""
return self._bounding_box
def _read(self, format_):
size = struct.calcsize(format_)
if size != len(self.buffer):
self.buffer = bytearray(size)
self.file.readinto(self.buffer)
return struct.unpack_from(format_, self.buffer)
def _seek_table(self, table):
self.file.seek(table.offset)
(format_,) = self._read("<I")
if format_ & _PCF_BYTE_MASK == 0:
raise RuntimeError("Only big endian supported")
return format_
def _read_encoding_table(self):
encoding = self.tables[_PCF_BDF_ENCODINGS]
self._seek_table(encoding)
return Encoding(*self._read(">hhhhh"))
def _read_bitmap_table(self):
bitmaps = self.tables[_PCF_BITMAPS]
format_ = self._seek_table(bitmaps)
(glyph_count,) = self._read(">I")
self.file.seek(bitmaps.offset + 8 + 4 * glyph_count)
bitmap_sizes = self._read(">4I")
return Bitmap(glyph_count, bitmap_sizes[format_ & 3])
def _read_metrics(self, compressed_metrics):
if compressed_metrics:
(
left_side_bearing,
right_side_bearing,
character_width,
character_ascent,
character_descent,
) = self._read("5B")
left_side_bearing -= 0x80
right_side_bearing -= 0x80
character_width -= 0x80
character_ascent -= 0x80
character_descent -= 0x80
attributes = 0
else:
(
left_side_bearing,
right_side_bearing,
character_width,
character_ascent,
character_descent,
attributes,
) = self._read(">5hH")
return Metrics(
left_side_bearing,
right_side_bearing,
character_width,
character_ascent,
character_descent,
attributes,
)
def _read_accelerator_tables(self):
# pylint: disable=too-many-locals
accelerators = self.tables.get(_PCF_BDF_ACCELERATORS)
if not accelerators:
accelerators = self.tables.get(_PCF_ACCELERATORS)
if not accelerators:
raise RuntimeError("Accelerator table missing")
format_ = self._seek_table(accelerators)
has_inkbounds = format_ & _PCF_ACCEL_W_INKBOUNDS
compressed_metrics = format_ & _PCF_COMPRESSED_METRICS
(
no_overlap,
constant_metrics,
terminal_font,
constant_width,
ink_inside,
ink_metrics,
draw_direction,
_,
font_ascent,
font_descent,
max_overlap,
) = self._read(">BBBBBBBBIII")
minbounds = self._read_metrics(compressed_metrics)
maxbounds = self._read_metrics(compressed_metrics)
if has_inkbounds:
ink_minbounds = self._read_metrics(compressed_metrics)
ink_maxbounds = self._read_metrics(compressed_metrics)
else:
ink_minbounds = minbounds
ink_maxbounds = maxbounds
return Accelerators(
no_overlap,
constant_metrics,
terminal_font,
constant_width,
ink_inside,
ink_metrics,
draw_direction,
font_ascent,
font_descent,
max_overlap,
minbounds,
maxbounds,
ink_minbounds,
ink_maxbounds,
)
def _read_properties(self):
property_table_offset = self.tables[_PCF_PROPERTIES]["offset"] property_table_offset = self.tables[_PCF_PROPERTIES]["offset"]
self.file.seek(property_table_offset) self.file.seek(property_table_offset)
(format,) = self.read("<I") (format_,) = self._read("<I")
if format & _PCF_BYTE_MASK == 0: if format_ & _PCF_BYTE_MASK == 0:
raise RuntimeError("Only big endian supported") raise RuntimeError("Only big endian supported")
(nprops,) = self.read(">I") (nprops,) = self._read(">I")
self.file.seek(property_table_offset + 8 + 9 * nprops) self.file.seek(property_table_offset + 8 + 9 * nprops)
pos = self.file.tell() pos = self.file.tell()
if pos % 4 > 0: if pos % 4 > 0:
self.file.read(4 - pos % 4) self.file.read(4 - pos % 4)
(string_size,) = self.read(">I") (string_size,) = self._read(">I")
strings = self.file.read(string_size) strings = self.file.read(string_size)
string_map = {} string_map = {}
i = 0 i = 0
for s in strings.split(b"\x00"): for value in strings.split(b"\x00"):
string_map[i] = s string_map[i] = value
i += len(s) + 1 i += len(value) + 1
self.file.seek(property_table_offset + 8) self.file.seek(property_table_offset + 8)
for _ in range(nprops): for _ in range(nprops):
name_offset, isStringProp, value = self.read(">IBI") name_offset, is_string_prop, value = self._read(">IBI")
if isStringProp: if is_string_prop:
print(string_map[name_offset], string_map[value]) yield (string_map[name_offset], string_map[value])
else: else:
print(string_map[name_offset], value) yield (string_map[name_offset], value)
return None
def load_glyphs(self, code_points): def load_glyphs(self, code_points):
metadata = True # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals
character = False if isinstance(code_points, int):
code_point = None code_points = (code_points,)
rounded_x = 1 elif isinstance(code_points, str):
bytes_per_row = 1 code_points = [ord(c) for c in code_points]
desired_character = False
current_info = None
current_y = 0
total_remaining = len(code_points)
x, _, _, _ = self.get_bounding_box() code_points = sorted(
# create a scratch bytearray to load pixels into c for c in code_points if self._glyphs.get(c, None) is None
scratch_row = memoryview(bytearray((((x - 1) // 32) + 1) * 4))
self.file.seek(0)
while True:
line = self.file.readline()
if not line:
break
if line.startswith(b"CHARS "):
metadata = False
elif line.startswith(b"SIZE"):
_, self.point_size, self.x_resolution, self.y_resolution = line.split()
elif line.startswith(b"COMMENT"):
pass
elif line.startswith(b"STARTCHAR"):
# print(lineno, line.strip())
# _, character_name = line.split()
character = True
elif line.startswith(b"ENDCHAR"):
character = False
if desired_character:
self._glyphs[code_point] = current_info
if total_remaining == 0:
return
desired_character = False
elif line.startswith(b"BBX"):
if desired_character:
_, x, y, dx, dy = line.split()
x = int(x)
y = int(y)
dx = int(dx)
dy = int(dy)
current_info["bounds"] = (x, y, dx, dy)
current_info["bitmap"] = displayio.Bitmap(x, y, 2)
elif line.startswith(b"BITMAP"):
if desired_character:
rounded_x = x // 8
if x % 8 > 0:
rounded_x += 1
bytes_per_row = rounded_x
if bytes_per_row % 4 > 0:
bytes_per_row += 4 - bytes_per_row % 4
current_y = 0
elif line.startswith(b"ENCODING"):
_, code_point = line.split()
code_point = int(code_point)
if code_point == code_points or code_point in code_points:
total_remaining -= 1
if code_point not in self._glyphs:
desired_character = True
current_info = {"bitmap": None, "bounds": None, "shift": None}
elif line.startswith(b"DWIDTH"):
if desired_character:
_, shift_x, shift_y = line.split()
shift_x = int(shift_x)
shift_y = int(shift_y)
current_info["shift"] = (shift_x, shift_y)
elif line.startswith(b"SWIDTH"):
pass
elif character:
if desired_character:
bits = int(line.strip(), 16)
for i in range(rounded_x):
val = (bits >> ((rounded_x - i - 1) * 8)) & 0xFF
scratch_row[i] = val
current_info["bitmap"]._load_row(
current_y, scratch_row[:bytes_per_row]
) )
current_y += 1 if not code_points:
elif metadata: return
# print(lineno, line.strip())
pass indices_offset = self.tables[_PCF_BDF_ENCODINGS].offset + 14
bitmap_offset_offsets = self.tables[_PCF_BITMAPS].offset + 8
first_bitmap_offset = self.tables[_PCF_BITMAPS].offset + 4 * (
6 + self._bitmaps.glyph_count
)
metrics_compressed = self.tables[_PCF_METRICS].format & _PCF_COMPRESSED_METRICS
first_metric_offset = self.tables[_PCF_METRICS].offset + (
6 if metrics_compressed else 8
)
metrics_size = 5 if metrics_compressed else 12
# These will each _tend to be_ forward reads in the file, at least
# sometimes we'll benefit from oofatfs's 512 byte cache and avoid
# excess reads
indices = [None] * len(code_points)
for i, code_point in enumerate(code_points):
enc1 = (code_point >> 8) & 0xFF
enc2 = code_point & 0xFF
if enc1 < self._encoding.min_byte1 or enc1 > self._encoding.max_byte1:
continue
if enc2 < self._encoding.min_byte2 or enc2 > self._encoding.max_byte2:
continue
encoding_idx = (
(enc1 - self._encoding.min_byte1)
* (self._encoding.max_byte2 - self._encoding.min_byte2 + 1)
+ enc2
- self._encoding.min_byte2
)
self.file.seek(indices_offset + 2 * encoding_idx)
(glyph_idx,) = self._read(">H")
if glyph_idx != 65535:
indices[i] = glyph_idx
all_metrics = [None] * len(code_points)
for i, code_point in enumerate(code_points):
index = indices[i]
if index is None:
continue
self.file.seek(first_metric_offset + metrics_size * index)
all_metrics[i] = self._read_metrics(metrics_compressed)
bitmap_offsets = [None] * len(code_points)
for i, code_point in enumerate(code_points):
index = indices[i]
if index is None:
continue
self.file.seek(bitmap_offset_offsets + 4 * index)
(bitmap_offset,) = self._read(">I")
bitmap_offsets[i] = bitmap_offset
# Batch creation of glyphs and bitmaps so that we need only gc.collect
# once
gc.collect()
bitmaps = [None] * len(code_points)
for i in range(len(all_metrics)): # pylint: disable=consider-using-enumerate
metrics = all_metrics[i]
if metrics is not None:
width = metrics.right_side_bearing - metrics.left_side_bearing
height = metrics.character_ascent + metrics.character_descent
bitmap = bitmaps[i] = self.bitmap_class(width, height, 2)
self._glyphs[code_points[i]] = Glyph(
bitmap,
0,
width,
height,
metrics.left_side_bearing,
-metrics.character_descent,
metrics.character_width,
0,
)
for i, code_point in enumerate(code_points):
metrics = all_metrics[i]
if metrics is None:
continue
self.file.seek(first_bitmap_offset + bitmap_offsets[i])
width = metrics.right_side_bearing - metrics.left_side_bearing
height = metrics.character_ascent + metrics.character_descent
bitmap = bitmaps[i]
words_per_row = (width + 31) // 32
buf = bytearray(4 * words_per_row)
start = 0
for _ in range(height):
self.file.readinto(buf)
for k in range(width):
if buf[k // 8] & (128 >> (k % 8)):
bitmap[start + k] = 1
start += width

View file

@ -8,7 +8,7 @@ import struct
class TTF: class TTF:
def __init__(self, f): def __init__(self, f, bitmap):
f.seek(0) f.seek(0)
self.file = f self.file = f

View file

@ -8,10 +8,19 @@ bitmap with pixels matching glyphs from a given String
import board import board
from adafruit_bitmap_font import bitmap_font # pylint: disable=wrong-import-position
import displayio import displayio
from adafruit_bitmap_font import bitmap_font
font = bitmap_font.load_font("fonts/Arial-16.bdf") # use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.)
# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.)
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus
display = board.DISPLAY
# try uncommenting different font files if you like
font_file = "fonts/Arial-16.bdf"
# font_file = "fonts/yasashi24.pcf"
font = bitmap_font.load_font(font_file)
bitmap = displayio.Bitmap(320, 240, 2) bitmap = displayio.Bitmap(320, 240, 2)
@ -59,7 +68,7 @@ group.x = 20
group.append(tile_grid) group.append(tile_grid)
# Add the Group to the Display # Add the Group to the Display
board.DISPLAY.show(group) display.show(group)
while True: while True:
pass pass

View file

@ -0,0 +1,48 @@
"""
This example uses addfruit_display_text.label to display text using a custom font
loaded by adafruit_bitmap_font.
Adapted for use on MagTag
"""
import time
import board
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
# use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.)
# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.)
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus
display = board.DISPLAY
# wait until we can refresh the display
time.sleep(display.time_to_refresh)
# try uncommenting different font files if you like
font_file = "fonts/Arial-16.bdf"
# font_file = "fonts/yasashi24.pcf"
# Set text, font, and color
text = "HELLO WORLD\nbitmap_font example"
font = bitmap_font.load_font(font_file)
color = 0xFFFFFF
background_color = 0x999999
# Create the tet label
text_area = label.Label(
font,
text=text,
color=color,
background_color=background_color,
padding_top=3,
padding_bottom=3,
padding_right=4,
padding_left=4,
)
text_area.line_spacing = 1.0
# Set the location
text_area.x = 20
text_area.y = 20
# Show it and refresh
display.show(text_area)
display.refresh()
while True:
pass

View file

@ -4,14 +4,21 @@ loaded by adafruit_bitmap_font
""" """
import board import board
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
# use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.)
# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.)
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus
display = board.DISPLAY display = board.DISPLAY
# try uncommenting different font files if you like
font_file = "fonts/Arial-16.bdf"
# font_file = "fonts/yasashi24.pcf"
# Set text, font, and color # Set text, font, and color
text = "HELLO WORLD" text = "HELLO WORLD"
font = bitmap_font.load_font("fonts/Arial-16.bdf") font = bitmap_font.load_font(font_file)
color = 0xFF00FF color = 0xFF00FF
# Create the tet label # Create the tet label

View file

@ -9,10 +9,13 @@ from adafruit_bitmap_font import bitmap_font # pylint: disable=wrong-import-pos
sys.path.append(os.path.join(sys.path[0], "../test")) sys.path.append(os.path.join(sys.path[0], "../test"))
font = bitmap_font.load_font(sys.argv[1]) font = bitmap_font.load_font(sys.argv[1])
specimen = "Adafruit CircuitPython" if len(sys.argv) == 2 else sys.argv[2]
_, height, _, dy = font.get_bounding_box() _, height, _, dy = font.get_bounding_box()
font.load_glyphs(specimen)
for y in range(height): for y in range(height):
for c in "Adafruit CircuitPython": for c in specimen:
glyph = font.get_glyph(ord(c)) glyph = font.get_glyph(ord(c))
if not glyph: if not glyph:
continue continue

View file

@ -26,7 +26,7 @@ COPYRIGHT "
_OTF_FONTFILE "arial.ttf" _OTF_FONTFILE "arial.ttf"
_OTF_PSNAME "ArialMT" _OTF_PSNAME "ArialMT"
ENDPROPERTIES ENDPROPERTIES
CHARS 3361 CHARS 318
STARTCHAR 0020 STARTCHAR 0020
ENCODING 32 ENCODING 32
SWIDTH 270 0 SWIDTH 270 0

30356
examples/fonts/yasashi24.bdf Normal file

File diff suppressed because it is too large Load diff

Binary file not shown.