diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2018-10-30 23:50:16 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2018-10-30 23:50:16 +0000 |
commit | 584d60df238070d9840cc864591a44fe93721ae5 (patch) | |
tree | 453d093cfcf48471e47a6daf3259dd8260fd60d7 /Build/source/libs/harfbuzz/harfbuzz-src/src | |
parent | 046ae60f6e5bda805763a12a2c95e3441e12e165 (diff) |
harfbuzz 2.1.0
git-svn-id: svn://tug.org/texlive/trunk@49031 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src')
112 files changed, 4707 insertions, 1761 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am index e0ea1c5de1f..fbd8f60237c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.am @@ -170,7 +170,6 @@ pkgconfig_DATA += harfbuzz-subset.pc EXTRA_DIST += harfbuzz-subset.pc.in FUZZING_CPPFLAGS = \ - -DHB_NDEBUG \ -DHB_MAX_NESTING_LEVEL=3 \ -DHB_SANITIZE_MAX_EDITS=3 \ -DHB_SANITIZE_MAX_OPS_FACTOR=3 \ @@ -269,7 +268,7 @@ EXTRA_DIST += \ CLEANFILES += $(pkgconfig_DATA) -DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated.def +DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated-symbols.txt if HAVE_GOBJECT DEF_FILES += harfbuzz-gobject.def endif @@ -283,8 +282,8 @@ harfbuzz-icu.def: $(HB_ICU_headers) $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^ harfbuzz-gobject.def: $(HB_GOBJECT_headers) $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^ -harfbuzz-deprecated.def: $(srcdir)/hb-deprecated.h - $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^ +harfbuzz-deprecated-symbols.txt: $(srcdir)/hb-deprecated.h + $(AM_V_GEN) PLAIN_LIST=1 $(srcdir)/gen-def.py "$@" $^ GENERATORS = \ @@ -295,6 +294,7 @@ GENERATORS = \ gen-os2-unicode-ranges.py \ gen-tag-table.py \ gen-use-table.py \ + gen-vowel-constraints.py \ $(NULL) EXTRA_DIST += $(GENERATORS) @@ -316,13 +316,17 @@ use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.tx $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \ || ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false) +vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt + $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \ + || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false) + emoji-table: gen-emoji-table.py emoji-data.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \ || ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false) built-sources: $(BUILT_SOURCES) -.PHONY: unicode-tables arabic-table indic-table tag-table use-table emoji-table built-sources +.PHONY: unicode-tables arabic-table indic-table tag-table use-table vowel-constraints emoji-table built-sources RAGEL_GENERATED = \ $(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \ @@ -343,6 +347,7 @@ noinst_PROGRAMS = \ main \ test \ test-buffer-serialize \ + test-name-table \ test-size-params \ test-would-substitute \ $(NULL) @@ -356,17 +361,30 @@ test_SOURCES = test.cc test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) -test_would_substitute_SOURCES = test-would-substitute.cc -test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) -test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) +test_buffer_serialize_SOURCES = test-buffer-serialize.cc +test_buffer_serialize_CPPFLAGS = $(HBCFLAGS) +test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS) + +test_name_table_SOURCES = test-name-table.cc +test_name_table_CPPFLAGS = $(HBCFLAGS) +test_name_table_LDADD = libharfbuzz.la $(HBLIBS) test_size_params_SOURCES = test-size-params.cc test_size_params_CPPFLAGS = $(HBCFLAGS) test_size_params_LDADD = libharfbuzz.la $(HBLIBS) -test_buffer_serialize_SOURCES = test-buffer-serialize.cc -test_buffer_serialize_CPPFLAGS = $(HBCFLAGS) -test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS) +test_would_substitute_SOURCES = test-would-substitute.cc +test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) +test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) + +if HAVE_FREETYPE +if HAVE_CAIRO_FT +noinst_PROGRAMS += test-ot-color +test_ot_color_SOURCES = test-ot-color.cc +test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS) +test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS) +endif # HAVE_CAIRO_FT +endif # HAVE_FREETYPE dist_check_SCRIPTS = \ check-c-linkage-decls.sh \ @@ -403,15 +421,6 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc dump_use_data_CPPFLAGS = $(HBCFLAGS) dump_use_data_LDADD = libharfbuzz.la $(HBLIBS) -if HAVE_FREETYPE -if HAVE_CAIRO_FT -check_PROGRAMS += dump-emoji -dump_emoji_SOURCES = dump-emoji.cc -dump_emoji_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS) -dump_emoji_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS) -endif # HAVE_CAIRO_FT -endif # HAVE_FREETYPE - check_PROGRAMS += test-ot-tag test-unicode-ranges TESTS += test-ot-tag test-unicode-ranges diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources index 59cde6bd1d5..561fbed6d36 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/Makefile.sources @@ -33,7 +33,10 @@ HB_BASE_sources = \ hb-ot-hmtx-table.hh \ hb-ot-kern-table.hh \ hb-ot-maxp-table.hh \ + hb-ot-name-language.cc \ + hb-ot-name-language.hh \ hb-ot-name-table.hh \ + hb-ot-name.cc \ hb-ot-os2-table.hh \ hb-ot-os2-unicode-ranges.hh \ hb-ot-post-macroman.hh \ @@ -101,6 +104,8 @@ HB_OT_sources = \ hb-aat-layout-trak-table.hh \ hb-aat-layout.hh \ hb-aat-ltag-table.hh \ + hb-aat-map.cc \ + hb-aat-map.hh \ hb-ot-face.hh \ hb-ot-face.cc \ hb-ot-font.cc \ @@ -142,6 +147,8 @@ HB_OT_sources = \ hb-ot-shape-complex-use.cc \ hb-ot-shape-complex-use.hh \ hb-ot-shape-complex-use-table.cc \ + hb-ot-shape-complex-vowel-constraints.cc \ + hb-ot-shape-complex-vowel-constraints.hh \ hb-ot-shape-complex.hh \ hb-ot-shape-normalize.hh \ hb-ot-shape-normalize.cc \ @@ -153,6 +160,7 @@ HB_OT_sources = \ hb-ot-var-fvar-table.hh \ hb-ot-var-hvar-table.hh \ hb-ot-var-mvar-table.hh \ + hb-ot-vorg-table.hh \ $(NULL) HB_OT_RAGEL_GENERATED_sources = \ @@ -170,12 +178,12 @@ HB_OT_RAGEL_sources = \ HB_OT_headers = \ hb-ot.h \ + hb-ot-color.h \ hb-ot-font.h \ hb-ot-layout.h \ hb-ot-math.h \ hb-ot-name.h \ hb-ot-shape.h \ - hb-ot-tag.h \ hb-ot-var.h \ $(NULL) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/dump-emoji.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/dump-emoji.cc deleted file mode 100644 index f45bc3106dd..00000000000 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/dump-emoji.cc +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright © 2018 Ebrahim Byagowi - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#include "hb-static.cc" -#include "hb-ot-color-cbdt-table.hh" -#include "hb-ot-color-colr-table.hh" -#include "hb-ot-color-cpal-table.hh" -#include "hb-ot-color-sbix-table.hh" -#include "hb-ot-color-svg-table.hh" - -#include "hb-ft.h" - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_GLYPH_H - -#include <cairo.h> -#include <cairo-ft.h> -#include <cairo-svg.h> - -#ifdef HAVE_GLIB -#include <glib.h> -#endif -#include <stdlib.h> -#include <stdio.h> - -static void cbdt_callback (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid) -{ - char output_path[255]; - sprintf (output_path, "out/cbdt-%d-%d.png", group, gid); - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); -} - -static void sbix_callback (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid) -{ - char output_path[255]; - sprintf (output_path, "out/sbix-%d-%d.png", group, gid); - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); -} - -static void svg_callback (const uint8_t* data, unsigned int length, - unsigned int start_glyph, unsigned int end_glyph) -{ - char output_path[255]; - if (start_glyph == end_glyph) - sprintf (output_path, "out/svg-%d.svg", start_glyph); - else - sprintf (output_path, "out/svg-%d-%d.svg", start_glyph, end_glyph); - - // append "z" if the content is gzipped - if ((data[0] == 0x1F) && (data[1] == 0x8B)) - strcat (output_path, "z"); - - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); -} - -static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upem, unsigned int num_glyphs, - const OT::COLR *colr, const OT::CPAL *cpal) -{ - for (unsigned int i = 0; i < num_glyphs; ++i) - { - unsigned int first_layer_index, num_layers; - if (colr->get_base_glyph_record (i, &first_layer_index, &num_layers)) - { - // Measure - cairo_text_extents_t extents; - { - cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); - cairo_t *cr = cairo_create (surface); - cairo_set_font_face (cr, cairo_face); - cairo_set_font_size (cr, upem); - - cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t)); - for (unsigned int j = 0; j < num_layers; ++j) - { - hb_codepoint_t glyph_id; - unsigned int color_index; - colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index); - glyphs[j].index = glyph_id; - } - cairo_glyph_extents (cr, glyphs, num_layers, &extents); - free (glyphs); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } - - // Add a slight margin - extents.width += extents.width / 10; - extents.height += extents.height / 10; - extents.x_bearing -= extents.width / 20; - extents.y_bearing -= extents.height / 20; - - // Render - unsigned int pallet_count = cpal->get_palette_count (); - for (unsigned int pallet = 0; pallet < pallet_count; ++pallet) { - char output_path[255]; - - // If we have more than one pallet, use a better namin - if (pallet_count == 1) - sprintf (output_path, "out/colr-%d.svg", i); - else - sprintf (output_path, "out/colr-%d-%d.svg", i, pallet); - - cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); - cairo_t *cr = cairo_create (surface); - cairo_set_font_face (cr, cairo_face); - cairo_set_font_size (cr, upem); - - for (unsigned int j = 0; j < num_layers; ++j) - { - hb_codepoint_t glyph_id; - unsigned int color_index; - colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index); - - uint32_t color = cpal->get_color_record_argb (color_index, pallet); - int alpha = color & 0xFF; - int r = (color >> 8) & 0xFF; - int g = (color >> 16) & 0xFF; - int b = (color >> 24) & 0xFF; - cairo_set_source_rgba (cr, r / 255., g / 255., b / 255., alpha); - - cairo_glyph_t glyph; - glyph.index = glyph_id; - glyph.x = -extents.x_bearing; - glyph.y = -extents.y_bearing; - cairo_show_glyphs (cr, &glyph, 1); - } - - cairo_surface_destroy (surface); - cairo_destroy (cr); - } - } - } -} - -static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, - unsigned int num_glyphs) -{ - // Dump every glyph available on the font - return; // disabled for now - for (unsigned int i = 0; i < num_glyphs; ++i) - { - cairo_text_extents_t extents; - cairo_glyph_t glyph = {0}; - glyph.index = i; - - // Measure - { - cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); - cairo_t *cr = cairo_create (surface); - cairo_set_font_face (cr, cairo_face); - cairo_set_font_size (cr, upem); - - cairo_glyph_extents (cr, &glyph, 1, &extents); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } - - // Add a slight margin - extents.width += extents.width / 10; - extents.height += extents.height / 10; - extents.x_bearing -= extents.width / 20; - extents.y_bearing -= extents.height / 20; - - // Render - { - char output_path[255]; - sprintf (output_path, "out/%d.svg", i); - cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); - cairo_t *cr = cairo_create (surface); - cairo_set_font_face (cr, cairo_face); - cairo_set_font_size (cr, upem); - glyph.x = -extents.x_bearing; - glyph.y = -extents.y_bearing; - cairo_show_glyphs (cr, &glyph, 1); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } - } -} - -int main (int argc, char **argv) -{ - if (argc != 2) { - fprintf (stderr, "usage: %s font-file.ttf\n" - "run it like `rm -rf out && mkdir out && %s font-file.ttf`\n", - argv[0], argv[0]); - exit (1); - } - - - FILE *font_name_file = fopen ("out/_font_name_file.txt", "r"); - if (font_name_file != nullptr) - { - fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n"); - exit (1); - } - - font_name_file = fopen ("out/_font_name_file.txt", "w"); - if (font_name_file == nullptr) - { - fprintf (stderr, "./out is not accessible, create it please\n"); - exit (1); - } - fwrite (argv[1], 1, strlen (argv[1]), font_name_file); - fclose (font_name_file); - - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); - hb_face_t *face = hb_face_create (blob, 0); - hb_font_t *font = hb_font_create (face); - - OT::CBDT::accelerator_t cbdt; - cbdt.init (face); - cbdt.dump (cbdt_callback); - cbdt.fini (); - - OT::sbix::accelerator_t sbix; - sbix.init (face); - sbix.dump (sbix_callback); - sbix.fini (); - - OT::SVG::accelerator_t svg; - svg.init (face); - svg.dump (svg_callback); - svg.fini (); - - hb_blob_t* colr_blob = hb_sanitize_context_t ().reference_table<OT::COLR> (face); - const OT::COLR *colr = colr_blob->as<OT::COLR> (); - - hb_blob_t* cpal_blob = hb_sanitize_context_t ().reference_table<OT::CPAL> (face); - const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> (); - - cairo_font_face_t *cairo_face; - { - FT_Library library; - FT_Init_FreeType (&library); - FT_Face ftface; - FT_New_Face (library, argv[1], 0, &ftface); - cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0); - } - unsigned int num_glyphs = hb_face_get_glyph_count (face); - unsigned int upem = hb_face_get_upem (face); - colr_cpal_rendering (cairo_face, upem, num_glyphs, colr, cpal); - dump_glyphs (cairo_face, upem, num_glyphs); - - - hb_font_destroy (font); - hb_face_destroy (face); - hb_blob_destroy (blob); - - return 0; -} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py index ba39eaae586..9111c698c36 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-def.py @@ -15,11 +15,10 @@ for h in header_paths: if h.endswith (".h"): with io.open (h, encoding='utf-8') as f: headers_content.append (f.read ()) -result = """EXPORTS +symbols = "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))) + +result = symbols if os.environ.get('PLAIN_LIST', '') else """EXPORTS %s -LIBRARY lib%s-0.dll""" % ( - "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))), - output_file.replace ('.def', '') -) +LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('.def', '')) with open (output_file, "w") as f: f.write (result) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py new file mode 100644 index 00000000000..c4e75aa96b3 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-vowel-constraints.py @@ -0,0 +1,221 @@ +#!/usr/bin/python + +"""Generator of the function to prohibit certain vowel sequences. + +It creates ``_hb_preprocess_text_vowel_constraints``, which inserts dotted +circles into sequences prohibited by the USE script development spec. +This function should be used as the ``preprocess_text`` of an +``hb_ot_complex_shaper_t``. +""" + +from __future__ import absolute_import, division, print_function, unicode_literals + +import collections +try: + from HTMLParser import HTMLParser + def write (s): + print (s.encode ('utf-8'), end='') +except ImportError: + from html.parser import HTMLParser + def write (s): + sys.stdout.flush () + sys.stdout.buffer.write (s.encode ('utf-8')) +import itertools +import io +import sys + +if len (sys.argv) != 3: + print ('usage: ./gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt', file=sys.stderr) + sys.exit (1) + +with io.open (sys.argv[2], encoding='utf-8') as f: + scripts_header = [f.readline () for i in range (2)] + scripts = {} + script_order = {} + for line in f: + j = line.find ('#') + if j >= 0: + line = line[:j] + fields = [x.strip () for x in line.split (';')] + if len (fields) == 1: + continue + uu = fields[0].split ('..') + start = int (uu[0], 16) + if len (uu) == 1: + end = start + else: + end = int (uu[1], 16) + script = fields[1] + for u in range (start, end + 1): + scripts[u] = script + if script not in script_order: + script_order[script] = start + +class ConstraintSet (object): + """A set of prohibited code point sequences. + + Args: + constraint (List[int]): A prohibited code point sequence. + + """ + def __init__ (self, constraint): + # Either a list or a dictionary. As a list of code points, it + # represents a prohibited code point sequence. As a dictionary, + # it represents a set of prohibited sequences, where each item + # represents the set of prohibited sequences starting with the + # key (a code point) concatenated with any of the values + # (ConstraintSets). + self._c = constraint + + def add (self, constraint): + """Add a constraint to this set.""" + if not constraint: + return + first = constraint[0] + rest = constraint[1:] + if isinstance (self._c, list): + if constraint == self._c[:len (constraint)]: + self._c = constraint + elif self._c != constraint[:len (self._c)]: + self._c = {self._c[0]: ConstraintSet (self._c[1:])} + if isinstance (self._c, dict): + if first in self._c: + self._c[first].add (rest) + else: + self._c[first] = ConstraintSet (rest) + + def _indent (self, depth): + return (' ' * depth).replace (' ', '\t') + + def __str__ (self, index=0, depth=4): + s = [] + indent = self._indent (depth) + if isinstance (self._c, list): + if len (self._c) == 0: + s.append ('{}matched = true;\n'.format (indent)) + elif len (self._c) == 1: + s.append ('{}matched = 0x{:04X}u == buffer->cur ({}).codepoint;\n'.format (indent, next (iter (self._c)), index or '')) + else: + s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index)) + s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), len (self._c))) + for i, cp in enumerate (self._c[1:], start=1): + s.append ('{}0x{:04X}u == buffer->cur ({}).codepoint{}\n'.format ( + self._indent (depth + 2), cp, index + i, ')' if i == len (self._c) - 1 else ' &&')) + s.append ('{}{{\n'.format (indent)) + for i in range (len (self._c)): + s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1))) + s.append ('{}_output_dotted_circle (buffer);\n'.format (self._indent (depth + 1))) + s.append ('{}}}\n'.format (indent)) + else: + s.append ('{}switch (buffer->cur ({}).codepoint)\n'.format(indent, index or '')) + s.append ('{}{{\n'.format (indent)) + cases = collections.defaultdict (set) + for first, rest in sorted (self._c.items ()): + cases[rest.__str__ (index + 1, depth + 2)].add (first) + for body, labels in sorted (cases.items (), key=lambda b_ls: sorted (b_ls[1])[0]): + for i, cp in enumerate (sorted (labels)): + if i % 4 == 0: + s.append (self._indent (depth + 1)) + else: + s.append (' ') + s.append ('case 0x{:04X}u:{}'.format (cp, '\n' if i % 4 == 3 else '')) + if len (labels) % 4 != 0: + s.append ('\n') + s.append (body) + s.append ('{}break;\n'.format (self._indent (depth + 2))) + s.append ('{}}}\n'.format (indent)) + return ''.join (s) + +constraints = {} +with io.open (sys.argv[1], encoding='utf-8') as f: + constraints_header = [f.readline ().strip () for i in range (2)] + for line in f: + j = line.find ('#') + if j >= 0: + line = line[:j] + constraint = [int (cp, 16) for cp in line.split (';')[0].split ()] + if not constraint: continue + assert 2 <= len (constraint), 'Prohibited sequence is too short: {}'.format (constraint) + script = scripts[constraint[0]] + if script in constraints: + constraints[script].add (constraint) + else: + constraints[script] = ConstraintSet (constraint) + assert constraints, 'No constraints found' + +print ('/* == Start of generated functions == */') +print ('/*') +print (' * The following functions are generated by running:') +print (' *') +print (' * %s use Scripts.txt' % sys.argv[0]) +print (' *') +print (' * on files with these headers:') +print (' *') +for line in constraints_header: + print (' * %s' % line.strip ()) +print (' *') +for line in scripts_header: + print (' * %s' % line.strip ()) +print (' */') +print () +print ('#include "hb-ot-shape-complex-vowel-constraints.hh"') +print () +print ('static void') +print ('_output_dotted_circle (hb_buffer_t *buffer)') +print ('{') +print (' hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);') +print (' _hb_glyph_info_reset_continuation (&dottedcircle);') +print ('}') +print () +print ('static void') +print ('_output_with_dotted_circle (hb_buffer_t *buffer)') +print ('{') +print (' _output_dotted_circle (buffer);') +print (' buffer->next_glyph ();') +print ('}') +print () + +print ('void') +print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,') +print ('\t\t\t\t hb_buffer_t *buffer,') +print ('\t\t\t\t hb_font_t *font HB_UNUSED)') +print ('{') +print (' /* UGLY UGLY UGLY business of adding dotted-circle in the middle of') +print (' * vowel-sequences that look like another vowel. Data for each script') +print (' * collected from the USE script development spec.') +print (' *') +print (' * https://github.com/harfbuzz/harfbuzz/issues/1019') +print (' */') +print (' bool processed = false;') +print (' buffer->clear_output ();') +print (' unsigned int count = buffer->len;') +print (' switch ((unsigned) buffer->props.script)') +print (' {') + +for script, constraints in sorted (constraints.items (), key=lambda s_c: script_order[s_c[0]]): + print (' case HB_SCRIPT_{}:'.format (script.upper ())) + print (' for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)') + print (' {') + print ('\tbool matched = false;') + write (str (constraints)) + print ('\tbuffer->next_glyph ();') + print ('\tif (matched) _output_with_dotted_circle (buffer);') + print (' }') + print (' processed = true;') + print (' break;') + print () + +print (' default:') +print (' break;') +print (' }') +print (' if (processed)') +print (' {') +print (' if (buffer->idx < count)') +print (' buffer->next_glyph ();') +print (' if (likely (buffer->successful))') +print (' buffer->swap_buffers ();') +print (' }') +print ('}') + +print () +print ('/* == End of generated functions == */') diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh index a99ccaf9f99..ce40abd5552 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh @@ -362,6 +362,7 @@ template <> } namespace AAT { +enum { DELETED_GLYPH = 0xFFFF }; /* * Extended State Table @@ -376,7 +377,10 @@ struct Entry /* Note, we don't recurse-sanitize data because we don't access it. * That said, in our DEFINE_SIZE_STATIC we access T::static_size, * which ensures that data has a simple sanitize(). To be determined - * if I need to remove that as well. */ + * if I need to remove that as well. + * + * XXX Because we are a template, our DEFINE_SIZE_STATIC assertion + * wouldn't be checked. */ return_trace (c->check_struct (this)); } @@ -393,7 +397,7 @@ struct Entry template <> struct Entry<void> { - inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); @@ -424,6 +428,7 @@ struct StateTable inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const { + if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH; const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs); return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS; } @@ -530,7 +535,7 @@ struct StateTableDriver unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT; bool last_was_dont_advance = false; - for (buffer->idx = 0;;) + for (buffer->idx = 0; buffer->successful;) { unsigned int klass = buffer->idx < buffer->len ? machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) : @@ -564,8 +569,6 @@ struct StateTableDriver if (unlikely (!c->transition (this, entry))) break; - if (unlikely (!buffer->successful)) return; - last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0; state = entry->newState; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh index e8eb43b8764..a88312501fb 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-kerx-table.hh @@ -78,12 +78,14 @@ struct KerxSubTableHeader struct KerxSubTableFormat0 { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, + hb_aat_apply_context_t *c) const { - if (header.tupleCount) return 0; /* TODO kerxTupleKern */ hb_glyph_pair_t pair = {left, right}; int i = pairs.bsearch (pair); - return i == -1 ? 0 : pairs[i].get_kerning (); + if (i == -1) return 0; + int v = pairs[i].get_kerning (); + return kerxTupleKern (v, header.tupleCount, this, c); } inline bool apply (hb_aat_apply_context_t *c) const @@ -93,13 +95,27 @@ struct KerxSubTableFormat0 if (!c->plan->requested_kerning) return false; - hb_kern_machine_t<KerxSubTableFormat0> machine (*this); - + accelerator_t accel (*this, c); + hb_kern_machine_t<accelerator_t> machine (accel); machine.kern (c->font, c->buffer, c->plan->kern_mask); return_trace (true); } + struct accelerator_t + { + const KerxSubTableFormat0 &table; + hb_aat_apply_context_t *c; + + inline accelerator_t (const KerxSubTableFormat0 &table_, + hb_aat_apply_context_t *c_) : + table (table_), c (c_) {} + + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return table.get_kerning (left, right, c); } + }; + + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -147,7 +163,7 @@ struct KerxSubTableFormat1 kernAction (&table->machine + table->kernAction), depth (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver, + inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->data.kernActionIndex != 0xFFFF; @@ -273,15 +289,6 @@ struct KerxSubTableFormat2 return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - leftClassTable.sanitize (c, this) && - rightClassTable.sanitize (c, this) && - c->check_range (this, array))); - } - struct accelerator_t { const KerxSubTableFormat2 &table; @@ -295,6 +302,15 @@ struct KerxSubTableFormat2 { return table.get_kerning (left, right, c); } }; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + leftClassTable.sanitize (c, this) && + rightClassTable.sanitize (c, this) && + c->check_range (this, array))); + } + protected: KerxSubTableHeader header; HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */ @@ -349,7 +365,7 @@ struct KerxSubTableFormat4 mark_set (false), mark (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver, + inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->data.ankrActionIndex != 0xFFFF; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh index 651af2188fd..a562091040c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-morx-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" #include "hb-ot-layout-common.hh" +#include "hb-aat-map.hh" /* * morx -- Extended Glyph Metamorphosis @@ -64,11 +65,11 @@ struct RearrangementSubtable Verb = 0x000F, /* The type of rearrangement specified. */ }; - inline driver_context_t (const RearrangementSubtable *table) : + inline driver_context_t (const RearrangementSubtable *table HB_UNUSED) : ret (false), start (0), end (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver, + inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return (entry->flags & Verb) && start < end; @@ -362,7 +363,7 @@ struct LigatureSubtable ligature (table+table->ligature), match_length (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver, + inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->flags & PerformAction; @@ -373,6 +374,7 @@ struct LigatureSubtable hb_buffer_t *buffer = driver->buffer; unsigned int flags = entry->flags; + DEBUG_MSG (APPLY, nullptr, "Ligature transition at %d", buffer->idx); if (flags & SetComponent) { if (unlikely (match_length >= ARRAY_LENGTH (match_positions))) @@ -383,10 +385,12 @@ struct LigatureSubtable match_length--; match_positions[match_length++] = buffer->out_len; + DEBUG_MSG (APPLY, nullptr, "Set component at %d", buffer->out_len); } if (flags & PerformAction) { + DEBUG_MSG (APPLY, nullptr, "Perform action with %d", match_length); unsigned int end = buffer->out_len; unsigned int action_idx = entry->data.ligActionIndex; unsigned int action; @@ -395,15 +399,21 @@ struct LigatureSubtable if (unlikely (!match_length)) return true; - /* TODO Only when ligation happens? */ - buffer->merge_out_clusters (match_positions[0], buffer->out_len); + if (buffer->idx >= buffer->len) + return false; // TODO Work on previous instead? unsigned int cursor = match_length; do { if (unlikely (!cursor)) + { + /* Stack underflow. Clear the stack. */ + DEBUG_MSG (APPLY, nullptr, "Stack underflow"); + match_length = 0; break; + } + DEBUG_MSG (APPLY, nullptr, "Moving to stack position %d", cursor - 1); buffer->move_to (match_positions[--cursor]); const HBUINT32 &actionData = ligAction[action_idx]; @@ -414,35 +424,41 @@ struct LigatureSubtable if (uoffset & 0x20000000) uoffset |= 0xC0000000; /* Sign-extend. */ int32_t offset = (int32_t) uoffset; - if (buffer->idx >= buffer->len) - return false; // TODO Work on previous instead? unsigned int component_idx = buffer->cur().codepoint + offset; const HBUINT16 &componentData = component[component_idx]; if (unlikely (!componentData.sanitize (&c->sanitizer))) return false; ligature_idx += componentData; + DEBUG_MSG (APPLY, nullptr, "Action store %d last %d", + bool (action & LigActionStore), + bool (action & LigActionLast)); if (action & (LigActionStore | LigActionLast)) { + const GlyphID &ligatureData = ligature[ligature_idx]; if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false; hb_codepoint_t lig = ligatureData; + DEBUG_MSG (APPLY, nullptr, "Produced ligature %d", lig); buffer->replace_glyph (lig); + unsigned int lig_end = match_positions[match_length - 1] + 1; /* Now go and delete all subsequent components. */ while (match_length - 1 > cursor) { + DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); buffer->move_to (match_positions[--match_length]); - buffer->skip_glyph (); - end--; + buffer->replace_glyph (DELETED_GLYPH); } + + buffer->move_to (lig_end); + buffer->merge_out_clusters (match_positions[cursor], buffer->out_len); } action_idx++; } while (!(action & LigActionLast)); - match_length = 0; buffer->move_to (end); } @@ -606,7 +622,7 @@ struct InsertionSubtable mark (0), insertionAction (table+table->insertionAction) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver, + inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) && @@ -826,9 +842,9 @@ struct ChainSubtable struct Chain { - inline void apply (hb_aat_apply_context_t *c) const + inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const { - uint32_t flags = defaultFlags; + hb_mask_t flags = defaultFlags; { /* Compute applicable flags. TODO Should move this to planning * stage and take user-requested features into account. */ @@ -836,14 +852,22 @@ struct Chain for (unsigned i = 0; i < count; i++) { const Feature &feature = featureZ[i]; - if (false) /* XXX Check if feature enabled... */ + uint16_t type = feature.featureType; + uint16_t setting = feature.featureSetting; + const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type); + if (info && info->setting == setting) { flags &= feature.disableFlags; flags |= feature.enableFlags; } } } + return flags; + } + inline void apply (hb_aat_apply_context_t *c, + hb_mask_t flags) const + { const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) @@ -915,7 +939,7 @@ struct Chain inline unsigned int get_size (void) const { return length; } - inline bool sanitize (hb_sanitize_context_t *c, unsigned int version) const + inline bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const { TRACE_SANITIZE (this); if (!length.sanitize (c) || @@ -963,6 +987,34 @@ struct morx inline bool has_data (void) const { return version != 0; } + inline void compile_flags (const hb_aat_map_builder_t *mapper, + hb_aat_map_t *map) const + { + const Chain *chain = &firstChain; + unsigned int count = chainCount; + for (unsigned int i = 0; i < count; i++) + { + map->chain_flags.push (chain->compile_flags (mapper)); + chain = &StructAfter<Chain> (*chain); + } + } + + inline static void remove_deleted_glyphs (hb_buffer_t *buffer) + { + if (unlikely (!buffer->successful)) return; + + buffer->clear_output (); + for (buffer->idx = 0; buffer->idx < buffer->len && buffer->successful;) + { + if (unlikely (buffer->cur().codepoint == DELETED_GLYPH)) + buffer->skip_glyph (); + else + buffer->next_glyph (); + } + if (likely (buffer->successful)) + buffer->swap_buffers (); + } + inline void apply (hb_aat_apply_context_t *c) const { if (unlikely (!c->buffer->successful)) return; @@ -971,10 +1023,11 @@ struct morx unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) { - chain->apply (c); + chain->apply (c, c->plan->aat_map.chain_flags[i]); if (unlikely (!c->buffer->successful)) return; chain = &StructAfter<Chain> (*chain); } + remove_deleted_glyphs (c->buffer); } inline bool sanitize (hb_sanitize_context_t *c) const diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh index 16729d16f5c..de2071ad6aa 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-trak-table.hh @@ -55,7 +55,7 @@ struct TrackTableEntry unsigned int index, unsigned int nSizes) const { - return hb_array_t<FWORD> ((base+valuesZ).arrayZ, nSizes)[index]; + return hb_array (base+valuesZ, nSizes)[index]; } public: @@ -88,7 +88,7 @@ struct TrackData const void *base) const { unsigned int sizes = nSizes; - hb_array_t<Fixed> size_table ((base+sizeTable).arrayZ, sizes); + hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes); float s0 = size_table[idx].to_float (); float s1 = size_table[idx + 1].to_float (); @@ -134,7 +134,7 @@ struct TrackData if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); /* TODO bfind() */ - hb_array_t<Fixed> size_table ((base+sizeTable).arrayZ, sizes); + hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes); unsigned int size_index; for (size_index = 0; size_index < sizes - 1; size_index++) if (size_table[size_index].to_float () >= csspx) @@ -184,6 +184,8 @@ struct trak { TRACE_APPLY (this); + hb_mask_t trak_mask = c->plan->trak_mask; + const float ptem = c->font->ptem; if (unlikely (ptem <= 0.f)) return_trace (false); @@ -197,6 +199,7 @@ struct trak hb_position_t advance_to_add = c->font->em_scalef_x (tracking); foreach_grapheme (buffer, start, end) { + if (!(buffer->info[start].mask & trak_mask)) continue; buffer->pos[start].x_advance += advance_to_add; buffer->pos[start].x_offset += offset_to_add; } @@ -209,6 +212,7 @@ struct trak hb_position_t advance_to_add = c->font->em_scalef_y (tracking); foreach_grapheme (buffer, start, end) { + if (!(buffer->info[start].mask & trak_mask)) continue; buffer->pos[start].y_advance += advance_to_add; buffer->pos[start].y_offset += offset_to_add; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc index e9da850b390..ec053938fdc 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.cc @@ -34,7 +34,7 @@ #include "hb-aat-layout-kerx-table.hh" #include "hb-aat-layout-morx-table.hh" #include "hb-aat-layout-trak-table.hh" -#include "hb-aat-ltag-table.hh" // Just so we compile it; unused otherwise. +#include "hb-aat-ltag-table.hh" /* Table data courtesy of Apple. Converted from mnemonics to integers @@ -181,6 +181,20 @@ _get_trak (hb_face_t *face) if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::trak); return *(hb_ot_face_data (face)->trak.get ()); } +static inline const AAT::ltag& +_get_ltag (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::ltag); + return *(hb_ot_face_data (face)->ltag.get ()); +} + + +void +hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, + hb_aat_map_t *map) +{ + _get_morx (mapper->face).compile_flags (mapper, map); +} hb_bool_t @@ -240,3 +254,10 @@ hb_aat_layout_track (hb_ot_shape_plan_t *plan, AAT::hb_aat_apply_context_t c (plan, font, buffer); trak.apply (&c); } + +hb_language_t +_hb_aat_language_get (hb_face_t *face, + unsigned int i) +{ + return _get_ltag (face).get_language (i); +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh index d0eb0190db6..8a558e6aa73 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout.hh @@ -52,6 +52,9 @@ struct hb_aat_feature_mapping_t HB_INTERNAL const hb_aat_feature_mapping_t * hb_aat_layout_find_feature_mapping (hb_tag_t tag); +HB_INTERNAL void +hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, + hb_aat_map_t *map); HB_INTERNAL hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face); @@ -77,4 +80,9 @@ hb_aat_layout_track (hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +HB_INTERNAL hb_language_t +_hb_aat_language_get (hb_face_t *face, + unsigned int i); + + #endif /* HB_AAT_LAYOUT_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh index 08a1b51a9e8..8a42b3510bf 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-ltag-table.hh @@ -25,7 +25,7 @@ #ifndef HB_AAT_LTAG_TABLE_HH #define HB_AAT_LTAG_TABLE_HH -#include "hb-aat-layout-common.hh" +#include "hb-open-type.hh" /* * ltag -- Language Tag @@ -36,9 +36,13 @@ namespace AAT { +using namespace OT; + struct FTStringRange { + friend struct ltag; + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -58,10 +62,19 @@ struct ltag { static const hb_tag_t tableTag = HB_AAT_TAG_ltag; + inline hb_language_t get_language (unsigned int i) const + { + const FTStringRange &range = tagRanges[i]; + return hb_language_from_string ((const char *) (this+range.tag).arrayZ, + range.length); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && tagRanges.sanitize (c, this))); + return_trace (likely (c->check_struct (this) && + version >= 1 && + tagRanges.sanitize (c, this))); } protected: diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc new file mode 100644 index 00000000000..f2736bfd119 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.cc @@ -0,0 +1,62 @@ +/* + * Copyright © 2009,2010 Red Hat, Inc. + * Copyright © 2010,2011,2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-aat-map.hh" + +#include "hb-aat-layout.hh" + + +void hb_aat_map_builder_t::add_feature (hb_tag_t tag, + unsigned int value) +{ + const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag); + if (!mapping) return; + + feature_info_t *info = features.push(); + info->type = mapping->aatFeatureType; + info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable; +} + +void +hb_aat_map_builder_t::compile (hb_aat_map_t &m, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) +{ + /* Sort features and merge duplicates */ + if (features.len) + { + features.qsort (); + unsigned int j = 0; + for (unsigned int i = 1; i < features.len; i++) + if (features[i].type != features[j].type) + features[++j] = features[i]; + features.shrink (j + 1); + } + + hb_aat_layout_compile_map (this, &m); +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh new file mode 100644 index 00000000000..846cdc1a920 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-map.hh @@ -0,0 +1,106 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_AAT_MAP_HH +#define HB_AAT_MAP_HH + +#include "hb.hh" + + +struct hb_ot_shape_plan_t; + +struct hb_aat_map_t +{ + friend struct hb_aat_map_builder_t; + + public: + + inline void init (void) + { + memset (this, 0, sizeof (*this)); + chain_flags.init (); + } + inline void fini (void) + { + chain_flags.fini (); + } + + public: + hb_vector_t<hb_mask_t, 1> chain_flags; +}; + +struct hb_aat_map_builder_t +{ + public: + + HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_, + const hb_segment_properties_t *props_ HB_UNUSED) : + face (face_) + { + features.init (); + } + + ~hb_aat_map_builder_t (void) + { + features.fini (); + } + + HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1); + + HB_INTERNAL void compile (hb_aat_map_t &m, + const int *coords, + unsigned int num_coords); + + public: + struct feature_info_t + { + uint16_t type; + uint16_t setting; + unsigned seq; /* For stable sorting only. */ + + static int cmp (const void *pa, const void *pb) + { + const feature_info_t *a = (const feature_info_t *) pa; + const feature_info_t *b = (const feature_info_t *) pb; + return (a->type != b->type) ? (a->type < b->type ? -1 : 1) : + (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); + } + + int cmp (const short unsigned int *ty) const + { + return (type != *ty) ? (type < *ty ? -1 : 1) : 0; + } + }; + + public: + hb_face_t *face; + + public: + hb_vector_t<feature_info_t, 32> features; +}; + + +#endif /* HB_AAT_MAP_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh index 5cb7ca5d53d..697de19c55d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-atomic.hh @@ -278,14 +278,11 @@ struct hb_atomic_int_t }; -template <typename T> struct hb_remove_ptr_t { typedef T value; }; -template <typename T> struct hb_remove_ptr_t<T *> { typedef T value; }; - #define HB_ATOMIC_PTR_INIT(V) {V} template <typename P> struct hb_atomic_ptr_t { - typedef typename hb_remove_ptr_t<P>::value T; + typedef typename hb_remove_pointer<P>::value T; inline void init (T* v_ = nullptr) { set_relaxed (v_); } inline void set_relaxed (T* v_) const { hb_atomic_ptr_impl_set_relaxed (&v, v_); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc index 368491c057d..51f22ce4dae 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.cc @@ -40,6 +40,19 @@ #include <stdlib.h> +/** + * SECTION: hb-blob + * @title: hb-blob + * @short_description: Binary data containers + * @include: hb.h + * + * Blobs wrap a chunk of binary data to handle lifecycle management of data + * while it is passed between client and HarfBuzz. Blobs are primarily used + * to create font faces, but also to access font face tables, as well as + * pass around other binary data. + **/ + + DEFINE_NULL_INSTANCE (hb_blob_t) = { HB_OBJECT_HEADER_STATIC, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.hh index bee8c9794ad..26e2dd70a0a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-blob.hh @@ -69,7 +69,6 @@ struct hb_blob_t public: hb_object_header_t header; - ASSERT_POD (); bool immutable; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc index c1d82ab8dfe..1bd603d4474 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer-serialize.cc @@ -58,7 +58,7 @@ hb_buffer_serialize_list_formats (void) * @str is a valid buffer serialization format, use * hb_buffer_serialize_list_formats() to get the list of supported formats. * - * Return value: + * Return value: * The parsed #hb_buffer_serialize_format_t. * * Since: 0.9.7 @@ -319,7 +319,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, * ## json * TODO. * - * Return value: + * Return value: * The number of serialized items. * * Since: 0.9.7 @@ -425,14 +425,14 @@ parse_int (const char *pp, const char *end, int32_t *pv) * hb_buffer_deserialize_glyphs: * @buffer: an #hb_buffer_t buffer. * @buf: (array length=buf_len): - * @buf_len: + * @buf_len: * @end_ptr: (out): - * @font: - * @format: + * @font: + * @format: * - * * - * Return value: + * + * Return value: * * Since: 0.9.7 **/ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc index ce9b0530ce9..5a8152ed4d2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.cc @@ -33,14 +33,15 @@ /** * SECTION: hb-buffer - * @title: Buffers + * @title: hb-buffer * @short_description: Input and output buffers * @include: hb.h * * Buffers serve dual role in HarfBuzz; they hold the input characters that are - * passed hb_shape(), and after shaping they hold the output glyphs. + * passed to hb_shape(), and after shaping they hold the output glyphs. **/ + /** * hb_segment_properties_equal: * @a: first #hb_segment_properties_t to compare. @@ -1665,7 +1666,7 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer, unsigned int item_offset, int item_length) { - hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf<hb_utf32_t> (buffer, text, text_length, item_offset, item_length); } /** @@ -1726,7 +1727,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, unsigned int item_offset, int item_length) { - hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf<hb_utf32_novalidate_t> (buffer, text, text_length, item_offset, item_length); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h index d0aed02d534..99e01716fb2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.h @@ -89,11 +89,12 @@ typedef struct hb_glyph_info_t * of each line after line-breaking, or limiting * the reshaping to a small piece around the * breaking point only. + * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. */ typedef enum { /*< flags >*/ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, - HB_GLYPH_FLAG_DEFINED = 0x00000001 /*< skip >*/ /* OR of all defined flags */ + HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ } hb_glyph_flags_t; HB_EXTERN hb_glyph_flags_t diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh index 0d888e1e052..37adeb083bf 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-buffer.hh @@ -86,7 +86,6 @@ HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); struct hb_buffer_t { hb_object_header_t header; - ASSERT_POD (); /* Information about how the text in the buffer should be treated */ hb_unicode_funcs_t *unicode; /* Unicode functions */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc index ba48dd56106..d7c1921f3ae 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.cc @@ -36,6 +36,16 @@ #endif +/** + * SECTION:hb-common + * @title: hb-common + * @short_description: Common data types + * @include: hb.h + * + * Common data types used across HarfBuzz are defined here. + **/ + + /* hb_options_t */ hb_atomic_int_t _hb_options; @@ -615,6 +625,19 @@ hb_user_data_array_t::get (hb_user_data_key_t *key) /* hb_version */ + +/** + * SECTION:hb-version + * @title: hb-version + * @short_description: Information about the version of HarfBuzz in use + * @include: hb.h + * + * These functions and macros allow accessing version of the HarfBuzz + * library used at compile- as well as run-time, and to direct code + * conditionally based on those versions, again, at compile- or run-time. + **/ + + /** * hb_version: * @major: (out): Library major version component. @@ -761,7 +784,7 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv) static void free_static_C_locale (void); #endif -static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_ptr_t<HB_LOCALE_T>::value, +static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>::value, hb_C_locale_lazy_loader_t> { static inline HB_LOCALE_T create (void) @@ -911,7 +934,7 @@ parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) has_start = parse_uint (pp, end, &feature->start); - if (parse_char (pp, end, ':')) { + if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) { parse_uint (pp, end, &feature->end); } else { if (has_start) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h index 2f09f431801..ae23698a576 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-common.h @@ -33,6 +33,10 @@ #ifndef HB_COMMON_H #define HB_COMMON_H +#ifndef HB_EXTERN +#define HB_EXTERN extern +#endif + #ifndef HB_BEGIN_DECLS # ifdef __cplusplus # define HB_BEGIN_DECLS extern "C" { @@ -444,6 +448,50 @@ HB_EXTERN void hb_variation_to_string (hb_variation_t *variation, char *buf, unsigned int size); +/** + * hb_color_t: + * + * Data type for holding color values. + * + * Since: 2.1.0 + */ +typedef uint32_t hb_color_t; + +#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a))) + +/** + * hb_color_get_alpha: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_alpha(color) ((color) & 0xFF) +/** + * hb_color_get_red: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_red(color) (((color) >> 8) & 0xFF) +/** + * hb_color_get_green: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_green(color) (((color) >> 16) & 0xFF) +/** + * hb_color_get_blue: + * + * + * + * Since: 2.1.0 + */ +#define hb_color_get_blue(color) (((color) >> 24) & 0xFF) + HB_END_DECLS diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc index 9f7745dbf88..184db4944a9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc @@ -35,6 +35,16 @@ #include "hb-aat-layout.hh" #include <math.h> + +/** + * SECTION:hb-coretext + * @title: hb-coretext + * @short_description: CoreText integration + * @include: hb-coretext.h + * + * Functions for using HarfBuzz with the CoreText fonts. + **/ + /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f @@ -464,8 +474,8 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, buffer->merge_clusters (i - 1, i + 1); } - hb_auto_t<hb_vector_t<feature_record_t> > feature_records; - hb_auto_t<hb_vector_t<range_record_t> > range_records; + hb_vector_t<feature_record_t> feature_records; + hb_vector_t<range_record_t> range_records; /* * Set up features. @@ -474,7 +484,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, if (num_features) { /* Sort features by start/end events. */ - hb_auto_t<hb_vector_t<feature_event_t> > feature_events; + hb_vector_t<feature_event_t> feature_events; for (unsigned int i = 0; i < num_features; i++) { const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag); @@ -513,7 +523,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } /* Scan events and save features for each range. */ - hb_auto_t<hb_vector_t<active_feature_t> > active_features; + hb_vector_t<active_feature_t> active_features; unsigned int last_index = 0; for (unsigned int i = 0; i < feature_events.len; i++) { @@ -586,7 +596,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } else { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ()); + active_features.remove (feature - active_features); } } } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh index 58c190d275d..d218e432810 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-debug.hh @@ -173,7 +173,7 @@ _hb_debug_msg_va (const char *what, fprintf (stderr, "\n"); } -template <> inline void +template <> inline void HB_PRINTF_FUNC(7, 0) _hb_debug_msg_va<0> (const char *what HB_UNUSED, const void *obj HB_UNUSED, const char *func HB_UNUSED, @@ -192,7 +192,7 @@ _hb_debug_msg (const char *what, int level_dir, const char *message, ...) HB_PRINTF_FUNC(7, 8); -template <int max_level> static inline void +template <int max_level> static inline void HB_PRINTF_FUNC(7, 8) _hb_debug_msg (const char *what, const void *obj, const char *func, @@ -216,7 +216,7 @@ _hb_debug_msg<0> (const char *what HB_UNUSED, int level_dir HB_UNUSED, const char *message HB_UNUSED, ...) HB_PRINTF_FUNC(7, 8); -template <> inline void +template <> inline void HB_PRINTF_FUNC(7, 8) _hb_debug_msg<0> (const char *what HB_UNUSED, const void *obj HB_UNUSED, const char *func HB_UNUSED, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h index 5af9bdbd85d..e39b79f74e5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-deprecated.h @@ -36,6 +36,18 @@ #include "hb-font.h" #include "hb-set.h" + +/** + * SECTION:hb-deprecated + * @title: hb-deprecated + * @short_description: Deprecated API + * @include: hb.h + * + * These API have been deprecated in favor of newer API, or because they + * were deemed unnecessary. + **/ + + HB_BEGIN_DECLS #ifndef HB_DISABLE_DEPRECATED @@ -146,12 +158,6 @@ hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, hb_unicode_decompose_compatibility_func_t func, void *user_data, hb_destroy_func_t destroy); -/** - * hb_unicode_decompose_compatibility: - * - * - * Deprecated: 2.0.0 - **/ HB_EXTERN HB_DEPRECATED unsigned int hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t u, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-dsalgs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-dsalgs.hh index eb15c089eb6..e8bd95c276c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-dsalgs.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-dsalgs.hh @@ -313,6 +313,27 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) */ static inline void * +hb_bsearch (const void *key, const void *base, + size_t nmemb, size_t size, + int (*compar)(const void *_key, const void *_item)) +{ + int min = 0, max = (int) nmemb - 1; + while (min <= max) + { + int mid = (min + max) / 2; + const void *p = (const void *) (((const char *) base) + (mid * size)); + int c = compar (key, p); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + return (void *) p; + } + return nullptr; +} + +static inline void * hb_bsearch_r (const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *_key, const void *_item, void *_arg), @@ -321,7 +342,7 @@ hb_bsearch_r (const void *key, const void *base, int min = 0, max = (int) nmemb - 1; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; const void *p = (const void *) (((const char *) base) + (mid * size)); int c = compar (key, p, arg); if (c < 0) @@ -490,43 +511,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } -template <typename Type> -struct hb_auto_t : Type -{ - hb_auto_t (void) { Type::init (); } - /* Explicitly allow the following only for pointer and references, - * to avoid any accidental copies. - * - * Apparently if we template for all types, then gcc seems to - * capture a reference argument in the type, but clang doesn't, - * causing unwanted copies and bugs that come with it. Ideally - * we should use C++11-style rvalue reference &&t1. */ - template <typename T1> explicit hb_auto_t (T1 *t1) { Type::init (t1); } - template <typename T1> explicit hb_auto_t (T1 &t1) { Type::init (t1); } - ~hb_auto_t (void) { Type::fini (); } - private: /* Hide */ - void init (void) {} - void fini (void) {} -}; - -template <typename T> -struct hb_array_t -{ - inline hb_array_t (void) : arrayZ (nullptr), len (0) {} - inline hb_array_t (const T *array_, unsigned int len_) : arrayZ (array_), len (len_) {} - - inline const T& operator [] (unsigned int i) const - { - if (unlikely (i >= len)) return Null(T); - return arrayZ[i]; - } - - inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } - - const T *arrayZ; - unsigned int len; -}; - struct hb_bytes_t { inline hb_bytes_t (void) : arrayZ (nullptr), len (0) {} @@ -555,6 +539,42 @@ struct hb_bytes_t unsigned int len; }; +template <typename T> +struct hb_array_t +{ + inline hb_array_t (void) : arrayZ (nullptr), len (0) {} + inline hb_array_t (T *array_, unsigned int len_) : arrayZ (array_), len (len_) {} + + inline T& operator [] (unsigned int i) const + { + if (unlikely (i >= len)) return Null(T); + return arrayZ[i]; + } + + inline hb_array_t<T> sub_array (unsigned int start_offset, unsigned int seg_count) const + { + unsigned int count = len; + if (unlikely (start_offset > count)) + count = 0; + else + count -= start_offset; + count = MIN (count, seg_count); + return hb_array_t<T> (arrayZ + start_offset, count); + } + + inline hb_bytes_t as_bytes (void) const + { + return hb_bytes_t (arrayZ, len * sizeof (T)); + } + + inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } + + T *arrayZ; + unsigned int len; +}; +template <typename T> static inline +hb_array_t<T> hb_array (T *array, unsigned int len) { return hb_array_t<T> (array, len); } + struct HbOpOr { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc index bba1ee3fa0c..7ca4b1ba25e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.cc @@ -36,6 +36,19 @@ /** + * SECTION:hb-face + * @title: hb-face + * @short_description: Font face objects + * @include: hb.h + * + * Font face is objects represent a single face in a font family. + * More exactly, a font face represents a single face in a binary font file. + * Font faces are typically built from a binary blob and a face index. + * Font faces are used to create fonts. + **/ + + +/** * hb_face_count: * @blob: a blob. * @@ -666,7 +679,7 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) } static hb_blob_t * -_hb_face_builder_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data) +_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) { hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh index f90453dbd1f..89673ff8424 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-face.hh @@ -42,7 +42,6 @@ struct hb_face_t { hb_object_header_t header; - ASSERT_POD (); hb_bool_t immutable; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc index b6b668dd8bc..135d310ca97 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc @@ -34,6 +34,19 @@ #include "hb-ot.h" +/** + * SECTION:hb-font + * @title: hb-font + * @short_description: Font objects + * @include: hb.h + * + * Font objects represent a font face at a certain size and other + * parameters (pixels per EM, points per EM, variation settings.) + * Fonts are created from font faces, and are used as input to + * hb_shape() among other things. + **/ + + /* * hb_font_funcs_t */ @@ -89,7 +102,7 @@ hb_font_get_font_v_extents_default (hb_font_t *font, static hb_bool_t hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t unicode, + hb_codepoint_t unicode HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { @@ -142,8 +155,8 @@ hb_font_get_nominal_glyphs_default (hb_font_t *font, static hb_bool_t hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t unicode, - hb_codepoint_t variation_selector, + hb_codepoint_t unicode HB_UNUSED, + hb_codepoint_t variation_selector HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { @@ -276,7 +289,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font, static hb_bool_t hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) @@ -301,7 +314,7 @@ hb_font_get_glyph_h_origin_default (hb_font_t *font, static hb_bool_t hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) @@ -326,8 +339,8 @@ hb_font_get_glyph_v_origin_default (hb_font_t *font, static hb_position_t hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, + hb_codepoint_t left_glyph HB_UNUSED, + hb_codepoint_t right_glyph HB_UNUSED, void *user_data HB_UNUSED) { return 0; @@ -345,8 +358,8 @@ hb_font_get_glyph_h_kerning_default (hb_font_t *font, static hb_position_t hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t top_glyph, - hb_codepoint_t bottom_glyph, + hb_codepoint_t top_glyph HB_UNUSED, + hb_codepoint_t bottom_glyph HB_UNUSED, void *user_data HB_UNUSED) { return 0; @@ -364,7 +377,7 @@ hb_font_get_glyph_v_kerning_default (hb_font_t *font, static hb_bool_t hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { @@ -389,8 +402,8 @@ hb_font_get_glyph_extents_default (hb_font_t *font, static hb_bool_t hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, - unsigned int point_index, + hb_codepoint_t glyph HB_UNUSED, + unsigned int point_index HB_UNUSED, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) @@ -416,7 +429,7 @@ hb_font_get_glyph_contour_point_default (hb_font_t *font, static hb_bool_t hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - hb_codepoint_t glyph, + hb_codepoint_t glyph HB_UNUSED, char *name, unsigned int size, void *user_data HB_UNUSED) { @@ -436,7 +449,8 @@ hb_font_get_glyph_name_default (hb_font_t *font, static hb_bool_t hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, - const char *name, int len, /* -1 means nul-terminated */ + const char *name HB_UNUSED, + int len HB_UNUSED, /* -1 means nul-terminated */ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh index 2df5e42ee6f..3dce233db3a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.hh @@ -62,7 +62,6 @@ struct hb_font_funcs_t { hb_object_header_t header; - ASSERT_POD (); hb_bool_t immutable; @@ -102,7 +101,6 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t); struct hb_font_t { hb_object_header_t header; - ASSERT_POD (); hb_bool_t immutable; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc index 18fb72a73cf..5e051105229 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc @@ -40,6 +40,17 @@ #include FT_TRUETYPE_TABLES_H +/** + * SECTION:hb-ft + * @title: hb-ft + * @short_description: FreeType integration + * @include: hb-ft.h + * + * Functions for using HarfBuzz with the FreeType library to provide face and + * font data. + **/ + + /* TODO: * * In general, this file does a fine job of what it's supposed to do. @@ -737,7 +748,7 @@ hb_ft_font_create_referenced (FT_Face ft_face) static void free_static_ft_library (void); #endif -static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_ptr_t<FT_Library>::value, +static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>::value, hb_ft_library_lazy_loader_t> { static inline FT_Library create (void) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc index a34acbba1d7..23a0d89c86b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-glib.cc @@ -33,6 +33,16 @@ #include "hb-machinery.hh" +/** + * SECTION:hb-glib + * @title: hb-glib + * @short_description: GLib integration + * @include: hb-glib.h + * + * Functions for using HarfBuzz with the GLib library to provide Unicode data. + **/ + + #if !GLIB_CHECK_VERSION(2,29,14) static const hb_script_t glib_script_to_script[] = diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc index 1b87585832e..23ca43656d0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-gobject-structs.cc @@ -26,6 +26,18 @@ #include "hb.hh" + +/** + * SECTION:hb-gobject + * @title: hb-gobject + * @short_description: GObject integration + * @include: hb-gobject.h + * + * Functions for using HarfBuzz with the GObject library to provide + * type data. + **/ + + /* g++ didn't like older gtype.h gcc-only code path. */ #include <glib.h> #if !GLIB_CHECK_VERSION(2,29,16) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc index 6b2b6f19d45..971241f92c1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-graphite2.cc @@ -33,7 +33,17 @@ #include <graphite2/Segment.h> -#include "hb-ot-tag.h" +#include "hb-ot-layout.h" + + +/** + * SECTION:hb-graphite2 + * @title: hb-graphite2 + * @short_description: Graphite2 integration + * @include: hb-graphite2.h + * + * Functions for using HarfBuzz with the Graphite2 fonts. + **/ HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face) @@ -197,11 +207,14 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED { } -/* +/** + * hb_graphite2_font_get_gr_font: + * * Since: 0.9.10 + * Deprecated: 1.4.2 */ gr_font * -hb_graphite2_font_get_gr_font (hb_font_t *font) +hb_graphite2_font_get_gr_font (hb_font_t *font HB_UNUSED) { return nullptr; } @@ -243,7 +256,7 @@ struct hb_graphite2_cluster_t { }; hb_bool_t -_hb_graphite2_shape (hb_shape_plan_t *shape_plan, +_hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc index e012314b507..12864677c35 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-icu.cc @@ -40,6 +40,16 @@ #include <unicode/uversion.h> +/** + * SECTION:hb-icu + * @title: hb-icu + * @short_description: ICU integration + * @include: hb-icu.h + * + * Functions for using HarfBuzz with the ICU library to provide Unicode data. + **/ + + hb_script_t hb_icu_script_to_script (UScriptCode script) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh index ae34c92f458..465bbb14f44 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-machinery.hh @@ -82,10 +82,8 @@ static inline Type& StructAfter(TObject &X) /* Check _assertion in a method environment */ #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ inline void _instance_assertion_on_line_##_line (void) const \ - { \ - static_assert ((_assertion), ""); \ - ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ - } + { static_assert ((_assertion), ""); } \ + static_assert (true, "") /* So we require semicolon here. */ # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) # define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) @@ -99,9 +97,9 @@ static inline Type& StructAfter(TObject &X) #define DEFINE_SIZE_STATIC(size) \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ + inline unsigned int get_size (void) const { return (size); } \ enum { static_size = (size) }; \ - enum { min_size = (size) }; \ - inline unsigned int get_size (void) const { return (size); } + enum { min_size = (size) } #define DEFINE_SIZE_UNION(size, _member) \ DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \ @@ -114,11 +112,11 @@ static inline Type& StructAfter(TObject &X) #define DEFINE_SIZE_ARRAY(size, array) \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof (array[0])); \ DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ - enum { min_size = (size) }; \ + enum { min_size = (size) } #define DEFINE_SIZE_ARRAY_SIZED(size, array) \ - DEFINE_SIZE_ARRAY(size, array); \ - inline unsigned int get_size (void) const { return (size - array[0].min_size + array.get_size ()); } + inline unsigned int get_size (void) const { return (size - array.min_size + array.get_size ()); } \ + DEFINE_SIZE_ARRAY(size, array) #define DEFINE_SIZE_ARRAY2(size, array1, array2) \ DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ @@ -136,7 +134,7 @@ struct hb_dispatch_context_t enum { max_debug_depth = MaxDebugDepth }; typedef Return return_t; template <typename T, typename F> - inline bool may_dispatch (const T *obj, const F *format) { return true; } + inline bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; } static return_t no_dispatch_return_value (void) { return Context::default_return_value (); } }; @@ -235,7 +233,7 @@ struct hb_sanitize_context_t : inline const char *get_name (void) { return "SANITIZE"; } template <typename T, typename F> - inline bool may_dispatch (const T *obj, const F *format) + inline bool may_dispatch (const T *obj HB_UNUSED, const F *format) { return format->sanitize (this); } template <typename T> inline return_t dispatch (const T &obj) { return obj.sanitize (this); } @@ -612,7 +610,7 @@ struct Supplier } inline Supplier (const hb_vector_t<Type> *v) { - head = v->arrayZ(); + head = *v; len = v->len; stride = sizeof (Type); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc index 225f37bc678..067a2b37169 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc @@ -27,7 +27,16 @@ #include "hb-map.hh" -/* Public API */ +/** + * SECTION:hb-map + * @title: hb-map + * @short_description: Object representing integer to integer mapping + * @include: hb.h + * + * Map objects are integer-to-integer hash-maps. Currently they are + * not used in the HarfBuzz public API, but are provided for client's + * use if desired. + **/ /** diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh index b55e3a9543e..c54c9d7b640 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh @@ -44,6 +44,10 @@ inline uint32_t Hash (const T &v) struct hb_map_t { + HB_NO_COPY_ASSIGN (hb_map_t); + inline hb_map_t (void) { init (); } + inline ~hb_map_t (void) { fini (); } + struct item_t { hb_codepoint_t key; @@ -77,9 +81,11 @@ struct hb_map_t inline void fini_shallow (void) { free (items); + items = nullptr; } inline void fini (void) { + population = occupancy = 0; hb_object_fini (this); fini_shallow (); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh index 87662265cf0..3d8a1ae6cce 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-null.hh @@ -47,7 +47,7 @@ static inline Type const & Null (void) { static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); return *reinterpret_cast<Type const *> (_hb_NullPool); } -#define Null(Type) Null<Type>() +#define Null(Type) Null<typename hb_remove_const<typename hb_remove_reference<Type>::value>::value>() /* Specializations for arbitrary-content Null objects expressed in bytes. */ #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \ @@ -90,7 +90,7 @@ static inline Type& Crap (void) { *obj = Null(Type); return *obj; } -#define Crap(Type) Crap<Type>() +#define Crap(Type) Crap<typename hb_remove_const<typename hb_remove_reference<Type>::value>::value>() template <typename Type> struct CrapOrNull { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh index ca85af691d9..106f5920685 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-object.hh @@ -195,12 +195,8 @@ struct hb_object_header_t { hb_reference_count_t ref_count; hb_atomic_ptr_t<hb_user_data_array_t> user_data; - -#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_ATOMIC_PTR_INIT (nullptr)} - - private: - ASSERT_POD (); }; +#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_ATOMIC_PTR_INIT (nullptr)} /* @@ -276,6 +272,7 @@ static inline void hb_object_fini (Type *obj) { user_data->fini (); free (user_data); + user_data = nullptr; } } template <typename Type> diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh index 817791ab083..80dc5e614b1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-file.hh @@ -330,8 +330,7 @@ struct ResourceTypeRecord inline const ResourceRecord& get_resource_record (unsigned int i, const void *type_base) const { - return hb_array_t<ResourceRecord> ((type_base+resourcesZ).arrayZ, - get_resource_count ()) [i]; + return hb_array (type_base+resourcesZ, get_resource_count ())[i]; } inline bool sanitize (hb_sanitize_context_t *c, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh index 08e72064af8..e9f99b10487 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh @@ -149,15 +149,14 @@ struct Tag : HBUINT32 /* Glyph index number, same as uint16 (length = 16 bits) */ typedef HBUINT16 GlyphID; -/* Name-table index, same as uint16 (length = 16 bits) */ -typedef HBUINT16 NameID; - /* Script/language-system/feature index */ struct Index : HBUINT16 { enum { NOT_FOUND_INDEX = 0xFFFFu }; }; DECLARE_NULL_NAMESPACE_BYTES (OT, Index); +typedef Index NameID; + /* Offset, Null offset = 0 */ template <typename Type, bool has_null=true> struct Offset : Type @@ -336,6 +335,8 @@ static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> template <typename Type> struct UnsizedArrayOf { + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type); + inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } inline Type& operator [] (unsigned int i) { return arrayZ[i]; } @@ -386,6 +387,14 @@ struct UnsizedArrayOf public: DEFINE_SIZE_ARRAY (0, arrayZ); }; +} /* namespace OT */ +template <typename T> static inline +hb_array_t<T> hb_array (OT::UnsizedArrayOf<T> &array, unsigned int len) +{ return hb_array (array.arrayZ, len); } +template <typename T> static inline +hb_array_t<const T> hb_array (const OT::UnsizedArrayOf<T> &array, unsigned int len) +{ return hb_array (array.arrayZ, len); } +namespace OT { /* Unsized array of offset's */ template <typename Type, typename OffsetType, bool has_null=true> @@ -417,7 +426,9 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null> template <typename Type, typename LenType=HBUINT16> struct ArrayOf { - const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType); + + inline const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const { unsigned int count = len; if (unlikely (start_offset > count)) @@ -516,7 +527,6 @@ struct ArrayOf ::qsort (arrayZ, len, sizeof (Type), Type::cmp); } - private: inline bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -533,8 +543,12 @@ template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {}; typedef ArrayOf<HBUINT8, HBUINT8> PString; /* Array of Offset's */ -template <typename Type, typename OffsetType=HBUINT16> -struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {}; +template <typename Type> +struct OffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT16> > {}; +template <typename Type> +struct LOffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT32> > {}; +template <typename Type> +struct LOffsetLArrayOf : ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32> {}; /* Array of offsets relative to the beginning of the array itself. */ template <typename Type> @@ -579,6 +593,8 @@ struct OffsetListOf : OffsetArrayOf<Type> template <typename Type, typename LenType=HBUINT16> struct HeadlessArrayOf { + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType); + inline const Type& operator [] (unsigned int i) const { if (unlikely (i >= lenP1 || !i)) return Null(Type); @@ -643,6 +659,8 @@ struct HeadlessArrayOf template <typename Type, typename LenType=HBUINT16> struct ArrayOfM1 { + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType); + inline const Type& operator [] (unsigned int i) const { if (unlikely (i > lenM1)) return Null(Type); @@ -695,7 +713,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType> int min = 0, max = (int) this->len - 1; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; int c = arr[mid].cmp (x); if (c < 0) max = mid - 1; @@ -747,6 +765,7 @@ struct BinSearchHeader template <typename Type, typename LenType=HBUINT16> struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {}; + struct VarSizedBinSearchHeader { @@ -772,6 +791,8 @@ struct VarSizedBinSearchHeader template <typename Type> struct VarSizedBinSearchArrayOf { + HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type); + inline const Type& operator [] (unsigned int i) const { if (unlikely (i >= header.nUnits)) return Null(Type); @@ -818,7 +839,7 @@ struct VarSizedBinSearchArrayOf int min = 0, max = (int) header.nUnits - 1; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size)); int c = p->cmp (key); if (c < 0) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh index e5793c387ea..a1c5a9747b1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh @@ -228,6 +228,10 @@ struct CmapSubtableFormat4 struct accelerator_t { + inline accelerator_t (void) {} + inline accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); } + inline ~accelerator_t (void) { fini (); } + inline void init (const CmapSubtableFormat4 *subtable) { segCount = subtable->segCountX2 / 2; @@ -249,7 +253,7 @@ struct CmapSubtableFormat4 unsigned int i; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; if (codepoint < startCount[mid]) max = mid - 1; else if (codepoint > endCount[mid]) @@ -327,12 +331,12 @@ struct CmapSubtableFormat4 inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { - hb_auto_t<accelerator_t> accel (this); + accelerator_t accel (this); return accel.get_glyph_func (&accel, codepoint, glyph); } inline void collect_unicodes (hb_set_t *out) const { - hb_auto_t<accelerator_t> accel (this); + accelerator_t accel (this); accel.collect_unicodes (out); } @@ -495,7 +499,7 @@ struct CmapSubtableLongSegmented { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - Supplier<CmapSubtableLongGroup> supplier (group_data.arrayZ(), group_data.len); + Supplier<CmapSubtableLongGroup> supplier (group_data, group_data.len); if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false); return true; } @@ -851,18 +855,6 @@ struct cmap struct subset_plan { - subset_plan(void) - { - format4_segments.init(); - format12_groups.init(); - } - - ~subset_plan(void) - { - format4_segments.fini(); - format12_groups.fini(); - } - inline size_t final_size() const { return 4 // header @@ -871,9 +863,7 @@ struct cmap + CmapSubtableFormat12::get_sub_table_size (this->format12_groups); } - // Format 4 hb_vector_t<CmapSubtableFormat4::segment_plan> format4_segments; - // Format 12 hb_vector_t<CmapSubtableLongGroup> format12_groups; }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh index 1e1fe095613..614cc80ce2b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cbdt-table.hh @@ -166,7 +166,7 @@ struct IndexSubtable } } - inline bool get_extents (hb_glyph_extents_t *extents) const + inline bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const { switch (u.header.indexFormat) { case 2: case 5: /* TODO */ @@ -343,26 +343,30 @@ struct CBLC } protected: - const IndexSubtableRecord *find_table (hb_codepoint_t glyph, - unsigned int *x_ppem, unsigned int *y_ppem, - const void **base) const + const BitmapSizeTable &choose_strike (hb_font_t *font) const { - /* TODO: Make it possible to select strike. */ + unsigned count = sizeTables.len; + if (unlikely (!count)) + return Null(BitmapSizeTable); + + unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem); + if (!requested_ppem) + requested_ppem = 1<<30; /* Choose largest strike. */ + unsigned int best_i = 0; + unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY); - unsigned int count = sizeTables.len; - for (uint32_t i = 0; i < count; ++i) + for (unsigned int i = 1; i < count; i++) { - unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex; - unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex; - if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) + unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY); + if ((requested_ppem <= ppem && ppem < best_ppem) || + (requested_ppem > best_ppem && ppem > best_ppem)) { - *x_ppem = sizeTables[i].ppemX; - *y_ppem = sizeTables[i].ppemY; - return sizeTables[i].find_table (glyph, this, base); + best_i = i; + best_ppem = ppem; } } - return nullptr; + return sizeTables[best_i]; } protected: @@ -376,13 +380,6 @@ struct CBDT { static const hb_tag_t tableTag = HB_OT_TAG_CBDT; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version.major == 2 || version.major == 3)); - } - struct accelerator_t { inline void init (hb_face_t *face) @@ -409,16 +406,16 @@ struct CBDT hb_blob_destroy (this->cbdt_blob); } - inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + inline bool get_extents (hb_font_t *font, hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const { - unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ - if (!cblc) - return false; // Not a color bitmap font. + return false; const void *base; - const IndexSubtableRecord *subtable_record = this->cblc->find_table (glyph, &x_ppem, &y_ppem, &base); - if (!subtable_record || !x_ppem || !y_ppem) + const BitmapSizeTable &strike = this->cblc->choose_strike (font); + const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base); + if (!subtable_record || !strike.ppemX || !strike.ppemY) return false; if (subtable_record->get_extents (extents, base)) @@ -437,80 +434,94 @@ struct CBDT case 17: { if (unlikely (image_length < GlyphBitmapDataFormat17::min_size)) return false; - const GlyphBitmapDataFormat17& glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); glyphFormat17.glyphMetrics.get_extents (extents); + break; + } + case 18: { + if (unlikely (image_length < GlyphBitmapDataFormat18::min_size)) + return false; + const GlyphBitmapDataFormat18& glyphFormat18 = + StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset); + glyphFormat18.glyphMetrics.get_extents (extents); + break; } - break; default: // TODO: Support other image formats. return false; } } - /* Convert to the font units. */ - extents->x_bearing *= upem / (float) x_ppem; - extents->y_bearing *= upem / (float) y_ppem; - extents->width *= upem / (float) x_ppem; - extents->height *= upem / (float) y_ppem; + /* Convert to font units. */ + double x_scale = upem / (double) strike.ppemX; + double y_scale = upem / (double) strike.ppemY; + extents->x_bearing = round (extents->x_bearing * x_scale); + extents->y_bearing = round (extents->y_bearing * y_scale); + extents->width = round (extents->width * x_scale); + extents->height = round (extents->height * y_scale); return true; } - inline void dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid)) const + inline hb_blob_t* reference_png (hb_font_t *font, + hb_codepoint_t glyph) const { if (!cblc) - return; // Not a color bitmap font. + return hb_blob_get_empty (); + + const void *base; + const BitmapSizeTable &strike = this->cblc->choose_strike (font); + const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base); + if (!subtable_record || !strike.ppemX || !strike.ppemY) + return hb_blob_get_empty (); + + unsigned int image_offset = 0, image_length = 0, image_format = 0; + if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format)) + return hb_blob_get_empty (); - for (unsigned int i = 0; i < cblc->sizeTables.len; ++i) { - const BitmapSizeTable &sizeTable = cblc->sizeTables[i]; - const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset; - for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j) - { - const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j]; - for (unsigned int gid = subtable_record.firstGlyphIndex; - gid <= subtable_record.lastGlyphIndex; ++gid) - { - unsigned int image_offset = 0, image_length = 0, image_format = 0; - - if (!subtable_record.get_image_data (gid, &subtable_array, - &image_offset, &image_length, &image_format)) - continue; - - switch (image_format) - { - case 17: { - const GlyphBitmapDataFormat17& glyphFormat17 = - StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); - callback ((const uint8_t *) &glyphFormat17.data.arrayZ, - glyphFormat17.data.len, i, gid); - } - break; - case 18: { - const GlyphBitmapDataFormat18& glyphFormat18 = - StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset); - callback ((const uint8_t *) &glyphFormat18.data.arrayZ, - glyphFormat18.data.len, i, gid); - } - break; - case 19: { - const GlyphBitmapDataFormat19& glyphFormat19 = - StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset); - callback ((const uint8_t *) &glyphFormat19.data.arrayZ, - glyphFormat19.data.len, i, gid); - } - break; - default: - continue; - } - } - } + if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) + return hb_blob_get_empty (); + + switch (image_format) + { + case 17: { + if (unlikely (image_length < GlyphBitmapDataFormat17::min_size)) + return hb_blob_get_empty (); + const GlyphBitmapDataFormat17& glyphFormat17 = + StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt_blob, + image_offset + GlyphBitmapDataFormat17::min_size, + glyphFormat17.data.len); + } + case 18: { + if (unlikely (image_length < GlyphBitmapDataFormat18::min_size)) + return hb_blob_get_empty (); + const GlyphBitmapDataFormat18& glyphFormat18 = + StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt_blob, + image_offset + GlyphBitmapDataFormat18::min_size, + glyphFormat18.data.len); + } + case 19: { + if (unlikely (image_length < GlyphBitmapDataFormat19::min_size)) + return hb_blob_get_empty (); + const GlyphBitmapDataFormat19& glyphFormat19 = + StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt_blob, + image_offset + GlyphBitmapDataFormat19::min_size, + glyphFormat19.data.len); + } + } } + + return hb_blob_get_empty (); } + inline bool has_data () const + { return cbdt_len; } + private: hb_blob_t *cblc_blob; hb_blob_t *cbdt_blob; @@ -521,6 +532,12 @@ struct CBDT unsigned int upem; }; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3)); + } protected: FixedVersion<> version; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh index a59d2bfa93e..b480af51d2c 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-colr-table.hh @@ -39,24 +39,39 @@ namespace OT { struct LayerRecord { - friend struct COLR; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - protected: - GlyphID glyphid; /* Glyph ID of layer glyph */ - HBUINT16 colorIdx; /* Index value to use with a selected color palette */ + public: + GlyphID glyphId; /* Glyph ID of layer glyph */ + Index colorIdx; /* Index value to use with a + * selected color palette. + * An index value of 0xFFFF + * is a special case indicating + * that the text foreground + * color (defined by a + * higher-level client) should + * be used and shall not be + * treated as actual index + * into CPAL ColorRecord array. */ public: DEFINE_SIZE_STATIC (4); }; struct BaseGlyphRecord { - friend struct COLR; + inline int cmp (hb_codepoint_t g) const + { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } + + static int cmp (const void *pa, const void *pb) + { + const hb_codepoint_t *a = (const hb_codepoint_t *) pa; + const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb; + return b->cmp (*a); + } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -64,29 +79,48 @@ struct BaseGlyphRecord return_trace (likely (c->check_struct (this))); } - inline int cmp (hb_codepoint_t g) const { - return g < glyphid ? -1 : g > glyphid ? 1 : 0; - } - - protected: - GlyphID glyphid; /* Glyph ID of reference glyph */ - HBUINT16 firstLayerIdx; /* Index to the layer record */ - HBUINT16 numLayers; /* Number of color layers associated with this glyph */ + public: + GlyphID glyphId; /* Glyph ID of reference glyph */ + HBUINT16 firstLayerIdx; /* Index (from beginning of + * the Layer Records) to the + * layer record. There will be + * numLayers consecutive entries + * for this base glyph. */ + HBUINT16 numLayers; /* Number of color layers + * associated with this glyph */ public: DEFINE_SIZE_STATIC (6); }; -static int compare_bgr (const void *pa, const void *pb) -{ - const hb_codepoint_t *a = (const hb_codepoint_t *) pa; - const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb; - return b->cmp (*a); -} - struct COLR { static const hb_tag_t tableTag = HB_OT_TAG_COLR; + inline bool has_data (void) const { return numBaseGlyphs; } + + inline unsigned int get_glyph_layers (hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const + { + const BaseGlyphRecord &record = get_glyph_record (glyph); + + hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers); + hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx, + record.numLayers); + if (count) + { + hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count); + *count = segment_layers.len; + for (unsigned int i = 0; i < segment_layers.len; i++) + { + layers[i].glyph = segment_layers.arrayZ[i].glyphId; + layers[i].color_index = segment_layers.arrayZ[i].colorIdx; + } + } + return glyph_layers.len; + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -95,45 +129,25 @@ struct COLR (this+layersZ).sanitize (c, numLayers))); } - inline bool get_base_glyph_record (hb_codepoint_t glyph_id, - unsigned int *first_layer /* OUT */, - unsigned int *num_layers /* OUT */) const - { - const BaseGlyphRecord* record; - record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs, - sizeof (BaseGlyphRecord), compare_bgr); - if (unlikely (!record)) - return false; - - *first_layer = record->firstLayerIdx; - *num_layers = record->numLayers; - return true; - } - - inline bool get_layer_record (unsigned int record, - hb_codepoint_t *glyph_id /* OUT */, - unsigned int *palette_index /* OUT */) const + private: + inline const BaseGlyphRecord &get_glyph_record (hb_codepoint_t glyph_id) const { - if (unlikely (record >= numLayers)) - { - *glyph_id = 0; - *palette_index = 0xFFFF; - return false; - } - const LayerRecord &layer = (this+layersZ)[record]; - *glyph_id = layer.glyphid; - *palette_index = layer.colorIdx; - return true; + const BaseGlyphRecord *rec = (BaseGlyphRecord *) bsearch (&glyph_id, + &(this+baseGlyphsZ), + numBaseGlyphs, + sizeof (BaseGlyphRecord), + BaseGlyphRecord::cmp); + return rec ? *rec : Null(BaseGlyphRecord); } protected: - HBUINT16 version; /* Table version number */ - HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */ + HBUINT16 version; /* Table version number (starts at 0). */ + HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ LOffsetTo<UnsizedArrayOf<BaseGlyphRecord>, false> baseGlyphsZ; /* Offset to Base Glyph records. */ LOffsetTo<UnsizedArrayOf<LayerRecord>, false> - layersZ; /* Offset to Layer Records */ - HBUINT16 numLayers; /* Number of Layer Records */ + layersZ; /* Offset to Layer Records. */ + HBUINT16 numLayers; /* Number of Layer Records. */ public: DEFINE_SIZE_STATIC (14); }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh index e354ced5c28..df4d9b4e7f1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh @@ -29,53 +29,8 @@ #define HB_OT_COLOR_CPAL_TABLE_HH #include "hb-open-type.hh" - - -/* - * Following parts to be moved to a public header. - */ - -/** - * hb_ot_color_t: - * ARGB data type for holding color values. - * - * Since: REPLACEME - */ -typedef uint32_t hb_ot_color_t; - - -/** - * hb_ot_color_palette_flags_t: - * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette. - * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background. - * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background. - * - * Since: REPLACEME - */ -typedef enum { /*< flags >*/ - HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u, - HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u, - HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u, -} hb_ot_color_palette_flags_t; - -// HB_EXTERN unsigned int -// hb_ot_color_get_palette_count (hb_face_t *face); - -// HB_EXTERN unsigned int -// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette); - -// HB_EXTERN hb_ot_color_palette_flags_t -// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette); - -// HB_EXTERN unsigned int -// hb_ot_color_get_palette_colors (hb_face_t *face, -// unsigned int palette, /* default=0 */ -// unsigned int start_offset, -// unsigned int *color_count /* IN/OUT */, -// hb_ot_color_t *colors /* OUT */); - - - +#include "hb-ot-color.h" +#include "hb-ot-name.h" /* @@ -92,29 +47,46 @@ struct CPALV1Tail { friend struct CPAL; - inline bool - sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const + private: + inline hb_ot_color_palette_flags_t + get_palette_flags (const void *base, + unsigned int palette_index, + unsigned int palette_count) const { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - (base+paletteFlagsZ).sanitize (c, palettes) && - (base+paletteLabelZ).sanitize (c, palettes) && - (base+paletteEntryLabelZ).sanitize (c, palettes)); + if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; + return (hb_ot_color_palette_flags_t) (uint32_t) + hb_array (base+paletteFlagsZ, palette_count)[palette_index]; } - private: - inline hb_ot_color_palette_flags_t - get_palette_flags (const void *base, unsigned int palette) const + inline hb_ot_name_id_t + get_palette_name_id (const void *base, + unsigned int palette_index, + unsigned int palette_count) const { - // range checked at the CPAL caller - return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette]; + if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID; + return hb_array (base+paletteLabelsZ, palette_count)[palette_index]; } - inline unsigned int - get_palette_name_id (const void *base, unsigned int palette) const + inline hb_ot_name_id_t + get_color_name_id (const void *base, + unsigned int color_index, + unsigned int color_count) const { - // range checked at the CPAL caller - return (base+paletteLabelZ)[palette]; + if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID; + return hb_array (base+colorLabelsZ, color_count)[color_index]; + } + + public: + inline bool sanitize (hb_sanitize_context_t *c, + const void *base, + unsigned int palette_count, + unsigned int color_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) && + (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) && + (!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count))); } protected: @@ -122,13 +94,13 @@ struct CPALV1Tail paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LOffsetTo<UnsizedArrayOf<HBUINT16>, false> - paletteLabelZ; /* Offset from the beginning of CPAL table to - * the Palette Labels Array. Set to 0 if no + LOffsetTo<UnsizedArrayOf<NameID>, false> + paletteLabelsZ; /* Offset from the beginning of CPAL table to + * the palette labels array. Set to 0 if no * array is provided. */ - LOffsetTo<UnsizedArrayOf<HBUINT16>, false> - paletteEntryLabelZ; /* Offset from the beginning of CPAL table to - * the Palette Entry Label Array. Set to 0 + LOffsetTo<UnsizedArrayOf<NameID>, false> + colorLabelsZ; /* Offset from the beginning of CPAL table to + * the color labels array. Set to 0 * if no array is provided. */ public: DEFINE_SIZE_STATIC (12); @@ -140,70 +112,70 @@ struct CPAL { static const hb_tag_t tableTag = HB_OT_TAG_CPAL; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this) && // it checks colorRecordIndices also - // see #get_size - (this+colorRecordsZ).sanitize (c, numColorRecords)))) - return_trace (false); - - // Check for indices sanity so no need for doing it runtime - for (unsigned int i = 0; i < numPalettes; ++i) - if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords)) - return_trace (false); - - // If version is zero, we are done here; otherwise we need to check tail also - if (version == 0) - return_trace (true); - - const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this); - return_trace (likely (v1.sanitize (c, this, numPalettes))); - } + inline bool has_data (void) const { return numPalettes; } inline unsigned int get_size (void) const - { - return min_size + numPalettes * sizeof (HBUINT16); - } + { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); } - inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const - { - if (unlikely (version == 0 || palette >= numPalettes)) - return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; + inline unsigned int get_palette_count () const { return numPalettes; } + inline unsigned int get_color_count () const { return numColors; } - const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this); - return cpal1.get_palette_flags (this, palette); - } + inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const + { return v1 ().get_palette_flags (this, palette_index, numPalettes); } - inline unsigned int get_palette_name_id (unsigned int palette) const - { - if (unlikely (version == 0 || palette >= numPalettes)) - return 0xFFFF; + inline hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const + { return v1 ().get_palette_name_id (this, palette_index, numPalettes); } - const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this); - return cpal1.get_palette_name_id (this, palette); - } + inline hb_ot_name_id_t get_color_name_id (unsigned int color_index) const + { return v1 ().get_color_name_id (this, color_index, numColors); } - inline unsigned int get_palette_count () const + inline unsigned int get_palette_colors (unsigned int palette_index, + unsigned int start_offset, + unsigned int *color_count, /* IN/OUT. May be NULL. */ + hb_color_t *colors /* OUT. May be NULL. */) const { - return numPalettes; + if (unlikely (palette_index >= numPalettes)) + { + if (color_count) *color_count = 0; + return 0; + } + unsigned int start_index = colorRecordIndicesZ[palette_index]; + hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords); + hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index, + numColors); + if (color_count) + { + hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count); + /* Always return numColors colors per palette even if it has out-of-bounds start index. */ + unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count); + *color_count = count; + for (unsigned int i = 0; i < count; i++) + colors[i] = segment_colors[i]; /* Bound-checked read. */ + } + return numColors; } - inline hb_ot_color_t - get_color_record_argb (unsigned int color_index, unsigned int palette) const + private: + inline const CPALV1Tail& v1 (void) const { - if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes)) - return 0; + if (version == 0) return Null(CPALV1Tail); + return StructAfter<CPALV1Tail> (*this); + } - // No need for more range check as it is already done on #sanitize - const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ; - return color_records[colorRecordIndicesZ[palette] + color_index]; + public: + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + (this+colorRecordsZ).sanitize (c, numColorRecords) && + colorRecordIndicesZ.sanitize (c, numPalettes) && + (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors))); } protected: HBUINT16 version; /* Table version number */ /* Version 0 */ - HBUINT16 numPaletteEntries; /* Number of palette entries in each palette. */ + HBUINT16 numColors; /* Number of colors in each palette. */ HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh index 1b643c77a59..4feb4e19374 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-sbix-table.hh @@ -62,8 +62,6 @@ struct SBIXGlyph struct SBIXStrike { - friend struct sbix; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -71,10 +69,58 @@ struct SBIXStrike imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1)); } - protected: + inline hb_blob_t *get_glyph_blob (unsigned int glyph_id, + hb_blob_t *sbix_blob, + hb_tag_t file_type, + int *x_offset, + int *y_offset, + unsigned int num_glyphs, + unsigned int *strike_ppem) const + { + if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */ + + unsigned int retry_count = 8; + unsigned int sbix_len = sbix_blob->length; + unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data; + assert (strike_offset < sbix_len); + + retry: + if (unlikely (glyph_id >= num_glyphs || + imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] || + imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size || + (unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset)) + return hb_blob_get_empty (); + + unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size; + unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size; + + const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]); + + if (glyph->graphicType == HB_TAG ('d','u','p','e')) + { + if (glyph_length >= 2) + { + glyph_id = *((HBUINT16 *) &glyph->data); + if (retry_count--) + goto retry; + } + return hb_blob_get_empty (); + } + + if (unlikely (file_type != glyph->graphicType)) + return hb_blob_get_empty (); + + if (strike_ppem) *strike_ppem = ppem; + if (x_offset) *x_offset = glyph->xOffset; + if (y_offset) *y_offset = glyph->yOffset; + return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length); + } + + public: HBUINT16 ppem; /* The PPEM size for which this strike was designed. */ HBUINT16 resolution; /* The device pixel density (in PPI) for which this * strike was designed. (E.g., 96 PPI, 192 PPI.) */ + protected: UnsizedArrayOf<LOffsetTo<SBIXGlyph> > imageOffsetsZ; /* Offset from the beginning of the strike data header * to bitmap data for an individual glyph ID. */ @@ -86,19 +132,17 @@ struct sbix { static const hb_tag_t tableTag = HB_OT_TAG_sbix; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this))); - } + inline bool has_data (void) const { return version; } + + inline const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; } struct accelerator_t { inline void init (hb_face_t *face) { sbix_blob = hb_sanitize_context_t().reference_table<sbix> (face); - sbix_len = hb_blob_get_length (sbix_blob); - sbix_table = sbix_blob->as<sbix> (); + table = sbix_blob->as<sbix> (); + num_glyphs = face->get_num_glyphs (); } inline void fini (void) @@ -106,42 +150,155 @@ struct sbix hb_blob_destroy (sbix_blob); } - inline void dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid)) const + inline bool has_data () const { - for (unsigned group = 0; group < sbix_table->strikes.len; ++group) + /* XXX Fix somehow and remove next line. + * https://github.com/harfbuzz/harfbuzz/issues/1146 */ + if (!num_glyphs) return false; + return table->has_data (); + } + + inline bool get_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + /* We only support PNG right now, and following function checks type. */ + return get_png_extents (font, glyph, extents); + } + + inline hb_blob_t *reference_png (hb_font_t *font, + hb_codepoint_t glyph_id, + int *x_offset, + int *y_offset, + unsigned int *available_ppem) const + { + return choose_strike (font).get_glyph_blob (glyph_id, sbix_blob, + HB_TAG ('p','n','g',' '), + x_offset, y_offset, + num_glyphs, available_ppem); + } + + private: + + inline const SBIXStrike &choose_strike (hb_font_t *font) const + { + unsigned count = table->strikes.len; + if (unlikely (!count)) + return Null(SBIXStrike); + + unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem); + if (!requested_ppem) + requested_ppem = 1<<30; /* Choose largest strike. */ + /* TODO Add DPI sensitivity as well? */ + unsigned int best_i = 0; + unsigned int best_ppem = table->get_strike (0).ppem; + + for (unsigned int i = 1; i < count; i++) + { + unsigned int ppem = (table->get_strike (i)).ppem; + if ((requested_ppem <= ppem && ppem < best_ppem) || + (requested_ppem > best_ppem && ppem > best_ppem)) + { + best_i = i; + best_ppem = ppem; + } + } + + return table->get_strike (best_i); + } + + struct PNGHeader + { + HBUINT8 signature[8]; + struct + { + struct + { + HBUINT32 length; + Tag type; + } header; + HBUINT32 width; + HBUINT32 height; + HBUINT8 bitDepth; + HBUINT8 colorType; + HBUINT8 compressionMethod; + HBUINT8 filterMethod; + HBUINT8 interlaceMethod; + } IHDR; + + public: + DEFINE_SIZE_STATIC (29); + }; + + inline bool get_png_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + /* Following code is safe to call even without data (XXX currently + * isn't. See has_data()), but faster to short-circuit. */ + if (!has_data ()) + return false; + + int x_offset = 0, y_offset = 0; + unsigned int strike_ppem = 0; + hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem); + + if (unlikely (blob->length < sizeof (PNGHeader))) + { + hb_blob_destroy (blob); + return false; + } + + const PNGHeader &png = *blob->as<PNGHeader>(); + + extents->x_bearing = x_offset; + extents->y_bearing = y_offset; + extents->width = png.IHDR.width; + extents->height = png.IHDR.height; + + /* Convert to font units. */ + if (strike_ppem) { - const SBIXStrike &strike = sbix_table->strikes[group](sbix_table); - for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph) - if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0) - { - const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike); - callback ((const uint8_t*) &sbixGlyph.data, - strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8, - group, glyph); - } + double scale = font->face->upem / (double) strike_ppem; + extents->x_bearing = round (extents->x_bearing * scale); + extents->y_bearing = round (extents->y_bearing * scale); + extents->width = round (extents->width * scale); + extents->height = round (extents->height * scale); } + + hb_blob_destroy (blob); + + return true; } private: hb_blob_t *sbix_blob; - const sbix *sbix_table; + const sbix *table; - unsigned int sbix_len; unsigned int num_glyphs; }; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + version >= 1 && + strikes.sanitize (c, this))); + } + protected: HBUINT16 version; /* Table version number — set to 1 */ HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines. * Bits 2 to 15: reserved (set to 0). */ - LArrayOf<LOffsetTo<SBIXStrike> > + LOffsetLArrayOf<SBIXStrike> strikes; /* Offsets from the beginning of the 'sbix' * table to data for each individual bitmap strike. */ public: DEFINE_SIZE_ARRAY (8, strikes); }; +struct sbix_accelerator_t : sbix::accelerator_t {}; + } /* namespace OT */ #endif /* HB_OT_COLOR_SBIX_TABLE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh index 53d466846a4..bb4c4f757c8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-svg-table.hh @@ -40,13 +40,21 @@ namespace OT { struct SVGDocumentIndexEntry { - friend struct SVG; + inline int cmp (hb_codepoint_t g) const + { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; } - inline bool sanitize (hb_sanitize_context_t *c, const void* base) const + inline hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const + { + return hb_blob_create_sub_blob (svg_blob, + index_offset + (unsigned int) svgDoc, + svgDocLength); + } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - (base+svgDoc).sanitize (c, svgDocLength)); + svgDoc.sanitize (c, base, svgDocLength)); } protected: @@ -57,48 +65,23 @@ struct SVGDocumentIndexEntry LOffsetTo<UnsizedArrayOf<HBUINT8>, false> svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ - HBUINT32 svgDocLength; /* Length of the SVG document. + HBUINT32 svgDocLength; /* Length of the SVG document. * Must be non-zero. */ public: DEFINE_SIZE_STATIC (12); }; -struct SVGDocumentIndex -{ - friend struct SVG; - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - entries.sanitize (c, this)); - } - - protected: - ArrayOf<SVGDocumentIndexEntry> - entries; /* Array of SVG Document Index Entries. */ - public: - DEFINE_SIZE_ARRAY (2, entries); -}; - struct SVG { static const hb_tag_t tableTag = HB_OT_TAG_SVG; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+svgDocIndex).sanitize (c))); - } - struct accelerator_t { inline void init (hb_face_t *face) { svg_blob = hb_sanitize_context_t().reference_table<SVG> (face); svg_len = hb_blob_get_length (svg_blob); - svg = svg_blob->as<SVG> (); + table = svg_blob->as<SVG> (); } inline void fini (void) @@ -106,37 +89,48 @@ struct SVG hb_blob_destroy (svg_blob); } - inline void - dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int start_glyph, unsigned int end_glyph)) const + inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const { - const SVGDocumentIndex &index = svg+svg->svgDocIndex; - const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries; - for (unsigned int i = 0; i < entries.len; ++i) - { - const SVGDocumentIndexEntry &entry = entries[i]; - callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength, - entry.startGlyphID, entry.endGlyphID); - } + if (unlikely (!svg_len)) + return hb_blob_get_empty (); + return table->get_glyph_entry (glyph_id).reference_blob (svg_blob, table->svgDocEntries); } + inline bool has_data () const { return svg_len; } + private: hb_blob_t *svg_blob; - const SVG *svg; + const SVG *table; unsigned int svg_len; }; + inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const + { + const SortedArrayOf<SVGDocumentIndexEntry> &docs = this+svgDocEntries; + return docs[docs.bsearch (glyph_id)]; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + (this+svgDocEntries).sanitize_shallow (c))); + } + protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo<SVGDocumentIndex> - svgDocIndex; /* Offset (relative to the start of the SVG table) to the + LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry> > + svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ + /* Array of SVG Document Index Entries. */ HBUINT32 reserved; /* Set to 0. */ public: DEFINE_SIZE_STATIC (10); }; +struct SVG_accelerator_t : SVG::accelerator_t {}; + } /* namespace OT */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc index 7cdff380ef2..b87ed56fa4a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.cc @@ -22,160 +22,314 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * Google Author(s): Sascha Brawer + * Google Author(s): Sascha Brawer, Behdad Esfahbod */ #include "hb-open-type.hh" +#include "hb-ot-color-cbdt-table.hh" #include "hb-ot-color-colr-table.hh" #include "hb-ot-color-cpal-table.hh" +#include "hb-ot-color-sbix-table.hh" +#include "hb-ot-color-svg-table.hh" +#include "hb-ot-face.hh" #include "hb-ot.h" #include <stdlib.h> #include <string.h> #include "hb-ot-layout.hh" -#include "hb-shaper.hh" -#if 0 -HB_MARK_AS_FLAG_T (hb_ot_color_palette_flags_t) -//HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) Hmm? + +/** + * SECTION:hb-ot-color + * @title: hb-ot-color + * @short_description: OpenType Color Fonts + * @include: hb-ot.h + * + * Functions for fetching color-font information from OpenType font faces. + **/ static inline const OT::COLR& _get_colr (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::COLR); - return *(hb_ot_face_data (face)->colr.get ()); + return *(hb_ot_face_data (face)->COLR.get ()); +} + +static inline const OT::CBDT_accelerator_t& +_get_cbdt (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CBDT_accelerator_t); + return *(hb_ot_face_data (face)->CBDT.get ()); } static inline const OT::CPAL& _get_cpal (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CPAL); - return *(hb_ot_face_data (face)->cpal.get ()); + return *(hb_ot_face_data (face)->CPAL.get ()); } +static inline const OT::sbix_accelerator_t& +_get_sbix (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::sbix_accelerator_t); + return *(hb_ot_face_data (face)->sbix.get ()); +} + +static inline const OT::SVG_accelerator_t& +_get_svg (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::SVG_accelerator_t); + return *(hb_ot_face_data (face)->SVG.get ()); +} + + +/* + * CPAL + */ + /** - * hb_ot_color_get_palette_count: + * hb_ot_color_has_palettes: + * @face: a font face. + * + * Returns: whether CPAL table is available. + * + * Since: 2.1.0 + */ +hb_bool_t +hb_ot_color_has_palettes (hb_face_t *face) +{ + return _get_cpal (face).has_data (); +} + +/** + * hb_ot_color_palette_get_count: * @face: a font face. * * Returns: the number of color palettes in @face, or zero if @face has * no colors. * - * Since: REPLACEME + * Since: 2.1.0 */ unsigned int -hb_ot_color_get_palette_count (hb_face_t *face) +hb_ot_color_palette_get_count (hb_face_t *face) { - const OT::CPAL& cpal = _get_cpal (face); - return cpal.get_palette_count (); + return _get_cpal (face).get_palette_count (); } - /** - * hb_ot_color_get_palette_name_id: - * @face: a font face. - * @palette: the index of the color palette whose name is being requested. + * hb_ot_color_palette_get_name_id: + * @face: a font face. + * @palette_index: the index of the color palette whose name is being requested. * * Retrieves the name id of a color palette. For example, a color font can * have themed palettes like "Spring", "Summer", "Fall", and "Winter". * * Returns: an identifier within @face's `name` table. - * If the requested palette has no name, or if @face has no colors, - * or if @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is 0xFFFF. The implementation does not check whether - * the returned palette name id is actually in @face's `name` table. + * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID. * - * Since: REPLACEME + * Since: 2.1.0 */ -unsigned int -hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette) +hb_ot_name_id_t +hb_ot_color_palette_get_name_id (hb_face_t *face, + unsigned int palette_index) { - const OT::CPAL& cpal = _get_cpal (face); - return cpal.get_palette_name_id (palette); + return _get_cpal (face).get_palette_name_id (palette_index); } +/** + * hb_ot_color_palette_color_get_name_id: + * @face: a font face. + * @color_index: palette entry index. + * + * Returns: Name ID associated with a palette entry, e.g. eye color + * + * Since: 2.1.0 + */ +hb_ot_name_id_t +hb_ot_color_palette_color_get_name_id (hb_face_t *face, + unsigned int color_index) +{ + return _get_cpal (face).get_color_name_id (color_index); +} /** - * hb_ot_color_get_palette_flags: - * @face: a font face - * @palette: the index of the color palette whose flags are being requested + * hb_ot_color_palette_get_flags: + * @face: a font face + * @palette_index: the index of the color palette whose flags are being requested * - * Returns: the flags for the requested color palette. If @face has no colors, - * or if @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT. + * Returns: the flags for the requested color palette. * - * Since: REPLACEME + * Since: 2.1.0 */ hb_ot_color_palette_flags_t -hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette) +hb_ot_color_palette_get_flags (hb_face_t *face, + unsigned int palette_index) { - const OT::CPAL& cpal = _get_cpal(face); - return cpal.get_palette_flags (palette); + return _get_cpal(face).get_palette_flags (palette_index); } - /** - * hb_ot_color_get_palette_colors: + * hb_ot_color_palette_get_colors: * @face: a font face. - * @palette: the index of the color palette whose colors + * @palette_index:the index of the color palette whose colors * are being requested. * @start_offset: the index of the first color being requested. * @color_count: (inout) (optional): on input, how many colors * can be maximally stored into the @colors array; * on output, how many colors were actually stored. - * @colors: (array length=color_count) (optional): - * an array of #hb_ot_color_t records. After calling + * @colors: (array length=color_count) (out) (optional): + * an array of #hb_color_t records. After calling * this function, @colors will be filled with * the palette colors. If @colors is NULL, the function * will just return the number of total colors * without storing any actual colors; this can be used * for allocating a buffer of suitable size before calling - * hb_ot_color_get_palette_colors() a second time. + * hb_ot_color_palette_get_colors() a second time. * * Retrieves the colors in a color palette. * - * Returns: the total number of colors in the palette. All palettes in - * a font have the same number of colors. If @face has no colors, or if - * @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is zero. + * Returns: the total number of colors in the palette. + * + * Since: 2.1.0 + */ +unsigned int +hb_ot_color_palette_get_colors (hb_face_t *face, + unsigned int palette_index, + unsigned int start_offset, + unsigned int *colors_count /* IN/OUT. May be NULL. */, + hb_color_t *colors /* OUT. May be NULL. */) +{ + return _get_cpal (face).get_palette_colors (palette_index, start_offset, colors_count, colors); +} + + +/* + * COLR + */ + +/** + * hb_ot_color_has_layers: + * @face: a font face. + * + * Returns: whether COLR table is available. + * + * Since: 2.1.0 + */ +hb_bool_t +hb_ot_color_has_layers (hb_face_t *face) +{ + return _get_colr (face).has_data (); +} + +/** + * hb_ot_color_glyph_get_layers: + * @face: a font face. + * @glyph: a layered color glyph id. + * @start_offset: starting offset of layers. + * @count: (inout) (optional): gets number of layers available to be written on buffer + * and returns number of written layers. + * @layers: (array length=count) (out) (optional): layers buffer to buffer. + * + * Returns: Total number of layers a layered color glyph have. * - * Since: REPLACEME + * Since: 2.1.0 */ unsigned int -hb_ot_color_get_palette_colors (hb_face_t *face, - unsigned int palette, /* default=0 */ - unsigned int start_offset, - unsigned int *color_count /* IN/OUT */, - hb_ot_color_t *colors /* OUT */) -{ - const OT::CPAL& cpal = _get_cpal(face); - if (unlikely (palette >= cpal.numPalettes)) - { - if (color_count) *color_count = 0; - return 0; - } - - const OT::ColorRecord* crec = &cpal.offsetFirstColorRecord (&cpal); - crec += cpal.colorRecordIndices[palette]; - - unsigned int num_results = 0; - if (likely (color_count && colors)) - { - for (unsigned int i = start_offset; - i < cpal.numPaletteEntries && num_results < *color_count; ++i) - { - hb_ot_color_t* result = &colors[num_results]; - result->red = crec[i].red; - result->green = crec[i].green; - result->blue = crec[i].blue; - result->alpha = crec[i].alpha; - ++num_results; - } - } - - if (likely (color_count)) *color_count = num_results; - return cpal.numPaletteEntries; -} -#endif +hb_ot_color_glyph_get_layers (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */) +{ + return _get_colr (face).get_glyph_layers (glyph, start_offset, count, layers); +} + + +/* + * SVG + */ + +/** + * hb_ot_color_has_svg: + * @face: a font face. + * + * Check whether @face has SVG glyph images. + * + * Returns true if available, false otherwise. + * + * Since: 2.1.0 + */ +hb_bool_t +hb_ot_color_has_svg (hb_face_t *face) +{ + return _get_svg (face).has_data (); +} + +/** + * hb_ot_color_glyph_reference_svg: + * @face: a font face. + * @glyph: a svg glyph index. + * + * Get SVG document for a glyph. + * + * Returns: (transfer full): respective svg blob of the glyph, if available. + * + * Since: 2.1.0 + */ +hb_blob_t * +hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) +{ + return _get_svg (face).reference_blob_for_glyph (glyph); +} + + +/* + * PNG: CBDT or sbix + */ + +/** + * hb_ot_color_has_png: + * @face: a font face. + * + * Check whether @face has PNG glyph images (either CBDT or sbix tables). + * + * Returns true if available, false otherwise. + * + * Since: 2.1.0 + */ +hb_bool_t +hb_ot_color_has_png (hb_face_t *face) +{ + return _get_cbdt (face).has_data () || _get_sbix (face).has_data (); +} + +/** + * hb_ot_color_glyph_reference_png: + * @font: a font object, not face. upem should be set on + * that font object if one wants to get optimal png blob, otherwise + * return the biggest one + * @glyph: a glyph index. + * + * Get PNG image for a glyph. + * + * Returns: (transfer full): respective PNG blob of the glyph, if available. + * + * Since: 2.1.0 + */ +hb_blob_t * +hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph) +{ + hb_blob_t *blob = hb_blob_get_empty (); + + if (_get_sbix (font->face).has_data ()) + blob = _get_sbix (font->face).reference_png (font, glyph, nullptr, nullptr, nullptr); + + if (!blob->length && _get_cbdt (font->face).has_data ()) + blob = _get_cbdt (font->face).reference_png (font, glyph); + + return blob; +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.h new file mode 100644 index 00000000000..a4f2053291e --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color.h @@ -0,0 +1,139 @@ +/* + * Copyright © 2016 Google, Inc. + * Copyright © 2018 Khaled Hosny + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Sascha Brawer, Behdad Esfahbod + */ + +#ifndef HB_OT_H_IN +#error "Include <hb-ot.h> instead." +#endif + +#ifndef HB_OT_COLOR_H +#define HB_OT_COLOR_H + +#include "hb.h" +#include "hb-ot-name.h" + +HB_BEGIN_DECLS + + +/* + * Color palettes. + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_palettes (hb_face_t *face); + +HB_EXTERN unsigned int +hb_ot_color_palette_get_count (hb_face_t *face); + +HB_EXTERN hb_ot_name_id_t +hb_ot_color_palette_get_name_id (hb_face_t *face, + unsigned int palette_index); + +HB_EXTERN hb_ot_name_id_t +hb_ot_color_palette_color_get_name_id (hb_face_t *face, + unsigned int color_index); + +/** + * hb_ot_color_palette_flags_t: + * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special + * to note about a color palette. + * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color + * palette is appropriate to use when displaying the font on a light background such as white. + * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color + * palette is appropriate to use when displaying the font on a dark background such as black. + * + * Since: 2.1.0 + */ +typedef enum { /*< flags >*/ + HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u, + HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND = 0x00000001u, + HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND = 0x00000002u, +} hb_ot_color_palette_flags_t; + +HB_EXTERN hb_ot_color_palette_flags_t +hb_ot_color_palette_get_flags (hb_face_t *face, + unsigned int palette_index); + +HB_EXTERN unsigned int +hb_ot_color_palette_get_colors (hb_face_t *face, + unsigned int palette_index, + unsigned int start_offset, + unsigned int *color_count, /* IN/OUT. May be NULL. */ + hb_color_t *colors /* OUT. May be NULL. */); + + +/* + * Color layers. + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_layers (hb_face_t *face); + +/** + * hb_ot_color_layer_t: + * + * Pairs of glyph and color index. + * + * Since: 2.1.0 + **/ +typedef struct hb_ot_color_layer_t +{ + hb_codepoint_t glyph; + unsigned int color_index; +} hb_ot_color_layer_t; + +HB_EXTERN unsigned int +hb_ot_color_glyph_get_layers (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */); + +/* + * SVG + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_svg (hb_face_t *face); + +HB_EXTERN hb_blob_t * +hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph); + +/* + * PNG: CBDT or sbix + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_png (hb_face_t *face); + +HB_EXTERN hb_blob_t * +hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph); + + +HB_END_DECLS + +#endif /* HB_OT_COLOR_H */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc index 1bc68d36690..cbceea9b158 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.cc @@ -30,8 +30,11 @@ #include "hb-ot-glyf-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-kern-table.hh" +#include "hb-ot-name-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-color-cbdt-table.hh" +#include "hb-ot-color-sbix-table.hh" +#include "hb-ot-color-svg-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.hh index e3059221855..f3b7945bbd2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-face.hh @@ -45,6 +45,9 @@ * This is as good as any place. */ #define HB_OT_TABLES \ /* OpenType shaping. */ \ + HB_OT_ACCELERATOR(OT, GDEF) \ + HB_OT_ACCELERATOR(OT, GSUB) \ + HB_OT_ACCELERATOR(OT, GPOS) \ HB_OT_TABLE(OT, JSTF) \ HB_OT_TABLE(OT, BASE) \ /* AAT shaping. */ \ @@ -59,16 +62,21 @@ /* OpenType math. */ \ HB_OT_TABLE(OT, MATH) \ /* OpenType fundamentals. */ \ - HB_OT_ACCELERATOR(OT, GDEF) \ - HB_OT_ACCELERATOR(OT, GSUB) \ - HB_OT_ACCELERATOR(OT, GPOS) \ HB_OT_ACCELERATOR(OT, cmap) \ HB_OT_ACCELERATOR(OT, hmtx) \ HB_OT_ACCELERATOR(OT, vmtx) \ HB_OT_ACCELERATOR(OT, post) \ HB_OT_ACCELERATOR(OT, kern) \ HB_OT_ACCELERATOR(OT, glyf) \ + HB_OT_TABLE(OT, VORG) \ + HB_OT_ACCELERATOR(OT, name) \ + HB_OT_TABLE(AAT, ltag) \ + /* OpenType color fonts. */ \ + HB_OT_TABLE(OT, COLR) \ + HB_OT_TABLE(OT, CPAL) \ HB_OT_ACCELERATOR(OT, CBDT) \ + HB_OT_ACCELERATOR(OT, sbix) \ + HB_OT_ACCELERATOR(OT, SVG) \ /* */ /* Declare tables. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc index e6df038d322..33a4388cebe 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-font.cc @@ -37,7 +37,21 @@ #include "hb-ot-kern-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" +#include "hb-ot-color-sbix-table.hh" + + +/** + * SECTION:hb-ot-font + * @title: hb-ot-font + * @short_description: OpenType font implementation + * @include: hb-ot.h + * + * Functions for using OpenType fonts with hb_shape(). Not that fonts returned + * by hb_font_create() default to using these functions, so most clients would + * never need to call these functions directly. + **/ static hb_bool_t @@ -138,9 +152,15 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, *x = font->get_glyph_h_advance (glyph) / 2; + const OT::VORG &VORG = *ot_face->VORG.get (); + if (VORG.has_data ()) + { + *y = font->em_scale_y (VORG.get_y_origin (glyph)); + return true; + } + hb_glyph_extents_t extents = {0}; - bool ret = ot_face->glyf->get_extents (glyph, &extents); - if (ret) + if (ot_face->glyf->get_extents (glyph, &extents)) { const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get (); hb_position_t tsb = vmtx.get_side_bearing (glyph); @@ -163,9 +183,11 @@ hb_ot_get_glyph_extents (hb_font_t *font, void *user_data HB_UNUSED) { const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; - bool ret = ot_face->glyf->get_extents (glyph, extents); + bool ret = ot_face->sbix->get_extents (font, glyph, extents); + if (!ret) + ret = ot_face->glyf->get_extents (glyph, extents); if (!ret) - ret = ot_face->CBDT->get_extents (glyph, extents); + ret = ot_face->CBDT->get_extents (font, glyph, extents); // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh index 2145ac02b2e..9437a83d870 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh @@ -47,7 +47,7 @@ struct loca static const hb_tag_t tableTag = HB_OT_TAG_loca; - inline bool sanitize (hb_sanitize_context_t *c) const + inline bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); return_trace (true); @@ -70,7 +70,7 @@ struct glyf { static const hb_tag_t tableTag = HB_OT_TAG_glyf; - inline bool sanitize (hb_sanitize_context_t *c) const + inline bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); /* We don't check for anything specific here. The users of the diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh index 5293fdada1c..60735858468 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-hmtx-table.hh @@ -56,7 +56,7 @@ struct LongMetric template <typename T, typename H> struct hmtxvmtx { - inline bool sanitize (hb_sanitize_context_t *c) const + inline bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const { TRACE_SANITIZE (this); /* We don't check for anything specific here. The users of the @@ -199,8 +199,8 @@ struct hmtxvmtx #define USE_TYPO_METRICS (1u<<7) if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) { - ascender = os2_table->sTypoAscender; - descender = os2_table->sTypoDescender; + ascender = abs (os2_table->sTypoAscender); + descender = -abs (os2_table->sTypoDescender); line_gap = os2_table->sTypoLineGap; got_font_extents = (ascender | descender) != 0; } @@ -212,8 +212,8 @@ struct hmtxvmtx num_advances = _hea_table->numberOfLongMetrics; if (!got_font_extents) { - ascender = _hea_table->ascender; - descender = _hea_table->descender; + ascender = abs (_hea_table->ascender); + descender = -abs (_hea_table->descender); line_gap = _hea_table->lineGap; got_font_extents = (ascender | descender) != 0; } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh index 98f6a079fac..7b1d39aa0c6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh @@ -51,6 +51,14 @@ #define HB_CLOSURE_MAX_STAGES 32 #endif +#ifndef HB_MAX_SCRIPTS +#define HB_MAX_SCRIPTS 500 +#endif + +#ifndef HB_MAX_LANGSYS +#define HB_MAX_LANGSYS 2000 +#endif + namespace OT { @@ -555,6 +563,8 @@ struct Feature unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_tags /* OUT */) const { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); } + inline void add_lookup_indexes_to (hb_set_t *lookup_indexes) const + { lookupIndex.add_indexes_to (lookup_indexes); } inline const FeatureParams &get_feature_params (void) const { return this+featureParams; } @@ -858,8 +868,8 @@ struct CoverageFormat1 public: /* Older compilers need this to be public. */ struct Iter { - inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }; - inline void fini (void) {}; + inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; } + inline void fini (void) {} inline bool more (void) { return i < c->glyphArray.len; } inline void next (void) { i++; } inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; } @@ -986,7 +996,7 @@ struct CoverageFormat2 i = c->rangeRecord.len; } } - inline void fini (void) {}; + inline void fini (void) {} inline bool more (void) { return i < c->rangeRecord.len; } inline void next (void) { @@ -1106,9 +1116,9 @@ struct Coverage struct Iter { - Iter (void) : format (0), u () {}; - inline void init (const Coverage &c_) + inline Iter (const Coverage &c_) { + memset (this, 0, sizeof (*this)); format = c_.u.format; switch (format) { @@ -1117,7 +1127,6 @@ struct Coverage default: return; } } - inline void fini (void) {} inline bool more (void) { switch (format) @@ -1603,7 +1612,7 @@ struct VariationStore protected: HBUINT16 format; LOffsetTo<VarRegionList> regions; - OffsetArrayOf<VarData, HBUINT32> dataSets; + LOffsetArrayOf<VarData> dataSets; public: DEFINE_SIZE_ARRAY (8, dataSets); }; @@ -1685,7 +1694,7 @@ struct ConditionSet } protected: - OffsetArrayOf<Condition, HBUINT32> conditions; + LOffsetArrayOf<Condition> conditions; public: DEFINE_SIZE_ARRAY (2, conditions); }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh index dad6c4ea93f..399ede434d8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gpos-table.hh @@ -663,7 +663,7 @@ struct PairSet int min = 0, max = (int) count - 1; while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid); hb_codepoint_t mid_x = record->secondGlyph; if (x < mid_x) @@ -719,7 +719,7 @@ struct PairPosFormat1 inline bool intersects (const hb_set_t *glyphs) const { unsigned int count = pairSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -1715,7 +1715,7 @@ GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) } void -GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED) { //_hb_buffer_assert_gsubgpos_vars (buffer); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh index 2ce52a1b494..d24ea59afec 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsub-table.hh @@ -48,7 +48,7 @@ struct SingleSubstFormat1 inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. * https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -62,7 +62,7 @@ struct SingleSubstFormat1 { TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. * https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -110,10 +110,10 @@ struct SingleSubstFormat1 inline bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - hb_auto_t<hb_vector_t<GlyphID> > from; - hb_auto_t<hb_vector_t<GlyphID> > to; + hb_vector_t<GlyphID> from; + hb_vector_t<GlyphID> to; hb_codepoint_t delta = deltaGlyphID; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (!c->plan->glyphset->has (iter.get_glyph ())) continue; @@ -157,7 +157,7 @@ struct SingleSubstFormat2 { TRACE_CLOSURE (this); unsigned int count = substitute.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -171,7 +171,7 @@ struct SingleSubstFormat2 TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = substitute.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -216,9 +216,9 @@ struct SingleSubstFormat2 inline bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - hb_auto_t<hb_vector_t<GlyphID> > from; - hb_auto_t<hb_vector_t<GlyphID> > to; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + hb_vector_t<GlyphID> from; + hb_vector_t<GlyphID> to; + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (!c->plan->glyphset->has (iter.get_glyph ())) continue; @@ -395,7 +395,7 @@ struct MultipleSubstFormat1 { TRACE_CLOSURE (this); unsigned int count = sequence.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -585,7 +585,7 @@ struct AlternateSubstFormat1 { TRACE_CLOSURE (this); unsigned int count = alternateSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -599,7 +599,7 @@ struct AlternateSubstFormat1 TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = alternateSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -906,7 +906,7 @@ struct LigatureSubstFormat1 inline bool intersects (const hb_set_t *glyphs) const { unsigned int count = ligatureSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -921,7 +921,7 @@ struct LigatureSubstFormat1 { TRACE_CLOSURE (this); unsigned int count = ligatureSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -935,7 +935,7 @@ struct LigatureSubstFormat1 TRACE_COLLECT_GLYPHS (this); if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = ligatureSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -1114,7 +1114,7 @@ struct ReverseChainSingleSubstFormat1 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); count = substitute.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh index a4066265c77..c4af42048e8 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh @@ -93,7 +93,7 @@ struct hb_closure_context_t : hb_face_t *face; hb_set_t *glyphs; - hb_auto_t<hb_set_t> out[1]; + hb_set_t out[1]; recurse_func_t recurse_func; unsigned int nesting_level_left; unsigned int debug_depth; @@ -271,7 +271,7 @@ struct hb_ot_apply_context_t : syllable arg1(0), #undef arg1 match_func (nullptr), - match_data (nullptr) {}; + match_data (nullptr) {} typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data); @@ -1441,7 +1441,7 @@ struct ContextFormat1 }; unsigned int count = ruleSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -1462,7 +1462,7 @@ struct ContextFormat1 }; unsigned int count = ruleSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -2105,7 +2105,7 @@ struct ChainContextFormat1 }; unsigned int count = ruleSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ @@ -2126,7 +2126,7 @@ struct ChainContextFormat1 }; unsigned int count = ruleSet.len; - for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ()) + for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc index fb1d9b11f25..e135e4a9ebe 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.cc @@ -41,14 +41,20 @@ // Just so we compile them; unused otherwise: #include "hb-ot-layout-base-table.hh" #include "hb-ot-layout-jstf-table.hh" -#include "hb-ot-color-colr-table.hh" -#include "hb-ot-color-cpal-table.hh" -#include "hb-ot-color-sbix-table.hh" -#include "hb-ot-color-svg-table.hh" #include "hb-ot-kern-table.hh" #include "hb-ot-name-table.hh" +/** + * SECTION:hb-ot-layout + * @title: hb-ot-layout + * @short_description: OpenType Layout + * @include: hb-ot.h + * + * Functions for querying OpenType Layout features in the font face. + **/ + + static const OT::kern::accelerator_t& _get_kern (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::kern::accelerator_t); @@ -555,19 +561,6 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face, return l.has_required_feature (); } -static void -_hb_ot_layout_language_add_feature_indexes_to (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index, - hb_set_t *feature_indexes /* OUT */) -{ - const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); - l.add_feature_indexes_to (feature_indexes); -} - - unsigned int hb_ot_layout_language_get_feature_indexes (hb_face_t *face, hb_tag_t table_tag, @@ -665,135 +658,136 @@ unsigned int hb_ot_layout_table_get_lookup_count (hb_face_t *face, hb_tag_t table_tag) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0; - switch (table_tag) + return get_gsubgpos_table (face, table_tag).get_lookup_count (); +} + + +struct hb_collect_features_context_t +{ + hb_collect_features_context_t (hb_face_t *face, + hb_tag_t table_tag, + hb_set_t *feature_indexes_) + : g (get_gsubgpos_table (face, table_tag)), + feature_indexes (feature_indexes_), + script_count(0),langsys_count(0) {} + + bool inline visited (const OT::Script &s) { - case HB_OT_TAG_GSUB: - { - return hb_ot_face_data (face)->GSUB->lookup_count; - } - case HB_OT_TAG_GPOS: - { - return hb_ot_face_data (face)->GPOS->lookup_count; - } + /* We might have Null() object here. Don't want to involve + * that in the memoize. So, detect empty objects and return. */ + if (unlikely (!s.has_default_lang_sys () && + !s.get_lang_sys_count ())) + return true; + + if (script_count++ > HB_MAX_SCRIPTS) + return true; + + return visited (s, visited_script); } - return 0; -} + bool inline visited (const OT::LangSys &l) + { + /* We might have Null() object here. Don't want to involve + * that in the memoize. So, detect empty objects and return. */ + if (unlikely (!l.has_required_feature () && + !l.get_feature_count ())) + return true; -static void -_hb_ot_layout_collect_lookups_lookups (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index, - hb_set_t *lookup_indexes /* OUT */) -{ - unsigned int lookup_indices[32]; - unsigned int offset, len; - - offset = 0; - do { - len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookups (face, - table_tag, - feature_index, - offset, &len, - lookup_indices); - - for (unsigned int i = 0; i < len; i++) - lookup_indexes->add (lookup_indices[i]); - - offset += len; - } while (len == ARRAY_LENGTH (lookup_indices)); -} + if (langsys_count++ > HB_MAX_LANGSYS) + return true; + + return visited (l, visited_langsys); + } + + private: + template <typename T> + bool inline visited (const T &p, hb_set_t &visited_set) + { + hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) &p - (uintptr_t) &g); + if (visited_set.has (delta)) + return true; + + visited_set.add (delta); + return false; + } + + public: + const OT::GSUBGPOS &g; + hb_set_t *feature_indexes; + + private: + hb_set_t visited_script; + hb_set_t visited_langsys; + unsigned int script_count; + unsigned int langsys_count; +}; static void -_hb_ot_layout_collect_features_features (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index, - const hb_tag_t *features, - hb_set_t *feature_indexes /* OUT */) +langsys_collect_features (hb_collect_features_context_t *c, + const OT::LangSys &l, + const hb_tag_t *features) { + if (c->visited (l)) return; + if (!features) { - unsigned int required_feature_index; - if (hb_ot_layout_language_get_required_feature (face, - table_tag, - script_index, - language_index, - &required_feature_index, - nullptr)) - feature_indexes->add (required_feature_index); - - /* All features */ - _hb_ot_layout_language_add_feature_indexes_to (face, - table_tag, - script_index, - language_index, - feature_indexes); + /* All features. */ + if (l.has_required_feature ()) + c->feature_indexes->add (l.get_required_feature_index ()); + + l.add_feature_indexes_to (c->feature_indexes); } else { + /* Ugh. Any faster way? */ for (; *features; features++) { - unsigned int feature_index; - if (hb_ot_layout_language_find_feature (face, - table_tag, - script_index, - language_index, - *features, - &feature_index)) - feature_indexes->add (feature_index); + hb_tag_t feature_tag = *features; + unsigned int num_features = l.get_feature_count (); + for (unsigned int i = 0; i < num_features; i++) + { + unsigned int feature_index = l.get_feature_index (i); + + if (feature_tag == c->g.get_feature_tag (feature_index)) + { + c->feature_indexes->add (feature_index); + break; + } + } } } } static void -_hb_ot_layout_collect_features_languages (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - const hb_tag_t *languages, - const hb_tag_t *features, - hb_set_t *feature_indexes /* OUT */) -{ - _hb_ot_layout_collect_features_features (face, - table_tag, - script_index, - HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, - features, - feature_indexes); +script_collect_features (hb_collect_features_context_t *c, + const OT::Script &s, + const hb_tag_t *languages, + const hb_tag_t *features) +{ + if (c->visited (s)) return; if (!languages) { - /* All languages */ - unsigned int count = hb_ot_layout_script_get_language_tags (face, - table_tag, - script_index, - 0, nullptr, nullptr); + /* All languages. */ + if (s.has_default_lang_sys ()) + langsys_collect_features (c, + s.get_default_lang_sys (), + features); + + unsigned int count = s.get_lang_sys_count (); for (unsigned int language_index = 0; language_index < count; language_index++) - _hb_ot_layout_collect_features_features (face, - table_tag, - script_index, - language_index, - features, - feature_indexes); + langsys_collect_features (c, + s.get_lang_sys (language_index), + features); } else { for (; *languages; languages++) { unsigned int language_index; - if (hb_ot_layout_script_select_language (face, - table_tag, - script_index, - 1, - languages, - &language_index)) - _hb_ot_layout_collect_features_features (face, - table_tag, - script_index, - language_index, - features, - feature_indexes); + if (s.find_lang_sys_index (*languages, &language_index)) + langsys_collect_features (c, + s.get_lang_sys (language_index), + features); } } } @@ -811,35 +805,27 @@ hb_ot_layout_collect_features (hb_face_t *face, const hb_tag_t *features, hb_set_t *feature_indexes /* OUT */) { + hb_collect_features_context_t c (face, table_tag, feature_indexes); if (!scripts) { - /* All scripts */ - unsigned int count = hb_ot_layout_table_get_script_tags (face, - table_tag, - 0, nullptr, nullptr); + /* All scripts. */ + unsigned int count = c.g.get_script_count (); for (unsigned int script_index = 0; script_index < count; script_index++) - _hb_ot_layout_collect_features_languages (face, - table_tag, - script_index, - languages, - features, - feature_indexes); + script_collect_features (&c, + c.g.get_script (script_index), + languages, + features); } else { for (; *scripts; scripts++) { unsigned int script_index; - if (hb_ot_layout_table_find_script (face, - table_tag, - *scripts, - &script_index)) - _hb_ot_layout_collect_features_languages (face, - table_tag, - script_index, - languages, - features, - feature_indexes); + if (c.g.find_script_index (*scripts, &script_index)) + script_collect_features (&c, + c.g.get_script (script_index), + languages, + features); } } } @@ -857,10 +843,14 @@ hb_ot_layout_collect_lookups (hb_face_t *face, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */) { - hb_auto_t<hb_set_t> feature_indexes; + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + hb_set_t feature_indexes; hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes); - for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; hb_set_next (&feature_indexes, &feature_index);) - _hb_ot_layout_collect_lookups_lookups (face, table_tag, feature_index, lookup_indexes); + + for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID; + hb_set_next (&feature_indexes, &feature_index);) + g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes); } /** @@ -993,7 +983,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face, unsigned int lookup_index, hb_set_t *glyphs) { - hb_auto_t<hb_map_t> done_lookups; + hb_map_t done_lookups; OT::hb_closure_context_t c (face, glyphs, &done_lookups); const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index); @@ -1014,7 +1004,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, const hb_set_t *lookups, hb_set_t *glyphs) { - hb_auto_t<hb_map_t> done_lookups; + hb_map_t done_lookups; OT::hb_closure_context_t c (face, glyphs, &done_lookups); const OT::GSUB& gsub = _get_gsub (face); @@ -1072,12 +1062,12 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) * Since: 0.9.10 **/ hb_bool_t -hb_ot_layout_get_size_params (hb_face_t *face, - unsigned int *design_size, /* OUT. May be NULL */ - unsigned int *subfamily_id, /* OUT. May be NULL */ - unsigned int *subfamily_name_id, /* OUT. May be NULL */ - unsigned int *range_start, /* OUT. May be NULL */ - unsigned int *range_end /* OUT. May be NULL */) +hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ + hb_ot_name_id_t *subfamily_name_id, /* OUT. May be NULL */ + unsigned int *range_start, /* OUT. May be NULL */ + unsigned int *range_end /* OUT. May be NULL */) { const OT::GPOS &gpos = _get_gpos (face); const hb_tag_t tag = HB_TAG ('s','i','z','e'); @@ -1105,7 +1095,7 @@ hb_ot_layout_get_size_params (hb_face_t *face, if (design_size) *design_size = 0; if (subfamily_id) *subfamily_id = 0; - if (subfamily_name_id) *subfamily_name_id = 0; + if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID; if (range_start) *range_start = 0; if (range_end) *range_end = 0; @@ -1115,8 +1105,8 @@ hb_ot_layout_get_size_params (hb_face_t *face, /** * hb_ot_layout_feature_get_name_ids: * @face: #hb_face_t to work upon - * @table_tag: - * @feature_index: + * @table_tag: table tag to query, "GSUB" or "GPOS". + * @feature_index: index of feature to query. * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string * for a user-interface label for this feature. (May be NULL.) * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string @@ -1137,14 +1127,14 @@ hb_ot_layout_get_size_params (hb_face_t *face, * Since: 2.0.0 **/ hb_bool_t -hb_ot_layout_feature_get_name_ids (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index, - hb_name_id_t *label_id, /* OUT. May be NULL */ - hb_name_id_t *tooltip_id, /* OUT. May be NULL */ - hb_name_id_t *sample_id, /* OUT. May be NULL */ - unsigned int *num_named_parameters, /* OUT. May be NULL */ - hb_name_id_t *first_param_id /* OUT. May be NULL */) +hb_ot_layout_feature_get_name_ids (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + hb_ot_name_id_t *label_id, /* OUT. May be NULL */ + hb_ot_name_id_t *tooltip_id, /* OUT. May be NULL */ + hb_ot_name_id_t *sample_id, /* OUT. May be NULL */ + unsigned int *num_named_parameters, /* OUT. May be NULL */ + hb_ot_name_id_t *first_param_id /* OUT. May be NULL */) { const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); @@ -1160,10 +1150,10 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face, { if (label_id) *label_id = ss_params.uiNameID; // ssXX features don't have the rest - if (tooltip_id) *tooltip_id = HB_NAME_ID_INVALID; - if (sample_id) *sample_id = HB_NAME_ID_INVALID; + if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID; + if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID; if (num_named_parameters) *num_named_parameters = 0; - if (first_param_id) *first_param_id = HB_NAME_ID_INVALID; + if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID; return true; } const OT::FeatureParamsCharacterVariants& cv_params = @@ -1179,19 +1169,19 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face, } } - if (label_id) *label_id = HB_NAME_ID_INVALID; - if (tooltip_id) *tooltip_id = HB_NAME_ID_INVALID; - if (sample_id) *sample_id = HB_NAME_ID_INVALID; + if (label_id) *label_id = HB_OT_NAME_ID_INVALID; + if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID; + if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID; if (num_named_parameters) *num_named_parameters = 0; - if (first_param_id) *first_param_id = HB_NAME_ID_INVALID; + if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID; return false; } /** - * hb_ot_layout_feature_get_characters:: + * hb_ot_layout_feature_get_characters: * @face: #hb_face_t to work upon - * @table_tag: - * @feature_index: + * @table_tag: table tag to query, "GSUB" or "GPOS". + * @feature_index: index of feature to query. * @start_offset: In case the resulting char_count was equal to its input value, there * is a chance there were more characters on the tag so this API can be * called with an offset till resulting char_count gets to a number @@ -1199,7 +1189,7 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face, * one shot copying). * @char_count: (inout) (allow-none): The count of characters for which this feature * provides glyph variants. (May be zero.) - * @characters: (out) (allow-none): A buffer pointer. The Unicode Scalar Value + * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. The Unicode codepoints * of the characters for which this feature provides glyph variants. * * Fetches characters listed by designer under feature parameters for "Character diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h index 9bd18c8af6d..7a016c39082 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout.h @@ -33,7 +33,6 @@ #include "hb.h" -#include "hb-ot-tag.h" #include "hb-ot-name.h" HB_BEGIN_DECLS @@ -47,6 +46,47 @@ HB_BEGIN_DECLS /* + * Script & Language tags. + */ + +#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') +#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') + +/** + * HB_OT_MAX_TAGS_PER_SCRIPT: + * + * Since: 2.0.0 + **/ +#define HB_OT_MAX_TAGS_PER_SCRIPT 3u +/** + * HB_OT_MAX_TAGS_PER_LANGUAGE: + * + * Since: 2.0.0 + **/ +#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u + +HB_EXTERN void +hb_ot_tags_from_script_and_language (hb_script_t script, + hb_language_t language, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */, + unsigned int *language_count /* IN/OUT */, + hb_tag_t *language_tags /* OUT */); + +HB_EXTERN hb_script_t +hb_ot_tag_to_script (hb_tag_t tag); + +HB_EXTERN hb_language_t +hb_ot_tag_to_language (hb_tag_t tag); + +HB_EXTERN void +hb_ot_tags_to_script_and_language (hb_tag_t script_tag, + hb_tag_t language_tag, + hb_script_t *script /* OUT */, + hb_language_t *language /* OUT */); + + +/* * GDEF */ @@ -324,23 +364,23 @@ Xhb_ot_layout_lookup_position (hb_font_t *font, /* Optical 'size' feature info. Returns true if found. * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */ HB_EXTERN hb_bool_t -hb_ot_layout_get_size_params (hb_face_t *face, - unsigned int *design_size, /* OUT. May be NULL */ - unsigned int *subfamily_id, /* OUT. May be NULL */ - hb_name_id_t *subfamily_name_id, /* OUT. May be NULL */ - unsigned int *range_start, /* OUT. May be NULL */ - unsigned int *range_end /* OUT. May be NULL */); +hb_ot_layout_get_size_params (hb_face_t *face, + unsigned int *design_size, /* OUT. May be NULL */ + unsigned int *subfamily_id, /* OUT. May be NULL */ + hb_ot_name_id_t *subfamily_name_id, /* OUT. May be NULL */ + unsigned int *range_start, /* OUT. May be NULL */ + unsigned int *range_end /* OUT. May be NULL */); HB_EXTERN hb_bool_t -hb_ot_layout_feature_get_name_ids (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index, - hb_name_id_t *label_id /* OUT. May be NULL */, - hb_name_id_t *tooltip_id /* OUT. May be NULL */, - hb_name_id_t *sample_id /* OUT. May be NULL */, - unsigned int *num_named_parameters /* OUT. May be NULL */, - hb_name_id_t *first_param_id /* OUT. May be NULL */); +hb_ot_layout_feature_get_name_ids (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + hb_ot_name_id_t *label_id /* OUT. May be NULL */, + hb_ot_name_id_t *tooltip_id /* OUT. May be NULL */, + hb_ot_name_id_t *sample_id /* OUT. May be NULL */, + unsigned int *num_named_parameters /* OUT. May be NULL */, + hb_ot_name_id_t *first_param_id /* OUT. May be NULL */); HB_EXTERN unsigned int diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc index 45d7dbdcfa7..fd8109950ed 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.cc @@ -79,8 +79,8 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, hb_ot_map_feature_flags_t flags, unsigned int value) { - feature_info_t *info = feature_infos.push(); if (unlikely (!tag)) return; + feature_info_t *info = feature_infos.push(); info->tag = tag; info->seq = feature_infos.len; info->max_value = value; @@ -175,6 +175,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, } /* Sort features and merge duplicates */ + if (feature_infos.len) { feature_infos.qsort (); unsigned int j = 0; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh index 40b9921fd30..fde85b1ddc0 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-map.hh @@ -162,7 +162,7 @@ struct hb_ot_map_t hb_mask_t global_mask; hb_vector_t<feature_map_t, 8> features; - hb_vector_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */ + hb_vector_t<lookup_map_t, 16> lookups[2]; /* GSUB/GPOS */ hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */ }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh index 2f871124cd1..e20935972e9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math-table.hh @@ -631,7 +631,7 @@ struct MathVariants inline const MathGlyphConstruction & get_glyph_construction (hb_codepoint_t glyph, hb_direction_t direction, - hb_font_t *font) const + hb_font_t *font HB_UNUSED) const { bool vertical = HB_DIRECTION_IS_VERTICAL (direction); unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc index c693f4807be..92c29480db1 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-math.cc @@ -29,6 +29,17 @@ #include "hb-ot-face.hh" #include "hb-ot-math-table.hh" + +/** + * SECTION:hb-ot-math + * @title: hb-ot-math + * @short_description: OpenType Math information + * @include: hb-ot.h + * + * Functions for fetching mathematics layout data from OpenType fonts. + **/ + + static inline const OT::MATH& _get_math (hb_face_t *face) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh index 2572ad288f5..648f232d960 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-maxp-table.hh @@ -117,7 +117,7 @@ struct maxp return result; } - static inline void drop_hint_fields (hb_subset_plan_t *plan, maxp *maxp_prime) + static inline void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime) { if (maxp_prime->version.major == 1) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language.cc new file mode 100644 index 00000000000..0e37e0acb09 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language.cc @@ -0,0 +1,457 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-ot-name-language.hh" + +/* Following two tables were generated by joining FreeType, FontConfig, + * and OpenType specification language lists, then filled in missing + * entries using: + * https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings + */ + +struct hb_ot_language_map_t +{ + static int cmp (const void *key, const void *item) + { + unsigned int a = * (unsigned int *) key; + unsigned int b = ((const hb_ot_language_map_t *) item)->code; + return a < b ? -1 : a > b ? +1 : 0; + } + + uint16_t code; + char lang[6]; +}; + +static const hb_ot_language_map_t +hb_ms_language_map[] = +{ + {0x0001, "ar"}, /* ??? */ + {0x0004, "zh"}, /* ??? */ + {0x0009, "en"}, /* ??? */ + {0x0401, "ar"}, /* Arabic (Saudi Arabia) */ + {0x0402, "bg"}, /* Bulgarian (Bulgaria) */ + {0x0403, "ca"}, /* Catalan (Catalan) */ + {0x0404, "zh-tw"}, /* Chinese (Taiwan) */ + {0x0405, "cs"}, /* Czech (Czech Republic) */ + {0x0406, "da"}, /* Danish (Denmark) */ + {0x0407, "de"}, /* German (Germany) */ + {0x0408, "el"}, /* Greek (Greece) */ + {0x0409, "en"}, /* English (United States) */ + {0x040A, "es"}, /* Spanish (Traditional Sort) (Spain) */ + {0x040B, "fi"}, /* Finnish (Finland) */ + {0x040C, "fr"}, /* French (France) */ + {0x040D, "he"}, /* Hebrew (Israel) */ + {0x040E, "hu"}, /* Hungarian (Hungary) */ + {0x040F, "is"}, /* Icelandic (Iceland) */ + {0x0410, "it"}, /* Italian (Italy) */ + {0x0411, "ja"}, /* Japanese (Japan) */ + {0x0412, "ko"}, /* Korean (Korea) */ + {0x0413, "nl"}, /* Dutch (Netherlands) */ + {0x0414, "no"}, /* Norwegian (Bokmal) (Norway) */ + {0x0415, "pl"}, /* Polish (Poland) */ + {0x0416, "pt"}, /* Portuguese (Brazil) */ + {0x0417, "rm"}, /* Romansh (Switzerland) */ + {0x0418, "ro"}, /* Romanian (Romania) */ + {0x0419, "ru"}, /* Russian (Russia) */ + {0x041A, "hr"}, /* Croatian (Croatia) */ + {0x041B, "sk"}, /* Slovak (Slovakia) */ + {0x041C, "sq"}, /* Albanian (Albania) */ + {0x041D, "sv"}, /* Swedish (Sweden) */ + {0x041E, "th"}, /* Thai (Thailand) */ + {0x041F, "tr"}, /* Turkish (Turkey) */ + {0x0420, "ur"}, /* Urdu (Islamic Republic of Pakistan) */ + {0x0421, "id"}, /* Indonesian (Indonesia) */ + {0x0422, "uk"}, /* Ukrainian (Ukraine) */ + {0x0423, "be"}, /* Belarusian (Belarus) */ + {0x0424, "sl"}, /* Slovenian (Slovenia) */ + {0x0425, "et"}, /* Estonian (Estonia) */ + {0x0426, "lv"}, /* Latvian (Latvia) */ + {0x0427, "lt"}, /* Lithuanian (Lithuania) */ + {0x0428, "tg"}, /* Tajik (Cyrillic) (Tajikistan) */ + {0x0429, "fa"}, /* Persian (Iran) */ + {0x042A, "vi"}, /* Vietnamese (Vietnam) */ + {0x042B, "hy"}, /* Armenian (Armenia) */ + {0x042C, "az"}, /* Azeri (Latin) (Azerbaijan) */ + {0x042D, "eu"}, /* Basque (Basque) */ + {0x042E, "hsb"}, /* Upper Sorbian (Germany) */ + {0x042F, "mk"}, /* Macedonian (FYROM) (Former Yugoslav Republic of Macedonia) */ + {0x0430, "st"}, /* ??? */ + {0x0431, "ts"}, /* ??? */ + {0x0432, "tn"}, /* Setswana (South Africa) */ + {0x0433, "ven"}, /* ??? */ + {0x0434, "xh"}, /* isiXhosa (South Africa) */ + {0x0435, "zu"}, /* isiZulu (South Africa) */ + {0x0436, "af"}, /* Afrikaans (South Africa) */ + {0x0437, "ka"}, /* Georgian (Georgia) */ + {0x0438, "fo"}, /* Faroese (Faroe Islands) */ + {0x0439, "hi"}, /* Hindi (India) */ + {0x043A, "mt"}, /* Maltese (Malta) */ + {0x043B, "se"}, /* Sami (Northern) (Norway) */ + {0x043C, "ga"}, /* ??? */ + {0x043D, "yi"}, /* ??? */ + {0x043E, "ms"}, /* Malay (Malaysia) */ + {0x043F, "kk"}, /* Kazakh (Kazakhstan) */ + {0x0440, "ky"}, /* Kyrgyz (Kyrgyzstan) */ + {0x0441, "sw"}, /* Kiswahili (Kenya) */ + {0x0442, "tk"}, /* Turkmen (Turkmenistan) */ + {0x0443, "uz"}, /* Uzbek (Latin) (Uzbekistan) */ + {0x0444, "tt"}, /* Tatar (Russia) */ + {0x0445, "bn"}, /* Bengali (India) */ + {0x0446, "pa"}, /* Punjabi (India) */ + {0x0447, "gu"}, /* Gujarati (India) */ + {0x0448, "or"}, /* Odia (formerly Oriya) (India) */ + {0x0449, "ta"}, /* Tamil (India) */ + {0x044A, "te"}, /* Telugu (India) */ + {0x044B, "kn"}, /* Kannada (India) */ + {0x044C, "ml"}, /* Malayalam (India) */ + {0x044D, "as"}, /* Assamese (India) */ + {0x044E, "mr"}, /* Marathi (India) */ + {0x044F, "sa"}, /* Sanskrit (India) */ + {0x0450, "mn"}, /* Mongolian (Cyrillic) (Mongolia) */ + {0x0451, "bo"}, /* Tibetan (PRC) */ + {0x0452, "cy"}, /* Welsh (United Kingdom) */ + {0x0453, "km"}, /* Khmer (Cambodia) */ + {0x0454, "lo"}, /* Lao (Lao P.D.R.) */ + {0x0455, "my"}, /* ??? */ + {0x0456, "gl"}, /* Galician (Galician) */ + {0x0457, "kok"}, /* Konkani (India) */ + {0x0458, "mni"}, /* ??? */ + {0x0459, "sd"}, /* ??? */ + {0x045A, "syr"}, /* Syriac (Syria) */ + {0x045B, "si"}, /* Sinhala (Sri Lanka) */ + {0x045C, "chr"}, /* ??? */ + {0x045D, "iu"}, /* Inuktitut (Canada) */ + {0x045E, "am"}, /* Amharic (Ethiopia) */ + {0x0460, "ks"}, /* ??? */ + {0x0461, "ne"}, /* Nepali (Nepal) */ + {0x0462, "fy"}, /* Frisian (Netherlands) */ + {0x0463, "ps"}, /* Pashto (Afghanistan) */ + {0x0464, "phi"}, /* Filipino (Philippines) */ + {0x0465, "div"}, /* Divehi (Maldives) */ + {0x0468, "ha"}, /* Hausa (Latin) (Nigeria) */ + {0x046A, "yo"}, /* Yoruba (Nigeria) */ + {0x046B, "quz"}, /* Quechua (Bolivia) */ + {0x046C, "nso"}, /* Sesotho sa Leboa (South Africa) */ + {0x046D, "ba"}, /* Bashkir (Russia) */ + {0x046E, "lb"}, /* Luxembourgish (Luxembourg) */ + {0x046F, "kl"}, /* Greenlandic (Greenland) */ + {0x0470, "ibo"}, /* Igbo (Nigeria) */ + {0x0471, "kau"}, /* ??? */ + {0x0472, "om"}, /* ??? */ + {0x0473, "ti"}, /* ??? */ + {0x0474, "gn"}, /* ??? */ + {0x0475, "haw"}, /* ??? */ + {0x0476, "la"}, /* ??? */ + {0x0477, "so"}, /* ??? */ + {0x0478, "ii"}, /* Yi (PRC) */ + {0x0479, "pap"}, /* ??? */ + {0x047A, "arn"}, /* Mapudungun (Chile) */ + {0x047C, "moh"}, /* Mohawk (Mohawk) */ + {0x047E, "br"}, /* Breton (France) */ + {0x0480, "ug"}, /* Uighur (PRC) */ + {0x0481, "mi"}, /* Maori (New Zealand) */ + {0x0482, "oc"}, /* Occitan (France) */ + {0x0483, "co"}, /* Corsican (France) */ + {0x0484, "gsw"}, /* Alsatian (France) */ + {0x0485, "sah"}, /* Yakut (Russia) */ + {0x0486, "qut"}, /* K'iche (Guatemala) */ + {0x0487, "rw"}, /* Kinyarwanda (Rwanda) */ + {0x0488, "wo"}, /* Wolof (Senegal) */ + {0x048C, "fa"}, /* Dari (Afghanistan) */ + {0x0801, "ar"}, /* Arabic (Iraq) */ + {0x0804, "zh-cn"}, /* Chinese (People’s Republic of China) */ + {0x0807, "de"}, /* German (Switzerland) */ + {0x0809, "en"}, /* English (United Kingdom) */ + {0x080A, "es"}, /* Spanish (Mexico) */ + {0x080C, "fr"}, /* French (Belgium) */ + {0x0810, "it"}, /* Italian (Switzerland) */ + {0x0812, "ko"}, /* ??? */ + {0x0813, "nl"}, /* Dutch (Belgium) */ + {0x0814, "nn"}, /* Norwegian (Nynorsk) (Norway) */ + {0x0816, "pt"}, /* Portuguese (Portugal) */ + {0x0818, "mo"}, /* ??? */ + {0x0819, "ru"}, /* ??? */ + {0x081A, "sr"}, /* Serbian (Latin) (Serbia) */ + {0x081D, "sv"}, /* Sweden (Finland) */ + {0x0820, "ur"}, /* ??? */ + {0x0827, "lt"}, /* ??? */ + {0x082C, "az"}, /* Azeri (Cyrillic) (Azerbaijan) */ + {0x082E, "dsb"}, /* Lower Sorbian (Germany) */ +//{0x083B, ""}, /* Sami (Northern) (Sweden) */ + {0x083C, "gd"}, /* Irish (Ireland) */ + {0x083E, "ms"}, /* Malay (Brunei Darussalam) */ + {0x0843, "uz"}, /* Uzbek (Cyrillic) (Uzbekistan) */ + {0x0845, "bn"}, /* Bengali (Bangladesh) */ + {0x0846, "ar"}, /* ??? */ + {0x0850, "mn"}, /* Mongolian (Traditional) (People’s Republic of China) */ + {0x0851, "dz"}, /* ??? */ + {0x085D, "iu"}, /* Inuktitut (Latin) (Canada) */ + {0x085F, "tzm"}, /* Tamazight (Latin) (Algeria) */ + {0x0861, "ne"}, /* ??? */ +//{0x086B, ""}, /* Quechua (Ecuador) */ + {0x0873, "ti"}, /* ??? */ + {0x0C01, "ar"}, /* Arabic (Egypt) */ + {0x0C04, "zh-hk"}, /* Chinese (Hong Kong S.A.R.) */ + {0x0C07, "de"}, /* German (Austria) */ + {0x0C09, "en"}, /* English (Australia) */ + {0x0C0A, "es"}, /* Spanish (Modern Sort) (Spain) */ + {0x0C0C, "fr"}, /* French (Canada) */ + {0x0C1A, "sr"}, /* Serbian (Cyrillic) (Serbia) */ + {0x0C3B, "se"}, /* Sami (Northern) (Finland) */ +//{0x0C6B, ""}, /* Quechua (Peru) */ + {0x1001, "ar"}, /* Arabic (Libya) */ + {0x1004, "zh-sg"}, /* Chinese (Singapore) */ + {0x1007, "de"}, /* German (Luxembourg) */ + {0x1009, "en"}, /* English (Canada) */ + {0x100A, "es"}, /* Spanish (Guatemala) */ + {0x100C, "fr"}, /* French (Switzerland) */ + {0x101A, "hr"}, /* Croatian (Latin) (Bosnia and Herzegovina) */ + {0x103B, "smj"}, /* Sami (Lule) (Norway) */ + {0x1401, "ar"}, /* Arabic (Algeria) */ +//{0x1404, ""}, /* Chinese (Macao S.A.R.) */ + {0x1407, "de"}, /* German (Liechtenstein) */ + {0x1409, "en"}, /* English (New Zealand) */ + {0x140A, "es"}, /* Spanish (Costa Rica) */ + {0x140C, "fr"}, /* French (Luxembourg) */ + {0x141A, "bs"}, /* Bosnian (Latin) (Bosnia and Herzegovina) */ +//{0x143B, ""}, /* Sami (Lule) (Sweden) */ + {0x1801, "ar"}, /* Arabic (Morocco) */ + {0x1809, "en"}, /* English (Ireland) */ + {0x180A, "es"}, /* Spanish (Panama) */ + {0x180C, "fr"}, /* French (Principality of Monaco) */ +//{0x181A, ""}, /* Serbian (Latin) (Bosnia and Herzegovina) */ + {0x183B, "sma"}, /* Sami (Southern) (Norway) */ + {0x1C01, "ar"}, /* Arabic (Tunisia) */ + {0x1C09, "en"}, /* English (South Africa) */ + {0x1C0A, "es"}, /* Spanish (Dominican Republic) */ + {0x1C0C, "fr"}, /* ??? */ +//{0x1C1A, ""}, /* Serbian (Cyrillic) (Bosnia and Herzegovina) */ +//{0x1C3B, ""}, /* Sami (Southern) (Sweden) */ + {0x2001, "ar"}, /* Arabic (Oman) */ + {0x2009, "en"}, /* English (Jamaica) */ + {0x200A, "es"}, /* Spanish (Venezuela) */ + {0x200C, "fr"}, /* ??? */ + {0x201A, "bs"}, /* Bosnian (Cyrillic) (Bosnia and Herzegovina) */ + {0x203B, "sms"}, /* Sami (Skolt) (Finland) */ + {0x2401, "ar"}, /* Arabic (Yemen) */ + {0x2409, "en"}, /* English (Caribbean) */ + {0x240A, "es"}, /* Spanish (Colombia) */ + {0x240C, "fr"}, /* ??? */ + {0x243B, "smn"}, /* Sami (Inari) (Finland) */ + {0x2801, "ar"}, /* Arabic (Syria) */ + {0x2809, "en"}, /* English (Belize) */ + {0x280A, "es"}, /* Spanish (Peru) */ + {0x280C, "fr"}, /* ??? */ + {0x2C01, "ar"}, /* Arabic (Jordan) */ + {0x2C09, "en"}, /* English (Trinidad and Tobago) */ + {0x2C0A, "es"}, /* Spanish (Argentina) */ + {0x2C0C, "fr"}, /* ??? */ + {0x3001, "ar"}, /* Arabic (Lebanon) */ + {0x3009, "en"}, /* English (Zimbabwe) */ + {0x300A, "es"}, /* Spanish (Ecuador) */ + {0x300C, "fr"}, /* ??? */ + {0x3401, "ar"}, /* Arabic (Kuwait) */ + {0x3409, "en"}, /* English (Republic of the Philippines) */ + {0x340A, "es"}, /* Spanish (Chile) */ + {0x340C, "fr"}, /* ??? */ + {0x3801, "ar"}, /* Arabic (U.A.E.) */ + {0x380A, "es"}, /* Spanish (Uruguay) */ + {0x380C, "fr"}, /* ??? */ + {0x3C01, "ar"}, /* Arabic (Bahrain) */ + {0x3C09, "en"}, /* ??? */ + {0x3C0A, "es"}, /* Spanish (Paraguay) */ + {0x3C0C, "fr"}, /* ??? */ + {0x4001, "ar"}, /* Arabic (Qatar) */ + {0x4009, "en"}, /* English (India) */ + {0x400A, "es"}, /* Spanish (Bolivia) */ + {0x4409, "en"}, /* English (Malaysia) */ + {0x440A, "es"}, /* Spanish (El Salvador) */ + {0x4809, "en"}, /* English (Singapore) */ + {0x480A, "es"}, /* Spanish (Honduras) */ + {0x4C0A, "es"}, /* Spanish (Nicaragua) */ + {0x500A, "es"}, /* Spanish (Puerto Rico) */ + {0x540A, "es"}, /* Spanish (United States) */ + {0xE40A, "es"}, /* ??? */ + {0xE40C, "fr"}, /* ??? */ +}; + +static const hb_ot_language_map_t +hb_mac_language_map[] = +{ + { 0, "en"}, /* English */ + { 1, "fr"}, /* French */ + { 2, "de"}, /* German */ + { 3, "it"}, /* Italian */ + { 4, "nl"}, /* Dutch */ + { 5, "sv"}, /* Swedish */ + { 6, "es"}, /* Spanish */ + { 7, "da"}, /* Danish */ + { 8, "pt"}, /* Portuguese */ + { 9, "no"}, /* Norwegian */ + { 10, "he"}, /* Hebrew */ + { 11, "ja"}, /* Japanese */ + { 12, "ar"}, /* Arabic */ + { 13, "fi"}, /* Finnish */ + { 14, "el"}, /* Greek */ + { 15, "is"}, /* Icelandic */ + { 16, "mt"}, /* Maltese */ + { 17, "tr"}, /* Turkish */ + { 18, "hr"}, /* Croatian */ + { 19, "zh-tw"}, /* Chinese (Traditional) */ + { 20, "ur"}, /* Urdu */ + { 21, "hi"}, /* Hindi */ + { 22, "th"}, /* Thai */ + { 23, "ko"}, /* Korean */ + { 24, "lt"}, /* Lithuanian */ + { 25, "pl"}, /* Polish */ + { 26, "hu"}, /* Hungarian */ + { 27, "et"}, /* Estonian */ + { 28, "lv"}, /* Latvian */ +//{ 29, ""}, /* Sami */ + { 30, "fo"}, /* Faroese */ + { 31, "fa"}, /* Farsi/Persian */ + { 32, "ru"}, /* Russian */ + { 33, "zh-cn"}, /* Chinese (Simplified) */ + { 34, "nl"}, /* Flemish */ + { 35, "ga"}, /* Irish Gaelic */ + { 36, "sq"}, /* Albanian */ + { 37, "ro"}, /* Romanian */ + { 38, "cs"}, /* Czech */ + { 39, "sk"}, /* Slovak */ + { 40, "sl"}, /* Slovenian */ + { 41, "yi"}, /* Yiddish */ + { 42, "sr"}, /* Serbian */ + { 43, "mk"}, /* Macedonian */ + { 44, "bg"}, /* Bulgarian */ + { 45, "uk"}, /* Ukrainian */ + { 46, "be"}, /* Byelorussian */ + { 47, "uz"}, /* Uzbek */ + { 48, "kk"}, /* Kazakh */ + { 49, "az"}, /* Azerbaijani (Cyrillic script) */ + { 50, "az"}, /* Azerbaijani (Arabic script) */ + { 51, "hy"}, /* Armenian */ + { 52, "ka"}, /* Georgian */ + { 53, "mo"}, /* Moldavian */ + { 54, "ky"}, /* Kirghiz */ + { 55, "tg"}, /* Tajiki */ + { 56, "tk"}, /* Turkmen */ + { 57, "mn"}, /* Mongolian (Mongolian script) */ + { 58, "mn"}, /* Mongolian (Cyrillic script) */ + { 59, "ps"}, /* Pashto */ + { 60, "ku"}, /* Kurdish */ + { 61, "ks"}, /* Kashmiri */ + { 62, "sd"}, /* Sindhi */ + { 63, "bo"}, /* Tibetan */ + { 64, "ne"}, /* Nepali */ + { 65, "sa"}, /* Sanskrit */ + { 66, "mr"}, /* Marathi */ + { 67, "bn"}, /* Bengali */ + { 68, "as"}, /* Assamese */ + { 69, "gu"}, /* Gujarati */ + { 70, "pa"}, /* Punjabi */ + { 71, "or"}, /* Oriya */ + { 72, "ml"}, /* Malayalam */ + { 73, "kn"}, /* Kannada */ + { 74, "ta"}, /* Tamil */ + { 75, "te"}, /* Telugu */ + { 76, "si"}, /* Sinhalese */ + { 77, "my"}, /* Burmese */ + { 78, "km"}, /* Khmer */ + { 79, "lo"}, /* Lao */ + { 80, "vi"}, /* Vietnamese */ + { 81, "id"}, /* Indonesian */ + { 82, "tl"}, /* Tagalog */ + { 83, "ms"}, /* Malay (Roman script) */ + { 84, "ms"}, /* Malay (Arabic script) */ + { 85, "am"}, /* Amharic */ + { 86, "ti"}, /* Tigrinya */ + { 87, "om"}, /* Galla */ + { 88, "so"}, /* Somali */ + { 89, "sw"}, /* Swahili */ + { 90, "rw"}, /* Kinyarwanda/Ruanda */ + { 91, "rn"}, /* Rundi */ + { 92, "ny"}, /* Nyanja/Chewa */ + { 93, "mg"}, /* Malagasy */ + { 94, "eo"}, /* Esperanto */ + {128, "cy"}, /* Welsh */ + {129, "eu"}, /* Basque */ + {130, "ca"}, /* Catalan */ + {131, "la"}, /* Latin */ + {132, "qu"}, /* Quechua */ + {133, "gn"}, /* Guarani */ + {134, "ay"}, /* Aymara */ + {135, "tt"}, /* Tatar */ + {136, "ug"}, /* Uighur */ + {137, "dz"}, /* Dzongkha */ + {138, "jw"}, /* Javanese (Roman script) */ + {139, "su"}, /* Sundanese (Roman script) */ + {140, "gl"}, /* Galician */ + {141, "af"}, /* Afrikaans */ + {142, "br"}, /* Breton */ + {143, "iu"}, /* Inuktitut */ + {144, "gd"}, /* Scottish Gaelic */ + {145, "gv"}, /* Manx Gaelic */ + {146, "ga"}, /* Irish Gaelic (with dot above) */ + {147, "to"}, /* Tongan */ + {148, "el"}, /* Greek (polytonic) */ + {149, "ik"}, /* Greenlandic */ + {150, "az"}, /* Azerbaijani (Roman script) */ +}; + + +static hb_language_t +_hb_ot_name_language_for (unsigned int code, + const hb_ot_language_map_t *array, + unsigned int len) +{ + const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *) + hb_bsearch (&code, + array, + len, + sizeof (array[0]), + hb_ot_language_map_t::cmp); + + if (entry) + return hb_language_from_string (entry->lang, -1); + + return HB_LANGUAGE_INVALID; +} + +hb_language_t +_hb_ot_name_language_for_ms_code (unsigned int code) +{ + return _hb_ot_name_language_for (code, + hb_ms_language_map, + ARRAY_LENGTH (hb_ms_language_map)); +} + +hb_language_t +_hb_ot_name_language_for_mac_code (unsigned int code) +{ + return _hb_ot_name_language_for (code, + hb_mac_language_map, + ARRAY_LENGTH (hb_mac_language_map)); +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language.hh new file mode 100644 index 00000000000..903076c0d56 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-language.hh @@ -0,0 +1,40 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_NAME_LANGUAGE_HH +#define HB_OT_NAME_LANGUAGE_HH + +#include "hb.hh" + + +HB_INTERNAL hb_language_t +_hb_ot_name_language_for_ms_code (unsigned int code); + +HB_INTERNAL hb_language_t +_hb_ot_name_language_for_mac_code (unsigned int code); + + +#endif /* HB_OT_NAME_LANGUAGE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh index bb49c2cb0d2..9f67b5745b3 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name-table.hh @@ -28,34 +28,69 @@ #define HB_OT_NAME_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-name-language.hh" +#include "hb-aat-layout.hh" namespace OT { +#define entry_score var.u16[0] +#define entry_index var.u16[1] + + /* * name -- Naming * https://docs.microsoft.com/en-us/typography/opentype/spec/name */ #define HB_OT_TAG_name HB_TAG('n','a','m','e') +#define UNSUPPORTED 42 struct NameRecord { - static int cmp (const void *pa, const void *pb) + inline hb_language_t language (hb_face_t *face) const { - const NameRecord *a = (const NameRecord *) pa; - const NameRecord *b = (const NameRecord *) pb; - int ret; - ret = b->platformID.cmp (a->platformID); - if (ret) return ret; - ret = b->encodingID.cmp (a->encodingID); - if (ret) return ret; - ret = b->languageID.cmp (a->languageID); - if (ret) return ret; - ret = b->nameID.cmp (a->nameID); - if (ret) return ret; - return 0; + unsigned int p = platformID; + unsigned int l = languageID; + + if (p == 3) + return _hb_ot_name_language_for_ms_code (l); + + if (p == 1) + return _hb_ot_name_language_for_mac_code (l); + + if (p == 0) + return _hb_aat_language_get (face, l); + + return HB_LANGUAGE_INVALID; + } + + inline uint16_t score (void) const + { + /* Same order as in cmap::find_best_subtable(). */ + unsigned int p = platformID; + unsigned int e = encodingID; + + /* 32-bit. */ + if (p == 3 && e == 10) return 0; + if (p == 0 && e == 6) return 1; + if (p == 0 && e == 4) return 2; + + /* 16-bit. */ + if (p == 3 && e == 1) return 3; + if (p == 0 && e == 3) return 4; + if (p == 0 && e == 2) return 5; + if (p == 0 && e == 1) return 6; + if (p == 0 && e == 0) return 7; + + /* Symbol. */ + if (p == 3 && e == 0) return 8; + + /* We treat all Mac Latin names as ASCII only. */ + if (p == 1 && e == 0) return 10; /* 10 is magic number :| */ + + return UNSUPPORTED; } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const @@ -75,39 +110,57 @@ struct NameRecord DEFINE_SIZE_STATIC (12); }; +static int +_hb_ot_name_entry_cmp_key (const void *pa, const void *pb) +{ + const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa; + const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb; + + /* Compare by name_id, then language. */ + + if (a->name_id != b->name_id) + return a->name_id < b->name_id ? -1 : +1; + + if (a->language == b->language) return 0; + if (!a->language) return -1; + if (!b->language) return +1; + return strcmp (hb_language_to_string (a->language), + hb_language_to_string (b->language)); +} + +static int +_hb_ot_name_entry_cmp (const void *pa, const void *pb) +{ + /* Compare by name_id, then language, then score, then index. */ + + int v = _hb_ot_name_entry_cmp_key (pa, pb); + if (v) + return v; + + const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa; + const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb; + + if (a->entry_score != b->entry_score) + return a->entry_score < b->entry_score ? -1 : +1; + + if (a->entry_index != b->entry_index) + return a->entry_index < b->entry_index ? -1 : +1; + + return 0; +} + struct name { static const hb_tag_t tableTag = HB_OT_TAG_name; - inline unsigned int get_name (unsigned int platform_id, - unsigned int encoding_id, - unsigned int language_id, - unsigned int name_id, - void *buffer, - unsigned int buffer_length) const - { - NameRecord key; - key.platformID.set (platform_id); - key.encodingID.set (encoding_id); - key.languageID.set (language_id); - key.nameID.set (name_id); - NameRecord *match = (NameRecord *) bsearch (&key, nameRecordZ.arrayZ, count, sizeof (nameRecordZ[0]), NameRecord::cmp); - - if (!match) - return 0; - - unsigned int length = MIN (buffer_length, (unsigned int) match->length); - memcpy (buffer, (char *) this + stringOffset + match->offset, length); - return length; - } - inline unsigned int get_size (void) const { return min_size + count * nameRecordZ[0].min_size; } inline bool sanitize_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - char *string_pool = (char *) this + stringOffset; + const void *string_pool = (this+stringOffset).arrayZ; unsigned int _count = count; + /* Move to run-time?! */ for (unsigned int i = 0; i < _count; i++) if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false); return_trace (true); @@ -119,19 +172,107 @@ struct name return_trace (c->check_struct (this) && likely (format == 0 || format == 1) && c->check_array (nameRecordZ.arrayZ, count) && - sanitize_records (c)); + c->check_range (this, stringOffset)); } + struct accelerator_t + { + inline void init (hb_face_t *face) + { + this->blob = hb_sanitize_context_t().reference_table<name> (face); + this->table = this->blob->as<name> (); + assert (this->blob->length >= this->table->stringOffset); + this->pool = (this->table+this->table->stringOffset).arrayZ; + this->pool_len = this->blob->length - this->table->stringOffset; + const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ, + this->table->count); + + this->names.init (); + this->names.alloc (all_names.len); + + for (uint16_t i = 0; i < all_names.len; i++) + { + hb_ot_name_entry_t *entry = this->names.push (); + + entry->name_id = all_names[i].nameID; + entry->language = all_names[i].language (face); + entry->entry_score = all_names[i].score (); + entry->entry_index = i; + } + + this->names.qsort (_hb_ot_name_entry_cmp); + /* Walk and pick best only for each name_id,language pair, + * while dropping unsupported encodings. */ + unsigned int j = 0; + for (unsigned int i = 0; i < this->names.len; i++) + { + if (this->names[i].entry_score == UNSUPPORTED || + this->names[i].language == HB_LANGUAGE_INVALID) + continue; + if (i && + this->names[i - 1].name_id == this->names[i].name_id && + this->names[i - 1].language == this->names[i].language) + continue; + this->names[j++] = this->names[i]; + } + this->names.resize (j); + } + + inline void fini (void) + { + this->names.fini (); + hb_blob_destroy (this->blob); + } + + inline int get_index (hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *width=nullptr) const + { + const hb_ot_name_entry_t key = {name_id, {0}, language}; + const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *) + hb_bsearch (&key, + this->names.arrayZ(), + this->names.len, + sizeof (key), + _hb_ot_name_entry_cmp_key); + if (!entry) + return -1; + + if (width) + *width = entry->entry_score < 10 ? 2 : 1; + + return entry->entry_index; + } + + inline hb_bytes_t get_name (unsigned int idx) const + { + const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count); + const NameRecord &record = all_names[idx]; + const hb_array_t<const char> string_pool ((const char *) pool, pool_len); + return string_pool.sub_array (record.offset, record.length).as_bytes (); + } + + private: + hb_blob_t *blob; + const void *pool; + unsigned int pool_len; + public: + const name *table; + hb_vector_t<hb_ot_name_entry_t> names; + }; + /* We only implement format 0 for now. */ HBUINT16 format; /* Format selector (=0/1). */ HBUINT16 count; /* Number of name records. */ - Offset16 stringOffset; /* Offset to start of string storage (from start of table). */ + OffsetTo<UnsizedArrayOf<HBUINT8>, HBUINT16, false> + stringOffset; /* Offset to start of string storage (from start of table). */ UnsizedArrayOf<NameRecord> nameRecordZ; /* The name records where count is the number of records. */ public: DEFINE_SIZE_ARRAY (6, nameRecordZ); }; +struct name_accelerator_t : name::accelerator_t {}; } /* namespace OT */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.cc new file mode 100644 index 00000000000..e0c97108757 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.cc @@ -0,0 +1,231 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb.hh" + +#include "hb-ot-name-table.hh" + +#include "hb-ot-face.hh" +#include "hb-utf.hh" + + +/** + * SECTION:hb-ot-name + * @title: hb-ot-name + * @short_description: OpenType font name information + * @include: hb-ot.h + * + * Functions for fetching name strings from OpenType fonts. + **/ + + +static inline const OT::name_accelerator_t& +_get_name (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::name_accelerator_t); + return *(hb_ot_face_data (face)->name.get ()); +} + +/** + * hb_ot_name_list_names: + * @face: font face. + * @num_entries: (out): number of returned entries. + * + * Enumerates all available name IDs and language combinations. Returned + * array is owned by the @face and should not be modified. It can be + * used as long as @face is alive. + * + * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries. + * Since: 2.1.0 + **/ +const hb_ot_name_entry_t * +hb_ot_name_list_names (hb_face_t *face, + unsigned int *num_entries /* OUT */) +{ + const OT::name_accelerator_t &name = _get_name (face); + *num_entries = name.names.len; + return name.names.arrayZ(); +} + + +template <typename in_utf_t, typename out_utf_t> +static inline unsigned int +hb_ot_name_convert_utf (const hb_bytes_t *bytes, + unsigned int *text_size /* IN/OUT */, + typename out_utf_t::codepoint_t *text /* OUT */) +{ + unsigned int src_len = bytes->len / sizeof (typename in_utf_t::codepoint_t); + const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes->arrayZ; + const typename in_utf_t::codepoint_t *src_end = src + src_len; + + typename out_utf_t::codepoint_t *dst = text; + + hb_codepoint_t unicode; + const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; + + if (text_size && *text_size) + { + (*text_size)--; /* Same room for NUL-termination. */ + const typename out_utf_t::codepoint_t *dst_end = text + *text_size; + + while (src < src_end && dst < dst_end) + { + const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement); + typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode); + if (dst_next == dst) + break; /* Out-of-room. */ + + dst = dst_next; + src = src_next; + }; + + *text_size = dst - text; + *dst = 0; /* NUL-terminate. */ + } + + /* Accumulate length of rest. */ + unsigned int dst_len = dst - text; + while (src < src_end) + { + src = in_utf_t::next (src, src_end, &unicode, replacement); + dst_len += out_utf_t::encode_len (unicode); + }; + return dst_len; +} + +template <typename utf_t> +static inline unsigned int +hb_ot_name_get_utf (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + typename utf_t::codepoint_t *text /* OUT */) +{ + const OT::name_accelerator_t &name = _get_name (face); + + if (!language) + language = hb_language_from_string ("en", 2); + + unsigned int width; + int idx = name.get_index (name_id, language, &width); + if (idx != -1) + { + hb_bytes_t bytes = name.get_name (idx); + + if (width == 2) /* UTF16-BE */ + return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (&bytes, text_size, text); + + if (width == 1) /* ASCII */ + return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (&bytes, text_size, text); + } + + if (text_size) + { + if (*text_size) + *text = 0; + *text_size = 0; + } + return 0; +} + +/** + * hb_ot_name_get_utf8: + * @face: font face. + * @name_id: OpenType name identifier to fetch. + * @language: language to fetch the name for. + * @text_size: (inout) (allow-none): input size of @text buffer, and output size of + * text written to buffer. + * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. + * + * Fetches a font name from the OpenType 'name' table. + * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed. + * Returns string in UTF-8 encoding. + * + * Returns: full length of the requested string, or 0 if not found. + * Since: 2.1.0 + **/ +unsigned int +hb_ot_name_get_utf8 (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + char *text /* OUT */) +{ + return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size, + (hb_utf8_t::codepoint_t *) text); +} + +/** + * hb_ot_name_get_utf16: + * @face: font face. + * @name_id: OpenType name identifier to fetch. + * @language: language to fetch the name for. + * @text_size: (inout) (allow-none): input size of @text buffer, and output size of + * text written to buffer. + * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. + * + * Fetches a font name from the OpenType 'name' table. + * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed. + * Returns string in UTF-16 encoding. + * + * Returns: full length of the requested string, or 0 if not found. + * Since: 2.1.0 + **/ +unsigned int +hb_ot_name_get_utf16 (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + uint16_t *text /* OUT */) +{ + return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text); +} + +/** + * hb_ot_name_get_utf32: + * @face: font face. + * @name_id: OpenType name identifier to fetch. + * @language: language to fetch the name for. + * @text_size: (inout) (allow-none): input size of @text buffer, and output size of + * text written to buffer. + * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. + * + * Fetches a font name from the OpenType 'name' table. + * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed. + * Returns string in UTF-32 encoding. + * + * Returns: full length of the requested string, or 0 if not found. + * Since: 2.1.0 + **/ +unsigned int +hb_ot_name_get_utf32 (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + uint32_t *text /* OUT */) +{ + return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text); +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.h index 49423e87cc8..8b831688427 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-name.h @@ -35,18 +35,94 @@ HB_BEGIN_DECLS /** - * hb_name_id_t: + * hb_ot_name_id_t: + * @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID. + * + * An integral type representing an OpenType 'name' table name identifier. + * There are predefined name IDs, as well as name IDs return from other + * API. These can be used to fetch name strings from a font face. * * Since: 2.0.0 - */ -typedef unsigned int hb_name_id_t; + **/ +enum +{ + HB_OT_NAME_ID_COPYRIGHT = 0, + HB_OT_NAME_ID_FONT_FAMILY = 1, + HB_OT_NAME_ID_FONT_SUBFAMILY = 2, + HB_OT_NAME_ID_UNIQUE_ID = 3, + HB_OT_NAME_ID_FULL_NAME = 4, + HB_OT_NAME_ID_VERSION_STRING = 5, + HB_OT_NAME_ID_POSTSCRIPT_NAME = 6, + HB_OT_NAME_ID_TRADEMARK = 7, + HB_OT_NAME_ID_MANUFACTURER = 8, + HB_OT_NAME_ID_DESIGNER = 9, + HB_OT_NAME_ID_DESCRIPTION = 10, + HB_OT_NAME_ID_VENDOR_URL = 11, + HB_OT_NAME_ID_DESIGNER_URL = 12, + HB_OT_NAME_ID_LICENSE = 13, + HB_OT_NAME_ID_LICENSE_URL = 14, +/*HB_OT_NAME_ID_RESERVED = 15,*/ + HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY = 16, + HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY = 17, + HB_OT_NAME_ID_MAC_FULL_NAME = 18, + HB_OT_NAME_ID_SAMPLE_TEXT = 19, + HB_OT_NAME_ID_CID_FINDFONT_NAME = 20, + HB_OT_NAME_ID_WWS_FAMILY = 21, + HB_OT_NAME_ID_WWS_SUBFAMILY = 22, + HB_OT_NAME_ID_LIGHT_BACKGROUND = 23, + HB_OT_NAME_ID_DARK_BACKGROUND = 24, + HB_OT_NAME_ID_VARIATIONS_PS_PREFIX = 25, + + HB_OT_NAME_ID_INVALID = 0xFFFF, +}; + +typedef unsigned int hb_ot_name_id_t; + /** - * HB_NAME_ID_INVALID + * hb_ot_name_entry_t: + * @name_id: name ID + * @language: language * - * Since: 2.0.0 + * Structure representing a name ID in a particular language. + * + * Since: 2.1.0 **/ -#define HB_NAME_ID_INVALID 0xFFFF +typedef struct hb_ot_name_entry_t +{ + hb_ot_name_id_t name_id; + /*< private >*/ + hb_var_int_t var; + /*< public >*/ + hb_language_t language; +} hb_ot_name_entry_t; + +HB_EXTERN const hb_ot_name_entry_t * +hb_ot_name_list_names (hb_face_t *face, + unsigned int *num_entries /* OUT */); + + +HB_EXTERN unsigned int +hb_ot_name_get_utf8 (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + char *text /* OUT */); + +HB_EXTERN unsigned int +hb_ot_name_get_utf16 (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + uint16_t *text /* OUT */); + +HB_EXTERN unsigned int +hb_ot_name_get_utf32 (hb_face_t *face, + hb_ot_name_id_t name_id, + hb_language_t language, + unsigned int *text_size /* IN/OUT */, + uint32_t *text /* OUT */); + HB_END_DECLS diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh index 19780088a7a..b0ccd00d7b6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-os2-unicode-ranges.hh @@ -34,7 +34,7 @@ namespace OT { struct OS2Range { static int - cmp (const void *_key, const void *_item, void *_arg) + cmp (const void *_key, const void *_item) { hb_codepoint_t cp = *((hb_codepoint_t *) _key); const OS2Range *range = (OS2Range *) _item; @@ -233,10 +233,10 @@ static const OS2Range _hb_os2_unicode_ranges[] = static unsigned int _hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp) { - OS2Range *range = (OS2Range*) hb_bsearch_r (&cp, _hb_os2_unicode_ranges, - ARRAY_LENGTH (_hb_os2_unicode_ranges), - sizeof (OS2Range), - OS2Range::cmp, nullptr); + OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges, + ARRAY_LENGTH (_hb_os2_unicode_ranges), + sizeof (OS2Range), + OS2Range::cmp); if (range != nullptr) return range->bit; return -1; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh index 2aa0367280a..eeb2da85f75 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic-fallback.hh @@ -194,8 +194,6 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, struct arabic_fallback_plan_t { - ASSERT_POD (); - unsigned int num_lookups; bool free_lookups; @@ -220,9 +218,9 @@ struct ManifestLookup typedef OT::ArrayOf<ManifestLookup> Manifest; static bool -arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, - const hb_ot_shape_plan_t *plan, - hb_font_t *font) +arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED, + const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED) { #ifdef HB_WITH_WIN1256 /* Does this font look like it's Windows-1256-encoded? */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc index b56443910de..8e56dde3d7f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-arabic.cc @@ -243,8 +243,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) struct arabic_shape_plan_t { - ASSERT_POD (); - /* The "+ 1" in the next array is to accommodate for the "NONE" command, * which is not an OpenType feature, but this simplifies the code by not * having to do a "if (... < NONE) ..." and just rely on the fact that @@ -416,7 +414,7 @@ retry: static void record_stch (const hb_ot_shape_plan_t *plan, - hb_font_t *font, + hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data; @@ -440,7 +438,7 @@ record_stch (const hb_ot_shape_plan_t *plan, } static void -apply_stch (const hb_ot_shape_plan_t *plan, +apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, hb_font_t *font) { @@ -626,7 +624,7 @@ info_is_mcm (const hb_glyph_info_t &info) } static void -reorder_marks_arabic (const hb_ot_shape_plan_t *plan, +reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, unsigned int start, unsigned int end) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc index 9595402582e..e143867e13a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-hangul.cc @@ -70,8 +70,6 @@ override_features_hangul (hb_ot_shape_planner_t *plan) struct hangul_shape_plan_t { - ASSERT_POD (); - hb_mask_t mask_array[HANGUL_FEATURE_COUNT]; }; @@ -128,7 +126,7 @@ is_zero_width_char (hb_font_t *font, } static void -preprocess_text_hangul (const hb_ot_shape_plan_t *plan, +preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, hb_font_t *font) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc index f1ae303adcc..4f98f748024 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-indic.cc @@ -25,6 +25,7 @@ */ #include "hb-ot-shape-complex-indic.hh" +#include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-layout.hh" @@ -115,7 +116,8 @@ indic_features[] = {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS}, /* * Other features. - * These features are applied all at once, after final_reordering. + * These features are applied all at once, after final_reordering + * but before clearing syllables. * Default Bengali font in Windows for example has intermixed * lookups for init,pres,abvs,blws features. */ @@ -250,8 +252,6 @@ struct would_substitute_feature_t struct indic_shape_plan_t { - ASSERT_POD (); - inline bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const { hb_codepoint_t glyph = virama_glyph.get_relaxed (); @@ -331,275 +331,6 @@ data_destroy_indic (void *data) free (data); } -static void -_output_with_dotted_circle (hb_buffer_t *buffer) -{ - hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); - _hb_glyph_info_reset_continuation (&dottedcircle); - - buffer->next_glyph (); -} - -static void -preprocess_text_indic (const hb_ot_shape_plan_t *plan, - hb_buffer_t *buffer, - hb_font_t *font) -{ - /* UGLY UGLY UGLY business of adding dotted-circle in the middle of - * vowel-sequences that look like another vowel. Data for each script - * collected from Unicode 11 book, tables named "Vowel Letters" with - * "Use" and "Do Not Use" columns. - * - * https://github.com/harfbuzz/harfbuzz/issues/1019 - */ - bool processed = false; - buffer->clear_output (); - unsigned int count = buffer->len; - switch ((unsigned) buffer->props.script) - { - case HB_SCRIPT_DEVANAGARI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0905u: - switch (buffer->cur(1).codepoint) - { - case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: - case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: - case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: - matched = true; - break; - } - break; - case 0x0906u: - switch (buffer->cur(1).codepoint) - { - case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: - case 0x0948u: - matched = true; - break; - } - break; - case 0x0909u: - switch (buffer->cur(1).codepoint) - { - case 0x0941u: - matched = true; - break; - } - break; - case 0x090Fu: - switch (buffer->cur(1).codepoint) - { - case 0x0945u: case 0x0946u: case 0x0947u: - matched = true; - break; - } - break; - case 0x0930u: - if (0x094Du == buffer->cur(1).codepoint && - buffer->idx + 2 < count && - 0x0907u == buffer->cur(2).codepoint) - { - buffer->next_glyph (); - buffer->next_glyph (); - buffer->output_glyph (0x25CCu); - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_BENGALI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0985u: - matched = 0x09BE == buffer->cur(1).codepoint; - break; - case 0x098Bu: - matched = 0x09C3 == buffer->cur(1).codepoint; - break; - case 0x098Cu: - matched = 0x09E2 == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_GURMUKHI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0A05u: - switch (buffer->cur(1).codepoint) - { - case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: - matched = true; - break; - } - break; - case 0x0A72u: - switch (buffer->cur(1).codepoint) - { - case 0x0A3Fu: case 0x0A40u: case 0x0A47u: - matched = true; - break; - } - break; - case 0x0A73u: - switch (buffer->cur(1).codepoint) - { - case 0x0A41u: case 0x0A42u: case 0x0A4Bu: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_GUJARATI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0A85u: - switch (buffer->cur(1).codepoint) - { - case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: - case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: - matched = true; - break; - } - break; - case 0x0AC5u: - matched = 0x0ABE == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_ORIYA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0B05u: - matched = 0x0B3E == buffer->cur(1).codepoint; - break; - case 0x0B0Fu: case 0x0B13u: - matched = 0x0B57 == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_TELUGU: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0C12u: - switch (buffer->cur(1).codepoint) - { - case 0x0C4Cu: case 0x0C55u: - matched = true; - break; - } - break; - case 0x0C3Fu: case 0x0C46u: case 0xC4Au: - matched = 0x0C55 == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_KANNADA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0C89u: case 0x0C8Bu: - matched = 0x0CBE == buffer->cur(1).codepoint; - break; - case 0x0C92u: - matched = 0x0CCC == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_MALAYALAM: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0D07u: case 0x0D09u: - matched = 0x0D57 == buffer->cur(1).codepoint; - break; - case 0x0D0Eu: - matched = 0x0D46 == buffer->cur(1).codepoint; - break; - case 0x0D12u: - switch (buffer->cur(1).codepoint) - { - case 0x0D3Eu: case 0x0D57u: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - default: - break; - } - if (processed) - { - if (buffer->idx < count) - buffer->next_glyph (); - if (likely (buffer->successful)) - buffer->swap_buffers (); - } -} - static indic_position_t consonant_position_from_face (const indic_shape_plan_t *indic_plan, const hb_codepoint_t consonant, @@ -1055,8 +786,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * * We could use buffer->sort() for this, if there was no special * reordering of pre-base stuff happening later... + * We don't want to merge_clusters all of that, which buffer->sort() + * would. */ - if (indic_plan->is_old_spec || end - base > 127) + if (indic_plan->is_old_spec || end - start > 127) buffer->merge_clusters (base, end); else { @@ -1785,6 +1518,14 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, } +static void +preprocess_text_indic (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + _hb_preprocess_text_vowel_constraints (plan, buffer, font); +} + static bool decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-khmer.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-khmer.cc index 88d16267b39..1142da3ec3b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-khmer.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-khmer.cc @@ -46,7 +46,7 @@ khmer_features[] = {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS}, /* * Other features. - * These features are applied all at once. + * These features are applied all at once after clearing syllables. */ {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS}, {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS}, @@ -174,8 +174,6 @@ struct would_substitute_feature_t struct khmer_shape_plan_t { - ASSERT_POD (); - inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const { hb_codepoint_t glyph = virama_glyph; @@ -267,7 +265,7 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, static void reorder_consonant_syllable (const hb_ot_shape_plan_t *plan, - hb_face_t *face, + hb_face_t *face HB_UNUSED, hb_buffer_t *buffer, unsigned int start, unsigned int end) { @@ -438,8 +436,6 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { - /* TODO: In USE, we clear syllables right after reorder. Figure out - * what Uniscribe does. */ hb_glyph_info_t *info = buffer->info; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc index e201a230938..dcada261ce5 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-myanmar.cc @@ -36,7 +36,7 @@ basic_features[] = { /* * Basic features. - * These features are applied in order, one at a time, after initial_reordering. + * These features are applied in order, one at a time, after reordering. */ HB_TAG('r','p','h','f'), HB_TAG('p','r','e','f'), @@ -48,7 +48,7 @@ other_features[] = { /* * Other features. - * These features are applied all at once, after final_reordering. + * These features are applied all at once, after clearing syllables. */ HB_TAG('p','r','e','s'), HB_TAG('a','b','v','s'), @@ -80,13 +80,13 @@ setup_syllables (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +reorder (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +clear_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_myanmar (hb_ot_shape_planner_t *plan) @@ -102,7 +102,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) map->enable_feature (HB_TAG('c','c','m','p')); - map->add_gsub_pause (initial_reordering); + map->add_gsub_pause (reorder); for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) { @@ -110,7 +110,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) map->add_gsub_pause (nullptr); } - map->add_gsub_pause (final_reordering); + map->add_gsub_pause (clear_syllables); for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) map->enable_feature (other_features[i], F_MANUAL_ZWJ); @@ -274,8 +274,8 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer, } static void -initial_reordering_syllable (const hb_ot_shape_plan_t *plan, - hb_face_t *face, +initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, hb_buffer_t *buffer, unsigned int start, unsigned int end) { @@ -348,30 +348,28 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +reorder (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { insert_dotted_circles (plan, font, buffer); foreach_syllable (buffer, start, end) initial_reordering_syllable (plan, font->face, buffer, start, end); + + HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); + HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); } static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { hb_glyph_info_t *info = buffer->info; unsigned int count = buffer->len; - - /* Zero syllables now... */ for (unsigned int i = 0; i < count; i++) info[i].syllable() = 0; - - HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); - HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc index f9a580ca207..3ab77fc5860 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use.cc @@ -28,6 +28,7 @@ #include "hb-ot-shape-complex-use.hh" #include "hb-ot-shape-complex-arabic.hh" +#include "hb-ot-shape-complex-vowel-constraints.hh" /* buffer var allocations */ #define use_category() complex_var_u8_0() @@ -79,7 +80,8 @@ other_features[] = { /* * Other features. - * These features are applied all at once, after reordering. + * These features are applied all at once, after reordering and + * clearing syllables. */ HB_TAG('a','b','v','s'), HB_TAG('b','l','w','s'), @@ -119,6 +121,10 @@ static void reorder (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +static void +clear_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_use (hb_ot_shape_planner_t *plan) @@ -147,6 +153,7 @@ collect_features_use (hb_ot_shape_planner_t *plan) map->enable_feature (basic_features[i], F_MANUAL_ZWJ); map->add_gsub_pause (reorder); + map->add_gsub_pause (clear_syllables); /* "Topographical features" */ for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++) @@ -164,8 +171,6 @@ collect_features_use (hb_ot_shape_planner_t *plan) struct use_shape_plan_t { - ASSERT_POD (); - hb_mask_t rphf_mask; arabic_shape_plan_t *arabic_plan; @@ -372,7 +377,7 @@ setup_syllables (const hb_ot_shape_plan_t *plan, } static void -clear_substitution_flags (const hb_ot_shape_plan_t *plan, +clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { @@ -384,7 +389,7 @@ clear_substitution_flags (const hb_ot_shape_plan_t *plan, static void record_rphf (const hb_ot_shape_plan_t *plan, - hb_font_t *font, + hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; @@ -406,8 +411,8 @@ record_rphf (const hb_ot_shape_plan_t *plan, } static void -record_pref (const hb_ot_shape_plan_t *plan, - hb_font_t *font, +record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { hb_glyph_info_t *info = buffer->info; @@ -558,17 +563,30 @@ reorder (const hb_ot_shape_plan_t *plan, { insert_dotted_circles (plan, font, buffer); - hb_glyph_info_t *info = buffer->info; - foreach_syllable (buffer, start, end) reorder_syllable (buffer, start, end); - /* Zero syllables now... */ + HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); +} + +static void +clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) info[i].syllable() = 0; +} - HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); + +static void +preprocess_text_use (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + _hb_preprocess_text_vowel_constraints (plan, buffer, font); } static bool @@ -591,7 +609,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = nullptr, /* override_features */ data_create_use, data_destroy_use, - nullptr, /* preprocess_text */ + preprocess_text_use, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, nullptr, /* decompose */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc new file mode 100644 index 00000000000..20af8711eed --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.cc @@ -0,0 +1,438 @@ +/* == Start of generated functions == */ +/* + * The following functions are generated by running: + * + * ./gen-vowel-constraints.py use Scripts.txt + * + * on files with these headers: + * + * # Copied from https://docs.microsoft.com/en-us/typography/script-development/use + * # On October 23, 2018; with documentd dated 02/07/2018. + * + * # Scripts-11.0.0.txt + * # Date: 2018-02-21, 05:34:31 GMT + */ + +#include "hb-ot-shape-complex-vowel-constraints.hh" + +static void +_output_dotted_circle (hb_buffer_t *buffer) +{ + hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); + _hb_glyph_info_reset_continuation (&dottedcircle); +} + +static void +_output_with_dotted_circle (hb_buffer_t *buffer) +{ + _output_dotted_circle (buffer); + buffer->next_glyph (); +} + +void +_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_buffer_t *buffer, + hb_font_t *font HB_UNUSED) +{ + /* UGLY UGLY UGLY business of adding dotted-circle in the middle of + * vowel-sequences that look like another vowel. Data for each script + * collected from the USE script development spec. + * + * https://github.com/harfbuzz/harfbuzz/issues/1019 + */ + bool processed = false; + buffer->clear_output (); + unsigned int count = buffer->len; + switch ((unsigned) buffer->props.script) + { + case HB_SCRIPT_DEVANAGARI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0905u: + switch (buffer->cur (1).codepoint) + { + case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: + case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: + case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: + matched = true; + break; + } + break; + case 0x0906u: + switch (buffer->cur (1).codepoint) + { + case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: + case 0x0948u: + matched = true; + break; + } + break; + case 0x0909u: + matched = 0x0941u == buffer->cur (1).codepoint; + break; + case 0x090Fu: + switch (buffer->cur (1).codepoint) + { + case 0x0945u: case 0x0946u: case 0x0947u: + matched = true; + break; + } + break; + case 0x0930u: + if (0x094Du == buffer->cur (1).codepoint && + buffer->idx + 2 < count && + 0x0907u == buffer->cur (2).codepoint) + { + buffer->next_glyph (); + buffer->next_glyph (); + _output_dotted_circle (buffer); + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_BENGALI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0985u: + matched = 0x09BEu == buffer->cur (1).codepoint; + break; + case 0x098Bu: + matched = 0x09C3u == buffer->cur (1).codepoint; + break; + case 0x098Cu: + matched = 0x09E2u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_GURMUKHI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0A05u: + switch (buffer->cur (1).codepoint) + { + case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: + matched = true; + break; + } + break; + case 0x0A72u: + switch (buffer->cur (1).codepoint) + { + case 0x0A3Fu: case 0x0A40u: case 0x0A47u: + matched = true; + break; + } + break; + case 0x0A73u: + switch (buffer->cur (1).codepoint) + { + case 0x0A41u: case 0x0A42u: case 0x0A4Bu: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_GUJARATI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0A85u: + switch (buffer->cur (1).codepoint) + { + case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: + case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: + matched = true; + break; + } + break; + case 0x0AC5u: + matched = 0x0ABEu == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_ORIYA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0B05u: + matched = 0x0B3Eu == buffer->cur (1).codepoint; + break; + case 0x0B0Fu: case 0x0B13u: + matched = 0x0B57u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TELUGU: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0C12u: + switch (buffer->cur (1).codepoint) + { + case 0x0C4Cu: case 0x0C55u: + matched = true; + break; + } + break; + case 0x0C3Fu: case 0x0C46u: case 0x0C4Au: + matched = 0x0C55u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_KANNADA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0C89u: case 0x0C8Bu: + matched = 0x0CBEu == buffer->cur (1).codepoint; + break; + case 0x0C92u: + matched = 0x0CCCu == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_MALAYALAM: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0D07u: case 0x0D09u: + matched = 0x0D57u == buffer->cur (1).codepoint; + break; + case 0x0D0Eu: + matched = 0x0D46u == buffer->cur (1).codepoint; + break; + case 0x0D12u: + switch (buffer->cur (1).codepoint) + { + case 0x0D3Eu: case 0x0D57u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_SINHALA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0D85u: + switch (buffer->cur (1).codepoint) + { + case 0x0DCFu: case 0x0DD0u: case 0x0DD1u: + matched = true; + break; + } + break; + case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u: + matched = 0x0DDFu == buffer->cur (1).codepoint; + break; + case 0x0D8Du: + matched = 0x0DD8u == buffer->cur (1).codepoint; + break; + case 0x0D91u: + switch (buffer->cur (1).codepoint) + { + case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu: + case 0x0DDDu: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_BRAHMI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11005u: + matched = 0x11038u == buffer->cur (1).codepoint; + break; + case 0x1100Bu: + matched = 0x1103Eu == buffer->cur (1).codepoint; + break; + case 0x1100Fu: + matched = 0x11042u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_KHUDAWADI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x112B0u: + switch (buffer->cur (1).codepoint) + { + case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u: + case 0x112E8u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TIRHUTA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11481u: + matched = 0x114B0u == buffer->cur (1).codepoint; + break; + case 0x1148Bu: case 0x1148Du: + matched = 0x114BAu == buffer->cur (1).codepoint; + break; + case 0x114AAu: + switch (buffer->cur (1).codepoint) + { + case 0x114B5u: case 0x114B6u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_MODI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11600u: case 0x11601u: + switch (buffer->cur (1).codepoint) + { + case 0x11639u: case 0x1163Au: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TAKRI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11680u: + switch (buffer->cur (1).codepoint) + { + case 0x116ADu: case 0x116B4u: case 0x116B5u: + matched = true; + break; + } + break; + case 0x11686u: + matched = 0x116B2u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + default: + break; + } + if (processed) + { + if (buffer->idx < count) + buffer->next_glyph (); + if (likely (buffer->successful)) + buffer->swap_buffers (); + } +} + +/* == End of generated functions == */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.hh new file mode 100644 index 00000000000..d9082d4eadb --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-vowel-constraints.hh @@ -0,0 +1,39 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH +#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH + +#include "hb.hh" + +#include "hb-ot-shape-complex.hh" + +HB_INTERNAL void +_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font); + +#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc index 4c5ccc97425..94bc4afb165 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-fallback.cc @@ -192,7 +192,7 @@ zero_mark_advances (hb_buffer_t *buffer, } static inline void -position_mark (const hb_ot_shape_plan_t *plan, +position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, hb_buffer_t *buffer, hb_glyph_extents_t &base_extents, @@ -472,7 +472,7 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, /* Adjusts width of various spaces. */ void -_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan, +_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, hb_buffer_t *buffer) { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc index a8229a98d94..82bb24b7db6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-normalize.cc @@ -213,17 +213,19 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor } static inline void -handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) +handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, + unsigned int end, + bool short_circuit HB_UNUSED) { /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ hb_buffer_t * const buffer = c->buffer; hb_font_t * const font = c->font; for (; buffer->idx < end - 1 && buffer->successful;) { if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { - /* The next two lines are some ugly lines... But work. */ if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) { - buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); + hb_codepoint_t unicode = buffer->cur().codepoint; + buffer->replace_glyphs (2, 1, &unicode); } else { diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc index a5538871bb8..c55d8dcb8b7 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc @@ -42,6 +42,16 @@ #include "hb-aat-layout.hh" +/** + * SECTION:hb-ot-shape + * @title: hb-ot-shape + * @short_description: OpenType shaping support + * @include: hb-ot.h + * + * Support functions for OpenType shaping related queries. + **/ + + static bool _hb_apply_morx (hb_face_t *face) { @@ -53,6 +63,16 @@ _hb_apply_morx (hb_face_t *face) hb_aat_layout_has_substitution (face); } +hb_ot_shape_planner_t::hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : + face (master_plan->face_unsafe), + props (master_plan->props), + map (face, &props), + aat_map (face, &props), + apply_morx (_hb_apply_morx (face)), + shaper (apply_morx ? + &_hb_ot_complex_shaper_default : + hb_ot_shape_complex_categorize (this)) {} + void hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, const int *coords, @@ -61,17 +81,21 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.props = props; plan.shaper = shaper; map.compile (plan.map, coords, num_coords); + if (apply_morx) + aat_map.compile (plan.aat_map, coords, num_coords); - plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); + plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); plan.kern_mask = plan.map.get_mask (kern_tag); + plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); plan.requested_kerning = !!plan.kern_mask; + plan.requested_tracking = !!plan.trak_mask; bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX; bool disable_gpos = plan.shaper->gpos_tag && plan.shaper->gpos_tag != plan.map.chosen_script[1]; @@ -87,7 +111,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, * Decide who does substitutions. GSUB, morx, or fallback. */ - plan.apply_morx = _hb_apply_morx (face); + plan.apply_morx = apply_morx; /* * Decide who does positioning. GPOS, kerx, kern, or fallback. @@ -116,7 +140,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.fallback_mark_positioning = true; /* Currently we always apply trak. */ - plan.apply_trak = hb_aat_layout_has_tracking (face); + plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); } @@ -177,12 +201,17 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); - map->enable_feature (HB_TAG('H','A','R','F')); + /* Tracking. We enable dummy feature here just to allow disabling + * AAT 'trak' table using features. + * https://github.com/harfbuzz/harfbuzz/issues/1303 */ + map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK); + + map->enable_feature (HB_TAG ('H','A','R','F')); if (planner->shaper->collect_features) planner->shaper->collect_features (planner); - map->enable_feature (HB_TAG('B','U','Z','Z')); + map->enable_feature (HB_TAG ('B','U','Z','Z')); for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) map->add_feature (common_features[i]); @@ -210,6 +239,16 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE, feature->value); } + + if (planner->apply_morx) + { + hb_aat_map_builder_t *aat_map = &planner->aat_map; + for (unsigned int i = 0; i < num_user_features; i++) + { + const hb_feature_t *feature = &user_features[i]; + aat_map->add_feature (feature->tag, feature->value); + } + } } @@ -247,7 +286,7 @@ _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED) } void -_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data) +_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED) { } @@ -271,13 +310,6 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, hb_ot_shape_planner_t planner (shape_plan); - /* Ugly that we have to do this here... - * If we are going to apply morx, choose default shaper. */ - if (_hb_apply_morx (planner.face)) - planner.shaper = &_hb_ot_complex_shaper_default; - else - planner.shaper = hb_ot_shape_complex_categorize (&planner); - hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh index c9c0d3e093d..1cb9e24d7f6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.hh @@ -30,6 +30,7 @@ #include "hb.hh" #include "hb-ot-map.hh" +#include "hb-aat-map.hh" #include "hb-shape-plan.hh" @@ -39,11 +40,15 @@ struct hb_ot_shape_plan_t hb_segment_properties_t props; const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_t map; + hb_aat_map_t aat_map; const void *data; - hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask; + hb_mask_t frac_mask, numr_mask, dnom_mask; + hb_mask_t rtlm_mask; hb_mask_t kern_mask; + hb_mask_t trak_mask; bool requested_kerning : 1; + bool requested_tracking : 1; bool has_frac : 1; bool has_gpos_mark : 1; bool fallback_glyph_classes : 1; @@ -74,9 +79,11 @@ struct hb_ot_shape_plan_t { memset (this, 0, sizeof (*this)); map.init (); + aat_map.init (); } void fini (void) { map.fini (); + aat_map.fini (); } }; @@ -85,21 +92,16 @@ struct hb_ot_shape_planner_t /* In the order that they are filled in. */ hb_face_t *face; hb_segment_properties_t props; - const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_builder_t map; + hb_aat_map_builder_t aat_map; + bool apply_morx : 1; + const struct hb_ot_complex_shaper_t *shaper; - hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : - face (master_plan->face_unsafe), - props (master_plan->props), - shaper (nullptr), - map (face, &props) {} + HB_INTERNAL hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan); HB_INTERNAL void compile (hb_ot_shape_plan_t &plan, const int *coords, unsigned int num_coords); - - private: - HB_DISALLOW_COPY_AND_ASSIGN (hb_ot_shape_planner_t); }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc index 4dba9c31a18..a569b8c22a2 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc @@ -242,7 +242,6 @@ hb_ot_tag_from_language (hb_language_t language) static void hb_ot_tags_from_language (const char *lang_str, const char *limit, - const char *private_use_subtag, unsigned int *count, hb_tag_t *tags) { @@ -389,7 +388,7 @@ hb_ot_tags_from_script_and_language (hb_script_t script, needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER); if (needs_language && language_count && language_tags && *language_count) - hb_ot_tags_from_language (lang_str, limit, private_use_subtag, language_count, language_tags); + hb_ot_tags_from_language (lang_str, limit, language_count, language_tags); } if (needs_script && script_count && script_tags && *script_count) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.h deleted file mode 100644 index 33a4dbdbc0d..00000000000 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright © 2009 Red Hat, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Red Hat Author(s): Behdad Esfahbod - */ - -#ifndef HB_OT_H_IN -#error "Include <hb-ot.h> instead." -#endif - -#ifndef HB_OT_TAG_H -#define HB_OT_TAG_H - -#include "hb.h" - -HB_BEGIN_DECLS - - -#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') -#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') - -/** - * HB_OT_MAX_TAGS_PER_SCRIPT: - * - * Since: 2.0.0 - **/ -#define HB_OT_MAX_TAGS_PER_SCRIPT 3u -/** - * HB_OT_MAX_TAGS_PER_LANGUAGE: - * - * Since: 2.0.0 - **/ -#define HB_OT_MAX_TAGS_PER_LANGUAGE 3u - -HB_EXTERN void -hb_ot_tags_from_script_and_language (hb_script_t script, - hb_language_t language, - unsigned int *script_count /* IN/OUT */, - hb_tag_t *script_tags /* OUT */, - unsigned int *language_count /* IN/OUT */, - hb_tag_t *language_tags /* OUT */); - -HB_EXTERN hb_script_t -hb_ot_tag_to_script (hb_tag_t tag); - -HB_EXTERN hb_language_t -hb_ot_tag_to_language (hb_tag_t tag); - -HB_EXTERN void -hb_ot_tags_to_script_and_language (hb_tag_t script_tag, - hb_tag_t language_tag, - hb_script_t *script /* OUT */, - hb_language_t *language /* OUT */); - - -HB_END_DECLS - -#endif /* HB_OT_TAG_H */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var.cc index 472ee845224..64087be8117 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var.cc @@ -32,6 +32,17 @@ #include "hb-ot-var-mvar-table.hh" #include "hb-ot-var.h" + +/** + * SECTION:hb-ot-var + * @title: hb-ot-var + * @short_description: OpenType Font Variations + * @include: hb-ot.h + * + * Functions for fetching information about OpenType Variable Fonts. + **/ + + /* * fvar/avar */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh new file mode 100644 index 00000000000..98af00e14b2 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-vorg-table.hh @@ -0,0 +1,182 @@ +/* + * Copyright © 2018 Adobe Systems Incorporated. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Adobe Author(s): Michiharu Ariza + */ + +#ifndef HB_OT_VORG_TABLE_HH +#define HB_OT_VORG_TABLE_HH + +#include "hb-open-type.hh" + +/* + * VORG -- Vertical Origin Table + * https://docs.microsoft.com/en-us/typography/opentype/spec/vorg + */ +#define HB_OT_TAG_VORG HB_TAG('V','O','R','G') + +namespace OT { + +struct VertOriginMetric +{ + inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + GlyphID glyph; + FWORD vertOriginY; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct VORG +{ + static const hb_tag_t tableTag = HB_OT_TAG_VORG; + + inline bool has_data (void) const { return version.to_int (); } + + inline int get_y_origin (hb_codepoint_t glyph) const + { + int i = vertYOrigins.bsearch (glyph); + if (i != -1) + return vertYOrigins[i].vertOriginY; + + return defaultVertOriginY; + } + + inline bool _subset (const hb_subset_plan_t *plan HB_UNUSED, + const VORG *vorg_table, + const hb_vector_t<VertOriginMetric> &subset_metrics, + unsigned int dest_sz, + void *dest) const + { + hb_serialize_context_t c (dest, dest_sz); + + VORG *subset_table = c.start_serialize<VORG> (); + if (unlikely (!c.extend_min (*subset_table))) + return false; + + subset_table->version.major.set (1); + subset_table->version.minor.set (0); + + subset_table->defaultVertOriginY.set (vorg_table->defaultVertOriginY); + subset_table->vertYOrigins.len.set (subset_metrics.len); + + bool success = true; + if (subset_metrics.len > 0) + { + unsigned int size = VertOriginMetric::static_size * subset_metrics.len; + VertOriginMetric *metrics = c.allocate_size<VertOriginMetric> (size); + if (likely (metrics != nullptr)) + memcpy (metrics, &subset_metrics[0], size); + else + success = false; + } + c.end_serialize (); + + return success; + } + + inline bool subset (hb_subset_plan_t *plan) const + { + hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table<VORG> (plan->source); + const VORG *vorg_table = vorg_blob->as<VORG> (); + + /* count the number of glyphs to be included in the subset table */ + hb_vector_t<VertOriginMetric> subset_metrics; + subset_metrics.init (); + unsigned int glyph = 0; + unsigned int i = 0; + while ((glyph < plan->glyphs.len) && (i < vertYOrigins.len)) + { + if (plan->glyphs[glyph] > vertYOrigins[i].glyph) + i++; + else if (plan->glyphs[glyph] < vertYOrigins[i].glyph) + glyph++; + else + { + VertOriginMetric *metrics = subset_metrics.push (); + metrics->glyph.set (glyph); + metrics->vertOriginY.set (vertYOrigins[i].vertOriginY); + glyph++; + i++; + } + } + + /* alloc the new table */ + unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.len; + void *dest = (void *) malloc (dest_sz); + if (unlikely (!dest)) + { + subset_metrics.fini (); + hb_blob_destroy (vorg_blob); + return false; + } + + /* serialize the new table */ + if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest)) + { + subset_metrics.fini (); + free (dest); + hb_blob_destroy (vorg_blob); + return false; + } + + hb_blob_t *result = hb_blob_create ((const char *)dest, + dest_sz, + HB_MEMORY_MODE_READONLY, + dest, + free); + bool success = plan->add_table (HB_OT_TAG_VORG, result); + hb_blob_destroy (result); + subset_metrics.fini (); + hb_blob_destroy (vorg_blob); + return success; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + version.major == 1 && + vertYOrigins.sanitize (c)); + } + + protected: + FixedVersion<> version; /* Version of VORG table. Set to 0x00010000u. */ + FWORD defaultVertOriginY; /* The default vertical origin. */ + SortedArrayOf<VertOriginMetric> + vertYOrigins; /* The array of vertical origins. */ + + public: + DEFINE_SIZE_ARRAY(8, vertYOrigins); +}; +} /* namespace OT */ + +#endif /* HB_OT_VORG_TABLE_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot.h index 4b6e3cf74bb..c168175ac35 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot.h @@ -30,11 +30,11 @@ #include "hb.h" +#include "hb-ot-color.h" #include "hb-ot-font.h" #include "hb-ot-layout.h" #include "hb-ot-math.h" #include "hb-ot-name.h" -#include "hb-ot-tag.h" #include "hb-ot-shape.h" #include "hb-ot-var.h" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh index 0f9329f621c..4e99df0eb55 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set-digest.hh @@ -48,8 +48,6 @@ template <typename mask_t, unsigned int shift> struct hb_set_digest_lowest_bits_t { - ASSERT_POD (); - enum { mask_bytes = sizeof (mask_t) }; enum { mask_bits = sizeof (mask_t) * 8 }; static const unsigned int num_bits = 0 @@ -117,8 +115,6 @@ struct hb_set_digest_lowest_bits_t template <typename head_t, typename tail_t> struct hb_set_digest_combiner_t { - ASSERT_POD (); - inline void init (void) { head.init (); tail.init (); diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc index 09dc4b483af..67ec5618028 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.cc @@ -27,7 +27,16 @@ #include "hb-set.hh" -/* Public API */ +/** + * SECTION:hb-set + * @title: hb-set + * @short_description: Object representing a set of integers + * @include: hb.h + * + * Set objects represent a mathematical set of integer values. They are + * used in non-shaping API to query certain set of characters or glyphs, + * or other integer values. + **/ /** @@ -391,7 +400,7 @@ hb_set_symmetric_difference (hb_set_t *set, * Deprecated: 1.6.1 **/ void -hb_set_invert (hb_set_t *set) +hb_set_invert (hb_set_t *set HB_UNUSED) { } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh index 7ca32976116..2dfcc242ae9 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh @@ -39,6 +39,10 @@ struct hb_set_t { + HB_NO_COPY_ASSIGN (hb_set_t); + inline hb_set_t (void) { init (); } + inline ~hb_set_t (void) { fini (); } + struct page_map_t { inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; } @@ -49,8 +53,8 @@ struct hb_set_t struct page_t { - inline void init0 (void) { memset (&v, 0, sizeof (v)); } - inline void init1 (void) { memset (&v, 0xff, sizeof (v)); } + inline void init0 (void) { memset (reinterpret_cast<char*>(&v), 0, sizeof (v)); } + inline void init1 (void) { memset (reinterpret_cast<char*>(&v), 0xff, sizeof (v)); } inline unsigned int len (void) const { return ARRAY_LENGTH_CONST (v); } @@ -199,6 +203,7 @@ struct hb_set_t } inline void fini_shallow (void) { + population = 0; page_map.fini (); pages.fini (); } @@ -368,8 +373,8 @@ struct hb_set_t if (!resize (count)) return; population = other->population; - memcpy (pages.arrayZ(), other->pages.arrayZ(), count * sizeof (pages.arrayZ()[0])); - memcpy (page_map.arrayZ(), other->page_map.arrayZ(), count * sizeof (page_map.arrayZ()[0])); + memcpy (pages, other->pages, count * sizeof (pages[0])); + memcpy (page_map, other->page_map, count * sizeof (page_map[0])); } inline bool is_equal (const hb_set_t *other) const @@ -669,7 +674,9 @@ struct hb_set_t return nullptr; pages[map.index].init0 (); - memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0])); + memmove (page_map + i + 1, + page_map + i, + (page_map.len - 1 - i) * sizeof (page_map[0])); page_map[i] = map; } return &pages[page_map[i].index]; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc index b2289f86994..4648cc7570e 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc @@ -31,6 +31,19 @@ #include "hb-buffer.hh" +/** + * SECTION:hb-shape-plan + * @title: hb-shape-plan + * @short_description: Object representing a shaping plan + * @include: hb.h + * + * Shape plans are not used for shaping directly, but can be access to query + * certain information about how shaping will perform given a set of input + * parameters (script, language, direction, features, etc.) + * Most client would not need to deal with shape plans directly. + **/ + + static void hb_shape_plan_plan (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, @@ -441,7 +454,7 @@ hb_non_global_user_features_present (const hb_feature_t *user_features, } static inline hb_bool_t -hb_coords_present (const int *coords, +hb_coords_present (const int *coords HB_UNUSED, unsigned int num_coords) { return num_coords != 0; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.hh index bf82b912be0..403c3ebdf32 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.hh @@ -34,7 +34,6 @@ struct hb_shape_plan_t { hb_object_header_t header; - ASSERT_POD (); hb_bool_t default_shaper_list; hb_face_t *face_unsafe; /* We don't carry a reference to face. */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc index e8eeff5b354..f98bc6e51a6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape.cc @@ -34,18 +34,20 @@ #include "hb-font.hh" #include "hb-machinery.hh" + /** * SECTION:hb-shape - * @title: Shaping + * @title: hb-shape * @short_description: Conversion of text strings into positioned glyphs * @include: hb.h * * Shaping is the central operation of HarfBuzz. Shaping operates on buffers, * which are sequences of Unicode characters that use the same font and have - * the same text direction, script and language. After shaping the buffer + * the same text direction, script, and language. After shaping the buffer * contains the output glyphs and their positions. **/ + #ifdef HB_USE_ATEXIT static void free_static_shaper_list (void); #endif diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh index 9fc86154e40..7f625f2e443 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-input.hh @@ -37,7 +37,6 @@ struct hb_subset_input_t { hb_object_header_t header; - ASSERT_POD (); hb_set_t *unicodes; hb_set_t *glyphs; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc index 0570060399d..64c8ad7982d 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc @@ -55,7 +55,7 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf, static void _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain) { - hb_auto_t<hb_set_t> lookup_indices; + hb_set_t lookup_indices; hb_ot_layout_collect_lookups (face, HB_OT_TAG_GSUB, nullptr, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh index c2c484a5bef..5ab32ad8f37 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh @@ -37,7 +37,6 @@ struct hb_subset_plan_t { hb_object_header_t header; - ASSERT_POD (); bool drop_hints : 1; bool drop_layout : 1; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc index 9f14b89ba59..ed61c628fdb 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc @@ -68,7 +68,7 @@ _subset2 (hb_subset_plan_t *plan) hb_bool_t result = false; if (source_blob->data) { - hb_auto_t<hb_vector_t<char> > buf; + hb_vector_t<char> buf; unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length); DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG(tag), buf_size); if (unlikely (!buf.alloc (buf_size))) @@ -77,7 +77,7 @@ _subset2 (hb_subset_plan_t *plan) return false; } retry: - hb_serialize_context_t serializer (buf.arrayZ(), buf_size); + hb_serialize_context_t serializer (buf, buf_size); hb_subset_context_t c (plan, &serializer); result = table->subset (&c); if (serializer.ran_out_of_room) diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh index 9cdd388d780..e43c79f5ee6 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.hh @@ -43,7 +43,7 @@ struct hb_subset_context_t : template <typename T> inline bool dispatch (const T &obj) { return obj.subset (this); } static bool default_return_value (void) { return true; } - bool stop_sublookup_iteration (bool r) const { return false; } + bool stop_sublookup_iteration (bool r HB_UNUSED) const { return false; } hb_subset_plan_t *plan; hb_serialize_context_t *serializer; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc index 7b821b46d5e..8cf7898a164 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.cc @@ -33,6 +33,20 @@ #include "hb-unicode.hh" +/** + * SECTION: hb-unicode + * @title: hb-unicode + * @short_description: Unicode character property access + * @include: hb.h + * + * Unicode functions are used to access Unicode character properties. + * Client can pass its own Unicode functions to HarfBuzz, or access + * the built-in Unicode functions that come with HarfBuzz. + * + * With the Unicode functions, one can query variour Unicode character + * properties, such as General Category, Script, Combining Class, etc. + **/ + /* * hb_unicode_funcs_t @@ -109,40 +123,23 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED } -#define HB_UNICODE_FUNCS_IMPLEMENT_SET \ - HB_UNICODE_FUNCS_IMPLEMENT (glib) \ - HB_UNICODE_FUNCS_IMPLEMENT (icu) \ - HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \ - HB_UNICODE_FUNCS_IMPLEMENT (nil) \ - /* ^--- Add new callbacks before nil */ - -#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty - -/* Prototype them all */ -#define HB_UNICODE_FUNCS_IMPLEMENT(set) \ -extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void); -HB_UNICODE_FUNCS_IMPLEMENT_SET -#undef HB_UNICODE_FUNCS_IMPLEMENT - +extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (void); +extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (void); +extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs (void); hb_unicode_funcs_t * hb_unicode_funcs_get_default (void) { -#define HB_UNICODE_FUNCS_IMPLEMENT(set) \ - return hb_##set##_get_unicode_funcs (); - #if defined(HAVE_UCDN) - HB_UNICODE_FUNCS_IMPLEMENT(ucdn) + return hb_ucdn_get_unicode_funcs (); #elif defined(HAVE_GLIB) - HB_UNICODE_FUNCS_IMPLEMENT(glib) + return hb_glib_get_unicode_funcs (); #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) - HB_UNICODE_FUNCS_IMPLEMENT(icu) + return hb_icu_get_unicode_funcs (); #else #define HB_UNICODE_FUNCS_NIL 1 - HB_UNICODE_FUNCS_IMPLEMENT(nil) + return hb_unicode_funcs_get_empty (); #endif - -#undef HB_UNICODE_FUNCS_IMPLEMENT } #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL) @@ -442,6 +439,7 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, * Return value: * * Since: 0.9.2 + * Deprecated: 2.0.0 **/ unsigned int hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, @@ -575,8 +573,8 @@ _hb_modified_combining_class[256] = bool _hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp) { - return hb_bsearch_r (&cp, _hb_unicode_emoji_Extended_Pictographic_table, - ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table), - sizeof (hb_unicode_range_t), - hb_unicode_range_t::cmp, nullptr); + return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table, + ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table), + sizeof (hb_unicode_range_t), + hb_unicode_range_t::cmp); } diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh index 6d6a4fa0ca1..0b66ce8a13b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-unicode.hh @@ -63,7 +63,6 @@ extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256]; struct hb_unicode_funcs_t { hb_object_header_t header; - ASSERT_POD (); hb_unicode_funcs_t *parent; @@ -369,7 +368,7 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t); struct hb_unicode_range_t { static int - cmp (const void *_key, const void *_item, void *_arg) + cmp (const void *_key, const void *_item) { hb_codepoint_t cp = *((hb_codepoint_t *) _key); const hb_unicode_range_t *range = (hb_unicode_range_t *) _item; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc index 44a67ae4c63..26b99ed157b 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-uniscribe.cc @@ -36,7 +36,17 @@ #include "hb-open-file.hh" #include "hb-ot-name-table.hh" -#include "hb-ot-tag.h" +#include "hb-ot-layout.h" + + +/** + * SECTION:hb-uniscribe + * @title: hb-uniscribe + * @short_description: Windows integration + * @include: hb-uniscribe.h + * + * Functions for using HarfBuzz with the Windows fonts. + **/ static inline uint16_t hb_uint16_swap (const uint16_t v) @@ -632,12 +642,12 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, /* * Set up features. */ - hb_auto_t<hb_vector_t<OPENTYPE_FEATURE_RECORD> > feature_records; - hb_auto_t<hb_vector_t<range_record_t> > range_records; + hb_vector_t<OPENTYPE_FEATURE_RECORD> feature_records; + hb_vector_t<range_record_t> range_records; if (num_features) { /* Sort features by start/end events. */ - hb_auto_t<hb_vector_t<feature_event_t> > feature_events; + hb_vector_t<feature_event_t> feature_events; for (unsigned int i = 0; i < num_features; i++) { active_feature_t feature; @@ -672,7 +682,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, } /* Scan events and save features for each range. */ - hb_auto_t<hb_vector_t<active_feature_t> > active_features; + hb_vector_t<active_feature_t> active_features; unsigned int last_index = 0; for (unsigned int i = 0; i < feature_events.len; i++) { @@ -717,7 +727,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, { active_feature_t *feature = active_features.find (&event->feature); if (feature) - active_features.remove (feature - active_features.arrayZ()); + active_features.remove (feature - active_features); } } @@ -728,7 +738,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < range_records.len; i++) { range_record_t *range = &range_records[i]; - range->props.potfRecords = feature_records.arrayZ() + reinterpret_cast<uintptr_t> (range->props.potfRecords); + range->props.potfRecords = feature_records + reinterpret_cast<uintptr_t> (range->props.potfRecords); } } @@ -844,8 +854,8 @@ retry: #undef MAX_ITEMS OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language)); - hb_auto_t<hb_vector_t<TEXTRANGE_PROPERTIES*> > range_properties; - hb_auto_t<hb_vector_t<int> > range_char_counts; + hb_vector_t<TEXTRANGE_PROPERTIES*> range_properties; + hb_vector_t<int> range_char_counts; unsigned int glyphs_offset = 0; unsigned int glyphs_len; @@ -902,8 +912,8 @@ retry: &items[i].a, script_tags[i], language_tag, - range_char_counts.arrayZ(), - range_properties.arrayZ(), + range_char_counts, + range_properties, range_properties.len, pchars + chars_offset, item_chars_len, @@ -943,8 +953,8 @@ retry: &items[i].a, script_tags[i], language_tag, - range_char_counts.arrayZ(), - range_properties.arrayZ(), + range_char_counts, + range_properties, range_properties.len, pchars + chars_offset, log_clusters + chars_offset, diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-utf.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-utf.hh index eccb632e489..54ede3c167a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-utf.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-utf.hh @@ -29,14 +29,16 @@ #include "hb.hh" +#include "hb-open-type.hh" + struct hb_utf8_t { typedef uint8_t codepoint_t; - static inline const uint8_t * - next (const uint8_t *text, - const uint8_t *end, + static inline const codepoint_t * + next (const codepoint_t *text, + const codepoint_t *end, hb_codepoint_t *unicode, hb_codepoint_t replacement) { @@ -103,13 +105,13 @@ struct hb_utf8_t return text; } - static inline const uint8_t * - prev (const uint8_t *text, - const uint8_t *start, + static inline const codepoint_t * + prev (const codepoint_t *text, + const codepoint_t *start, hb_codepoint_t *unicode, hb_codepoint_t replacement) { - const uint8_t *end = text--; + const codepoint_t *end = text--; while (start < text && (*text & 0xc0) == 0x80 && end - text < 4) text--; @@ -121,20 +123,71 @@ struct hb_utf8_t } static inline unsigned int - strlen (const uint8_t *text) + strlen (const codepoint_t *text) { return ::strlen ((const char *) text); } + + static inline unsigned int + encode_len (hb_codepoint_t unicode) + { + if (unicode < 0x0080u) return 1; + if (unicode < 0x0800u) return 2; + if (unicode < 0x10000u) return 3; + if (unicode < 0x110000u) return 4; + return 3; + } + + static inline codepoint_t * + encode (codepoint_t *text, + const codepoint_t *end, + hb_codepoint_t unicode) + { + if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu))) + unicode = 0xFFFDu; + if (unicode < 0x0080u) + *text++ = unicode; + else if (unicode < 0x0800u) + { + if (end - text >= 2) + { + *text++ = 0xC0u + (0x1Fu & (unicode >> 6)); + *text++ = 0x80u + (0x3Fu & (unicode )); + } + } + else if (unicode < 0x10000u) + { + if (end - text >= 3) + { + *text++ = 0xE0u + (0x0Fu & (unicode >> 12)); + *text++ = 0x80u + (0x3Fu & (unicode >> 6)); + *text++ = 0x80u + (0x3Fu & (unicode )); + } + } + else + { + if (end - text >= 4) + { + *text++ = 0xF0u + (0x07u & (unicode >> 18)); + *text++ = 0x80u + (0x3Fu & (unicode >> 12)); + *text++ = 0x80u + (0x3Fu & (unicode >> 6)); + *text++ = 0x80u + (0x3Fu & (unicode )); + } + } + return text; + } }; -struct hb_utf16_t +template <typename TCodepoint> +struct hb_utf16_xe_t { - typedef uint16_t codepoint_t; + static_assert (sizeof (TCodepoint) == 2, ""); + typedef TCodepoint codepoint_t; - static inline const uint16_t * - next (const uint16_t *text, - const uint16_t *end, + static inline const codepoint_t * + next (const codepoint_t *text, + const codepoint_t *end, hb_codepoint_t *unicode, hb_codepoint_t replacement) { @@ -164,9 +217,9 @@ struct hb_utf16_t return text; } - static inline const uint16_t * - prev (const uint16_t *text, - const uint16_t *start, + static inline const codepoint_t * + prev (const codepoint_t *text, + const codepoint_t *start, hb_codepoint_t *unicode, hb_codepoint_t replacement) { @@ -198,23 +251,51 @@ struct hb_utf16_t static inline unsigned int - strlen (const uint16_t *text) + strlen (const codepoint_t *text) { unsigned int l = 0; while (*text++) l++; return l; } + + static inline unsigned int + encode_len (hb_codepoint_t unicode) + { + return unicode < 0x10000 ? 1 : 2; + } + + static inline codepoint_t * + encode (codepoint_t *text, + const codepoint_t *end, + hb_codepoint_t unicode) + { + if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu))) + unicode = 0xFFFDu; + if (unicode < 0x10000u) + *text++ = unicode; + else if (end - text >= 2) + { + unicode -= 0x10000u; + *text++ = 0xD800u + (unicode >> 10); + *text++ = 0xDC00u + (unicode & 0x03FFu); + } + return text; + } }; +typedef hb_utf16_xe_t<uint16_t> hb_utf16_t; +typedef hb_utf16_xe_t<OT::HBUINT16> hb_utf16_be_t; -template <bool validate=true> -struct hb_utf32_t + +template <typename TCodepoint, bool validate=true> +struct hb_utf32_xe_t { - typedef uint32_t codepoint_t; + static_assert (sizeof (TCodepoint) == 4, ""); + typedef TCodepoint codepoint_t; - static inline const uint32_t * - next (const uint32_t *text, - const uint32_t *end HB_UNUSED, + static inline const TCodepoint * + next (const TCodepoint *text, + const TCodepoint *end HB_UNUSED, hb_codepoint_t *unicode, hb_codepoint_t replacement) { @@ -224,9 +305,9 @@ struct hb_utf32_t return text; } - static inline const uint32_t * - prev (const uint32_t *text, - const uint32_t *start HB_UNUSED, + static inline const TCodepoint * + prev (const TCodepoint *text, + const TCodepoint *start HB_UNUSED, hb_codepoint_t *unicode, hb_codepoint_t replacement) { @@ -237,22 +318,42 @@ struct hb_utf32_t } static inline unsigned int - strlen (const uint32_t *text) + strlen (const TCodepoint *text) { unsigned int l = 0; while (*text++) l++; return l; } + + static inline unsigned int + encode_len (hb_codepoint_t unicode HB_UNUSED) + { + return 1; + } + + static inline codepoint_t * + encode (codepoint_t *text, + const codepoint_t *end HB_UNUSED, + hb_codepoint_t unicode) + { + if (validate && unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu))) + unicode = 0xFFFDu; + *text++ = unicode; + return text; + } }; +typedef hb_utf32_xe_t<uint32_t> hb_utf32_t; +typedef hb_utf32_xe_t<uint32_t, false> hb_utf32_novalidate_t; + struct hb_latin1_t { typedef uint8_t codepoint_t; - static inline const uint8_t * - next (const uint8_t *text, - const uint8_t *end HB_UNUSED, + static inline const codepoint_t * + next (const codepoint_t *text, + const codepoint_t *end HB_UNUSED, hb_codepoint_t *unicode, hb_codepoint_t replacement HB_UNUSED) { @@ -260,23 +361,95 @@ struct hb_latin1_t return text; } - static inline const uint8_t * - prev (const uint8_t *text, - const uint8_t *start HB_UNUSED, + static inline const codepoint_t * + prev (const codepoint_t *text, + const codepoint_t *start HB_UNUSED, + hb_codepoint_t *unicode, + hb_codepoint_t replacement HB_UNUSED) + { + *unicode = *--text; + return text; + } + + static inline unsigned int + strlen (const codepoint_t *text) + { + unsigned int l = 0; + while (*text++) l++; + return l; + } + + static inline unsigned int + encode_len (hb_codepoint_t unicode HB_UNUSED) + { + return 1; + } + + static inline codepoint_t * + encode (codepoint_t *text, + const codepoint_t *end HB_UNUSED, + hb_codepoint_t unicode) + { + if (unlikely (unicode >= 0x0100u)) + unicode = '?'; + *text++ = unicode; + return text; + } +}; + + +struct hb_ascii_t +{ + typedef uint8_t codepoint_t; + + static inline const codepoint_t * + next (const codepoint_t *text, + const codepoint_t *end HB_UNUSED, + hb_codepoint_t *unicode, + hb_codepoint_t replacement HB_UNUSED) + { + *unicode = *text++; + if (*unicode >= 0x0080u) + *unicode = replacement; + return text; + } + + static inline const codepoint_t * + prev (const codepoint_t *text, + const codepoint_t *start HB_UNUSED, hb_codepoint_t *unicode, hb_codepoint_t replacement) { *unicode = *--text; + if (*unicode >= 0x0080u) + *unicode = replacement; return text; } static inline unsigned int - strlen (const uint8_t *text) + strlen (const codepoint_t *text) { unsigned int l = 0; while (*text++) l++; return l; } + + static inline unsigned int + encode_len (hb_codepoint_t unicode HB_UNUSED) + { + return 1; + } + + static inline codepoint_t * + encode (codepoint_t *text, + const codepoint_t *end HB_UNUSED, + hb_codepoint_t unicode) + { + if (unlikely (unicode >= 0x0080u)) + unicode = '?'; + *text++ = unicode; + return text; + } }; #endif /* HB_UTF_HH */ diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh index 766e5fb8e61..fe06addf7bb 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh @@ -34,6 +34,10 @@ template <typename Type, unsigned int StaticSize=8> struct hb_vector_t { + HB_NO_COPY_ASSIGN_TEMPLATE2 (hb_vector_t, Type, StaticSize); + inline hb_vector_t (void) { init (); } + inline ~hb_vector_t (void) { fini (); } + unsigned int len; private: unsigned int allocated; /* == 0 means allocation failed. */ @@ -48,6 +52,22 @@ struct hb_vector_t arrayZ_ = nullptr; } + inline void fini (void) + { + if (arrayZ_) + free (arrayZ_); + arrayZ_ = nullptr; + allocated = len = 0; + } + inline void fini_deep (void) + { + Type *array = arrayZ(); + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + array[i].fini (); + fini (); + } + inline Type * arrayZ (void) { return arrayZ_ ? arrayZ_ : static_array; } inline const Type * arrayZ (void) const @@ -66,6 +86,12 @@ struct hb_vector_t return arrayZ()[i]; } + template <typename T> inline operator T * (void) { return arrayZ(); } + template <typename T> inline operator const T * (void) const { return arrayZ(); } + + inline Type * operator + (unsigned int i) { return arrayZ() + i; } + inline const Type * operator + (unsigned int i) const { return arrayZ() + i; } + inline Type *push (void) { if (unlikely (!resize (len + 1))) @@ -232,7 +258,7 @@ struct hb_vector_t const Type *array = this->arrayZ(); while (min <= max) { - int mid = (min + max) / 2; + int mid = ((unsigned int) min + (unsigned int) max) / 2; int c = array[mid].cmp (&x); if (c < 0) max = mid - 1; @@ -249,23 +275,6 @@ struct hb_vector_t *i = max; return false; } - - inline void fini_deep (void) - { - Type *array = arrayZ(); - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - array[i].fini (); - fini (); - } - - inline void fini (void) - { - if (arrayZ_) - free (arrayZ_); - arrayZ_ = nullptr; - allocated = len = 0; - } }; diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h index fc75a69187c..c5e7072fbac 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.h @@ -28,10 +28,6 @@ #define HB_H #define HB_H_IN -#ifndef HB_EXTERN -#define HB_EXTERN extern -#endif - #include "hb-blob.h" #include "hb-buffer.h" #include "hb-common.h" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh index 098b5660401..fa6a7404d9f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb.hh @@ -337,35 +337,40 @@ static_assert ((sizeof (hb_mask_t) == 4), ""); static_assert ((sizeof (hb_var_int_t) == 4), ""); -/* We like our types POD */ +#if __cplusplus >= 201103L -#define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; } -#define _ASSERT_TYPE_POD0(_line, _type) _ASSERT_TYPE_POD1 (_line, _type) -#define ASSERT_TYPE_POD(_type) _ASSERT_TYPE_POD0 (__LINE__, _type) +/* We only enable these with C++11 or later, since earlier language + * does not allow structs with constructors in unions, and we need + * those. */ -#ifdef __GNUC__ -# define _ASSERT_INSTANCE_POD1(_line, _instance) \ - HB_STMT_START { \ - typedef __typeof__(_instance) _type_##_line; \ - _ASSERT_TYPE_POD1 (_line, _type_##_line); \ - } HB_STMT_END -#else -# define _ASSERT_INSTANCE_POD1(_line, _instance) typedef int _assertion_on_line_##_line##_not_tested -#endif -# define _ASSERT_INSTANCE_POD0(_line, _instance) _ASSERT_INSTANCE_POD1 (_line, _instance) -# define ASSERT_INSTANCE_POD(_instance) _ASSERT_INSTANCE_POD0 (__LINE__, _instance) +#define HB_NO_COPY_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) +#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \ + TypeName(const TypeName<T1, T2>&); \ + void operator=(const TypeName<T1, T2>&) +#define HB_NO_CREATE_COPY_ASSIGN(TypeName) \ + TypeName(void); \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) +#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) \ + TypeName(void); \ + TypeName(const TypeName<T>&); \ + void operator=(const TypeName<T>&) +#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \ + TypeName(void); \ + TypeName(const TypeName<T1, T2>&); \ + void operator=(const TypeName<T1, T2>&) -/* Check _assertion in a method environment */ -#define _ASSERT_POD1(_line) \ - HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \ - { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ } -# define _ASSERT_POD0(_line) _ASSERT_POD1 (_line) -# define ASSERT_POD() _ASSERT_POD0 (__LINE__) +#else /* __cpluspplus >= 201103L */ +#define HB_NO_COPY_ASSIGN(TypeName) +#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) +#define HB_NO_CREATE_COPY_ASSIGN(TypeName) +#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) +#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) -#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) +#endif /* __cpluspplus >= 201103L */ /* @@ -495,6 +500,15 @@ _hb_memalign(void **memptr, size_t alignment, size_t size) #define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g')) +/* Some really basic things everyone wants. */ +template <typename T> struct hb_remove_const { typedef T value; }; +template <typename T> struct hb_remove_const<const T> { typedef T value; }; +template <typename T> struct hb_remove_reference { typedef T value; }; +template <typename T> struct hb_remove_reference<T &> { typedef T value; }; +template <typename T> struct hb_remove_pointer { typedef T value; }; +template <typename T> struct hb_remove_pointer<T *> { typedef T value; }; + + /* Headers we include for everyone. Keep sorted. They express dependency amongst * themselves, but no other file should include them.*/ #include "hb-atomic.hh" diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-name-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-name-table.cc new file mode 100644 index 00000000000..33305272945 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-name-table.cc @@ -0,0 +1,67 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb.h" +#include "hb-ot.h" + +#include <stdlib.h> +#include <stdio.h> + +int +main (int argc, char **argv) +{ + if (argc != 2) { + fprintf (stderr, "usage: %s font-file\n", argv[0]); + exit (1); + } + + hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_face_t *face = hb_face_create (blob, 0 /* first face */); + hb_blob_destroy (blob); + blob = NULL; + + unsigned int count; + const hb_ot_name_entry_t *entries = hb_ot_name_list_names (face, &count); + + for (unsigned int i = 0; i < count; i++) + { + printf ("%d %s ", + entries[i].name_id, + hb_language_to_string (entries[i].language)); + + char buf[64]; + unsigned int buf_size = sizeof (buf); + hb_ot_name_get_utf8 (face, + entries[i].name_id, + entries[i].language, + &buf_size, + buf); + + printf ("%s\n", buf); + } + + return count ? 0 : 1; +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc new file mode 100644 index 00000000000..2cb9b03b248 --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-ot-color.cc @@ -0,0 +1,347 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * Copyright © 2018 Khaled Hosny + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.h" +#include "hb-ot.h" + +#include "hb-ft.h" + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include <cairo.h> +#include <cairo-ft.h> +#include <cairo-svg.h> + +#include <stdlib.h> +#include <stdio.h> + +static void +png_dump (hb_face_t *face, unsigned int face_index) +{ + unsigned glyph_count = hb_face_get_glyph_count (face); + hb_font_t *font = hb_font_create (face); + + /* ugly hack, scans the font for strikes, not needed for regular clients */ + #define STRIKES_MAX 20 + unsigned int strikes_count = 0; + unsigned int strikes[STRIKES_MAX] = {0}; + { + /* find a sample glyph */ + unsigned int sample_glyph_id; + /* we don't care much about different strikes for different glyphs */ + for (sample_glyph_id = 0; sample_glyph_id < glyph_count; sample_glyph_id++) + { + hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); + unsigned int blob_length = hb_blob_get_length (blob); + hb_blob_destroy (blob); + if (blob_length != 0) + break; + } + /* find strikes it has */ + unsigned int upem = hb_face_get_upem (face); + unsigned int blob_length = 0; + for (unsigned int ppem = 1; ppem <= upem && strikes_count < STRIKES_MAX; ppem++) + { + hb_font_set_ppem (font, ppem, ppem); + hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); + unsigned int new_blob_length = hb_blob_get_length (blob); + if (blob_length != new_blob_length) + { + strikes_count++; + blob_length = new_blob_length; + } + if (strikes_count != 0) + strikes[strikes_count - 1] = ppem; + hb_blob_destroy (blob); + } + /* can't report the biggest strike correctly, and, we can't do anything about it */ + } + #undef STRIKES_MAX + + for (unsigned int strike = 0; strike < strikes_count; strike++) + for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) + { + unsigned int ppem = strikes[strike]; + hb_font_set_ppem (font, ppem, ppem); + hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id); + + if (hb_blob_get_length (blob) == 0) continue; + + unsigned int length; + const char *data = hb_blob_get_data (blob, &length); + + char output_path[255]; + sprintf (output_path, "out/png-%d-%d-%d.png", glyph_id, strike, face_index); + + FILE *f = fopen (output_path, "wb"); + fwrite (data, 1, length, f); + fclose (f); + + hb_blob_destroy (blob); + } + + hb_font_destroy (font); +} + +static void +svg_dump (hb_face_t *face, unsigned int face_index) +{ + unsigned glyph_count = hb_face_get_glyph_count (face); + + for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) + { + hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id); + + if (hb_blob_get_length (blob) == 0) continue; + + unsigned int length; + const char *data = hb_blob_get_data (blob, &length); + + char output_path[255]; + sprintf (output_path, "out/svg-%d-%d.svg%s", + glyph_id, + face_index, + // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 + (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : ""); + + FILE *f = fopen (output_path, "wb"); + fwrite (data, 1, length, f); + fclose (f); + + hb_blob_destroy (blob); + } +} + +static void +layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int face_index) +{ + unsigned int upem = hb_face_get_upem (face); + + unsigned glyph_count = hb_face_get_glyph_count (face); + for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid) + { + unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr); + if (!num_layers) + continue; + + hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t)); + + hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers); + if (num_layers) + { + // Measure + cairo_text_extents_t extents; + { + cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); + cairo_t *cr = cairo_create (surface); + cairo_set_font_face (cr, cairo_face); + cairo_set_font_size (cr, upem); + + cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t)); + for (unsigned int j = 0; j < num_layers; ++j) + glyphs[j].index = layers[j].glyph; + cairo_glyph_extents (cr, glyphs, num_layers, &extents); + free (glyphs); + cairo_surface_destroy (surface); + cairo_destroy (cr); + } + + // Add a slight margin + extents.width += extents.width / 10; + extents.height += extents.height / 10; + extents.x_bearing -= extents.width / 20; + extents.y_bearing -= extents.height / 20; + + // Render + unsigned int palette_count = hb_ot_color_palette_get_count (face); + for (unsigned int palette = 0; palette < palette_count; palette++) { + char output_path[255]; + + unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr); + if (!num_colors) + continue; + + hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t)); + hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors); + if (num_colors) + { + sprintf (output_path, "out/colr-%d-%d-%d.svg", gid, palette, face_index); + + cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); + cairo_t *cr = cairo_create (surface); + cairo_set_font_face (cr, cairo_face); + cairo_set_font_size (cr, upem); + + for (unsigned int layer = 0; layer < num_layers; ++layer) + { + hb_color_t color = 0x000000FF; + if (layers[layer].color_index != 0xFFFF) + color = colors[layers[layer].color_index]; + cairo_set_source_rgba (cr, + hb_color_get_red (color) / 255., + hb_color_get_green (color) / 255., + hb_color_get_blue (color) / 255., + hb_color_get_alpha (color) / 255.); + + cairo_glyph_t glyph; + glyph.index = layers[layer].glyph; + glyph.x = -extents.x_bearing; + glyph.y = -extents.y_bearing; + cairo_show_glyphs (cr, &glyph, 1); + } + + cairo_surface_destroy (surface); + cairo_destroy (cr); + } + free (colors); + } + } + + free (layers); + } +} + +static void +dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, + unsigned int num_glyphs, unsigned int face_index) +{ + for (unsigned int i = 0; i < num_glyphs; ++i) + { + cairo_text_extents_t extents; + cairo_glyph_t glyph = {0}; + glyph.index = i; + + // Measure + { + cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); + cairo_t *cr = cairo_create (surface); + cairo_set_font_face (cr, cairo_face); + cairo_set_font_size (cr, upem); + + cairo_glyph_extents (cr, &glyph, 1, &extents); + cairo_surface_destroy (surface); + cairo_destroy (cr); + } + + // Add a slight margin + extents.width += extents.width / 10; + extents.height += extents.height / 10; + extents.x_bearing -= extents.width / 20; + extents.y_bearing -= extents.height / 20; + + // Render + { + char output_path[255]; + sprintf (output_path, "out/%d-%d.svg", face_index, i); + cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); + cairo_t *cr = cairo_create (surface); + cairo_set_font_face (cr, cairo_face); + cairo_set_font_size (cr, upem); + glyph.x = -extents.x_bearing; + glyph.y = -extents.y_bearing; + cairo_show_glyphs (cr, &glyph, 1); + cairo_surface_destroy (surface); + cairo_destroy (cr); + } + } +} + +int +main (int argc, char **argv) +{ + if (argc != 2) { + fprintf (stderr, "usage: %s font-file.ttf\n" + "run it like `rm -rf out && mkdir out && %s font-file.ttf`\n", + argv[0], argv[0]); + exit (1); + } + + + FILE *font_name_file = fopen ("out/.dumped_font_name", "r"); + if (font_name_file != nullptr) + { + fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n"); + exit (1); + } + + font_name_file = fopen ("out/.dumped_font_name", "w"); + if (font_name_file == nullptr) + { + fprintf (stderr, "./out is not accessible as a folder, create it please\n"); + exit (1); + } + fwrite (argv[1], 1, strlen (argv[1]), font_name_file); + fclose (font_name_file); + + hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + unsigned int num_faces = hb_face_count (blob); + if (num_faces == 0) + { + fprintf (stderr, "error: The file (%s) was corrupted, empty or not found", argv[1]); + exit (1); + } + + for (unsigned int face_index = 0; face_index < hb_face_count (blob); face_index++) + { + hb_face_t *face = hb_face_create (blob, face_index); + hb_font_t *font = hb_font_create (face); + + if (hb_ot_color_has_png (face)) printf ("Dumping png (cbdt/sbix)...\n"); + png_dump (face, face_index); + + if (hb_ot_color_has_svg (face)) printf ("Dumping svg...\n"); + svg_dump (face, face_index); + + cairo_font_face_t *cairo_face; + { + FT_Library library; + FT_Init_FreeType (&library); + FT_Face ft_face; + FT_New_Face (library, argv[1], 0, &ft_face); + cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); + } + if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face)) + printf ("Dumping layered color glyphs...\n"); + layered_glyph_dump (face, cairo_face, face_index); + + unsigned int num_glyphs = hb_face_get_glyph_count (face); + unsigned int upem = hb_face_get_upem (face); + + // disabled when color font as cairo rendering of NotoColorEmoji is soooo slow + if (!hb_ot_color_has_layers (face) && + !hb_ot_color_has_png (face) && + !hb_ot_color_has_svg (face)) + dump_glyphs (cairo_face, upem, num_glyphs, face_index); + + hb_font_destroy (font); + hb_face_destroy (face); + } + + hb_blob_destroy (blob); + + return 0; +} diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-size-params.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-size-params.cc index e53a47d8df6..12eec618838 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-size-params.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-size-params.cc @@ -46,7 +46,7 @@ main (int argc, char **argv) blob = nullptr; unsigned int p[5]; - bool ret = hb_ot_layout_get_size_params (face, p, p+1, p+2, p+3, p+4); + bool ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4); printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.); |