1#!/usr/bin/env vpython3 2# 3# [VPYTHON:BEGIN] 4# wheel: < 5# name: "infra/python/wheels/freetype-py/${vpython_platform}" 6# version: "version:2.2.0.chromium.4" 7# > 8# [VPYTHON:END] 9 10# Copyright 2019 The ANGLE Project Authors. All rights reserved. 11# Use of this source code is governed by a BSD-style license that can be 12# found in the LICENSE file. 13# 14# gen_vk_overlay_fonts.py: 15# Code generation for overlay fonts. Should be run if the font file under overlay/ is changed, 16# or the font sizes declared in this file are modified. The font is assumed to be monospace. 17# The output will contain ASCII characters in order from ' ' to '~'. The output will be images 18# with 95 layers, with each smaller font size having half the size of the previous to form a mip 19# chain. 20# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 21 22import sys 23 24if len(sys.argv) < 2: 25 from freetype import * 26 27out_file_cpp = 'Overlay_font_autogen.cpp' 28out_file_h = 'Overlay_font_autogen.h' 29font_file = 'overlay/DejaVuSansMono-Bold.ttf' 30 31template_out_file_h = u"""// GENERATED FILE - DO NOT EDIT. 32// Generated by {script_name} using {font_file}. 33// 34// Copyright 2022 The ANGLE Project Authors. All rights reserved. 35// Use of this source code is governed by a BSD-style license that can be 36// found in the LICENSE file. 37// 38// {out_file_name}: 39// Autogenerated overlay font data. 40 41#include "libANGLE/Overlay.h" 42 43namespace gl 44{{ 45namespace overlay 46{{ 47constexpr uint32_t kFontMipCount = {font_count}; 48constexpr uint32_t kFontCharacters = {char_count}; 49constexpr uint32_t kFontGlyphWidth = {max_font_width}; 50constexpr uint32_t kFontGlyphHeight = {max_font_height}; 51constexpr uint32_t kFontMipDataSize[kFontMipCount] = {{{font_mip_data_sizes}}}; 52constexpr uint32_t kFontMipDataOffset[kFontMipCount] = {{{font_mip_data_offsets}}}; 53constexpr uint32_t kFontTotalDataSize = {total_font_data_size}; 54{font_mips} 55}} // namespace overlay 56}} // namespace gl 57 58""" 59 60template_out_file_cpp = u"""// GENERATED FILE - DO NOT EDIT. 61// Generated by {script_name} using images from {font_file}. 62// 63// Copyright 2022 The ANGLE Project Authors. All rights reserved. 64// Use of this source code is governed by a BSD-style license that can be 65// found in the LICENSE file. 66// 67// {out_file_name}: 68// Autogenerated overlay font data. 69 70#include "libANGLE/Overlay.h" 71#include "libANGLE/Overlay_font_autogen.h" 72 73#include <numeric> 74 75namespace gl 76{{ 77using namespace overlay; 78 79// Save binary size if the font images are never to be used. 80#if ANGLE_ENABLE_OVERLAY 81namespace 82{{ 83constexpr uint8_t kFontData[{total_font_data_size}] = {{ 84// clang-format off 85{all_font_data} 86// clang-format on 87}}; 88}} // anonymous namespace 89 90const uint8_t *OverlayState::getFontData() const 91{{ 92 return kFontData; 93}} 94#else 95const uint8_t *OverlayState::getFontData() const 96{{ 97 return nullptr; 98}} 99#endif 100}} // namespace gl 101""" 102 103 104def main(): 105 if len(sys.argv) == 2 and sys.argv[1] == 'inputs': 106 # disabled because of issues on Windows. http://anglebug.com/3892 107 # print(font_file) 108 return 109 if len(sys.argv) == 2 and sys.argv[1] == 'outputs': 110 print(','.join([out_file_cpp, out_file_h])) 111 return 112 113 # Font sizes are chosen such that the sizes form a mip chain. 114 font_defs = [('large', 29), ('small', 14)] 115 chars = ' !"#$%&\'()*+,-./0123456789:;<=>?' + \ 116 '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' + \ 117 '`abcdefghijklmnopqrstuvwxyz{|}~' 118 char_count = len(chars) 119 120 font_glyph_widths = [] 121 font_glyph_heights = [] 122 font_data = "" 123 font_mips = [] 124 current_font_mip = 0 125 font_data_sizes = [] 126 font_data_offsets = [] 127 total_font_data_size = 0 128 129 # Load the font file. 130 face = Face(font_file) 131 assert (face.is_fixed_width) 132 133 for font_name, font_size in font_defs: 134 135 # Since the font is fixed width, we can retrieve its size right away. 136 face.set_char_size(font_size << 6) 137 glyph_width = face.size.max_advance >> 6 138 glyph_ascender = face.size.ascender >> 6 139 glyph_descender = face.size.descender >> 6 140 glyph_height = glyph_ascender - glyph_descender 141 font_glyph_widths.append(glyph_width) 142 font_glyph_heights.append(glyph_height) 143 144 # Make sure the fonts form a mipchain 145 if current_font_mip > 0: 146 assert (glyph_width == font_glyph_widths[current_font_mip - 1] // 2) 147 assert (glyph_height == font_glyph_heights[current_font_mip - 1] // 2) 148 149 font_tag = font_name.capitalize() 150 font_mip = str(current_font_mip) 151 font_mip_symbol = 'kFontMip' + font_tag 152 153 font_data += '// ' + font_tag + '\n' 154 155 # Font pixels are packed in 32-bit values. 156 font_data_size = char_count * glyph_width * glyph_height 157 font_data_sizes.append(font_data_size) 158 font_data_offsets.append(total_font_data_size) 159 total_font_data_size += font_data_size 160 161 for charIndex in range(char_count): 162 char = chars[charIndex] 163 font_data += "// '" + char + "'\n" 164 165 # Render the character. 166 face.load_char(char) 167 bitmap = face.glyph.bitmap 168 left = face.glyph.bitmap_left 169 top = face.glyph.bitmap_top 170 width = bitmap.width 171 rows = bitmap.rows 172 pitch = bitmap.pitch 173 174 offset_x = left 175 offset_y = glyph_height - (top - glyph_descender) 176 177 # Some glyphs like '#', '&' etc generate a larger glyph than the "fixed" font width. 178 if offset_x + width > glyph_width: 179 offset_x = glyph_width - width 180 if offset_x < 0: 181 width += offset_x 182 offset_x = 0 183 184 assert (offset_x + width <= glyph_width) 185 assert (offset_y + rows <= glyph_height) 186 187 # Write the character bitmap in the font image. 188 for y in range(glyph_height): 189 for x in range(glyph_width): 190 if y < offset_y or y >= offset_y + rows or x < offset_x or x >= offset_x + width: 191 font_data += ' 0,' 192 else: 193 pixel_value = bitmap.buffer[(y - offset_y) * pitch + (x - offset_x)] 194 if pixel_value == 0: 195 font_data += ' 0,' 196 else: 197 font_data += '0x{:02X},'.format(pixel_value) 198 font_data += '\n' 199 200 font_mips.append('constexpr uint32_t ' + font_mip_symbol + ' = ' + font_mip + ';') 201 current_font_mip += 1 202 203 with open(out_file_h, 'w') as outfile: 204 outfile.write( 205 template_out_file_h.format( 206 script_name=__file__, 207 font_file=font_file, 208 out_file_name=out_file_h, 209 font_count=len(font_defs), 210 char_count=char_count, 211 max_font_width=font_glyph_widths[0], 212 max_font_height=font_glyph_heights[0], 213 font_mip_data_sizes=','.join([str(s) for s in font_data_sizes]), 214 font_mip_data_offsets=','.join([str(s) for s in font_data_offsets]), 215 total_font_data_size=total_font_data_size, 216 font_mips='\n'.join(font_mips))) 217 outfile.close() 218 219 with open(out_file_cpp, 'w') as outfile: 220 outfile.write( 221 template_out_file_cpp.format( 222 script_name=__file__, 223 font_file=font_file, 224 out_file_name=out_file_cpp, 225 total_font_data_size=total_font_data_size, 226 all_font_data=font_data)) 227 outfile.close() 228 229 230if __name__ == '__main__': 231 sys.exit(main()) 232