BdfFontFile.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #
  2. # The Python Imaging Library
  3. # $Id$
  4. #
  5. # bitmap distribution font (bdf) file parser
  6. #
  7. # history:
  8. # 1996-05-16 fl created (as bdf2pil)
  9. # 1997-08-25 fl converted to FontFile driver
  10. # 2001-05-25 fl removed bogus __init__ call
  11. # 2002-11-20 fl robustification (from Kevin Cazabon, Dmitry Vasiliev)
  12. # 2003-04-22 fl more robustification (from Graham Dumpleton)
  13. #
  14. # Copyright (c) 1997-2003 by Secret Labs AB.
  15. # Copyright (c) 1997-2003 by Fredrik Lundh.
  16. #
  17. # See the README file for information on usage and redistribution.
  18. #
  19. """
  20. Parse X Bitmap Distribution Format (BDF)
  21. """
  22. from . import FontFile, Image
  23. bdf_slant = {
  24. "R": "Roman",
  25. "I": "Italic",
  26. "O": "Oblique",
  27. "RI": "Reverse Italic",
  28. "RO": "Reverse Oblique",
  29. "OT": "Other",
  30. }
  31. bdf_spacing = {"P": "Proportional", "M": "Monospaced", "C": "Cell"}
  32. def bdf_char(f):
  33. # skip to STARTCHAR
  34. while True:
  35. s = f.readline()
  36. if not s:
  37. return None
  38. if s[:9] == b"STARTCHAR":
  39. break
  40. id = s[9:].strip().decode("ascii")
  41. # load symbol properties
  42. props = {}
  43. while True:
  44. s = f.readline()
  45. if not s or s[:6] == b"BITMAP":
  46. break
  47. i = s.find(b" ")
  48. props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii")
  49. # load bitmap
  50. bitmap = []
  51. while True:
  52. s = f.readline()
  53. if not s or s[:7] == b"ENDCHAR":
  54. break
  55. bitmap.append(s[:-1])
  56. bitmap = b"".join(bitmap)
  57. [x, y, l, d] = [int(p) for p in props["BBX"].split()]
  58. [dx, dy] = [int(p) for p in props["DWIDTH"].split()]
  59. bbox = (dx, dy), (l, -d - y, x + l, -d), (0, 0, x, y)
  60. try:
  61. im = Image.frombytes("1", (x, y), bitmap, "hex", "1")
  62. except ValueError:
  63. # deal with zero-width characters
  64. im = Image.new("1", (x, y))
  65. return id, int(props["ENCODING"]), bbox, im
  66. class BdfFontFile(FontFile.FontFile):
  67. """Font file plugin for the X11 BDF format."""
  68. def __init__(self, fp):
  69. super().__init__()
  70. s = fp.readline()
  71. if s[:13] != b"STARTFONT 2.1":
  72. raise SyntaxError("not a valid BDF file")
  73. props = {}
  74. comments = []
  75. while True:
  76. s = fp.readline()
  77. if not s or s[:13] == b"ENDPROPERTIES":
  78. break
  79. i = s.find(b" ")
  80. props[s[:i].decode("ascii")] = s[i + 1 : -1].decode("ascii")
  81. if s[:i] in [b"COMMENT", b"COPYRIGHT"]:
  82. if s.find(b"LogicalFontDescription") < 0:
  83. comments.append(s[i + 1 : -1].decode("ascii"))
  84. while True:
  85. c = bdf_char(fp)
  86. if not c:
  87. break
  88. id, ch, (xy, dst, src), im = c
  89. if 0 <= ch < len(self.glyph):
  90. self.glyph[ch] = xy, dst, src, im