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