font-generator.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Font Generator
  5. # Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. import argparse
  20. import cairo
  21. import codecs
  22. import math
  23. import re
  24. class FontGenerator:
  25. def __init__(self):
  26. self.font_size = 24
  27. self.letters = u"""!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""
  28. self.font_family = "WenQuanYi Micro Hei"
  29. self.columns = 20
  30. self.glyph_width = 20
  31. self.glyph_height = 20
  32. self.draw_outline = False
  33. self.draw_shadow = False
  34. def generate_image(self):
  35. rows = (len(self.letters) + self.columns - 1) // self.columns
  36. width = self.glyph_width * self.columns
  37. height = self.glyph_height * rows
  38. surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, width, height)
  39. cr = cairo.Context (surface)
  40. # cr.translate(0.5, 0.5)
  41. self.draw_glyphs(cr, self.columns, rows)
  42. return surface
  43. def draw_glyphs(self, cr, cols, rows):
  44. if False:
  45. cr.set_source_rgb(255, 255, 255)
  46. cr.fill()
  47. elif self.checkerboard:
  48. for row in range(rows):
  49. for col in range(cols):
  50. idx = row * cols + col
  51. cr.rectangle(col * self.glyph_width,
  52. row * self.glyph_height,
  53. self.glyph_width,
  54. self.glyph_height)
  55. if (col + row % 2) % 2 == 0 :
  56. cr.set_source_rgb(0.5, 0.5, 0.5)
  57. else:
  58. cr.set_source_rgb(0.75, 0.75, 0.75)
  59. cr.fill()
  60. cr.select_font_face(self.font_family, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
  61. cr.set_font_size(self.font_size)
  62. fascent, fdescent, fheight, fxadvance, fyadvance = cr.font_extents()
  63. print self.glyph_height, fheight
  64. for row in range(rows):
  65. for col in range(cols):
  66. idx = row * cols + col
  67. if idx < len(self.letters):
  68. letter = self.letters[idx]
  69. xbearing, ybearing, width, height, xadvance, yadvance = cr.text_extents(letter)
  70. #cr.move_to(cx + 0.5 - xbearing - width / 2,
  71. # 0.5 - fdescent + fheight / 2)
  72. gx = col * self.glyph_width + self.glyph_width/2.0 - xbearing - width/2.0
  73. gy = row * self.glyph_height + self.glyph_height/2.0 - fdescent + fheight/2
  74. if self.draw_outline or self.draw_shadow:
  75. cr.move_to(gx, gy)
  76. cr.set_line_width(2.0)
  77. cr.set_line_join(cairo.LINE_JOIN_ROUND)
  78. cr.set_source_rgb(0, 0, 0)
  79. cr.text_path(letter)
  80. cr.stroke_preserve()
  81. if self.draw_shadow:
  82. cr.set_source_rgb(0, 0, 0)
  83. else:
  84. cr.set_source_rgb(255, 255, 255)
  85. cr.fill()
  86. else:
  87. cr.set_source_rgb(255, 255, 255)
  88. cr.move_to(gx, gy)
  89. cr.show_text(letter)
  90. if __name__ == "__main__":
  91. parser = argparse.ArgumentParser(description='Font Generator')
  92. parser.add_argument('-o', '--output', metavar='FILE', type=str, required=True,
  93. help="output file")
  94. parser.add_argument('--font-size', metavar='INT', type=int,
  95. help="font size")
  96. parser.add_argument('--font', metavar='NAME', type=str, help="font")
  97. parser.add_argument('--columns', metavar='INT', type=int, help="font")
  98. parser.add_argument('--letters', metavar='NAME', type=str, help="letters")
  99. parser.add_argument('--letters-from-file', metavar='FILE', type=str, help="letters from file")
  100. parser.add_argument('--outline', action="store_true", help="draw outline")
  101. parser.add_argument('--shadow', action="store_true", help="draw shadow")
  102. parser.add_argument('--glyph-width', type=int, help="glyph width")
  103. parser.add_argument('--glyph-height', type=int, help="glyph height")
  104. parser.add_argument('--checkerboard', action="store_true", help="draw checkerboard background")
  105. args = parser.parse_args()
  106. generator = FontGenerator()
  107. if args.font_size is not None:
  108. generator.font_size = args.font_size
  109. if args.letters is not None:
  110. generator.letters = args.letters
  111. if args.letters_from_file is not None:
  112. with codecs.open(args.letters_from_file, encoding='utf-8') as fin:
  113. generator.letters = re.sub(r"\s", "", fin.read())
  114. if args.font is not None:
  115. generator.font_family = args.font
  116. if args.letters is not None:
  117. generator.letters = args.letters.decode('utf8')
  118. if args.columns is not None:
  119. generator.columns = args.columns
  120. if args.outline is not None:
  121. generator.draw_outline = args.outline
  122. if args.shadow is not None:
  123. generator.draw_shadow = args.shadow
  124. if args.checkerboard is not None:
  125. generator.checkerboard = args.checkerboard
  126. if args.glyph_width is not None:
  127. generator.glyph_width = args.glyph_width
  128. if args.glyph_height is not None:
  129. generator.glyph_height = args.glyph_height
  130. img = generator.generate_image()
  131. img.write_to_png(args.output)
  132. # EOF #