xref: /aosp_15_r20/external/noto-fonts/scripts/subset_noto_sans_symbols.py (revision e5825d3be9fd13b272e7df556d285d1f07f3b027)
1*e5825d3bSAndroid Build Coastguard Worker#!/usr/bin/python
2*e5825d3bSAndroid Build Coastguard Worker# coding=UTF-8
3*e5825d3bSAndroid Build Coastguard Worker#
4*e5825d3bSAndroid Build Coastguard Worker# Copyright 2014 Google Inc. All rights reserved.
5*e5825d3bSAndroid Build Coastguard Worker#
6*e5825d3bSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
7*e5825d3bSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
8*e5825d3bSAndroid Build Coastguard Worker# You may obtain a copy of the License at
9*e5825d3bSAndroid Build Coastguard Worker#
10*e5825d3bSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
11*e5825d3bSAndroid Build Coastguard Worker#
12*e5825d3bSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
13*e5825d3bSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
14*e5825d3bSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*e5825d3bSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
16*e5825d3bSAndroid Build Coastguard Worker# limitations under the License.
17*e5825d3bSAndroid Build Coastguard Worker
18*e5825d3bSAndroid Build Coastguard Worker"""Create a curated subset of NotoSansSymbols for Android."""
19*e5825d3bSAndroid Build Coastguard Worker
20*e5825d3bSAndroid Build Coastguard Worker__author__ = '[email protected] (Roozbeh Pournader)'
21*e5825d3bSAndroid Build Coastguard Worker
22*e5825d3bSAndroid Build Coastguard Workerimport contextlib
23*e5825d3bSAndroid Build Coastguard Workerimport os
24*e5825d3bSAndroid Build Coastguard Workerimport sys
25*e5825d3bSAndroid Build Coastguard Workerimport tempfile
26*e5825d3bSAndroid Build Coastguard Worker
27*e5825d3bSAndroid Build Coastguard Workerfrom fontTools import ttLib
28*e5825d3bSAndroid Build Coastguard Workerfrom pathlib import PurePosixPath
29*e5825d3bSAndroid Build Coastguard Worker
30*e5825d3bSAndroid Build Coastguard Workerfrom nototools import subset
31*e5825d3bSAndroid Build Coastguard Workerfrom nototools import unicode_data
32*e5825d3bSAndroid Build Coastguard Worker
33*e5825d3bSAndroid Build Coastguard Worker# Unicode blocks that we want to include in the font
34*e5825d3bSAndroid Build Coastguard WorkerBLOCKS_TO_INCLUDE = """
35*e5825d3bSAndroid Build Coastguard Worker20D0..20FF; Combining Diacritical Marks for Symbols
36*e5825d3bSAndroid Build Coastguard Worker2100..214F; Letterlike Symbols
37*e5825d3bSAndroid Build Coastguard Worker2190..21FF; Arrows
38*e5825d3bSAndroid Build Coastguard Worker2200..22FF; Mathematical Operators
39*e5825d3bSAndroid Build Coastguard Worker2300..23FF; Miscellaneous Technical
40*e5825d3bSAndroid Build Coastguard Worker2400..243F; Control Pictures
41*e5825d3bSAndroid Build Coastguard Worker2440..245F; Optical Character Recognition
42*e5825d3bSAndroid Build Coastguard Worker2460..24FF; Enclosed Alphanumerics
43*e5825d3bSAndroid Build Coastguard Worker2500..257F; Box Drawing
44*e5825d3bSAndroid Build Coastguard Worker2580..259F; Block Elements
45*e5825d3bSAndroid Build Coastguard Worker25A0..25FF; Geometric Shapes
46*e5825d3bSAndroid Build Coastguard Worker2600..26FF; Miscellaneous Symbols
47*e5825d3bSAndroid Build Coastguard Worker2700..27BF; Dingbats
48*e5825d3bSAndroid Build Coastguard Worker27C0..27EF; Miscellaneous Mathematical Symbols-A
49*e5825d3bSAndroid Build Coastguard Worker27F0..27FF; Supplemental Arrows-A
50*e5825d3bSAndroid Build Coastguard Worker2800..28FF; Braille Patterns
51*e5825d3bSAndroid Build Coastguard Worker2900..297F; Supplemental Arrows-B
52*e5825d3bSAndroid Build Coastguard Worker2980..29FF; Miscellaneous Mathematical Symbols-B
53*e5825d3bSAndroid Build Coastguard Worker2A00..2AFF; Supplemental Mathematical Operators
54*e5825d3bSAndroid Build Coastguard Worker2B00..2BFF; Miscellaneous Symbols and Arrows
55*e5825d3bSAndroid Build Coastguard Worker4DC0..4DFF; Yijing Hexagram Symbols
56*e5825d3bSAndroid Build Coastguard Worker10140..1018F; Ancient Greek Numbers
57*e5825d3bSAndroid Build Coastguard Worker10190..101CF; Ancient Symbols
58*e5825d3bSAndroid Build Coastguard Worker101D0..101FF; Phaistos Disc
59*e5825d3bSAndroid Build Coastguard Worker1D000..1D0FF; Byzantine Musical Symbols
60*e5825d3bSAndroid Build Coastguard Worker1D100..1D1FF; Musical Symbols
61*e5825d3bSAndroid Build Coastguard Worker1D200..1D24F; Ancient Greek Musical Notation
62*e5825d3bSAndroid Build Coastguard Worker1D300..1D35F; Tai Xuan Jing Symbols
63*e5825d3bSAndroid Build Coastguard Worker1D360..1D37F; Counting Rod Numerals
64*e5825d3bSAndroid Build Coastguard Worker1D400..1D7FF; Mathematical Alphanumeric Symbols
65*e5825d3bSAndroid Build Coastguard Worker1F000..1F02F; Mahjong Tiles
66*e5825d3bSAndroid Build Coastguard Worker1F030..1F09F; Domino Tiles
67*e5825d3bSAndroid Build Coastguard Worker1F0A0..1F0FF; Playing Cards
68*e5825d3bSAndroid Build Coastguard Worker1F700..1F77F; Alchemical Symbols
69*e5825d3bSAndroid Build Coastguard Worker"""
70*e5825d3bSAndroid Build Coastguard Worker
71*e5825d3bSAndroid Build Coastguard Worker# One-off characters to be included. At the moment, this is the Bitcoin sign
72*e5825d3bSAndroid Build Coastguard Worker# (since it's not supported in Roboto yet, and the Japanese TV symbols of
73*e5825d3bSAndroid Build Coastguard Worker# Unicode 9.
74*e5825d3bSAndroid Build Coastguard WorkerONE_OFF_ADDITIONS = {
75*e5825d3bSAndroid Build Coastguard Worker    0x20BF, # ₿ BITCOIN SIGN
76*e5825d3bSAndroid Build Coastguard Worker    0x1F19B, # �� SQUARED THREE D
77*e5825d3bSAndroid Build Coastguard Worker    0x1F19C, # �� SQUARED SECOND SCREEN
78*e5825d3bSAndroid Build Coastguard Worker    0x1F19D, # �� SQUARED TWO K;So;0;L;;;;;N;;;;;
79*e5825d3bSAndroid Build Coastguard Worker    0x1F19E, # �� SQUARED FOUR K;So;0;L;;;;;N;;;;;
80*e5825d3bSAndroid Build Coastguard Worker    0x1F19F, # �� SQUARED EIGHT K;So;0;L;;;;;N;;;;;
81*e5825d3bSAndroid Build Coastguard Worker    0x1F1A0, # �� SQUARED FIVE POINT ONE;So;0;L;;;;;N;;;;;
82*e5825d3bSAndroid Build Coastguard Worker    0x1F1A1, # �� SQUARED SEVEN POINT ONE;So;0;L;;;;;N;;;;;
83*e5825d3bSAndroid Build Coastguard Worker    0x1F1A2, # �� SQUARED TWENTY-TWO POINT TWO;So;0;L;;;;;N;;;;;
84*e5825d3bSAndroid Build Coastguard Worker    0x1F1A3, # �� SQUARED SIXTY P;So;0;L;;;;;N;;;;;
85*e5825d3bSAndroid Build Coastguard Worker    0x1F1A4, # �� SQUARED ONE HUNDRED TWENTY P;So;0;L;;;;;N;;;;;
86*e5825d3bSAndroid Build Coastguard Worker    0x1F1A5, # �� SQUARED LATIN SMALL LETTER D;So;0;L;;;;;N;;;;;
87*e5825d3bSAndroid Build Coastguard Worker    0x1F1A6, # �� SQUARED HC;So;0;L;;;;;N;;;;;
88*e5825d3bSAndroid Build Coastguard Worker    0x1F1A7, # �� SQUARED HDR;So;0;L;;;;;N;;;;;
89*e5825d3bSAndroid Build Coastguard Worker    0x1F1A8, # �� SQUARED HI-RES;So;0;L;;;;;N;;;;;
90*e5825d3bSAndroid Build Coastguard Worker    0x1F1A9, # �� SQUARED LOSSLESS;So;0;L;;;;;N;;;;;
91*e5825d3bSAndroid Build Coastguard Worker    0x1F1AA, # �� SQUARED SHV;So;0;L;;;;;N;;;;;
92*e5825d3bSAndroid Build Coastguard Worker    0x1F1AB, # �� SQUARED UHD;So;0;L;;;;;N;;;;;
93*e5825d3bSAndroid Build Coastguard Worker    0x1F1AC, # �� SQUARED VOD;So;0;L;;;;;N;;;;;
94*e5825d3bSAndroid Build Coastguard Worker    0x1F23B, # �� SQUARED CJK UNIFIED IDEOGRAPH-914D
95*e5825d3bSAndroid Build Coastguard Worker}
96*e5825d3bSAndroid Build Coastguard Worker
97*e5825d3bSAndroid Build Coastguard Worker# letter-based characters, provided by Roboto
98*e5825d3bSAndroid Build Coastguard WorkerLETTERLIKE_CHARS_IN_ROBOTO = {
99*e5825d3bSAndroid Build Coastguard Worker    0x2100, # ℀ ACCOUNT OF
100*e5825d3bSAndroid Build Coastguard Worker    0x2101, # ℁ ADDRESSED TO THE SUBJECT
101*e5825d3bSAndroid Build Coastguard Worker    0x2103, # ℃ DEGREE CELSIUS
102*e5825d3bSAndroid Build Coastguard Worker    0x2105, # ℅ CARE OF
103*e5825d3bSAndroid Build Coastguard Worker    0x2106, # ℆ CADA UNA
104*e5825d3bSAndroid Build Coastguard Worker    0x2109, # ℉ DEGREE FAHRENHEIT
105*e5825d3bSAndroid Build Coastguard Worker    0x2113, # ℓ SCRIPT SMALL L
106*e5825d3bSAndroid Build Coastguard Worker    0x2116, # № NUMERO SIGN
107*e5825d3bSAndroid Build Coastguard Worker    0x2117, # ℗ SOUND RECORDING COPYRIGHT
108*e5825d3bSAndroid Build Coastguard Worker    0x211E, # ℞ PRESCRIPTION TAKE
109*e5825d3bSAndroid Build Coastguard Worker    0x211F, # ℟ RESPONSE
110*e5825d3bSAndroid Build Coastguard Worker    0x2120, # ℠ SERVICE MARK
111*e5825d3bSAndroid Build Coastguard Worker    0x2121, # ℡ TELEPHONE SIGN
112*e5825d3bSAndroid Build Coastguard Worker    0x2122, # ™ TRADE MARK SIGN
113*e5825d3bSAndroid Build Coastguard Worker    0x2123, # ℣ VERSICLE
114*e5825d3bSAndroid Build Coastguard Worker    0x2125, # ℥ OUNCE SIGN
115*e5825d3bSAndroid Build Coastguard Worker    0x2126, # Ω OHM SIGN
116*e5825d3bSAndroid Build Coastguard Worker    0x212A, # K KELVIN SIGN
117*e5825d3bSAndroid Build Coastguard Worker    0x212B, # Å ANGSTROM SIGN
118*e5825d3bSAndroid Build Coastguard Worker    0x212E, # ℮ ESTIMATED SYMBOL
119*e5825d3bSAndroid Build Coastguard Worker    0x2132, # Ⅎ TURNED CAPITAL F
120*e5825d3bSAndroid Build Coastguard Worker    0x213B, # ℻ FACSIMILE SIGN
121*e5825d3bSAndroid Build Coastguard Worker    0x214D, # ⅍ AKTIESELSKAB
122*e5825d3bSAndroid Build Coastguard Worker    0x214F, # ⅏ SYMBOL FOR SAMARITAN SOURCE
123*e5825d3bSAndroid Build Coastguard Worker}
124*e5825d3bSAndroid Build Coastguard Worker
125*e5825d3bSAndroid Build Coastguard WorkerDEFAULT_EMOJI = unicode_data.get_presentation_default_emoji()
126*e5825d3bSAndroid Build Coastguard Worker
127*e5825d3bSAndroid Build Coastguard WorkerEMOJI_ADDITIONS_FILE = os.path.join(
128*e5825d3bSAndroid Build Coastguard Worker    os.path.dirname(__file__), os.path.pardir, os.path.pardir,
129*e5825d3bSAndroid Build Coastguard Worker    'unicode', 'additions', 'emoji-data.txt')
130*e5825d3bSAndroid Build Coastguard Worker
131*e5825d3bSAndroid Build Coastguard Worker
132*e5825d3bSAndroid Build Coastguard Worker# Characters we have decided we are doing as emoji-style in Android,
133*e5825d3bSAndroid Build Coastguard Worker# despite UTR#51's recommendation
134*e5825d3bSAndroid Build Coastguard Workerdef get_android_emoji():
135*e5825d3bSAndroid Build Coastguard Worker    """Return additional Android default emojis."""
136*e5825d3bSAndroid Build Coastguard Worker    android_emoji = set()
137*e5825d3bSAndroid Build Coastguard Worker    with open(EMOJI_ADDITIONS_FILE) as emoji_additions:
138*e5825d3bSAndroid Build Coastguard Worker        data = unicode_data._parse_semicolon_separated_data(
139*e5825d3bSAndroid Build Coastguard Worker            emoji_additions.read())
140*e5825d3bSAndroid Build Coastguard Worker        for codepoint, prop in data:
141*e5825d3bSAndroid Build Coastguard Worker            if prop == 'Emoji_Presentation':
142*e5825d3bSAndroid Build Coastguard Worker                android_emoji.add(int(codepoint, 16))
143*e5825d3bSAndroid Build Coastguard Worker    return android_emoji
144*e5825d3bSAndroid Build Coastguard Worker
145*e5825d3bSAndroid Build Coastguard Workerdef rename_postscript_name(source_font, target_font, new_name):
146*e5825d3bSAndroid Build Coastguard Worker    """Rename the post script name to given one"""
147*e5825d3bSAndroid Build Coastguard Worker    with contextlib.closing(ttLib.TTFont(source_font)) as ttf:
148*e5825d3bSAndroid Build Coastguard Worker      nameTable = ttf['name']
149*e5825d3bSAndroid Build Coastguard Worker      for name in nameTable.names:
150*e5825d3bSAndroid Build Coastguard Worker        if (name.nameID == 6 and name.platformID == 3 and name.platEncID == 1
151*e5825d3bSAndroid Build Coastguard Worker            and name.langID == 0x0409):
152*e5825d3bSAndroid Build Coastguard Worker          name.string = new_name
153*e5825d3bSAndroid Build Coastguard Worker      ttf.save(target_font)
154*e5825d3bSAndroid Build Coastguard Worker
155*e5825d3bSAndroid Build Coastguard Workerdef main(argv):
156*e5825d3bSAndroid Build Coastguard Worker    """Subset the Noto Symbols font.
157*e5825d3bSAndroid Build Coastguard Worker
158*e5825d3bSAndroid Build Coastguard Worker    The first argument is the source file name, and the second argument is
159*e5825d3bSAndroid Build Coastguard Worker    the target file name.
160*e5825d3bSAndroid Build Coastguard Worker    """
161*e5825d3bSAndroid Build Coastguard Worker
162*e5825d3bSAndroid Build Coastguard Worker    target_coverage = set()
163*e5825d3bSAndroid Build Coastguard Worker    # Add all characters in BLOCKS_TO_INCLUDE
164*e5825d3bSAndroid Build Coastguard Worker    for first, last, _ in unicode_data._parse_code_ranges(BLOCKS_TO_INCLUDE):
165*e5825d3bSAndroid Build Coastguard Worker        target_coverage.update(range(first, last+1))
166*e5825d3bSAndroid Build Coastguard Worker
167*e5825d3bSAndroid Build Coastguard Worker    # Add one-off characters
168*e5825d3bSAndroid Build Coastguard Worker    target_coverage |= ONE_OFF_ADDITIONS
169*e5825d3bSAndroid Build Coastguard Worker    # Remove characters preferably coming from Roboto
170*e5825d3bSAndroid Build Coastguard Worker    target_coverage -= LETTERLIKE_CHARS_IN_ROBOTO
171*e5825d3bSAndroid Build Coastguard Worker    # Remove characters that are supposed to default to emoji
172*e5825d3bSAndroid Build Coastguard Worker    android_emoji = get_android_emoji()
173*e5825d3bSAndroid Build Coastguard Worker    target_coverage -= DEFAULT_EMOJI | android_emoji
174*e5825d3bSAndroid Build Coastguard Worker
175*e5825d3bSAndroid Build Coastguard Worker    # Remove dentistry symbols, as their main use appears to be for CJK:
176*e5825d3bSAndroid Build Coastguard Worker    # http://www.unicode.org/L2/L2000/00098-n2195.pdf
177*e5825d3bSAndroid Build Coastguard Worker    target_coverage -= set(range(0x23BE, 0x23CC+1))
178*e5825d3bSAndroid Build Coastguard Worker
179*e5825d3bSAndroid Build Coastguard Worker    # Remove COMBINING ENCLOSING KEYCAP. It's needed for Android's color emoji
180*e5825d3bSAndroid Build Coastguard Worker    # mechanism to work properly.
181*e5825d3bSAndroid Build Coastguard Worker    target_coverage.remove(0x20E3)
182*e5825d3bSAndroid Build Coastguard Worker
183*e5825d3bSAndroid Build Coastguard Worker    source_file_name = argv[1]
184*e5825d3bSAndroid Build Coastguard Worker    target_file_name = argv[2]
185*e5825d3bSAndroid Build Coastguard Worker
186*e5825d3bSAndroid Build Coastguard Worker    tmp = tempfile.NamedTemporaryFile()
187*e5825d3bSAndroid Build Coastguard Worker    subset.subset_font(
188*e5825d3bSAndroid Build Coastguard Worker        source_file_name,
189*e5825d3bSAndroid Build Coastguard Worker        tmp.name,
190*e5825d3bSAndroid Build Coastguard Worker        include=target_coverage)
191*e5825d3bSAndroid Build Coastguard Worker
192*e5825d3bSAndroid Build Coastguard Worker    # Use given file name as the PostScript name.
193*e5825d3bSAndroid Build Coastguard Worker    postScriptName = PurePosixPath(target_file_name).stem
194*e5825d3bSAndroid Build Coastguard Worker    rename_postscript_name(tmp.name, target_file_name, postScriptName)
195*e5825d3bSAndroid Build Coastguard Worker
196*e5825d3bSAndroid Build Coastguard Worker    second_subset_coverage = DEFAULT_EMOJI | android_emoji
197*e5825d3bSAndroid Build Coastguard Worker    second_subset_file_name = argv[3]
198*e5825d3bSAndroid Build Coastguard Worker    subset.subset_font(
199*e5825d3bSAndroid Build Coastguard Worker        source_file_name,
200*e5825d3bSAndroid Build Coastguard Worker        tmp.name,
201*e5825d3bSAndroid Build Coastguard Worker        include=second_subset_coverage)
202*e5825d3bSAndroid Build Coastguard Worker
203*e5825d3bSAndroid Build Coastguard Worker    # Use given file name as the PostScript name.
204*e5825d3bSAndroid Build Coastguard Worker    postScriptName = PurePosixPath(second_subset_file_name).stem
205*e5825d3bSAndroid Build Coastguard Worker    rename_postscript_name(tmp.name, second_subset_file_name, postScriptName)
206*e5825d3bSAndroid Build Coastguard Worker
207*e5825d3bSAndroid Build Coastguard Workerif __name__ == '__main__':
208*e5825d3bSAndroid Build Coastguard Worker    main(sys.argv)
209