From a2eafa8d4729e5950c5cf241293c0ddfddb183b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 9 Feb 2023 22:19:47 +0100 Subject: [PATCH] fonts: Convert simsun.ttc / msyh.ttf / malgun.ttf to TrueType. CW-Bug-Id: #21346 --- Makefile.in | 3 +- fonts/scripts/otf2ttf.LICENSE | 1640 +++++++++++++++++++++++++++++++++ fonts/scripts/otf2ttf.py | 174 ++++ 3 files changed, 1816 insertions(+), 1 deletion(-) create mode 100644 fonts/scripts/otf2ttf.LICENSE create mode 100644 fonts/scripts/otf2ttf.py diff --git a/Makefile.in b/Makefile.in index f984d93d..b6e4788f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1147,7 +1147,8 @@ $(FONTS_OBJ)/source-han/%.ttf: $$(%.ttf_CIDFONT) $$(%.ttf_FEATURES) $$(%.ttf_SEQ # to run it in a dedicated temporary directory to prevent concurrent instances # to step onto each other's feet (TEMP_DIR=`mktemp -d` && cd $$TEMP_DIR && afdko sfntedit -a CFF=$(abspath $($(notdir $@)).cff) $(abspath $@.tmp) && rm -fr $$TEMP_DIR) - mv $@.tmp $@ + python3 $(FONTS)/scripts/otf2ttf.py -o $@ $@.tmp + rm $@.tmp $(FONTS_OBJ)/ume-gothic/%.ttf: $$(%.ttf_FONT) $$(%.ttf_NAMETABLE_PATCH) mkdir -p $(FONTS_OBJ)/ume-gothic diff --git a/fonts/scripts/otf2ttf.LICENSE b/fonts/scripts/otf2ttf.LICENSE new file mode 100644 index 00000000..f4725487 --- /dev/null +++ b/fonts/scripts/otf2ttf.LICENSE @@ -0,0 +1,1640 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + afdko/LICENSE.md at develop · adobe-type-tools/afdko · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ Skip to content + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + + + + +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+ + + + + + + +Permalink + +
+ +
+
+ + + develop + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + +
+ +
+
+
+

Name already in use

+
+
+ +
+
+
+
+ +
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch? +
+ +
+
+ + +
+
+ + + + Go to file + +
+ + + + +
+
+
+ + + + + + + + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + + + + +
+ +
+ + +
+ + 46 lines (37 sloc) + + 2.25 KB +
+ +
+ + + + + +
+ +
+
+
+
+ +
+
+
+
+
+ + + Open in GitHub Desktop +
+
+
+
+
+ + + +
+
+ + + +
+
+ +
+ +
+
+ + +
+

Copyright 2014-2021 Adobe. All rights reserved.

+

Licensed under the Apache License, Version 2.0 (the "License"); +you may not use these files except in compliance with the License. +You may obtain a copy of the License at

+

http://www.apache.org/licenses/LICENSE-2.0

+

Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.

+
+

The file ExternalAntlr4Cpp.cmake is copied from the Antlr 4 project +(https://github.com/antlr/antlr4/tree/master/runtime/Cpp/cmake) under +the BSD 3-clause license:

+

[The "BSD 3-clause license"] +Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.

+

Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met:

+
    +
  1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission.
  6. +
+

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+
+
+ +
+ + + + +
+ + +
+ + +
+
+ + + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + diff --git a/fonts/scripts/otf2ttf.py b/fonts/scripts/otf2ttf.py new file mode 100644 index 00000000..9a195e48 --- /dev/null +++ b/fonts/scripts/otf2ttf.py @@ -0,0 +1,174 @@ +# Copied from https://github.com/adobe-type-tools/afdko/blob/develop/python/afdko/otf2ttf.py + +import argparse +import glob +import logging +import os +import sys +from functools import partial, singledispatch +from itertools import chain +from multiprocessing import Pool + +from fontTools import configLogger +from fontTools.misc.cliTools import makeOutputFileName +from fontTools.pens.cu2quPen import Cu2QuPen +from fontTools.pens.ttGlyphPen import TTGlyphPen +from fontTools.ttLib import TTCollection, TTFont, TTLibError, newTable + +log = logging.getLogger() +configLogger(logger=log) + +# default approximation error, measured in UPEM +MAX_ERR = 1.0 + +# default 'post' table format +POST_FORMAT = 2.0 + +# assuming the input contours' direction is correctly set (counter-clockwise), +# we just flip it to clockwise +REVERSE_DIRECTION = True + + +def glyphs_to_quadratic( + glyphs, max_err=MAX_ERR, reverse_direction=REVERSE_DIRECTION): + quadGlyphs = {} + for gname in glyphs.keys(): + glyph = glyphs[gname] + ttPen = TTGlyphPen(glyphs) + cu2quPen = Cu2QuPen(ttPen, max_err, + reverse_direction=reverse_direction) + glyph.draw(cu2quPen) + quadGlyphs[gname] = ttPen.glyph() + return quadGlyphs + + +def update_hmtx(ttFont, glyf): + hmtx = ttFont["hmtx"] + for glyphName, glyph in glyf.glyphs.items(): + if hasattr(glyph, 'xMin'): + hmtx[glyphName] = (hmtx[glyphName][0], glyph.xMin) + + +@singledispatch +def otf_to_ttf(ttFont, post_format=POST_FORMAT, **kwargs): + if ttFont.sfntVersion != "OTTO": + raise TTLibError("Not a OpenType font (bad sfntVersion)") + assert "CFF " in ttFont + + glyphOrder = ttFont.getGlyphOrder() + + ttFont["loca"] = newTable("loca") + ttFont["glyf"] = glyf = newTable("glyf") + glyf.glyphOrder = glyphOrder + glyf.glyphs = glyphs_to_quadratic(ttFont.getGlyphSet(), **kwargs) + del ttFont["CFF "] + if "VORG" in ttFont: + del ttFont["VORG"] + glyf.compile(ttFont) + update_hmtx(ttFont, glyf) + + ttFont["maxp"] = maxp = newTable("maxp") + maxp.tableVersion = 0x00010000 + maxp.maxZones = 1 + maxp.maxTwilightPoints = 0 + maxp.maxStorage = 0 + maxp.maxFunctionDefs = 0 + maxp.maxInstructionDefs = 0 + maxp.maxStackElements = 0 + maxp.maxSizeOfInstructions = 0 + maxp.maxComponentElements = max( + len(g.components if hasattr(g, 'components') else []) + for g in glyf.glyphs.values()) + maxp.compile(ttFont) + + post = ttFont["post"] + post.formatType = post_format + post.extraNames = [] + post.mapping = {} + post.glyphOrder = glyphOrder + try: + post.compile(ttFont) + except OverflowError: + post.formatType = 3 + log.warning("Dropping glyph names, they do not fit in 'post' table.") + + ttFont.sfntVersion = "\000\001\000\000" + + +@otf_to_ttf.register(TTCollection) +def _(fonts, **kwargs): + skip = 0 + for font in fonts: + try: + otf_to_ttf(font, **kwargs) + except TTLibError as warn: + skip += 1 + log.warning(warn) + + if skip == len(fonts): + raise TTLibError("a Font Collection that has Not a OpenType font") + + +def run(path, options): + try: + font = TTFont(path, fontNumber=options.face_index) + extension = '.ttf' + except TTLibError: + font = TTCollection(path) + extension = '.ttc' + + if options.output and not os.path.isdir(options.output): + output = options.output + else: + output = makeOutputFileName(path, outputDir=options.output, + extension=extension, + overWrite=options.overwrite) + + try: + otf_to_ttf(font, + post_format=options.post_format, + max_err=options.max_error, + reverse_direction=options.reverse_direction) + except TTLibError as warn: + log.warning(f'"{path}" cannot be converted since it is {warn}.') + else: + font.save(output) + + +def main(args=None): + parser = argparse.ArgumentParser() + parser.add_argument("input", nargs='+', metavar="INPUT") + parser.add_argument("-o", "--output") + parser.add_argument("-e", "--max-error", type=float, default=MAX_ERR) + parser.add_argument("--post-format", type=float, default=POST_FORMAT) + parser.add_argument( + "--keep-direction", dest='reverse_direction', action='store_false') + parser.add_argument("--face-index", type=int, default=-1) + parser.add_argument("--overwrite", action='store_true') + options = parser.parse_args(args) + + if options.output and len(options.input) > 1: + if not os.path.isdir(options.output): + parser.error("-o/--output option must be a directory when " + "processing multiple fonts") + + files = list(chain.from_iterable(map(glob.glob, options.input))) + + # Set the pool capacity to be the minimum of file quantity and CPU count, + # at least 1. + poolCapacity = max(min(os.cpu_count(), len(files)), 1) + # Limit parallel capacity to 60 on win32 to avoid WaitForMultipleObjects + # errors. See https://bugs.python.org/issue45077 + if poolCapacity > 60 and sys.platform == "win32": + poolCapacity = 60 + # Do not use "with" statement, or code coverage will malfunction. + pool = Pool(poolCapacity) + try: + pool.map(partial(run, options=options), files) + finally: + pool.close() + pool.join() + + +if __name__ == "__main__": + sys.exit(main())