| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | """ |
| | Parse X Bitmap Distribution Format (BDF) |
| | """ |
| | from __future__ import annotations |
| |
|
| | from typing import BinaryIO |
| |
|
| | from . import FontFile, Image |
| |
|
| |
|
| | def bdf_char( |
| | f: BinaryIO, |
| | ) -> ( |
| | tuple[ |
| | str, |
| | int, |
| | tuple[tuple[int, int], tuple[int, int, int, int], tuple[int, int, int, int]], |
| | Image.Image, |
| | ] |
| | | None |
| | ): |
| | |
| | while True: |
| | s = f.readline() |
| | if not s: |
| | return None |
| | if s.startswith(b"STARTCHAR"): |
| | break |
| | id = s[9:].strip().decode("ascii") |
| |
|
| | |
| | props = {} |
| | while True: |
| | s = f.readline() |
| | if not s or s.startswith(b"BITMAP"): |
| | break |
| | i = s.find(b" ") |
| | props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii") |
| |
|
| | |
| | bitmap = bytearray() |
| | while True: |
| | s = f.readline() |
| | if not s or s.startswith(b"ENDCHAR"): |
| | break |
| | bitmap += s[:-1] |
| |
|
| | |
| | |
| | |
| | |
| | width, height, x_disp, y_disp = (int(p) for p in props["BBX"].split()) |
| |
|
| | |
| | |
| | dwx, dwy = (int(p) for p in props["DWIDTH"].split()) |
| |
|
| | bbox = ( |
| | (dwx, dwy), |
| | (x_disp, -y_disp - height, width + x_disp, -y_disp), |
| | (0, 0, width, height), |
| | ) |
| |
|
| | try: |
| | im = Image.frombytes("1", (width, height), bitmap, "hex", "1") |
| | except ValueError: |
| | |
| | im = Image.new("1", (width, height)) |
| |
|
| | return id, int(props["ENCODING"]), bbox, im |
| |
|
| |
|
| | class BdfFontFile(FontFile.FontFile): |
| | """Font file plugin for the X11 BDF format.""" |
| |
|
| | def __init__(self, fp: BinaryIO) -> None: |
| | super().__init__() |
| |
|
| | s = fp.readline() |
| | if not s.startswith(b"STARTFONT 2.1"): |
| | msg = "not a valid BDF file" |
| | raise SyntaxError(msg) |
| |
|
| | props = {} |
| | comments = [] |
| |
|
| | while True: |
| | s = fp.readline() |
| | if not s or s.startswith(b"ENDPROPERTIES"): |
| | break |
| | i = s.find(b" ") |
| | props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii") |
| | if s[:i] in [b"COMMENT", b"COPYRIGHT"]: |
| | if s.find(b"LogicalFontDescription") < 0: |
| | comments.append(s[i + 1 : -1].decode("ascii")) |
| |
|
| | while True: |
| | c = bdf_char(fp) |
| | if not c: |
| | break |
| | id, ch, (xy, dst, src), im = c |
| | if 0 <= ch < len(self.glyph): |
| | self.glyph[ch] = xy, dst, src, im |
| |
|