commit
e215e4b51d
|
@ -0,0 +1,25 @@
|
|||
name: arm
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
arm-none-eabi:
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: devkitpro/devkitarm:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cmake -S . -B build \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/3DS.cmake
|
||||
- name: Build
|
||||
run: make CXX_FLAGS="-w -DHB_NO_MT"
|
||||
working-directory: build
|
47
NEWS
47
NEWS
|
@ -1,3 +1,50 @@
|
|||
Overview of changes leading to 5.3.1
|
||||
Wednesday, October 19, 2022
|
||||
====================================
|
||||
- Subsetter repacker fixes. (Garret Rieger)
|
||||
- Adjust Grapheme clusters for Katakana voiced sound marks. (Behdad Esfahbod)
|
||||
- New “hb-subset” option “--preprocess-face”. (Garret Rieger)
|
||||
|
||||
|
||||
Overview of changes leading to 5.3.0
|
||||
Saturday, October 8, 2022
|
||||
"Women, Life, Freedom" #MahsaAmini
|
||||
====================================
|
||||
- Don’t add glyphs from dropped MATH or COLR tables to the subset glyphs.
|
||||
(Khaled Hosny)
|
||||
- Map “rlig” to appropriate AAT feature selectors. (Jonathan Kew)
|
||||
- Update USE data files to latest version. (David Corbett)
|
||||
- Check “CBDT” extents first before outline tables, to help with fonts that
|
||||
also include an empty “glyf” table. (Khaled Hosny)
|
||||
- More work towards variable font instancing in the subsetter. (Qunxin Liu)
|
||||
- Subsetter repacker improvements. (Garret Rieger)
|
||||
- New API:
|
||||
+hb_ot_layout_lookup_get_optical_bound()
|
||||
+hb_face_builder_sort_tables()
|
||||
|
||||
|
||||
Overview of changes leading to 5.2.0
|
||||
Saturday, September 17, 2022
|
||||
====================================
|
||||
- Fix regressions in hb-ft font functions for FT_Face’s with transformation
|
||||
matrix. (Behdad Esfahbod)
|
||||
- The experimental hb-repacker API now supports splitting several GPOS subtable
|
||||
types when needed. (Garret Rieger)
|
||||
- The HarfBuzz extensions to OpenType font format are now opt-in behind
|
||||
build-time flags. (Behdad Esfahbod)
|
||||
- The experimental hb-subset variable fonts instantiation API can now
|
||||
instantiate more font tables and arbitrary axis locations. (Qunxin Liu)
|
||||
- Unicode 15 support. (David Corbett)
|
||||
- Various documentation improvements. (Behdad Esfahbod, Matthias Clasen)
|
||||
- The hb-view command line tool now detects WezTerm inline images support.
|
||||
(Wez Furlong)
|
||||
- Fix FreeType and ICU dependency lookup with meson. (Xavier Claessens)
|
||||
|
||||
- New API:
|
||||
+HB_SCRIPT_KAWI
|
||||
+HB_SCRIPT_NAG_MUNDARI
|
||||
|
||||
|
||||
Overview of changes leading to 5.1.0
|
||||
Sunday, July 31, 2022
|
||||
====================================
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[5.1.0],
|
||||
[5.3.1],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
<index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="deprecated-api-index" role="deprecated"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
|
||||
|
||||
<index id="api-index-5-3-0" role="5.3.0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-0-0" role="5.0.0"><title>Index of new symbols in 5.0.0</title><xi:include href="xml/api-index-5.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-4-0" role="4.4.0"><title>Index of new symbols in 4.4.0</title><xi:include href="xml/api-index-4.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-4-3-0" role="4.3.0"><title>Index of new symbols in 4.3.0</title><xi:include href="xml/api-index-4.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
|
|
|
@ -285,6 +285,7 @@ hb_face_collect_variation_selectors
|
|||
hb_face_collect_variation_unicodes
|
||||
hb_face_builder_create
|
||||
hb_face_builder_add_table
|
||||
hb_face_builder_sort_tables
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -554,6 +555,7 @@ hb_ot_layout_language_get_feature_tags
|
|||
hb_ot_layout_language_get_required_feature
|
||||
hb_ot_layout_lookup_collect_glyphs
|
||||
hb_ot_layout_lookup_get_glyph_alternates
|
||||
hb_ot_layout_lookup_get_optical_bound
|
||||
hb_ot_layout_lookup_substitute_closure
|
||||
hb_ot_layout_lookups_substitute_closure
|
||||
hb_ot_layout_lookup_would_substitute
|
||||
|
@ -786,4 +788,7 @@ hb_subset_plan_old_to_new_glyph_mapping
|
|||
hb_link_t
|
||||
hb_object_t
|
||||
hb_subset_repack_or_fail
|
||||
hb_subset_preprocess
|
||||
hb_subset_input_pin_axis_location
|
||||
hb_subset_input_pin_axis_to_default
|
||||
</SECTION>
|
||||
|
|
|
@ -54,6 +54,12 @@ There's four key pieces to the harfbuzz approach:
|
|||
to calculate the final position of each subtable and then check if any offsets to it will
|
||||
overflow.
|
||||
|
||||
* Content Aware Preprocessing: if the overflow resolver is aware of the format of the underlying
|
||||
tables (eg. GSUB, GPOS) then in some cases preprocessing can be done to increase the chance of
|
||||
successfully packing the graph. For example for GSUB and GPOS we can preprocess the graph and
|
||||
promote lookups to extension lookups (upgrades a 16 bit offset to 32 bits) or split large lookup
|
||||
subtables into two or more pieces.
|
||||
|
||||
* Offset resolution strategies: given a particular occurrence of an overflow these strategies
|
||||
modify the graph to attempt to resolve the overflow.
|
||||
|
||||
|
@ -64,6 +70,7 @@ def repack(graph):
|
|||
graph.topological_sort()
|
||||
|
||||
if (graph.will_overflow())
|
||||
preprocess(graph)
|
||||
assign_spaces(graph)
|
||||
graph.topological_sort()
|
||||
|
||||
|
@ -185,6 +192,37 @@ The assign_spaces() step in the high level algorithm is responsible for identify
|
|||
subgraphs and assigning unique spaces to each one. More information on the space assignment can be
|
||||
found in the next section.
|
||||
|
||||
# Graph Preprocessing
|
||||
|
||||
For certain table types we can preprocess and modify the graph structure to reduce the occurences
|
||||
of overflows. Currently the repacker implements preprocessing only for GPOS and GSUB tables.
|
||||
|
||||
## GSUB/GPOS Table Splitting
|
||||
|
||||
The GSUB/GPOS preprocessor scans each lookup subtable and determines if the subtable's children are
|
||||
so large that no overflow resolution is possible (for example a single subtable that exceeds 65kb
|
||||
cannot be pointed over). When such cases are detected table splitting is invoked:
|
||||
|
||||
* The subtable is first analyzed to determine the smallest number of split points that will allow
|
||||
for successful offset overflow resolution.
|
||||
|
||||
* Then the subtable in the graph representation is modified to actually perform the split at the
|
||||
previously computed split points. At a high level splits are done by inserting new subtables
|
||||
which contain a subset of the data of the original subtable and then shrinking the original subtable.
|
||||
|
||||
Table splitting must be aware of the underlying format of each subtable type and thus needs custom
|
||||
code for each subtable type. Currently subtable splitting is only supported for GPOS subtable types.
|
||||
|
||||
## GSUB/GPOS Extension Lookup Promotion
|
||||
|
||||
In GSUB/GPOS tables lookups can be regular lookups which use 16 bit offsets to the children subtables
|
||||
or extension lookups which use 32 bit offsets to the children subtables. If the sub graph of all
|
||||
regular lookups is too large then it can be difficult to find an overflow free configuration. This
|
||||
can be remedied by promoting one or more regular lookups to extension lookups.
|
||||
|
||||
During preprocessing the graph is scanned to determine the size of the subgraph of regular lookups.
|
||||
If the graph is found to be too big then the analysis finds a set of lookups to promote to reduce
|
||||
the subgraph size. Lastly the graph is modified to convert those lookups to extension lookups.
|
||||
|
||||
# Offset Resolution Strategies
|
||||
|
||||
|
@ -237,29 +275,20 @@ The harfbuzz repacker has tests defined using generic graphs: https://github.com
|
|||
|
||||
# Future Improvements
|
||||
|
||||
The above resolution strategies are not sufficient to resolve all overflows. For example consider
|
||||
the case where a single subtable is 65k and the graph structure requires an offset to point over it.
|
||||
Currently for GPOS tables the repacker implementation is sufficient to handle both subsetting and the
|
||||
general case of font compilation repacking. However for GSUB the repacker is only sufficient for
|
||||
subsetting related overflows. To enable general case repacking of GSUB, support for splitting of
|
||||
GSUB subtables will need to be added. Other table types such as COLRv1 shouldn't require table
|
||||
splitting due to the wide use of 24 bit offsets throughout the table.
|
||||
|
||||
The current harfbuzz implementation is suitable for the vast majority of subsetting related overflows.
|
||||
Subsetting related overflows are typically easy to solve since all subsets are derived from a font
|
||||
that was originally overflow free. A more general purpose version of the algorithm suitable for font
|
||||
creation purposes will likely need some additional offset resolution strategies:
|
||||
Beyond subtable splitting there are a couple of "nice to have" improvements, but these are not required
|
||||
to support the general case:
|
||||
|
||||
* Extension demotion: currently extension promotion is supported but in some cases if the non-extension
|
||||
subgraph is underfilled then packed size can be reduced by demoting extension lookups back to regular
|
||||
lookups.
|
||||
|
||||
* Currently only children nodes are moved to resolve offsets. However, in many cases moving a parent
|
||||
node closer to it's children will have less impact on the size of other offsets. Thus the algorithm
|
||||
should use a heuristic (based on parent and child subtable sizes) to decide if the children's
|
||||
priority should be increased or the parent's priority decreased.
|
||||
|
||||
* Many subtables can be split into two smaller subtables without impacting the overall functionality.
|
||||
This should be done when an overflow is the result of a very large table which can't be moved
|
||||
to avoid offsets pointing over it.
|
||||
|
||||
* Lookup subtables in GSUB/GPOS can be upgraded to extension lookups which uses a 32 bit offset.
|
||||
Overflows from a Lookup subtable to it's child should be resolved by converting to an extension
|
||||
lookup.
|
||||
|
||||
Once additional resolution strategies are added to the algorithm it's likely that we'll need to
|
||||
switch to using a [backtracking algorithm](https://en.wikipedia.org/wiki/Backtracking) to explore
|
||||
the various combinations of resolution strategies until a non-overflowing combination is found. This
|
||||
will require the ability to restore the graph to an earlier state. It's likely that using a stack
|
||||
of undoable resolution commands could be used to accomplish this.
|
||||
|
|
36
meson.build
36
meson.build
|
@ -1,6 +1,6 @@
|
|||
project('harfbuzz', 'c', 'cpp',
|
||||
meson_version: '>= 0.55.0',
|
||||
version: '5.1.0',
|
||||
version: '5.3.1',
|
||||
default_options: [
|
||||
'cpp_rtti=false', # Just to support msvc, we are passing -fno-exceptions also anyway
|
||||
'cpp_std=c++11',
|
||||
|
@ -83,25 +83,39 @@ check_funcs = [
|
|||
|
||||
m_dep = cpp.find_library('m', required: false)
|
||||
|
||||
# https://github.com/harfbuzz/harfbuzz/pull/2498
|
||||
freetype_dep = dependency(cpp.get_argument_syntax() == 'msvc' ? 'freetype' : 'freetype2',
|
||||
required: get_option('freetype'),
|
||||
default_options: ['harfbuzz=disabled'])
|
||||
|
||||
# Try pkgconfig name
|
||||
freetype_dep = dependency('freetype2', required: false)
|
||||
if not freetype_dep.found()
|
||||
# Try cmake name
|
||||
freetype_dep = dependency('freetype', required: false)
|
||||
endif
|
||||
if not freetype_dep.found()
|
||||
# Subproject fallback, `allow_fallback: true` means the fallback will be
|
||||
# tried even if the freetype option is set to `auto`.
|
||||
freetype_dep = dependency('freetype2',
|
||||
required: get_option('freetype'),
|
||||
default_options: ['harfbuzz=disabled'],
|
||||
allow_fallback: true)
|
||||
endif
|
||||
|
||||
glib_dep = dependency('glib-2.0', required: get_option('glib'))
|
||||
gobject_dep = dependency('gobject-2.0', required: get_option('gobject'))
|
||||
graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
|
||||
graphite_dep = dependency('graphite2', required: get_option('graphite'))
|
||||
|
||||
if cpp.get_argument_syntax() == 'msvc'
|
||||
# Try pkgconfig name
|
||||
icu_dep = dependency('icu-uc', required: false)
|
||||
if not icu_dep.found()
|
||||
# Try cmake name
|
||||
icu_dep = dependency('ICU',
|
||||
required: get_option('icu'),
|
||||
required: false,
|
||||
components: 'uc',
|
||||
method: 'cmake')
|
||||
else
|
||||
icu_dep = dependency('icu-uc',
|
||||
required: get_option('icu'),
|
||||
method: 'pkg-config')
|
||||
endif
|
||||
if not icu_dep.found()
|
||||
# Subproject fallback if icu option is enabled
|
||||
icu_dep = dependency('icu-uc', required: get_option('icu'))
|
||||
endif
|
||||
|
||||
if icu_dep.found() and icu_dep.type_name() == 'pkgconfig'
|
||||
|
|
|
@ -97,6 +97,19 @@ void AddGlyphs(unsigned num_glyphs_in_font,
|
|||
}
|
||||
}
|
||||
|
||||
// Preprocess face and populate the subset accelerator on it to speed up
|
||||
// the subsetting operations.
|
||||
static hb_face_t* preprocess_face(hb_face_t* face)
|
||||
{
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
hb_face_t* new_face = hb_subset_preprocess(face);
|
||||
hb_face_destroy(face);
|
||||
return new_face;
|
||||
#else
|
||||
return face;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* benchmark for subsetting a font */
|
||||
static void BM_subset (benchmark::State &state,
|
||||
operation_t operation,
|
||||
|
@ -110,6 +123,8 @@ static void BM_subset (benchmark::State &state,
|
|||
assert (blob);
|
||||
face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
face = preprocess_face (face);
|
||||
}
|
||||
|
||||
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
|
||||
|
|
|
@ -341,6 +341,7 @@ HB_SUBSET_sources = \
|
|||
hb-subset-cff2.hh \
|
||||
hb-subset-input.cc \
|
||||
hb-subset-input.hh \
|
||||
hb-subset-accelerator.hh \
|
||||
hb-subset-plan.cc \
|
||||
hb-subset-plan.hh \
|
||||
hb-subset-repacker.cc \
|
||||
|
|
|
@ -39,7 +39,7 @@ struct GPOS : GSUBGPOS
|
|||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
|
||||
hb_subset_layout_context_t l (c, tableTag);
|
||||
return GSUBGPOS::subset<PosLookup> (&l);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,24 @@ struct SinglePosFormat1
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer;
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer);
|
||||
|
||||
valueFormat.apply_value (&c, this, values, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
|
|
|
@ -68,7 +68,7 @@ struct SinglePosFormat2
|
|||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
if (likely (index >= valueCount)) return_trace (false);
|
||||
if (unlikely (index >= valueCount)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
|
@ -92,6 +92,28 @@ struct SinglePosFormat2
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
if (unlikely (index >= valueCount)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer;
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer);
|
||||
|
||||
valueFormat.apply_value (&c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
|
|
|
@ -27,7 +27,7 @@ struct GSUB : GSUBGPOS
|
|||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
|
||||
hb_subset_layout_context_t l (c, tableTag);
|
||||
return GSUBGPOS::subset<SubstLookup> (&l);
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ struct Ligature
|
|||
match_positions[i] += delta;
|
||||
if (i)
|
||||
*p++ = ',';
|
||||
sprintf (p, "%u", match_positions[i]);
|
||||
snprintf (p, sizeof(buf), "%u", match_positions[i]);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ struct Sequence
|
|||
{
|
||||
if (buf < p)
|
||||
*p++ = ',';
|
||||
sprintf (p, "%u", i);
|
||||
snprintf (p, sizeof(buf), "%u", i);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ struct SingleSubstFormat1_3
|
|||
hb_codepoint_t max_before = intersection.get_max ();
|
||||
hb_codepoint_t min_after = (min_before + d) & mask;
|
||||
hb_codepoint_t max_after = (max_before + d) & mask;
|
||||
if (pop >= max_before - min_before &&
|
||||
if (intersection.get_population () == max_before - min_before + 1 &&
|
||||
((min_before <= min_after && min_after <= max_before) ||
|
||||
(min_before <= max_after && max_after <= max_before)))
|
||||
return;
|
||||
|
|
|
@ -16,6 +16,11 @@ struct glyf_accelerator_t;
|
|||
namespace glyf_impl {
|
||||
|
||||
|
||||
#ifndef HB_GLYF_MAX_POINTS
|
||||
#define HB_GLYF_MAX_POINTS 10000
|
||||
#endif
|
||||
|
||||
|
||||
enum phantom_point_index_t
|
||||
{
|
||||
PHANTOM_LEFT = 0,
|
||||
|
@ -102,17 +107,19 @@ struct Glyph
|
|||
hb_bytes_t &dest_bytes /* OUT */) const
|
||||
{
|
||||
GlyphHeader *glyph_header = nullptr;
|
||||
if (all_points.length > 4)
|
||||
if (type != EMPTY && all_points.length > 4)
|
||||
{
|
||||
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||
if (unlikely (!glyph_header)) return false;
|
||||
}
|
||||
|
||||
int xMin, xMax;
|
||||
xMin = xMax = roundf (all_points[0].x);
|
||||
|
||||
int yMin, yMax;
|
||||
yMin = yMax = roundf (all_points[0].y);
|
||||
int xMin = 0, xMax = 0;
|
||||
int yMin = 0, yMax = 0;
|
||||
if (all_points.length > 4)
|
||||
{
|
||||
xMin = xMax = roundf (all_points[0].x);
|
||||
yMin = yMax = roundf (all_points[0].y);
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i < all_points.length - 4; i++)
|
||||
{
|
||||
|
@ -128,7 +135,7 @@ struct Glyph
|
|||
|
||||
/*for empty glyphs: all_points only include phantom points.
|
||||
*just update metrics and then return */
|
||||
if (all_points.length == 4)
|
||||
if (!glyph_header)
|
||||
return true;
|
||||
|
||||
glyph_header->numberOfContours = header->numberOfContours;
|
||||
|
@ -145,10 +152,17 @@ struct Glyph
|
|||
hb_font_t *font,
|
||||
const glyf_accelerator_t &glyf,
|
||||
hb_bytes_t &dest_start, /* IN/OUT */
|
||||
hb_bytes_t &dest_end /* OUT */) const
|
||||
hb_bytes_t &dest_end /* OUT */)
|
||||
{
|
||||
contour_point_vector_t all_points, deltas;
|
||||
get_points (font, glyf, all_points, &deltas, false);
|
||||
if (!get_points (font, glyf, all_points, &deltas, false, false))
|
||||
return false;
|
||||
|
||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
||||
// it
|
||||
if (gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
type = EMPTY;
|
||||
|
||||
switch (type) {
|
||||
case COMPOSITE:
|
||||
|
@ -171,7 +185,12 @@ struct Glyph
|
|||
break;
|
||||
}
|
||||
|
||||
return compile_header_bytes (plan, all_points, dest_start);
|
||||
if (!compile_header_bytes (plan, all_points, dest_start))
|
||||
{
|
||||
dest_end.fini ();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,6 +201,7 @@ struct Glyph
|
|||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||
bool shift_points_hori = true,
|
||||
bool use_my_metrics = true,
|
||||
bool phantom_only = false,
|
||||
unsigned int depth = 0) const
|
||||
|
@ -238,8 +258,7 @@ struct Glyph
|
|||
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
{
|
||||
if (unlikely (!deltas->resize (points.length))) return false;
|
||||
for (unsigned i = 0 ; i < points.length; i++)
|
||||
deltas->arrayZ[i] = points.arrayZ[i];
|
||||
deltas->copy_vector (points);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
|
@ -271,14 +290,9 @@ struct Glyph
|
|||
comp_points.reset ();
|
||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||
.get_points (font, glyf_accelerator, comp_points,
|
||||
deltas, use_my_metrics, phantom_only, depth + 1)))
|
||||
deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
|
||||
return false;
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
if (use_my_metrics && item.is_use_my_metrics ())
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
/* Apply component transformation & translation */
|
||||
item.transform_points (comp_points);
|
||||
|
||||
|
@ -299,6 +313,14 @@ struct Glyph
|
|||
}
|
||||
}
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
if (use_my_metrics && item.is_use_my_metrics ())
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
||||
return false;
|
||||
|
||||
all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||
|
||||
comp_index++;
|
||||
|
@ -310,7 +332,7 @@ struct Glyph
|
|||
all_points.extend (phantoms);
|
||||
}
|
||||
|
||||
if (depth == 0) /* Apply at top level */
|
||||
if (depth == 0 && shift_points_hori) /* Apply at top level */
|
||||
{
|
||||
/* Undocumented rasterizer behavior:
|
||||
* Shift points horizontally by the updated left side bearing
|
||||
|
@ -332,10 +354,16 @@ struct Glyph
|
|||
|
||||
hb_bytes_t get_bytes () const { return bytes; }
|
||||
|
||||
Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
|
||||
hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
gid (gid_)
|
||||
Glyph () : bytes (),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
gid (-1),
|
||||
type(EMPTY)
|
||||
{}
|
||||
|
||||
Glyph (hb_bytes_t bytes_,
|
||||
hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
gid (gid_)
|
||||
{
|
||||
int num_contours = header->numberOfContours;
|
||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||
|
|
|
@ -271,31 +271,29 @@ struct SimpleGlyph
|
|||
}
|
||||
//convert absolute values to relative values
|
||||
unsigned num_points = all_points.length - 4;
|
||||
hb_vector_t<hb_pair_t<int, int>> deltas;
|
||||
deltas.resize (num_points);
|
||||
|
||||
for (unsigned i = 0; i < num_points; i++)
|
||||
{
|
||||
deltas[i].first = i == 0 ? roundf (all_points[i].x) : roundf (all_points[i].x) - roundf (all_points[i-1].x);
|
||||
deltas[i].second = i == 0 ? roundf (all_points[i].y) : roundf (all_points[i].y) - roundf (all_points[i-1].y);
|
||||
}
|
||||
|
||||
hb_vector_t<uint8_t> flags, x_coords, y_coords;
|
||||
flags.alloc (num_points);
|
||||
x_coords.alloc (2*num_points);
|
||||
y_coords.alloc (2*num_points);
|
||||
if (unlikely (!flags.alloc (num_points))) return false;
|
||||
if (unlikely (!x_coords.alloc (2*num_points))) return false;
|
||||
if (unlikely (!y_coords.alloc (2*num_points))) return false;
|
||||
|
||||
uint8_t lastflag = 0, repeat = 0;
|
||||
int prev_x = 0.f, prev_y = 0.f;
|
||||
|
||||
for (unsigned i = 0; i < num_points; i++)
|
||||
{
|
||||
uint8_t flag = all_points[i].flag;
|
||||
flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
|
||||
|
||||
encode_coord (deltas[i].first, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
||||
encode_coord (deltas[i].second, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
||||
float cur_x = roundf (all_points[i].x);
|
||||
float cur_y = roundf (all_points[i].y);
|
||||
encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
||||
encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
||||
if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
|
||||
encode_flag (flag, repeat, lastflag, flags);
|
||||
|
||||
prev_x = cur_x;
|
||||
prev_y = cur_y;
|
||||
}
|
||||
|
||||
unsigned len_before_instrs = 2 * header.numberOfContours + 2;
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace glyf_impl {
|
|||
|
||||
struct SubsetGlyph
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
hb_codepoint_t old_gid;
|
||||
Glyph source_glyph;
|
||||
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||
|
|
|
@ -72,10 +72,13 @@ struct glyf
|
|||
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
||||
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
||||
_populate_subset_glyphs (c->plan, &glyphs);
|
||||
_populate_subset_glyphs (c->plan, glyphs);
|
||||
|
||||
if (!c->plan->pinned_at_default)
|
||||
_compile_subset_glyphs_with_deltas (c->plan, &glyphs);
|
||||
{
|
||||
if (!_compile_subset_glyphs_with_deltas (c->plan, &glyphs))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
auto padded_offsets =
|
||||
+ hb_iter (glyphs)
|
||||
|
@ -105,9 +108,9 @@ struct glyf
|
|||
|
||||
void
|
||||
_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
|
||||
|
||||
void
|
||||
bool
|
||||
_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||
|
||||
|
@ -180,7 +183,7 @@ struct glyf_accelerator_t
|
|||
contour_point_vector_t all_points;
|
||||
|
||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only)))
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, true, phantom_only)))
|
||||
return false;
|
||||
|
||||
if (consumer.is_consuming_contour_points ())
|
||||
|
@ -374,44 +377,43 @@ struct glyf_accelerator_t
|
|||
|
||||
inline void
|
||||
glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
|
||||
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
unsigned num_glyphs = plan->num_output_glyphs ();
|
||||
if (!glyphs.resize (num_glyphs)) return;
|
||||
|
||||
+ hb_range (plan->num_output_glyphs ())
|
||||
| hb_map ([&] (hb_codepoint_t new_gid)
|
||||
{
|
||||
glyf_impl::SubsetGlyph subset_glyph = {0};
|
||||
subset_glyph.new_gid = new_gid;
|
||||
for (auto p : plan->glyph_map->iter ())
|
||||
{
|
||||
unsigned new_gid = p.second;
|
||||
glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
|
||||
subset_glyph.old_gid = p.first;
|
||||
|
||||
/* should never fail: all old gids should be mapped */
|
||||
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
|
||||
return subset_glyph;
|
||||
if (unlikely (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
|
||||
plan->pinned_at_default)
|
||||
subset_glyph.source_glyph = glyf_impl::Glyph ();
|
||||
else
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
|
||||
if (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
subset_glyph.source_glyph = glyf_impl::Glyph ();
|
||||
else
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
return subset_glyph;
|
||||
})
|
||||
| hb_sink (glyphs)
|
||||
;
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
inline bool
|
||||
glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
hb_font_t *font = hb_font_create (plan->source);
|
||||
if (unlikely (!font)) return false;
|
||||
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
vars.alloc (plan->user_axes_location->get_population ());
|
||||
if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
|
||||
return false;
|
||||
|
||||
for (auto _ : *plan->user_axes_location)
|
||||
{
|
||||
|
@ -423,9 +425,16 @@ glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
|||
|
||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
|
||||
for (auto& subset_glyph : *glyphs)
|
||||
const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf);
|
||||
{
|
||||
if (!const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hb_font_destroy (font);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-icu', 'harfbuzz-gobject'
|
|||
symprefix = '_' if suffix == 'dylib' else ''
|
||||
|
||||
EXPORTED_SYMBOLS = [s.split ()[2]
|
||||
for s in re.findall (r'^.+ [BCDGIRST] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
|
||||
for s in re.findall (r'^.+ [BCDGIRSTu] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
|
||||
if not re.match (r'.* %s(%s)\b' % (symprefix, IGNORED_SYMBOLS), s)]
|
||||
|
||||
# run again c++filt also if is available
|
||||
|
|
|
@ -21,7 +21,9 @@ if '--experimental-api' not in sys.argv:
|
|||
experimental_symbols = \
|
||||
"""hb_subset_repack_or_fail
|
||||
hb_subset_input_pin_axis_location
|
||||
hb_subset_input_pin_axis_to_default""".splitlines ()
|
||||
hb_subset_input_pin_axis_to_default
|
||||
hb_subset_preprocess
|
||||
""".splitlines ()
|
||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||
symbols = "\n".join (symbols)
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ property_names = [
|
|||
'Number_Joiner',
|
||||
'Number',
|
||||
'Brahmi_Joining_Number',
|
||||
'Symbol_Modifier',
|
||||
'Hieroglyph',
|
||||
'Hieroglyph_Joiner',
|
||||
'Hieroglyph_Segment_Begin',
|
||||
|
@ -214,8 +215,7 @@ def is_CONS_MED(U, UISC, UDI, UGC, AJT):
|
|||
return (UISC == Consonant_Medial and UGC != Lo or
|
||||
UISC == Consonant_Initial_Postfixed)
|
||||
def is_CONS_MOD(U, UISC, UDI, UGC, AJT):
|
||||
return (UISC in [Nukta, Gemination_Mark, Consonant_Killer] and
|
||||
not is_SYM_MOD(U, UISC, UDI, UGC, AJT))
|
||||
return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
|
||||
def is_CONS_SUB(U, UISC, UDI, UGC, AJT):
|
||||
return UISC == Consonant_Subjoined and UGC != Lo
|
||||
def is_CONS_WITH_STACKER(U, UISC, UDI, UGC, AJT):
|
||||
|
@ -257,7 +257,7 @@ def is_SAKOT(U, UISC, UDI, UGC, AJT):
|
|||
# Split off of HALANT
|
||||
return U == 0x1A60
|
||||
def is_SYM_MOD(U, UISC, UDI, UGC, AJT):
|
||||
return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
|
||||
return UISC == Symbol_Modifier
|
||||
def is_VOWEL(U, UISC, UDI, UGC, AJT):
|
||||
return (UISC == Pure_Killer or
|
||||
UGC != Lo and UISC in [Vowel, Vowel_Dependent])
|
||||
|
@ -359,9 +359,6 @@ def map_to_use(data):
|
|||
# TODO: These don't have UISC assigned in Unicode 13.0.0, but have UIPC
|
||||
if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
|
||||
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/627
|
||||
if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
|
||||
|
||||
# TODO: U+1CED should only be allowed after some of
|
||||
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
|
||||
if U == 0x1CED: UISC = Tone_Mark
|
||||
|
@ -372,23 +369,9 @@ def map_to_use(data):
|
|||
|
||||
# Resolve Indic_Positional_Category
|
||||
|
||||
# TODO: These should die, but have UIPC in Unicode 13.0.0
|
||||
if U in [0x953, 0x954]: UIPC = Not_Applicable
|
||||
|
||||
# TODO: These are not in USE's override list that we have, nor are they in Unicode 13.0.0
|
||||
if 0xA926 <= U <= 0xA92A: UIPC = Top
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/1037
|
||||
# and https://github.com/harfbuzz/harfbuzz/issues/1631
|
||||
if U in [0x11302, 0x11303, 0x114C1]: UIPC = Top
|
||||
if 0x1CF8 <= U <= 0x1CF9: UIPC = Top
|
||||
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/issues/3550
|
||||
if U == 0x10A38: UIPC = Bottom
|
||||
|
||||
# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
|
||||
# also https://github.com/harfbuzz/harfbuzz/issues/1012
|
||||
if 0x1112A <= U <= 0x1112B: UIPC = Top
|
||||
if 0x11131 <= U <= 0x11132: UIPC = Top
|
||||
|
||||
assert (UIPC in [Not_Applicable, Visual_Order_Left] or U == 0x0F7F or
|
||||
USE in use_positions), "%s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UDI, UGC, AJT)
|
||||
|
|
|
@ -70,8 +70,8 @@ struct graph_t
|
|||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
"vertex [%lu] bytes != [%lu] bytes, depth = %u",
|
||||
table_size (),
|
||||
other.table_size (),
|
||||
(unsigned long) table_size (),
|
||||
(unsigned long) other.table_size (),
|
||||
depth);
|
||||
|
||||
auto a = as_bytes ();
|
||||
|
@ -495,6 +495,12 @@ struct graph_t
|
|||
return as_table_from_index<T> (index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
||||
}
|
||||
|
||||
template <typename T, typename ...Ts>
|
||||
vertex_and_table_t<T> as_mutable_table (unsigned parent, const void* offset, Ts... ds)
|
||||
{
|
||||
return as_table_from_index<T> (mutable_index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
||||
}
|
||||
|
||||
template <typename T, typename ...Ts>
|
||||
vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds)
|
||||
{
|
||||
|
@ -574,7 +580,7 @@ struct graph_t
|
|||
|
||||
while (roots)
|
||||
{
|
||||
unsigned next = HB_SET_VALUE_INVALID;
|
||||
uint32_t next = HB_SET_VALUE_INVALID;
|
||||
if (unlikely (!check_success (!roots.in_error ()))) break;
|
||||
if (!roots.next (&next)) break;
|
||||
|
||||
|
@ -655,8 +661,8 @@ struct graph_t
|
|||
|
||||
auto new_subgraph =
|
||||
+ subgraph.keys ()
|
||||
| hb_map([&] (unsigned node_idx) {
|
||||
const unsigned *v;
|
||||
| hb_map([&] (uint32_t node_idx) {
|
||||
const uint32_t *v;
|
||||
if (index_map.has (node_idx, &v)) return *v;
|
||||
return node_idx;
|
||||
})
|
||||
|
@ -666,10 +672,10 @@ struct graph_t
|
|||
remap_obj_indices (index_map, parents.iter (), true);
|
||||
|
||||
// Update roots set with new indices as needed.
|
||||
unsigned next = HB_SET_VALUE_INVALID;
|
||||
uint32_t next = HB_SET_VALUE_INVALID;
|
||||
while (roots.next (&next))
|
||||
{
|
||||
const unsigned *v;
|
||||
const uint32_t *v;
|
||||
if (index_map.has (next, &v))
|
||||
{
|
||||
roots.del (next);
|
||||
|
@ -684,7 +690,7 @@ struct graph_t
|
|||
{
|
||||
for (const auto& link : vertices_[node_idx].obj.all_links ())
|
||||
{
|
||||
const unsigned *v;
|
||||
const uint32_t *v;
|
||||
if (subgraph.has (link.objidx, &v))
|
||||
{
|
||||
subgraph.set (link.objidx, *v + 1);
|
||||
|
@ -833,7 +839,20 @@ struct graph_t
|
|||
* parent to the clone. The copy is a shallow copy, objects
|
||||
* linked from child are not duplicated.
|
||||
*/
|
||||
bool duplicate (unsigned parent_idx, unsigned child_idx)
|
||||
unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
|
||||
{
|
||||
unsigned new_idx = duplicate (parent_idx, child_idx);
|
||||
if (new_idx == (unsigned) -1) return child_idx;
|
||||
return new_idx;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Creates a copy of child and re-assigns the link from
|
||||
* parent to the clone. The copy is a shallow copy, objects
|
||||
* linked from child are not duplicated.
|
||||
*/
|
||||
unsigned duplicate (unsigned parent_idx, unsigned child_idx)
|
||||
{
|
||||
update_parents ();
|
||||
|
||||
|
@ -849,7 +868,7 @@ struct graph_t
|
|||
// to child are from parent.
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
|
||||
parent_idx, child_idx);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
|
||||
|
@ -869,7 +888,7 @@ struct graph_t
|
|||
reassign_link (l, parent_idx, clone_idx);
|
||||
}
|
||||
|
||||
return true;
|
||||
return clone_idx;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1164,7 +1183,7 @@ struct graph_t
|
|||
{
|
||||
for (auto& link : vertices_[i].obj.all_links_writer ())
|
||||
{
|
||||
const unsigned *v;
|
||||
const uint32_t *v;
|
||||
if (!id_map.has (link.objidx, &v)) continue;
|
||||
if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
|
||||
|
||||
|
|
|
@ -131,8 +131,10 @@ struct Lookup : public OT::Lookup
|
|||
for (unsigned i = 0; i < subTable.len; i++)
|
||||
{
|
||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||
unsigned parent_index = this_index;
|
||||
if (is_ext) {
|
||||
unsigned ext_subtable_index = subtable_index;
|
||||
parent_index = ext_subtable_index;
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
|
||||
c.graph.object (ext_subtable_index).head;
|
||||
|
@ -150,9 +152,9 @@ struct Lookup : public OT::Lookup
|
|||
switch (type)
|
||||
{
|
||||
case 2:
|
||||
new_sub_tables = split_subtable<PairPos> (c, subtable_index); break;
|
||||
new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, subtable_index); break;
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -172,13 +174,14 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
template<typename T>
|
||||
hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_idx,
|
||||
unsigned objidx)
|
||||
{
|
||||
T* sub_table = (T*) c.graph.object (objidx).head;
|
||||
if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
|
||||
return hb_vector_t<unsigned> ();
|
||||
|
||||
return sub_table->split_subtables (c, objidx);
|
||||
return sub_table->split_subtables (c, parent_idx, objidx);
|
||||
}
|
||||
|
||||
void add_sub_tables (gsubgpos_graph_context_t& c,
|
||||
|
|
|
@ -209,7 +209,9 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
return vertex_len >= MarkBasePosFormat1::static_size;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
||||
|
@ -261,7 +263,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
this_index,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
std::move (class_to_info),
|
||||
c.graph.vertices_[mark_array_id].position_to_index_map (),
|
||||
};
|
||||
|
@ -365,8 +367,8 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
|
||||
classCount = count;
|
||||
|
||||
auto mark_coverage = sc.c.graph.as_table<Coverage> (this_index,
|
||||
&markCoverage);
|
||||
auto mark_coverage = sc.c.graph.as_mutable_table<Coverage> (this_index,
|
||||
&markCoverage);
|
||||
if (!mark_coverage) return false;
|
||||
hb_set_t marks = sc.marks_for (0, count);
|
||||
auto new_coverage =
|
||||
|
@ -380,17 +382,17 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
return false;
|
||||
|
||||
|
||||
auto base_array = sc.c.graph.as_table<AnchorMatrix> (this_index,
|
||||
&baseArray,
|
||||
old_count);
|
||||
auto base_array = sc.c.graph.as_mutable_table<AnchorMatrix> (this_index,
|
||||
&baseArray,
|
||||
old_count);
|
||||
if (!base_array || !base_array.table->shrink (sc.c,
|
||||
base_array.index,
|
||||
old_count,
|
||||
count))
|
||||
return false;
|
||||
|
||||
auto mark_array = sc.c.graph.as_table<MarkArray> (this_index,
|
||||
&markArray);
|
||||
auto mark_array = sc.c.graph.as_mutable_table<MarkArray> (this_index,
|
||||
&markArray);
|
||||
if (!mark_array || !mark_array.table->shrink (sc.c,
|
||||
sc.mark_array_links,
|
||||
mark_array.index,
|
||||
|
@ -469,11 +471,12 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 2: HB_FALLTHROUGH;
|
||||
// Don't split 24bit PairPos's.
|
||||
|
|
|
@ -47,7 +47,9 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
min_size + pairSet.get_size () - pairSet.len.get_size();
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
||||
|
@ -81,7 +83,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
this_index,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
};
|
||||
|
||||
return actuate_subtable_split<split_context_t> (split_context, split_points);
|
||||
|
@ -125,23 +127,19 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
pairSet.len = count;
|
||||
c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
|
||||
|
||||
unsigned coverage_id = c.graph.mutable_index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
auto& coverage_v = c.graph.vertices_[coverage_id];
|
||||
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
if (!coverage_table || !coverage_table->sanitize (coverage_v))
|
||||
return false;
|
||||
auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
|
||||
if (!coverage) return false;
|
||||
|
||||
unsigned coverage_size = coverage.vertex->table_size ();
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
+ hb_zip (coverage.table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second < count;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return Coverage::make_coverage (c, new_coverage, coverage_id, coverage_size);
|
||||
return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
|
||||
}
|
||||
|
||||
// Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
|
||||
|
@ -206,7 +204,9 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
min_size + class1_count * get_class1_record_size ();
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
|
||||
const unsigned class_def_2_size = size_of (c, this_index, &classDef2);
|
||||
|
@ -287,7 +287,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
this_index,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
class1_record_size,
|
||||
total_value_len,
|
||||
value_1_len,
|
||||
|
@ -508,40 +508,37 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
graph.vertices_[split_context.this_index].obj.tail -=
|
||||
(old_count - count) * split_context.class1_record_size;
|
||||
|
||||
unsigned coverage_id =
|
||||
graph.mutable_index_for_offset (split_context.this_index, &coverage);
|
||||
unsigned class_def_1_id =
|
||||
graph.mutable_index_for_offset (split_context.this_index, &classDef1);
|
||||
auto& coverage_v = graph.vertices_[coverage_id];
|
||||
auto& class_def_1_v = graph.vertices_[class_def_1_id];
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head;
|
||||
if (!coverage_table
|
||||
|| !coverage_table->sanitize (coverage_v)
|
||||
|| !class_def_1_table
|
||||
|| !class_def_1_table->sanitize (class_def_1_v))
|
||||
return false;
|
||||
auto coverage =
|
||||
graph.as_mutable_table<Coverage> (split_context.this_index, &this->coverage);
|
||||
if (!coverage) return false;
|
||||
|
||||
auto class_def_1 =
|
||||
graph.as_mutable_table<ClassDef> (split_context.this_index, &classDef1);
|
||||
if (!class_def_1) return false;
|
||||
|
||||
auto klass_map =
|
||||
+ coverage_table->iter ()
|
||||
+ coverage.table->iter ()
|
||||
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid));
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
|
||||
})
|
||||
| hb_filter ([&] (hb_codepoint_t klass) {
|
||||
return klass < count;
|
||||
}, hb_second)
|
||||
;
|
||||
|
||||
auto new_coverage = + klass_map | hb_map_retains_sorting (hb_first);
|
||||
if (!Coverage::make_coverage (split_context.c,
|
||||
+ klass_map | hb_map_retains_sorting (hb_first),
|
||||
coverage_id,
|
||||
coverage_v.table_size ()))
|
||||
+ new_coverage,
|
||||
coverage.index,
|
||||
// existing ranges my not be kept, worst case size is a format 1
|
||||
// coverage table.
|
||||
4 + new_coverage.len() * 2))
|
||||
return false;
|
||||
|
||||
return ClassDef::make_class_def (split_context.c,
|
||||
+ klass_map,
|
||||
class_def_1_id,
|
||||
class_def_1_v.table_size ());
|
||||
class_def_1.index,
|
||||
class_def_1.vertex->table_size ());
|
||||
}
|
||||
|
||||
hb_hashmap_t<unsigned, unsigned>
|
||||
|
@ -605,13 +602,15 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
|
||||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
|
|
|
@ -1,29 +1,5 @@
|
|||
# Set these variables so that the `${prefix}/lib` expands to something we can
|
||||
# remove.
|
||||
set(_harfbuzz_remove_string "REMOVE_ME")
|
||||
set(exec_prefix "${_harfbuzz_remove_string}")
|
||||
set(prefix "${_harfbuzz_remove_string}")
|
||||
|
||||
# Compute the installation prefix by stripping components from our current
|
||||
# location.
|
||||
get_filename_component(_harfbuzz_prefix "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY)
|
||||
get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
|
||||
set(_harfbuzz_libdir "@libdir@")
|
||||
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_libdir "${_harfbuzz_libdir}")
|
||||
set(_harfbuzz_libdir_iter "${_harfbuzz_libdir}")
|
||||
while (_harfbuzz_libdir_iter)
|
||||
set(_harfbuzz_libdir_prev_iter "${_harfbuzz_libdir_iter}")
|
||||
get_filename_component(_harfbuzz_libdir_iter "${_harfbuzz_libdir_iter}" DIRECTORY)
|
||||
if (_harfbuzz_libdir_prev_iter STREQUAL _harfbuzz_libdir_iter)
|
||||
break()
|
||||
endif ()
|
||||
get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY)
|
||||
endwhile ()
|
||||
unset(_harfbuzz_libdir_iter)
|
||||
|
||||
# Get the include subdir.
|
||||
set(_harfbuzz_includedir "@includedir@")
|
||||
string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_includedir "${_harfbuzz_includedir}")
|
||||
|
||||
# Extract version information from libtool.
|
||||
set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@")
|
||||
|
@ -48,29 +24,29 @@ endif ()
|
|||
# Add the libraries.
|
||||
add_library(harfbuzz::harfbuzz SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::harfbuzz PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}")
|
||||
|
||||
add_library(harfbuzz::icu SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::icu PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
|
||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}")
|
||||
|
||||
add_library(harfbuzz::subset SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::subset PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
|
||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}")
|
||||
|
||||
# Only add the gobject library if it was built.
|
||||
set(_harfbuzz_have_gobject "@have_gobject@")
|
||||
if (_harfbuzz_have_gobject)
|
||||
add_library(harfbuzz::gobject SHARED IMPORTED)
|
||||
set_target_properties(harfbuzz::gobject PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_includedir}/harfbuzz"
|
||||
INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz"
|
||||
IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
|
||||
IMPORTED_LOCATION "${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}")
|
||||
endif ()
|
||||
|
||||
# Clean out variables we used in our scope.
|
||||
|
@ -80,7 +56,3 @@ unset(_harfbuzz_revision)
|
|||
unset(_harfbuzz_age)
|
||||
unset(_harfbuzz_includedir)
|
||||
unset(_harfbuzz_libdir)
|
||||
unset(_harfbuzz_prefix)
|
||||
unset(exec_prefix)
|
||||
unset(prefix)
|
||||
unset(_harfbuzz_remove_string)
|
||||
|
|
|
@ -70,9 +70,9 @@ struct DecompositionAction
|
|||
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBFixed lowerLimit; /* If the distance factor is less than this value,
|
||||
F16DOT16 lowerLimit; /* If the distance factor is less than this value,
|
||||
* then the ligature is decomposed. */
|
||||
HBFixed upperLimit; /* If the distance factor is greater than this value,
|
||||
F16DOT16 upperLimit; /* If the distance factor is greater than this value,
|
||||
* then the ligature is decomposed. */
|
||||
HBUINT16 order; /* Numerical order in which this ligature will
|
||||
* be decomposed; you may want infrequent ligatures
|
||||
|
@ -118,7 +118,7 @@ struct ConditionalAddGlyphAction
|
|||
protected:
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBFixed substThreshold; /* Distance growth factor (in ems) at which
|
||||
F16DOT16 substThreshold; /* Distance growth factor (in ems) at which
|
||||
* this glyph is replaced and the growth factor
|
||||
* recalculated. */
|
||||
HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is
|
||||
|
@ -146,13 +146,13 @@ struct DuctileGlyphAction
|
|||
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
|
||||
* This would normally be 0x64756374 ('duct'),
|
||||
* but you may use any axis the font contains. */
|
||||
HBFixed minimumLimit; /* The lowest value for the ductility axis that
|
||||
F16DOT16 minimumLimit; /* The lowest value for the ductility axis that
|
||||
* still yields an acceptable appearance. Normally
|
||||
* this will be 1.0. */
|
||||
HBFixed noStretchValue; /* This is the default value that corresponds to
|
||||
F16DOT16 noStretchValue; /* This is the default value that corresponds to
|
||||
* no change in appearance. Normally, this will
|
||||
* be 1.0. */
|
||||
HBFixed maximumLimit; /* The highest value for the ductility axis that
|
||||
F16DOT16 maximumLimit; /* The highest value for the ductility axis that
|
||||
* still yields an acceptable appearance. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (22);
|
||||
|
@ -271,14 +271,14 @@ struct JustWidthDeltaEntry
|
|||
};
|
||||
|
||||
protected:
|
||||
HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
|
||||
F16DOT16 beforeGrowLimit;/* The ratio by which the advance width of the
|
||||
* glyph is permitted to grow on the left or top side. */
|
||||
HBFixed beforeShrinkLimit;
|
||||
F16DOT16 beforeShrinkLimit;
|
||||
/* The ratio by which the advance width of the
|
||||
* glyph is permitted to shrink on the left or top side. */
|
||||
HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
|
||||
F16DOT16 afterGrowLimit; /* The ratio by which the advance width of the glyph
|
||||
* is permitted to shrink on the left or top side. */
|
||||
HBFixed afterShrinkLimit;
|
||||
F16DOT16 afterShrinkLimit;
|
||||
/* The ratio by which the advance width of the glyph
|
||||
* is at most permitted to shrink on the right or
|
||||
* bottom side. */
|
||||
|
|
|
@ -62,7 +62,7 @@ struct TrackTableEntry
|
|||
}
|
||||
|
||||
protected:
|
||||
HBFixed track; /* Track value for this record. */
|
||||
F16DOT16 track; /* Track value for this record. */
|
||||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
|
@ -82,7 +82,7 @@ struct TrackData
|
|||
const void *base) const
|
||||
{
|
||||
unsigned int sizes = nSizes;
|
||||
hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
|
||||
float s0 = size_table[idx].to_float ();
|
||||
float s1 = size_table[idx + 1].to_float ();
|
||||
|
@ -120,7 +120,7 @@ struct TrackData
|
|||
if (!sizes) return 0.;
|
||||
if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
|
||||
|
||||
hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
hb_array_t<const F16DOT16> 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 () >= ptem)
|
||||
|
@ -141,7 +141,7 @@ struct TrackData
|
|||
protected:
|
||||
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
|
||||
HBUINT16 nSizes; /* Number of point sizes included in this table. */
|
||||
NNOffset32To<UnsizedArrayOf<HBFixed>>
|
||||
NNOffset32To<UnsizedArrayOf<F16DOT16>>
|
||||
sizeTable; /* Offset from start of the tracking table to
|
||||
* Array[nSizes] of size values.. */
|
||||
UnsizedArrayOf<TrackTableEntry>
|
||||
|
|
|
@ -131,6 +131,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
|
|||
{HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS, (hb_aat_layout_feature_selector_t) 4},
|
||||
{HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('r','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF},
|
||||
{HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
|
||||
{HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
|
||||
{HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
|
||||
|
|
|
@ -495,8 +495,8 @@ hb_language_matches (hb_language_t language,
|
|||
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
|
||||
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
|
||||
* @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
|
||||
* @HB_SCRIPT_KAWI: `Kawi`, Since: REPLACEME
|
||||
* @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: REPLACEME
|
||||
* @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0
|
||||
* @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0
|
||||
* @HB_SCRIPT_INVALID: No script set
|
||||
*
|
||||
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
|
||||
|
@ -719,7 +719,7 @@ typedef enum
|
|||
HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
|
||||
|
||||
/*
|
||||
* Since REPLACEME
|
||||
* Since 5.2.0
|
||||
*/
|
||||
HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/
|
||||
HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
|
||||
#define HB_NO_LAYOUT_FEATURE_PARAMS
|
||||
#define HB_NO_LAYOUT_COLLECT_GLYPHS
|
||||
#define HB_NO_LAYOUT_RARELY_USED
|
||||
#define HB_NO_LAYOUT_UNUSED
|
||||
#define HB_NO_MATH
|
||||
#define HB_NO_META
|
||||
|
|
|
@ -69,9 +69,9 @@ struct shared_ptr
|
|||
operator T * () const { return p; }
|
||||
T& operator * () const { return *get (); }
|
||||
T* operator -> () const { return get (); }
|
||||
operator bool () { return p; }
|
||||
bool operator == (const shared_ptr &o) { return p == o.p; }
|
||||
bool operator != (const shared_ptr &o) { return p != o.p; }
|
||||
operator bool () const { return p; }
|
||||
bool operator == (const shared_ptr &o) const { return p == o.p; }
|
||||
bool operator != (const shared_ptr &o) const { return p != o.p; }
|
||||
|
||||
static T* get_empty() { return v::get_empty (); }
|
||||
T* reference() { return v::reference (p); }
|
||||
|
|
|
@ -633,20 +633,29 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
|
|||
* face-builder: A face that has add_table().
|
||||
*/
|
||||
|
||||
struct face_table_info_t
|
||||
{
|
||||
hb_blob_t* data;
|
||||
unsigned order;
|
||||
};
|
||||
|
||||
struct hb_face_builder_data_t
|
||||
{
|
||||
hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
|
||||
hb_hashmap_t<hb_tag_t, face_table_info_t> tables;
|
||||
};
|
||||
|
||||
static int compare_entries (const void* pa, const void* pb)
|
||||
{
|
||||
const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
|
||||
const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
|
||||
const auto& a = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pa;
|
||||
const auto& b = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pb;
|
||||
|
||||
/* Order by blob size first (smallest to largest) and then table tag */
|
||||
|
||||
if (a.second->length != b.second->length)
|
||||
return a.second->length < b.second->length ? -1 : +1;
|
||||
if (a.second.order != b.second.order)
|
||||
return a.second.order < b.second.order ? -1 : +1;
|
||||
|
||||
if (a.second.data->length != b.second.data->length)
|
||||
return a.second.data->length < b.second.data->length ? -1 : +1;
|
||||
|
||||
return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
|
||||
}
|
||||
|
@ -668,8 +677,8 @@ _hb_face_builder_data_destroy (void *user_data)
|
|||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
|
||||
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
hb_blob_destroy (b);
|
||||
for (auto info : data->tables.values())
|
||||
hb_blob_destroy (info.data);
|
||||
|
||||
data->tables.fini ();
|
||||
|
||||
|
@ -683,8 +692,8 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
unsigned int table_count = data->tables.get_population ();
|
||||
unsigned int face_length = table_count * 16 + 12;
|
||||
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (b));
|
||||
for (auto info : data->tables.values())
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (info.data));
|
||||
|
||||
char *buf = (char *) hb_malloc (face_length);
|
||||
if (unlikely (!buf))
|
||||
|
@ -699,7 +708,7 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
|
||||
|
||||
// Sort the tags so that produced face is deterministic.
|
||||
hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
|
||||
hb_vector_t<hb_pair_t <hb_tag_t, face_table_info_t>> sorted_entries;
|
||||
data->tables.iter () | hb_sink (sorted_entries);
|
||||
if (unlikely (sorted_entries.in_error ()))
|
||||
{
|
||||
|
@ -708,7 +717,13 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
}
|
||||
|
||||
sorted_entries.qsort (compare_entries);
|
||||
bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
|
||||
|
||||
bool ret = f->serialize_single (&c,
|
||||
sfnt_tag,
|
||||
+ sorted_entries.iter()
|
||||
| hb_map ([&] (hb_pair_t<hb_tag_t, face_table_info_t> _) {
|
||||
return hb_pair_t<hb_tag_t, hb_blob_t*> (_.first, _.second.data);
|
||||
}));
|
||||
|
||||
c.end_serialize ();
|
||||
|
||||
|
@ -729,7 +744,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
|
|||
if (!tag)
|
||||
return _hb_face_builder_data_reference_blob (data);
|
||||
|
||||
return hb_blob_reference (data->tables[tag]);
|
||||
return hb_blob_reference (data->tables[tag].data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -777,8 +792,8 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
|
|||
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
|
||||
|
||||
hb_blob_t* previous = data->tables.get (tag);
|
||||
if (!data->tables.set (tag, hb_blob_reference (blob)))
|
||||
hb_blob_t* previous = data->tables.get (tag).data;
|
||||
if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), 0}))
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return false;
|
||||
|
@ -787,3 +802,36 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
|
|||
hb_blob_destroy (previous);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_builder_sort_tables:
|
||||
* @face: A face object created with hb_face_builder_create()
|
||||
* @tags: (array zero-terminated=1): ordered list of table tags terminated by
|
||||
* %HB_TAG_NONE
|
||||
*
|
||||
* Set the ordering of tables for serialization. Any tables not
|
||||
* specified in the tags list will be ordered after the tables in
|
||||
* tags, ordered by the default sort ordering.
|
||||
*
|
||||
* Since: 5.3.0
|
||||
**/
|
||||
void
|
||||
hb_face_builder_sort_tables (hb_face_t *face,
|
||||
const hb_tag_t *tags)
|
||||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
|
||||
|
||||
// Sort all unspecified tables after any specified tables.
|
||||
for (auto& info : data->tables.values_ref())
|
||||
info.order = -1;
|
||||
|
||||
unsigned order = 0;
|
||||
for (const hb_tag_t* tag = tags;
|
||||
*tag;
|
||||
tag++)
|
||||
{
|
||||
face_table_info_t* info;
|
||||
if (!data->tables.has (*tag, &info)) continue;
|
||||
info->order = order++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,6 +171,10 @@ hb_face_builder_add_table (hb_face_t *face,
|
|||
hb_tag_t tag,
|
||||
hb_blob_t *blob);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_face_builder_sort_tables (hb_face_t *face,
|
||||
const hb_tag_t *tags);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
|
|
@ -133,6 +133,18 @@ struct
|
|||
|
||||
template <typename T> constexpr auto
|
||||
operator () (T *v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (const hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (const hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
}
|
||||
HB_FUNCOBJ (hb_deref);
|
||||
|
||||
|
|
|
@ -141,27 +141,24 @@ typedef HBINT32 FWORD32;
|
|||
/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
|
||||
typedef HBUINT16 UFWORD;
|
||||
|
||||
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
||||
struct F2DOT14 : HBINT16
|
||||
template <typename Type, unsigned fraction_bits>
|
||||
struct HBFixed : Type
|
||||
{
|
||||
F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; }
|
||||
// 16384 means 1<<14
|
||||
float to_float () const { return ((int32_t) v) / 16384.f; }
|
||||
void set_float (float f) { v = roundf (f * 16384.f); }
|
||||
static constexpr float shift = (float) (1 << fraction_bits);
|
||||
static_assert (Type::static_size * 8 > fraction_bits, "");
|
||||
|
||||
HBFixed& operator = (typename Type::type i ) { Type::operator= (i); return *this; }
|
||||
float to_float () const { return ((int32_t) Type::v) / shift; }
|
||||
void set_float (float f) { Type::v = roundf (f * shift); }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
DEFINE_SIZE_STATIC (Type::static_size);
|
||||
};
|
||||
|
||||
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
||||
using F2DOT14 = HBFixed<HBINT16, 14>;
|
||||
|
||||
/* 32-bit signed fixed-point number (16.16). */
|
||||
struct HBFixed : HBINT32
|
||||
{
|
||||
HBFixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; }
|
||||
// 65536 means 1<<16
|
||||
float to_float () const { return ((int32_t) v) / 65536.f; }
|
||||
void set_float (float f) { v = roundf (f * 65536.f); }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
using F16DOT16 = HBFixed<HBINT32, 16>;
|
||||
|
||||
/* Date represented in number of seconds since 12:00 midnight, January 1,
|
||||
* 1904. The value is represented as a signed 64-bit integer. */
|
||||
|
|
|
@ -358,14 +358,14 @@ struct Affine2x3
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
HBFixed xx;
|
||||
HBFixed yx;
|
||||
HBFixed xy;
|
||||
HBFixed yy;
|
||||
HBFixed dx;
|
||||
HBFixed dy;
|
||||
F16DOT16 xx;
|
||||
F16DOT16 yx;
|
||||
F16DOT16 xy;
|
||||
F16DOT16 yy;
|
||||
F16DOT16 dx;
|
||||
F16DOT16 dy;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6 * HBFixed::static_size);
|
||||
DEFINE_SIZE_STATIC (6 * F16DOT16::static_size);
|
||||
};
|
||||
|
||||
struct PaintColrLayers
|
||||
|
|
|
@ -295,8 +295,8 @@ hb_ot_color_has_png (hb_face_t *face)
|
|||
* @glyph: a glyph index
|
||||
*
|
||||
* Fetches the PNG image for a glyph. This function takes a font object, not a face object,
|
||||
* as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
|
||||
* object. If UPEM is unset, the blob returned will be the largest PNG available.
|
||||
* as input. To get an optimally sized PNG blob, the PPEM values must be set on the @font
|
||||
* object. If PPEM is unset, the blob returned will be the largest PNG available.
|
||||
*
|
||||
* If the glyph has no PNG image, the singleton empty blob is returned.
|
||||
*
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
#include "hb-ot-os2-table.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-ot-vorg-table.hh"
|
||||
|
@ -349,15 +348,13 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
|||
|
||||
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
|
||||
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
|
||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
|
||||
if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
|
||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
|
||||
// TODO Hook up side-bearings variations.
|
||||
return false;
|
||||
|
|
|
@ -94,6 +94,19 @@ static bool ClassDef_remap_and_serialize (
|
|||
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
|
||||
hb_map_t *klass_map /*IN/OUT*/);
|
||||
|
||||
struct hb_collect_feature_substitutes_with_var_context_t
|
||||
{
|
||||
const hb_map_t *axes_index_tag_map;
|
||||
const hb_hashmap_t<hb_tag_t, int> *axes_location;
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
|
||||
hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
|
||||
|
||||
// not stored in subset_plan
|
||||
hb_set_t *feature_indices;
|
||||
bool apply;
|
||||
unsigned cur_record_idx;
|
||||
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
|
||||
};
|
||||
|
||||
struct hb_prune_langsys_context_t
|
||||
{
|
||||
|
@ -160,24 +173,40 @@ struct hb_subset_layout_context_t :
|
|||
const hb_map_t *lookup_index_map;
|
||||
const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
|
||||
const hb_map_t *feature_index_map;
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map;
|
||||
|
||||
unsigned cur_script_index;
|
||||
unsigned cur_feature_var_record_idx;
|
||||
|
||||
hb_subset_layout_context_t (hb_subset_context_t *c_,
|
||||
hb_tag_t tag_,
|
||||
hb_map_t *lookup_map_,
|
||||
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
|
||||
hb_map_t *feature_index_map_) :
|
||||
hb_tag_t tag_) :
|
||||
subset_context (c_),
|
||||
table_tag (tag_),
|
||||
lookup_index_map (lookup_map_),
|
||||
script_langsys_map (script_langsys_map_),
|
||||
feature_index_map (feature_index_map_),
|
||||
cur_script_index (0xFFFFu),
|
||||
cur_feature_var_record_idx (0u),
|
||||
script_count (0),
|
||||
langsys_count (0),
|
||||
feature_index_count (0),
|
||||
lookup_index_count (0)
|
||||
{}
|
||||
{
|
||||
if (tag_ == HB_OT_TAG_GSUB)
|
||||
{
|
||||
lookup_index_map = c_->plan->gsub_lookups;
|
||||
script_langsys_map = c_->plan->gsub_langsys;
|
||||
feature_index_map = c_->plan->gsub_features;
|
||||
feature_substitutes_map = c_->plan->gsub_feature_substitutes_map;
|
||||
feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gsub_feature_record_cond_idx_map;
|
||||
}
|
||||
else
|
||||
{
|
||||
lookup_index_map = c_->plan->gpos_lookups;
|
||||
script_langsys_map = c_->plan->gpos_langsys;
|
||||
feature_index_map = c_->plan->gpos_features;
|
||||
feature_substitutes_map = c_->plan->gpos_feature_substitutes_map;
|
||||
feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gpos_feature_record_cond_idx_map;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned script_count;
|
||||
|
@ -324,6 +353,31 @@ struct subset_record_array_t
|
|||
const void *base;
|
||||
};
|
||||
|
||||
template<typename OutputArray, typename Arg>
|
||||
struct subset_record_array_arg_t
|
||||
{
|
||||
subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_,
|
||||
const void *base_,
|
||||
Arg &&arg_) : subset_layout_context (c_),
|
||||
out (out_), base (base_), arg (arg_) {}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
operator () (T&& record)
|
||||
{
|
||||
auto snap = subset_layout_context->subset_context->serializer->snapshot ();
|
||||
bool ret = record.subset (subset_layout_context, base, arg);
|
||||
if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
|
||||
else out->len++;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_subset_layout_context_t *subset_layout_context;
|
||||
OutputArray *out;
|
||||
const void *base;
|
||||
Arg &&arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper to subset a RecordList/record array. Subsets each Record in the array and
|
||||
* discards the record if the subset operation returns false.
|
||||
|
@ -335,6 +389,13 @@ struct
|
|||
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
||||
const void *base) const
|
||||
{ return subset_record_array_t<OutputArray> (c, out, base); }
|
||||
|
||||
/* Variant with one extra argument passed to subset */
|
||||
template<typename OutputArray, typename Arg>
|
||||
subset_record_array_arg_t<OutputArray, Arg>
|
||||
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
||||
const void *base, Arg &&arg) const
|
||||
{ return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); }
|
||||
}
|
||||
HB_FUNCOBJ (subset_record_array);
|
||||
|
||||
|
@ -431,94 +492,6 @@ struct IndexArray : Array16Of<Index>
|
|||
};
|
||||
|
||||
|
||||
struct Record_sanitize_closure_t {
|
||||
hb_tag_t tag;
|
||||
const void *list_base;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct Record
|
||||
{
|
||||
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->subset_context->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
const Record_sanitize_closure_t closure = {tag, base};
|
||||
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
|
||||
}
|
||||
|
||||
Tag tag; /* 4-byte Tag identifier */
|
||||
Offset16To<Type>
|
||||
offset; /* Offset from beginning of object holding
|
||||
* the Record */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
||||
{
|
||||
const Offset16To<Type>& get_offset (unsigned int i) const
|
||||
{ return (*this)[i].offset; }
|
||||
Offset16To<Type>& get_offset (unsigned int i)
|
||||
{ return (*this)[i].offset; }
|
||||
const Tag& get_tag (unsigned int i) const
|
||||
{ return (*this)[i].tag; }
|
||||
unsigned int get_tags (unsigned int start_offset,
|
||||
unsigned int *record_count /* IN/OUT */,
|
||||
hb_tag_t *record_tags /* OUT */) const
|
||||
{
|
||||
if (record_count)
|
||||
{
|
||||
+ this->sub_array (start_offset, record_count)
|
||||
| hb_map (&Record<Type>::tag)
|
||||
| hb_sink (hb_array (record_tags, *record_count))
|
||||
;
|
||||
}
|
||||
return this->len;
|
||||
}
|
||||
bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordListOf : RecordArrayOf<Type>
|
||||
{
|
||||
const Type& operator [] (unsigned int i) const
|
||||
{ return this+this->get_offset (i); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ this->iter ()
|
||||
| hb_apply (subset_record_array (l, out, this))
|
||||
;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (RecordArrayOf<Type>::sanitize (c, this));
|
||||
}
|
||||
};
|
||||
|
||||
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
|
||||
struct FeatureParamsSize
|
||||
{
|
||||
|
@ -801,6 +774,10 @@ struct FeatureParams
|
|||
DEFINE_SIZE_MIN (0);
|
||||
};
|
||||
|
||||
struct Record_sanitize_closure_t {
|
||||
hb_tag_t tag;
|
||||
const void *list_base;
|
||||
};
|
||||
|
||||
struct Feature
|
||||
{
|
||||
|
@ -897,6 +874,103 @@ struct Feature
|
|||
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct Record
|
||||
{
|
||||
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->subset_context->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!f_sub)
|
||||
return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
|
||||
|
||||
const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
|
||||
auto *s = c->subset_context->serializer;
|
||||
s->push ();
|
||||
|
||||
out->offset = 0;
|
||||
bool ret = f.subset (c->subset_context, c, &tag);
|
||||
if (ret)
|
||||
s->add_link (out->offset, s->pop_pack ());
|
||||
else
|
||||
s->pop_discard ();
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
const Record_sanitize_closure_t closure = {tag, base};
|
||||
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
|
||||
}
|
||||
|
||||
Tag tag; /* 4-byte Tag identifier */
|
||||
Offset16To<Type>
|
||||
offset; /* Offset from beginning of object holding
|
||||
* the Record */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
||||
{
|
||||
const Offset16To<Type>& get_offset (unsigned int i) const
|
||||
{ return (*this)[i].offset; }
|
||||
Offset16To<Type>& get_offset (unsigned int i)
|
||||
{ return (*this)[i].offset; }
|
||||
const Tag& get_tag (unsigned int i) const
|
||||
{ return (*this)[i].tag; }
|
||||
unsigned int get_tags (unsigned int start_offset,
|
||||
unsigned int *record_count /* IN/OUT */,
|
||||
hb_tag_t *record_tags /* OUT */) const
|
||||
{
|
||||
if (record_count)
|
||||
{
|
||||
+ this->sub_array (start_offset, record_count)
|
||||
| hb_map (&Record<Type>::tag)
|
||||
| hb_sink (hb_array (record_tags, *record_count))
|
||||
;
|
||||
}
|
||||
return this->len;
|
||||
}
|
||||
bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordListOf : RecordArrayOf<Type>
|
||||
{
|
||||
const Type& operator [] (unsigned int i) const
|
||||
{ return this+this->get_offset (i); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ this->iter ()
|
||||
| hb_apply (subset_record_array (l, out, this))
|
||||
;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (RecordArrayOf<Type>::sanitize (c, this));
|
||||
}
|
||||
};
|
||||
|
||||
struct RecordListOfFeature : RecordListOf<Feature>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c,
|
||||
|
@ -907,11 +981,20 @@ struct RecordListOfFeature : RecordListOf<Feature>
|
|||
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
unsigned count = this->len;
|
||||
|
||||
+ hb_zip (*this, hb_range (count))
|
||||
| hb_filter (l->feature_index_map, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_apply (subset_record_array (l, out, this))
|
||||
| hb_apply ([l, out, this] (const hb_pair_t<const Record<Feature>&, unsigned>& _)
|
||||
{
|
||||
const Feature *f_sub = nullptr;
|
||||
const Feature **f = nullptr;
|
||||
if (l->feature_substitutes_map->has (_.second, &f))
|
||||
f_sub = *f;
|
||||
|
||||
subset_record_array (l, out, this, f_sub) (_.first);
|
||||
})
|
||||
;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
};
|
||||
|
@ -996,7 +1079,7 @@ struct LangSys
|
|||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
const unsigned *v;
|
||||
const uint32_t *v;
|
||||
out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
|
||||
|
||||
if (!l->visitFeatureIndex (featureIndex.len))
|
||||
|
@ -1305,7 +1388,13 @@ struct Lookup
|
|||
outMarkFilteringSet = markFilteringSet;
|
||||
}
|
||||
|
||||
return_trace (out->subTable.len);
|
||||
// Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
|
||||
// indices being consistent with those computed during planning. So if an empty lookup is
|
||||
// discarded during the subset phase it will invalidate all subsequent lookup indices.
|
||||
// Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning
|
||||
// phase, but it can happen in rare cases such as when during closure subtable is considered
|
||||
// degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TSubTable>
|
||||
|
@ -1465,7 +1554,7 @@ struct ClassDefFormat1_3
|
|||
|
||||
startGlyph = glyph_min;
|
||||
if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
|
||||
for (const hb_pair_t<hb_codepoint_t, unsigned> gid_klass_pair : + it)
|
||||
for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it)
|
||||
{
|
||||
unsigned idx = gid_klass_pair.first - glyph_min;
|
||||
classValue[idx] = gid_klass_pair.second;
|
||||
|
@ -1592,11 +1681,11 @@ struct ClassDefFormat1_3
|
|||
if (klass == 0)
|
||||
{
|
||||
unsigned start_glyph = startGlyph;
|
||||
for (unsigned g = HB_SET_VALUE_INVALID;
|
||||
for (uint32_t g = HB_SET_VALUE_INVALID;
|
||||
hb_set_next (glyphs, &g) && g < start_glyph;)
|
||||
intersect_glyphs->add (g);
|
||||
|
||||
for (unsigned g = startGlyph + count - 1;
|
||||
for (uint32_t g = startGlyph + count - 1;
|
||||
hb_set_next (glyphs, &g);)
|
||||
intersect_glyphs->add (g);
|
||||
|
||||
|
@ -2692,6 +2781,13 @@ struct VariationStore
|
|||
/*
|
||||
* Feature Variations
|
||||
*/
|
||||
enum Cond_with_Var_flag_t
|
||||
{
|
||||
KEEP_COND_WITH_VAR = 0,
|
||||
DROP_COND_WITH_VAR = 1,
|
||||
DROP_RECORD_WITH_VAR = 2,
|
||||
MEM_ERR_WITH_VAR = 3,
|
||||
};
|
||||
|
||||
struct ConditionFormat1
|
||||
{
|
||||
|
@ -2702,10 +2798,52 @@ struct ConditionFormat1
|
|||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (true);
|
||||
|
||||
const hb_map_t *index_map = c->plan->axes_index_map;
|
||||
if (index_map->is_empty ()) return_trace (true);
|
||||
|
||||
if (!index_map->has (axisIndex))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
private:
|
||||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
hb_map_t *condition_map /* OUT */) const
|
||||
{
|
||||
//invalid axis index, drop the entire record
|
||||
if (!c->axes_index_tag_map->has (axisIndex))
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
|
||||
|
||||
//axis not pinned, keep the condition
|
||||
if (!c->axes_location->has (axis_tag))
|
||||
{
|
||||
// add axisIndex->value into the hashmap so we can check if the record is
|
||||
// unique with variations
|
||||
int16_t min_val = filterRangeMinValue;
|
||||
int16_t max_val = filterRangeMaxValue;
|
||||
hb_codepoint_t val = (max_val << 16) + min_val;
|
||||
|
||||
condition_map->set (axisIndex, val);
|
||||
return KEEP_COND_WITH_VAR;
|
||||
}
|
||||
|
||||
//axis pinned, check if condition is met
|
||||
//TODO: add check for axis Ranges
|
||||
int v = c->axes_location->get (axis_tag);
|
||||
|
||||
//condition not met, drop the entire record
|
||||
if (v < filterRangeMinValue || v > filterRangeMaxValue)
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
//axis pinned and condition met, drop the condition
|
||||
return DROP_COND_WITH_VAR;
|
||||
}
|
||||
|
||||
bool evaluate (const int *coords, unsigned int coord_len) const
|
||||
{
|
||||
int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
|
||||
|
@ -2737,6 +2875,15 @@ struct Condition
|
|||
}
|
||||
}
|
||||
|
||||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
hb_map_t *condition_map /* OUT */) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.keep_with_variations (c, condition_map);
|
||||
default:return KEEP_COND_WITH_VAR;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
|
@ -2778,15 +2925,65 @@ struct ConditionSet
|
|||
return true;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{
|
||||
hb_map_t *condition_map = hb_map_create ();
|
||||
if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR;
|
||||
hb::shared_ptr<hb_map_t> p {condition_map};
|
||||
|
||||
hb_set_t *cond_set = hb_set_create ();
|
||||
if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR;
|
||||
hb::shared_ptr<hb_set_t> s {cond_set};
|
||||
|
||||
unsigned num_kept_cond = 0, cond_idx = 0;
|
||||
for (const auto& offset : conditions)
|
||||
{
|
||||
Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map);
|
||||
// one condition is not met, drop the entire record
|
||||
if (ret == DROP_RECORD_WITH_VAR)
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
// axis not pinned, keep this condition
|
||||
if (ret == KEEP_COND_WITH_VAR)
|
||||
{
|
||||
cond_set->add (cond_idx);
|
||||
num_kept_cond++;
|
||||
}
|
||||
cond_idx++;
|
||||
}
|
||||
|
||||
// all conditions met
|
||||
if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
|
||||
|
||||
//check if condition_set is unique with variations
|
||||
if (c->conditionset_map->has (p))
|
||||
//duplicate found, drop the entire record
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
c->conditionset_map->set (p, 1);
|
||||
c->record_cond_idx_map->set (c->cur_record_idx, s);
|
||||
|
||||
return KEEP_COND_WITH_VAR;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ conditions.iter ()
|
||||
| hb_apply (subset_offset_array (c, out->conditions, this))
|
||||
;
|
||||
hb_set_t *retained_cond_set = nullptr;
|
||||
if (l->feature_record_cond_idx_map != nullptr)
|
||||
retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
|
||||
|
||||
unsigned int count = conditions.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (retained_cond_set != nullptr && !retained_cond_set->has (i))
|
||||
continue;
|
||||
subset_offset_array (c, out->conditions, this) (conditions[i]);
|
||||
}
|
||||
|
||||
return_trace (bool (out->conditions));
|
||||
}
|
||||
|
@ -2820,10 +3017,19 @@ struct FeatureTableSubstitutionRecord
|
|||
feature_indexes->add (featureIndex);
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
const hb_set_t *feature_indices,
|
||||
const void *base) const
|
||||
{
|
||||
if (feature_indices->has (featureIndex))
|
||||
feature_substitutes_map->set (featureIndex, &(base+feature));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (!c->feature_index_map->has (featureIndex)) {
|
||||
if (!c->feature_index_map->has (featureIndex) ||
|
||||
c->feature_substitutes_map->has (featureIndex)) {
|
||||
// Feature that is being substituted is not being retained, so we don't
|
||||
// need this.
|
||||
return_trace (false);
|
||||
|
@ -2865,10 +3071,16 @@ struct FeatureTableSubstitution
|
|||
}
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
+ hb_iter (substitutions)
|
||||
| hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
|
||||
| hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record)
|
||||
{
|
||||
if (feature_substitutes_map == nullptr) return true;
|
||||
return !feature_substitutes_map->has (record.featureIndex);
|
||||
})
|
||||
| hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
|
||||
{ r.collect_lookups (this, lookup_indexes); })
|
||||
;
|
||||
|
@ -2890,6 +3102,12 @@ struct FeatureTableSubstitution
|
|||
return false;
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{
|
||||
for (const FeatureTableSubstitutionRecord& record : substitutions)
|
||||
record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
|
@ -2929,9 +3147,10 @@ struct FeatureVariationRecord
|
|||
|
||||
void collect_lookups (const void *base,
|
||||
const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
|
||||
return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
|
||||
}
|
||||
|
||||
void closure_features (const void *base,
|
||||
|
@ -2946,13 +3165,25 @@ struct FeatureVariationRecord
|
|||
return (base+substitutions).intersects_features (feature_index_map);
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
const void *base) const
|
||||
{
|
||||
// ret == 1, all conditions met
|
||||
if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR &&
|
||||
c->apply)
|
||||
{
|
||||
(base+substitutions).collect_feature_substitutes_with_variations (c);
|
||||
c->apply = false; // set variations only once
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->subset_context->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->conditions.serialize_subset (c->subset_context, conditions, base);
|
||||
out->conditions.serialize_subset (c->subset_context, conditions, base, c);
|
||||
out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
|
||||
|
||||
return_trace (true);
|
||||
|
@ -3002,6 +3233,16 @@ struct FeatureVariations
|
|||
return (this+record.substitutions).find_substitute (feature_index);
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{
|
||||
unsigned int count = varRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
c->cur_record_idx = i;
|
||||
varRecords[i].collect_feature_substitutes_with_variations (c, this);
|
||||
}
|
||||
}
|
||||
|
||||
FeatureVariations* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
@ -3009,17 +3250,25 @@ struct FeatureVariations
|
|||
}
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
for (const FeatureVariationRecord& r : varRecords)
|
||||
r.collect_lookups (this, feature_indexes, lookup_indexes);
|
||||
r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes);
|
||||
}
|
||||
|
||||
void closure_features (const hb_map_t *lookup_indexes,
|
||||
const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
|
||||
hb_set_t *feature_indexes /* OUT */) const
|
||||
{
|
||||
for (const FeatureVariationRecord& record : varRecords)
|
||||
record.closure_features (this, lookup_indexes, feature_indexes);
|
||||
unsigned int count = varRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (feature_record_cond_idx_map != nullptr &&
|
||||
!feature_record_cond_idx_map->has (i))
|
||||
continue;
|
||||
varRecords[i].closure_features (this, lookup_indexes, feature_indexes);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
|
@ -3041,7 +3290,13 @@ struct FeatureVariations
|
|||
}
|
||||
|
||||
unsigned count = (unsigned) (keep_up_to + 1);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (l->feature_record_cond_idx_map != nullptr &&
|
||||
!l->feature_record_cond_idx_map->has (i))
|
||||
continue;
|
||||
|
||||
l->cur_feature_var_record_idx = i;
|
||||
subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
|
||||
}
|
||||
return_trace (bool (out->varRecords));
|
||||
|
|
|
@ -4236,13 +4236,19 @@ struct GSUBGPOS
|
|||
}
|
||||
|
||||
void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes);
|
||||
get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{ get_feature_variations ().collect_feature_substitutes_with_variations (c); }
|
||||
#endif
|
||||
|
||||
template <typename TLookup>
|
||||
void closure_lookups (hb_face_t *face,
|
||||
const hb_set_t *glyphs,
|
||||
|
@ -4278,6 +4284,8 @@ struct GSUBGPOS
|
|||
}
|
||||
|
||||
void prune_features (const hb_map_t *lookup_indices, /* IN */
|
||||
const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */
|
||||
hb_set_t *feature_indices /* IN/OUT */) const
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
|
@ -4285,7 +4293,7 @@ struct GSUBGPOS
|
|||
// if the FeatureVariation's table and the alternate version(s) intersect the
|
||||
// set of lookup indices.
|
||||
hb_set_t alternate_feature_indices;
|
||||
get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices);
|
||||
get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices);
|
||||
if (unlikely (alternate_feature_indices.in_error()))
|
||||
{
|
||||
feature_indices->err ();
|
||||
|
@ -4295,7 +4303,6 @@ struct GSUBGPOS
|
|||
|
||||
for (unsigned i : feature_indices->iter())
|
||||
{
|
||||
const Feature& f = get_feature (i);
|
||||
hb_tag_t tag = get_feature_tag (i);
|
||||
if (tag == HB_TAG ('p', 'r', 'e', 'f'))
|
||||
// Note: Never ever drop feature 'pref', even if it's empty.
|
||||
|
@ -4305,11 +4312,16 @@ struct GSUBGPOS
|
|||
continue;
|
||||
|
||||
|
||||
if (!f.featureParams.is_null () &&
|
||||
const Feature *f = &(get_feature (i));
|
||||
const Feature** p = nullptr;
|
||||
if (feature_substitutes_map->has (i, &p))
|
||||
f = *p;
|
||||
|
||||
if (!f->featureParams.is_null () &&
|
||||
tag == HB_TAG ('s', 'i', 'z', 'e'))
|
||||
continue;
|
||||
|
||||
if (!f.intersects_lookup_indexes (lookup_indices)
|
||||
if (!f->intersects_lookup_indexes (lookup_indices)
|
||||
#ifndef HB_NO_VAR
|
||||
&& !alternate_feature_indices.has (i)
|
||||
#endif
|
||||
|
|
|
@ -1271,7 +1271,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
|
|||
hb_set_next (&feature_indexes, &feature_index);)
|
||||
g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
|
||||
|
||||
g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes);
|
||||
g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1709,6 +1709,8 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_ot_layout_feature_get_name_ids:
|
||||
* @face: #hb_face_t to work upon
|
||||
|
@ -2341,6 +2343,7 @@ struct hb_get_glyph_alternates_dispatch_t :
|
|||
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
|
||||
};
|
||||
|
||||
#ifndef HB_NO_LAYOUT_RARELY_USED
|
||||
/**
|
||||
* hb_ot_layout_lookup_get_glyph_alternates:
|
||||
* @face: a face.
|
||||
|
@ -2373,4 +2376,72 @@ hb_ot_layout_lookup_get_glyph_alternates (hb_face_t *face,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct hb_position_single_dispatch_t :
|
||||
hb_dispatch_context_t<hb_position_single_dispatch_t, bool>
|
||||
{
|
||||
static return_t default_return_value () { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
private:
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( obj.position_single (std::forward<Ts> (ds)...) )
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( default_return_value () )
|
||||
public:
|
||||
template <typename T, typename ...Ts> auto
|
||||
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
|
||||
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
|
||||
};
|
||||
|
||||
/**
|
||||
* hb_ot_layout_lookup_get_optical_bound:
|
||||
* @font: a font.
|
||||
* @lookup_index: index of the feature lookup to query.
|
||||
* @direction: edge of the glyph to query.
|
||||
* @glyph: a glyph id.
|
||||
*
|
||||
* Fetches the optical bound of a glyph positioned at the margin of text.
|
||||
* The direction identifies which edge of the glyph to query.
|
||||
*
|
||||
* Return value: Adjustment value. Negative values mean the glyph will stick out of the margin.
|
||||
*
|
||||
* Since: 5.3.0
|
||||
**/
|
||||
hb_position_t
|
||||
hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
|
||||
unsigned lookup_index,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t glyph)
|
||||
{
|
||||
const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index);
|
||||
hb_glyph_position_t pos = {0};
|
||||
hb_position_single_dispatch_t c;
|
||||
lookup.dispatch (&c, font, direction, glyph, pos);
|
||||
hb_position_t ret = 0;
|
||||
switch (direction)
|
||||
{
|
||||
case HB_DIRECTION_LTR:
|
||||
ret = pos.x_offset;
|
||||
break;
|
||||
case HB_DIRECTION_RTL:
|
||||
ret = pos.x_advance - pos.x_offset;
|
||||
break;
|
||||
case HB_DIRECTION_TTB:
|
||||
ret = pos.y_offset;
|
||||
break;
|
||||
case HB_DIRECTION_BTT:
|
||||
ret = pos.y_advance - pos.y_offset;
|
||||
break;
|
||||
case HB_DIRECTION_INVALID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -403,6 +403,16 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|||
unsigned int *range_start, /* OUT. May be NULL */
|
||||
unsigned int *range_end /* OUT. May be NULL */);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
|
||||
unsigned lookup_index,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t glyph);
|
||||
|
||||
|
||||
/*
|
||||
* GSUB/GPOS
|
||||
*/
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_layout_feature_get_name_ids (hb_face_t *face,
|
||||
|
@ -423,6 +433,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
|
|||
unsigned int *char_count /* IN/OUT. May be NULL */,
|
||||
hb_codepoint_t *characters /* OUT. May be NULL */);
|
||||
|
||||
|
||||
/*
|
||||
* BASE
|
||||
*/
|
||||
|
|
|
@ -78,14 +78,14 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
|
|||
|
||||
post::accelerator_t _post (c->plan->source);
|
||||
|
||||
hb_hashmap_t<hb_bytes_t, unsigned, true> glyph_name_to_new_index;
|
||||
hb_hashmap_t<hb_bytes_t, uint32_t, true> glyph_name_to_new_index;
|
||||
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
|
||||
unsigned old_index = glyphNameIndex[old_gid];
|
||||
|
||||
unsigned new_index;
|
||||
const unsigned *new_index2;
|
||||
const uint32_t *new_index2;
|
||||
if (old_index <= 257) new_index = old_index;
|
||||
else if (old_new_index_map.has (old_index, &new_index2))
|
||||
{
|
||||
|
|
|
@ -282,7 +282,7 @@ struct post
|
|||
* 0x00020000 for version 2.0
|
||||
* 0x00025000 for version 2.5 (deprecated)
|
||||
* 0x00030000 for version 3.0 */
|
||||
HBFixed italicAngle; /* Italic angle in counter-clockwise degrees
|
||||
F16DOT16 italicAngle; /* Italic angle in counter-clockwise degrees
|
||||
* from the vertical. Zero for upright text,
|
||||
* negative for text that leans to the right
|
||||
* (forward). */
|
||||
|
|
|
@ -527,18 +527,20 @@ hb_set_unicode_props (hb_buffer_t *buffer)
|
|||
}
|
||||
#endif
|
||||
/* Or part of the Other_Grapheme_Extend that is not marks.
|
||||
* As of Unicode 11 that is just:
|
||||
* As of Unicode 15 that is just:
|
||||
*
|
||||
* 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER
|
||||
* FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
|
||||
* E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
|
||||
*
|
||||
* ZWNJ is special, we don't want to merge it as there's no need, and keeping
|
||||
* it separate results in more granular clusters. Ignore Katakana for now.
|
||||
* it separate results in more granular clusters.
|
||||
* Tags are used for Emoji sub-region flag sequences:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1556
|
||||
* Katakana ones were requested:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3844
|
||||
*/
|
||||
else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
|
||||
else if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu)))
|
||||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
|
||||
* # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
|
||||
* # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
|
||||
* # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
|
||||
* # Override values For Indic_Positional_Category
|
||||
* # Not derivable
|
||||
* # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
|
||||
|
@ -34,6 +35,7 @@
|
|||
* # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
|
||||
* # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
|
||||
* # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
|
||||
* # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
|
||||
* UnicodeData.txt does not have a header.
|
||||
*/
|
||||
|
||||
|
@ -90,7 +92,7 @@
|
|||
#pragma GCC diagnostic pop
|
||||
|
||||
static const uint8_t
|
||||
hb_use_u8[3115] =
|
||||
hb_use_u8[3141] =
|
||||
{
|
||||
16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
|
@ -125,11 +127,11 @@ hb_use_u8[3115] =
|
|||
2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 89, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 94, 94, 95, 96, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
|
||||
94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
|
||||
94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 93, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 95, 95, 96, 97, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
|
||||
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
|
||||
95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
|
||||
0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -226,70 +228,72 @@ hb_use_u8[3115] =
|
|||
0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 18, 20, 151,
|
||||
20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0,
|
||||
0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
|
||||
20, 106, 155, 0, 0, 156, 157, 29, 158, 28, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 159, 42, 0, 0, 0,
|
||||
20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0,
|
||||
47, 125, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 7, 7, 2, 2,
|
||||
28, 2, 2, 2, 2, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
|
||||
8, 16, 17, 19, 20, 160, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7,
|
||||
8, 16, 17, 19, 20, 159, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7,
|
||||
28, 7, 2, 28, 2, 2, 56, 15, 21, 14, 21, 45, 30, 31, 30, 32,
|
||||
0, 0, 0, 0, 33, 0, 0, 0, 2, 2, 21, 0, 9, 9, 9, 44,
|
||||
0, 9, 9, 44, 0, 0, 0, 0, 0, 2, 2, 63, 23, 18, 18, 18,
|
||||
20, 21, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
|
||||
161, 162, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
|
||||
158, 9, 163, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
|
||||
63, 23, 18, 18, 0, 46, 46, 9, 164, 35, 0, 0, 0, 0, 0, 0,
|
||||
160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
|
||||
157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
|
||||
63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80,
|
||||
164, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 165,
|
||||
23, 18, 20, 20, 163, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
|
||||
163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164,
|
||||
23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
|
||||
133, 21, 20, 18, 74, 19, 20, 0, 0, 2, 2, 2, 7, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 164, 35, 0,
|
||||
0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 163, 35, 0,
|
||||
0, 2, 2, 2, 7, 28, 0, 2, 2, 2, 2, 28, 7, 2, 2, 2,
|
||||
2, 21, 21, 16, 30, 31, 10, 166, 167, 168, 169, 0, 0, 0, 0, 0,
|
||||
2, 21, 21, 16, 30, 31, 10, 165, 166, 167, 168, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 0, 2, 2, 2, 63, 23, 18, 18, 0, 20, 21,
|
||||
27, 106, 0, 31, 0, 0, 0, 0, 0, 50, 18, 20, 20, 20, 137, 2,
|
||||
2, 2, 170, 171, 9, 13, 172, 70, 173, 0, 0, 1, 144, 0, 0, 0,
|
||||
0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 174, 174,
|
||||
174, 174, 174, 174, 13, 175, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
|
||||
164, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0,
|
||||
2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0,
|
||||
0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173,
|
||||
173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
|
||||
163, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 7, 2, 28, 2, 2, 50, 20, 20, 29, 0, 36, 20,
|
||||
25, 9, 157, 176, 172, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2,
|
||||
25, 9, 156, 175, 171, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 21, 21, 45, 20, 33, 80, 66, 0, 0, 0,
|
||||
0, 2, 177, 64, 45, 0, 0, 0, 0, 9, 178, 2, 2, 2, 2, 2,
|
||||
0, 2, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0,
|
||||
0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18,
|
||||
0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114,
|
||||
114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
|
||||
38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
|
||||
35, 0, 4, 118, 118, 118, 119, 0, 0, 9, 9, 9, 47, 2, 2, 2,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0,
|
||||
0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B,
|
||||
O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,
|
||||
B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre,
|
||||
VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre,
|
||||
O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,
|
||||
CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv,
|
||||
B, O, CS, CS,VMPst, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O,
|
||||
CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B,
|
||||
VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,
|
||||
VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ,
|
||||
CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B,
|
||||
CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst,
|
||||
FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,
|
||||
VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw,
|
||||
FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ,
|
||||
O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,
|
||||
VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B,
|
||||
FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,
|
||||
VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre,
|
||||
VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre,VMAbv,VMAbv,
|
||||
H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, IS,
|
||||
R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw, FBlw,CMAbv,
|
||||
IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, O, VBlw,
|
||||
44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 20,
|
||||
20, 2, 2, 42, 42, 42, 90, 0, 0, O, O, O, GB, B, B, GB,
|
||||
O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,
|
||||
CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw,
|
||||
VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,
|
||||
VMPst, O, B, VBlw, O, O, VPre, VPre, O, VPre, H, O, VPst,FMAbv, O,CMBlw,
|
||||
O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst,
|
||||
VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, B, O, CS, CS,VMPst, B, VAbv, VAbv,
|
||||
B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB,
|
||||
SUB, O, SUB, SUB, O,FMBlw, O, B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv,
|
||||
MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,
|
||||
VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,
|
||||
VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB,
|
||||
B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw,
|
||||
SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,
|
||||
SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,
|
||||
CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,
|
||||
VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H,
|
||||
O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,
|
||||
VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst,
|
||||
CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R,
|
||||
R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst,
|
||||
H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R,
|
||||
MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, B,
|
||||
H, B,VMBlw, O, VBlw,
|
||||
};
|
||||
static const uint16_t
|
||||
hb_use_u16[776] =
|
||||
hb_use_u16[784] =
|
||||
{
|
||||
0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
|
||||
|
@ -332,14 +336,14 @@ hb_use_u16[776] =
|
|||
9,242, 73,243, 0, 0, 0, 0,244, 9, 9,245,246, 2,247, 9,
|
||||
248,249, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,250,
|
||||
251, 48, 9,252,253, 2, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 98,254, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
9, 9, 9,255, 0, 0, 0, 0, 9, 9, 9, 9,256,257,258,258,
|
||||
259,260, 0, 0, 0, 0,261, 0, 9, 9, 9, 9, 9,262, 0, 0,
|
||||
9, 9, 9, 9, 9, 9,105, 70, 94,263, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,264, 9, 9, 70,265,266, 0, 0, 0,
|
||||
0, 9,267, 0, 9, 9,268, 2, 9, 9, 9, 9,269, 2, 0, 0,
|
||||
129,129,129,129,129,129,129,129,160,160,160,160,160,160,160,160,
|
||||
160,160,160,160,160,160,160,129,
|
||||
9, 9, 9,254,255,256, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
9, 9, 9,257, 0, 0, 0, 0, 9, 9, 9, 9,258,259,260,260,
|
||||
261,262, 0, 0, 0, 0,263, 0, 9, 9, 9, 9, 9,264, 0, 0,
|
||||
9, 9, 9, 9, 9, 9,105, 70, 94,265, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,266, 9, 9, 70,267,268, 0, 0, 0,
|
||||
0, 9,269, 0, 9, 9,270, 2, 0, 0, 0, 0, 0, 9,271, 2,
|
||||
9, 9, 9, 9,272, 2, 0, 0,129,129,129,129,129,129,129,129,
|
||||
160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
|
@ -350,7 +354,7 @@ hb_use_b4 (const uint8_t* a, unsigned i)
|
|||
static inline uint_fast8_t
|
||||
hb_use_get_category (unsigned u)
|
||||
{
|
||||
return u<921600u?hb_use_u8[2753+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
|
||||
return u<921600u?hb_use_u8[2777+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
|
||||
}
|
||||
|
||||
#undef B
|
||||
|
|
|
@ -342,6 +342,40 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
break;
|
||||
|
||||
case HB_SCRIPT_KHOJKI:
|
||||
for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
|
||||
{
|
||||
bool matched = false;
|
||||
switch (buffer->cur ().codepoint)
|
||||
{
|
||||
case 0x11200u:
|
||||
switch (buffer->cur (1).codepoint)
|
||||
{
|
||||
case 0x1122Cu: case 0x11231u: case 0x11233u:
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x11206u:
|
||||
matched = 0x1122Cu == buffer->cur (1).codepoint;
|
||||
break;
|
||||
case 0x1122Cu:
|
||||
switch (buffer->cur (1).codepoint)
|
||||
{
|
||||
case 0x11230u: case 0x11231u:
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x11240u:
|
||||
matched = 0x1122Eu == buffer->cur (1).codepoint;
|
||||
break;
|
||||
}
|
||||
(void) buffer->next_glyph ();
|
||||
if (matched) _output_with_dotted_circle (buffer);
|
||||
}
|
||||
break;
|
||||
|
||||
case HB_SCRIPT_KHUDAWADI:
|
||||
for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
|
||||
{
|
||||
|
|
|
@ -136,7 +136,7 @@ struct AxisValueFormat1
|
|||
NameID valueNameID; /* The name ID for entries in the 'name' table
|
||||
* that provide a display string for this
|
||||
* attribute value. */
|
||||
HBFixed value; /* A numeric value for this attribute value. */
|
||||
F16DOT16 value; /* A numeric value for this attribute value. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
@ -195,10 +195,10 @@ struct AxisValueFormat2
|
|||
NameID valueNameID; /* The name ID for entries in the 'name' table
|
||||
* that provide a display string for this
|
||||
* attribute value. */
|
||||
HBFixed nominalValue; /* A numeric value for this attribute value. */
|
||||
HBFixed rangeMinValue; /* The minimum value for a range associated
|
||||
F16DOT16 nominalValue; /* A numeric value for this attribute value. */
|
||||
F16DOT16 rangeMinValue; /* The minimum value for a range associated
|
||||
* with the specified name ID. */
|
||||
HBFixed rangeMaxValue; /* The maximum value for a range associated
|
||||
F16DOT16 rangeMaxValue; /* The maximum value for a range associated
|
||||
* with the specified name ID. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
|
@ -258,8 +258,8 @@ struct AxisValueFormat3
|
|||
NameID valueNameID; /* The name ID for entries in the 'name' table
|
||||
* that provide a display string for this
|
||||
* attribute value. */
|
||||
HBFixed value; /* A numeric value for this attribute value. */
|
||||
HBFixed linkedValue; /* The numeric value for a style-linked mapping
|
||||
F16DOT16 value; /* A numeric value for this attribute value. */
|
||||
F16DOT16 linkedValue; /* The numeric value for a style-linked mapping
|
||||
* from this value. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (16);
|
||||
|
@ -280,7 +280,7 @@ struct AxisValueRecord
|
|||
HBUINT16 axisIndex; /* Zero-base index into the axis record array
|
||||
* identifying the axis to which this value
|
||||
* applies. Must be less than designAxisCount. */
|
||||
HBFixed value; /* A numeric value for this attribute value. */
|
||||
F16DOT16 value; /* A numeric value for this attribute value. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
|
|
@ -44,9 +44,47 @@ struct InstanceRecord
|
|||
{
|
||||
friend struct fvar;
|
||||
|
||||
hb_array_t<const HBFixed> get_coordinates (unsigned int axis_count) const
|
||||
hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const
|
||||
{ return coordinatesZ.as_array (axis_count); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
unsigned axis_count,
|
||||
bool has_postscript_nameid) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (subfamilyNameID))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (flags))) return_trace (false);
|
||||
|
||||
const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
|
||||
const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
|
||||
for (unsigned i = 0 ; i < axis_count; i++)
|
||||
{
|
||||
uint32_t *axis_tag;
|
||||
// only keep instances whose coordinates == pinned axis location
|
||||
if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue;
|
||||
|
||||
if (axes_location->has (*axis_tag) &&
|
||||
fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
|
||||
return_trace (false);
|
||||
|
||||
if (!c->plan->axes_index_map->has (i))
|
||||
continue;
|
||||
|
||||
if (!c->serializer->embed (coords[i]))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (has_postscript_nameid)
|
||||
{
|
||||
NameID name_id;
|
||||
name_id = StructAfter<NameID> (coords);
|
||||
if (!c->serializer->embed (name_id))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -58,7 +96,7 @@ struct InstanceRecord
|
|||
NameID subfamilyNameID;/* The name ID for entries in the 'name' table
|
||||
* that provide subfamily names for this instance. */
|
||||
HBUINT16 flags; /* Reserved for future use — set to 0. */
|
||||
UnsizedArrayOf<HBFixed>
|
||||
UnsizedArrayOf<F16DOT16>
|
||||
coordinatesZ; /* The coordinates array for this instance. */
|
||||
//NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
|
||||
// * table that provide PostScript names for this
|
||||
|
@ -151,9 +189,9 @@ struct AxisRecord
|
|||
public:
|
||||
Tag axisTag; /* Tag identifying the design variation for the axis. */
|
||||
protected:
|
||||
HBFixed minValue; /* The minimum coordinate value for the axis. */
|
||||
HBFixed defaultValue; /* The default coordinate value for the axis. */
|
||||
HBFixed maxValue; /* The maximum coordinate value for the axis. */
|
||||
F16DOT16 minValue; /* The minimum coordinate value for the axis. */
|
||||
F16DOT16 defaultValue; /* The default coordinate value for the axis. */
|
||||
F16DOT16 maxValue; /* The maximum coordinate value for the axis. */
|
||||
public:
|
||||
HBUINT16 flags; /* Axis flags. */
|
||||
NameID axisNameID; /* The name ID for entries in the 'name' table that
|
||||
|
@ -268,7 +306,7 @@ struct fvar
|
|||
|
||||
if (coords_length && *coords_length)
|
||||
{
|
||||
hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount)
|
||||
hb_array_t<const F16DOT16> instanceCoords = instance->get_coordinates (axisCount)
|
||||
.sub_array (0, coords_length);
|
||||
for (unsigned int i = 0; i < instanceCoords.length; i++)
|
||||
coords[i] = instanceCoords.arrayZ[i].to_float ();
|
||||
|
@ -301,7 +339,7 @@ struct fvar
|
|||
|
||||
if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount))
|
||||
| hb_filter (pinned_axes, hb_second)
|
||||
| hb_map ([&] (const hb_pair_t<const HBFixed&, unsigned>& _)
|
||||
| hb_map ([&] (const hb_pair_t<const F16DOT16&, unsigned>& _)
|
||||
{
|
||||
hb_tag_t axis_tag = pinned_axes.get (_.second);
|
||||
float location = user_axes_location->get (axis_tag);
|
||||
|
@ -321,6 +359,48 @@ struct fvar
|
|||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
unsigned retained_axis_count = c->plan->axes_index_map->get_population ();
|
||||
if (!retained_axis_count) //all axes are pinned
|
||||
return_trace (false);
|
||||
|
||||
fvar *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
bool has_postscript_nameid = false;
|
||||
if (instanceSize >= axisCount * 4 + 6)
|
||||
has_postscript_nameid = true;
|
||||
|
||||
if (!c->serializer->check_assign (out->instanceSize, retained_axis_count * 4 + (has_postscript_nameid ? 6 : 4),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
auto axes_records = get_axes ();
|
||||
for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
|
||||
{
|
||||
if (!c->plan->axes_index_map->has (i)) continue;
|
||||
if (unlikely (!c->serializer->embed (axes_records[i])))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
|
||||
{
|
||||
const InstanceRecord *instance = get_instance (i);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (!instance->subset (c, axisCount, has_postscript_nameid))
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
public:
|
||||
hb_array_t<const AxisRecord> get_axes () const
|
||||
{ return hb_array (&(this+firstAxis), axisCount); }
|
||||
|
@ -346,8 +426,8 @@ struct fvar
|
|||
HBUINT16 instanceCount; /* The number of named instances defined in the font
|
||||
* (the number of records in the instances array). */
|
||||
HBUINT16 instanceSize; /* The size in bytes of each InstanceRecord — set
|
||||
* to either axisCount * sizeof(HBFixed) + 4, or to
|
||||
* axisCount * sizeof(HBFixed) + 6. */
|
||||
* to either axisCount * sizeof(F16DOT16) + 4, or to
|
||||
* axisCount * sizeof(F16DOT16) + 6. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (16);
|
||||
|
|
|
@ -209,7 +209,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& over
|
|||
// Only move at most half of the roots in a space at a time.
|
||||
unsigned extra = roots_to_isolate.get_population () - maximum_to_move;
|
||||
while (extra--) {
|
||||
unsigned root = HB_SET_VALUE_INVALID;
|
||||
uint32_t root = HB_SET_VALUE_INVALID;
|
||||
roots_to_isolate.previous (&root);
|
||||
roots_to_isolate.del (root);
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
|
|||
{
|
||||
// The child object is shared, we may be able to eliminate the overflow
|
||||
// by duplicating it.
|
||||
if (!sorted_graph.duplicate (r.parent, r.child)) continue;
|
||||
if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright © 2022 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): Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef HB_SUBSET_ACCELERATOR_HH
|
||||
#define HB_SUBSET_ACCELERATOR_HH
|
||||
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-map.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
extern HB_INTERNAL hb_user_data_key_t _hb_subset_accelerator_user_data_key;
|
||||
|
||||
struct hb_subset_accelerator_t
|
||||
{
|
||||
static hb_user_data_key_t* user_data_key()
|
||||
{
|
||||
return &_hb_subset_accelerator_user_data_key;
|
||||
}
|
||||
|
||||
static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
|
||||
const hb_set_t& unicodes_) {
|
||||
hb_subset_accelerator_t* accel =
|
||||
(hb_subset_accelerator_t*) hb_malloc (sizeof(hb_subset_accelerator_t));
|
||||
new (accel) hb_subset_accelerator_t (unicode_to_gid_, unicodes_);
|
||||
return accel;
|
||||
}
|
||||
|
||||
static void destroy(void* value) {
|
||||
if (!value) return;
|
||||
|
||||
hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value;
|
||||
accel->~hb_subset_accelerator_t ();
|
||||
hb_free (accel);
|
||||
}
|
||||
|
||||
hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_,
|
||||
const hb_set_t& unicodes_)
|
||||
: unicode_to_gid(unicode_to_gid_), unicodes(unicodes_) {}
|
||||
|
||||
const hb_map_t unicode_to_gid;
|
||||
const hb_set_t unicodes;
|
||||
// TODO(garretrieger): cumulative glyf checksum map
|
||||
// TODO(garretrieger): sanitized table cache.
|
||||
|
||||
bool in_error () const
|
||||
{
|
||||
return unicode_to_gid.in_error() || unicodes.in_error ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_SUBSET_ACCELERATOR_HH */
|
|
@ -89,7 +89,6 @@ hb_subset_input_create_or_fail (void)
|
|||
|
||||
hb_tag_t default_no_subset_tables[] = {
|
||||
HB_TAG ('a', 'v', 'a', 'r'),
|
||||
HB_TAG ('f', 'v', 'a', 'r'),
|
||||
HB_TAG ('g', 'a', 's', 'p'),
|
||||
HB_TAG ('c', 'v', 't', ' '),
|
||||
HB_TAG ('f', 'p', 'g', 'm'),
|
||||
|
@ -391,9 +390,9 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
|
|||
*
|
||||
* Return value: `true` if success, `false` otherwise
|
||||
*
|
||||
* Since: REPLACEME
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_bool_t
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
|
||||
hb_face_t *face,
|
||||
hb_tag_t axis_tag)
|
||||
|
@ -415,9 +414,9 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
|
|||
*
|
||||
* Return value: `true` if success, `false` otherwise
|
||||
*
|
||||
* Since: REPLACEME
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_bool_t
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
||||
hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
|
@ -432,3 +431,51 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
/**
|
||||
* hb_subset_preprocess
|
||||
* @input: a #hb_face_t object.
|
||||
*
|
||||
* Preprocesses the face and attaches data that will be needed by the
|
||||
* subsetter. Future subsetting operations can then use the precomputed data
|
||||
* to speed up the subsetting operation.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset_preprocess (hb_face_t *source)
|
||||
{
|
||||
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
|
||||
hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
|
||||
hb_set_invert (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG));
|
||||
hb_set_invert (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG));
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_NAME_ID));
|
||||
hb_set_invert (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_NAME_ID));
|
||||
|
||||
hb_subset_input_set_flags(input,
|
||||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
|
||||
HB_SUBSET_FLAGS_GLYPH_NAMES |
|
||||
HB_SUBSET_FLAGS_RETAIN_GIDS);
|
||||
input->attach_accelerator_data = true;
|
||||
|
||||
hb_face_t* new_source = hb_subset_or_fail (source, input);
|
||||
hb_subset_input_destroy (input);
|
||||
|
||||
return new_source;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -59,6 +59,7 @@ struct hb_subset_input_t
|
|||
};
|
||||
|
||||
unsigned flags;
|
||||
bool attach_accelerator_data = false;
|
||||
hb_hashmap_t<hb_tag_t, float> *axes_location;
|
||||
|
||||
inline unsigned num_sets () const
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "hb-subset-plan.hh"
|
||||
#include "hb-subset-accelerator.hh"
|
||||
#include "hb-map.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
|
@ -129,7 +130,9 @@ template <typename T>
|
|||
static void _collect_layout_indices (hb_subset_plan_t *plan,
|
||||
const T& table,
|
||||
hb_set_t *lookup_indices, /* OUT */
|
||||
hb_set_t *feature_indices /* OUT */)
|
||||
hb_set_t *feature_indices, /* OUT */
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */)
|
||||
{
|
||||
unsigned num_features = table.get_feature_count ();
|
||||
hb_vector_t<hb_tag_t> features;
|
||||
|
@ -154,16 +157,37 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
|
|||
retain_all_features ? nullptr : features.arrayZ,
|
||||
feature_indices);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
// collect feature substitutes with variations
|
||||
if (!plan->user_axes_location->is_empty ())
|
||||
{
|
||||
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
|
||||
OT::hb_collect_feature_substitutes_with_var_context_t c =
|
||||
{
|
||||
plan->axes_old_index_tag_map,
|
||||
plan->axes_location,
|
||||
feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
feature_indices,
|
||||
true,
|
||||
0,
|
||||
&conditionset_map
|
||||
};
|
||||
table.collect_feature_substitutes_with_variations (&c);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (unsigned feature_index : *feature_indices)
|
||||
{
|
||||
//TODO: replace HB_OT_LAYOUT_NO_VARIATIONS_INDEX with variation_index for
|
||||
//instancing
|
||||
const OT::Feature &f = table.get_feature_variation (feature_index, HB_OT_LAYOUT_NO_VARIATIONS_INDEX);
|
||||
f.add_lookup_indexes_to (lookup_indices);
|
||||
const OT::Feature* f = &(table.get_feature (feature_index));
|
||||
const OT::Feature **p = nullptr;
|
||||
if (feature_substitutes_map->has (feature_index, &p))
|
||||
f = *p;
|
||||
|
||||
f->add_lookup_indexes_to (lookup_indices);
|
||||
}
|
||||
|
||||
//TODO: update for instancing: only collect lookups from feature_indexes that have no variations
|
||||
table.feature_variation_collect_lookups (feature_indices, lookup_indices);
|
||||
table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
|
||||
}
|
||||
|
||||
|
||||
|
@ -171,6 +195,7 @@ static inline void
|
|||
_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
|
||||
const hb_map_t *lookup_indices,
|
||||
const hb_set_t *feature_indices,
|
||||
const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
|
||||
hb_map_t *duplicate_feature_map /* OUT */)
|
||||
{
|
||||
if (feature_indices->is_empty ()) return;
|
||||
|
@ -195,16 +220,22 @@ _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
|
|||
hb_set_t* same_tag_features = unique_features.get (t);
|
||||
for (unsigned other_f_index : same_tag_features->iter ())
|
||||
{
|
||||
const OT::Feature& f = g.get_feature (i);
|
||||
const OT::Feature& other_f = g.get_feature (other_f_index);
|
||||
const OT::Feature* f = &(g.get_feature (i));
|
||||
const OT::Feature **p = nullptr;
|
||||
if (feature_substitutes_map->has (i, &p))
|
||||
f = *p;
|
||||
|
||||
const OT::Feature* other_f = &(g.get_feature (other_f_index));
|
||||
if (feature_substitutes_map->has (other_f_index, &p))
|
||||
f = *p;
|
||||
|
||||
auto f_iter =
|
||||
+ hb_iter (f.lookupIndex)
|
||||
+ hb_iter (f->lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
auto other_f_iter =
|
||||
+ hb_iter (other_f.lookupIndex)
|
||||
+ hb_iter (other_f->lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
|
@ -237,7 +268,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
hb_set_t *gids_to_retain,
|
||||
hb_map_t *lookups,
|
||||
hb_map_t *features,
|
||||
script_langsys_map *langsys_map)
|
||||
script_langsys_map *langsys_map,
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map)
|
||||
{
|
||||
hb_blob_ptr_t<T> table = plan->source_table<T> ();
|
||||
hb_tag_t table_tag = table->tableTag;
|
||||
|
@ -245,7 +278,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
_collect_layout_indices<T> (plan,
|
||||
*table,
|
||||
&lookup_indices,
|
||||
&feature_indices);
|
||||
&feature_indices,
|
||||
feature_record_cond_idx_map,
|
||||
feature_substitutes_map);
|
||||
|
||||
if (table_tag == HB_OT_TAG_GSUB)
|
||||
hb_ot_layout_lookups_substitute_closure (plan->source,
|
||||
|
@ -257,9 +292,12 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
_remap_indexes (&lookup_indices, lookups);
|
||||
|
||||
// prune features
|
||||
table->prune_features (lookups, &feature_indices);
|
||||
table->prune_features (lookups,
|
||||
plan->user_axes_location->is_empty () ? nullptr : feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
&feature_indices);
|
||||
hb_map_t duplicate_feature_map;
|
||||
_GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map);
|
||||
_GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map);
|
||||
|
||||
feature_indices.clear ();
|
||||
table->prune_langsys (&duplicate_feature_map, plan->layout_scripts, langsys_map, &feature_indices);
|
||||
|
@ -419,41 +457,73 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
|||
hb_subset_plan_t *plan)
|
||||
{
|
||||
OT::cmap::accelerator_t cmap (plan->source);
|
||||
|
||||
unsigned size_threshold = plan->source->get_num_glyphs ();
|
||||
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
|
||||
{
|
||||
|
||||
const hb_map_t* unicode_to_gid = nullptr;
|
||||
if (plan->accelerator)
|
||||
unicode_to_gid = &plan->accelerator->unicode_to_gid;
|
||||
|
||||
// This is approach to collection is faster, but can only be used if glyphs
|
||||
// are not being explicitly added to the subset and the input unicodes set is
|
||||
// not excessively large (eg. an inverted set).
|
||||
plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||
if (!unicode_to_gid) {
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
||||
}
|
||||
} else {
|
||||
// Use in memory unicode to gid map it's faster then looking up from
|
||||
// the map. This code is mostly duplicated from above to avoid doing
|
||||
// conditionals on the presence of the unicode_to_gid map each
|
||||
// iteration.
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
hb_codepoint_t gid = unicode_to_gid->get (cp);
|
||||
if (gid == HB_MAP_VALUE_INVALID)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This approach is slower, but can handle adding in glyphs to the subset and will match
|
||||
// them with cmap entries.
|
||||
hb_map_t unicode_glyphid_map;
|
||||
hb_set_t cmap_unicodes;
|
||||
cmap.collect_mapping (&cmap_unicodes, &unicode_glyphid_map);
|
||||
plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
|
||||
+ glyphs->get_population (),
|
||||
cmap_unicodes.get_population ()));
|
||||
|
||||
for (hb_codepoint_t cp : cmap_unicodes)
|
||||
hb_map_t unicode_glyphid_map_storage;
|
||||
hb_set_t cmap_unicodes_storage;
|
||||
const hb_map_t* unicode_glyphid_map = &unicode_glyphid_map_storage;
|
||||
const hb_set_t* cmap_unicodes = &cmap_unicodes_storage;
|
||||
|
||||
if (!plan->accelerator) {
|
||||
cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage);
|
||||
plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
|
||||
+ glyphs->get_population (),
|
||||
cmap_unicodes->get_population ()));
|
||||
} else {
|
||||
unicode_glyphid_map = &plan->accelerator->unicode_to_gid;
|
||||
cmap_unicodes = &plan->accelerator->unicodes;
|
||||
}
|
||||
|
||||
for (hb_codepoint_t cp : *cmap_unicodes)
|
||||
{
|
||||
hb_codepoint_t gid = unicode_glyphid_map[cp];
|
||||
hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
|
||||
if (!unicodes->has (cp) && !glyphs->has (gid))
|
||||
continue;
|
||||
|
||||
|
@ -509,9 +579,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
|
|||
|
||||
static void
|
||||
_populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
bool close_over_gsub,
|
||||
bool close_over_gpos,
|
||||
bool close_over_gdef)
|
||||
hb_set_t* drop_tables)
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
#ifndef HB_NO_SUBSET_CFF
|
||||
|
@ -523,32 +591,42 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
_cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (close_over_gsub)
|
||||
if (!drop_tables->has (HB_OT_TAG_GSUB))
|
||||
// closure all glyphs/lookups/features needed for GSUB substitutions.
|
||||
_closure_glyphs_lookups_features<GSUB> (
|
||||
plan,
|
||||
plan->_glyphset_gsub,
|
||||
plan->gsub_lookups,
|
||||
plan->gsub_features,
|
||||
plan->gsub_langsys);
|
||||
plan->gsub_langsys,
|
||||
plan->gsub_feature_record_cond_idx_map,
|
||||
plan->gsub_feature_substitutes_map);
|
||||
|
||||
if (close_over_gpos)
|
||||
if (!drop_tables->has (HB_OT_TAG_GPOS))
|
||||
_closure_glyphs_lookups_features<GPOS> (
|
||||
plan,
|
||||
plan->_glyphset_gsub,
|
||||
plan->gpos_lookups,
|
||||
plan->gpos_features,
|
||||
plan->gpos_langsys);
|
||||
plan->gpos_langsys,
|
||||
plan->gpos_feature_record_cond_idx_map,
|
||||
plan->gpos_feature_substitutes_map);
|
||||
#endif
|
||||
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
||||
|
||||
hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
|
||||
_math_closure (plan, plan->_glyphset_mathed);
|
||||
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
|
||||
if (!drop_tables->has (HB_OT_TAG_MATH))
|
||||
{
|
||||
_math_closure (plan, plan->_glyphset_mathed);
|
||||
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
|
||||
}
|
||||
|
||||
hb_set_t cur_glyphset = *plan->_glyphset_mathed;
|
||||
_colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
|
||||
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
|
||||
if (!drop_tables->has (HB_OT_TAG_COLR))
|
||||
{
|
||||
_colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
|
||||
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
|
||||
}
|
||||
|
||||
hb_set_set (plan->_glyphset_colred, &cur_glyphset);
|
||||
|
||||
|
@ -570,7 +648,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (close_over_gdef)
|
||||
if (!drop_tables->has (HB_OT_TAG_GDEF))
|
||||
_collect_layout_variation_indices (plan);
|
||||
#endif
|
||||
}
|
||||
|
@ -659,18 +737,22 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
seg_maps = face->table.avar->get_segment_maps ();
|
||||
|
||||
bool axis_not_pinned = false;
|
||||
unsigned axis_count = 0;
|
||||
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
||||
for (const auto& axis : axes)
|
||||
{
|
||||
hb_tag_t axis_tag = axis.get_axis_tag ();
|
||||
plan->axes_old_index_tag_map->set (old_axis_idx, axis_tag);
|
||||
|
||||
if (!plan->user_axes_location->has (axis_tag))
|
||||
{
|
||||
axis_not_pinned = true;
|
||||
plan->axes_index_map->set (old_axis_idx, new_axis_idx);
|
||||
new_axis_idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int normalized_v = axis.normalize_axis_value (plan->user_axes_location->get (axis_tag));
|
||||
if (has_avar && axis_count < face->table.avar->get_axis_count ())
|
||||
if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
|
||||
{
|
||||
normalized_v = seg_maps->map (normalized_v);
|
||||
}
|
||||
|
@ -681,7 +763,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
if (has_avar)
|
||||
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
||||
|
||||
axis_count++;
|
||||
old_axis_idx++;
|
||||
}
|
||||
plan->all_axes_pinned = !axis_not_pinned;
|
||||
}
|
||||
|
@ -741,6 +823,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
|
||||
plan->gsub_features = hb_map_create ();
|
||||
plan->gpos_features = hb_map_create ();
|
||||
|
||||
plan->check_success (plan->gsub_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
|
||||
plan->check_success (plan->gpos_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
|
||||
|
||||
plan->check_success (plan->gsub_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
|
||||
plan->check_success (plan->gpos_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
|
||||
|
||||
plan->colrv1_layers = hb_map_create ();
|
||||
plan->colr_palettes = hb_map_create ();
|
||||
plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
|
@ -751,12 +840,21 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
|
||||
if (plan->user_axes_location && input->axes_location)
|
||||
*plan->user_axes_location = *input->axes_location;
|
||||
plan->check_success (plan->axes_index_map = hb_map_create ());
|
||||
plan->check_success (plan->axes_old_index_tag_map = hb_map_create ());
|
||||
plan->all_axes_pinned = false;
|
||||
plan->pinned_at_default = true;
|
||||
|
||||
plan->check_success (plan->vmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
plan->check_success (plan->hmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
|
||||
void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key());
|
||||
|
||||
plan->attach_accelerator_data = input->attach_accelerator_data;
|
||||
if (accel)
|
||||
plan->accelerator = (hb_subset_accelerator_t*) accel;
|
||||
|
||||
|
||||
if (unlikely (plan->in_error ())) {
|
||||
hb_subset_plan_destroy (plan);
|
||||
return nullptr;
|
||||
|
@ -768,10 +866,7 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
|
||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
|
||||
|
||||
_populate_gids_to_retain (plan,
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GSUB),
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GPOS),
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GDEF));
|
||||
_populate_gids_to_retain (plan, input->sets.drop_tables);
|
||||
|
||||
_create_old_gid_to_new_gid_map (face,
|
||||
input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
|
||||
|
|
|
@ -31,11 +31,16 @@
|
|||
|
||||
#include "hb-subset.h"
|
||||
#include "hb-subset-input.hh"
|
||||
#include "hb-subset-accelerator.hh"
|
||||
|
||||
#include "hb-map.hh"
|
||||
#include "hb-bimap.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
namespace OT {
|
||||
struct Feature;
|
||||
}
|
||||
|
||||
struct hb_subset_plan_t
|
||||
{
|
||||
hb_subset_plan_t ()
|
||||
|
@ -67,9 +72,15 @@ struct hb_subset_plan_t
|
|||
hb_map_destroy (gpos_features);
|
||||
hb_map_destroy (colrv1_layers);
|
||||
hb_map_destroy (colr_palettes);
|
||||
hb_map_destroy (axes_index_map);
|
||||
hb_map_destroy (axes_old_index_tag_map);
|
||||
|
||||
hb_hashmap_destroy (gsub_langsys);
|
||||
hb_hashmap_destroy (gpos_langsys);
|
||||
hb_hashmap_destroy (gsub_feature_record_cond_idx_map);
|
||||
hb_hashmap_destroy (gpos_feature_record_cond_idx_map);
|
||||
hb_hashmap_destroy (gsub_feature_substitutes_map);
|
||||
hb_hashmap_destroy (gpos_feature_substitutes_map);
|
||||
hb_hashmap_destroy (axes_location);
|
||||
hb_hashmap_destroy (sanitized_table_cache);
|
||||
hb_hashmap_destroy (hmtx_map);
|
||||
|
@ -87,6 +98,7 @@ struct hb_subset_plan_t
|
|||
|
||||
bool successful;
|
||||
unsigned flags;
|
||||
bool attach_accelerator_data = false;
|
||||
|
||||
// For each cp that we'd like to retain maps to the corresponding gid.
|
||||
hb_set_t *unicodes;
|
||||
|
@ -143,6 +155,15 @@ struct hb_subset_plan_t
|
|||
hb_map_t *gsub_features;
|
||||
hb_map_t *gpos_features;
|
||||
|
||||
//active feature variation records/condition index with variations
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map;
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map;
|
||||
|
||||
//feature index-> address of substituation feature table mapping with
|
||||
//variations
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map;
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map;
|
||||
|
||||
//active layers/palettes we'd like to retain
|
||||
hb_map_t *colrv1_layers;
|
||||
hb_map_t *colr_palettes;
|
||||
|
@ -158,6 +179,10 @@ struct hb_subset_plan_t
|
|||
hb_hashmap_t<hb_tag_t, int> *axes_location;
|
||||
//user specified axes location map
|
||||
hb_hashmap_t<hb_tag_t, float> *user_axes_location;
|
||||
//retained old axis index -> new axis index mapping in fvar axis array
|
||||
hb_map_t *axes_index_map;
|
||||
//axis_index->axis_tag mapping in fvar axis array
|
||||
hb_map_t *axes_old_index_tag_map;
|
||||
bool all_axes_pinned;
|
||||
bool pinned_at_default;
|
||||
|
||||
|
@ -166,6 +191,8 @@ struct hb_subset_plan_t
|
|||
//vmtx metrics map: new gid->(advance, lsb)
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map;
|
||||
|
||||
const hb_subset_accelerator_t* accelerator;
|
||||
|
||||
public:
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -50,11 +50,13 @@
|
|||
#include "hb-ot-color-cbdt-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-var-gvar-table.hh"
|
||||
#include "hb-ot-var-hvar-table.hh"
|
||||
#include "hb-ot-math-table.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
#include "hb-repacker.hh"
|
||||
#include "hb-subset-accelerator.hh"
|
||||
|
||||
using OT::Layout::GSUB;
|
||||
using OT::Layout::GPOS;
|
||||
|
@ -80,6 +82,10 @@ using OT::Layout::GPOS;
|
|||
* retain glyph ids option and configure the subset to pass through the layout tables untouched.
|
||||
*/
|
||||
|
||||
|
||||
hb_user_data_key_t _hb_subset_accelerator_user_data_key = {};
|
||||
|
||||
|
||||
/*
|
||||
* The list of tables in the open type spec. Used to check for tables that may need handling
|
||||
* if we are unable to list the tables in a face.
|
||||
|
@ -475,6 +481,9 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
|
||||
case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
|
||||
#endif
|
||||
case HB_OT_TAG_fvar:
|
||||
if (plan->user_axes_location->is_empty ()) return _passthrough (plan, tag);
|
||||
return _subset<const OT::fvar> (plan, buf);
|
||||
case HB_OT_TAG_STAT:
|
||||
/*TODO(qxliu): change the condition as we support more complex
|
||||
* instancing operation*/
|
||||
|
@ -490,6 +499,27 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
}
|
||||
}
|
||||
|
||||
static void _attach_accelerator_data (const hb_subset_plan_t* plan,
|
||||
hb_face_t* face /* IN/OUT */)
|
||||
{
|
||||
hb_subset_accelerator_t* accel =
|
||||
hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
|
||||
*plan->unicodes);
|
||||
|
||||
if (accel->in_error ())
|
||||
{
|
||||
hb_subset_accelerator_t::destroy (accel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hb_face_set_user_data(face,
|
||||
hb_subset_accelerator_t::user_data_key(),
|
||||
accel,
|
||||
hb_subset_accelerator_t::destroy,
|
||||
true))
|
||||
hb_subset_accelerator_t::destroy (accel);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_or_fail:
|
||||
* @source: font face data to be subset.
|
||||
|
@ -572,6 +602,10 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
|
|||
offset += num_tables;
|
||||
}
|
||||
|
||||
if (success && plan->attach_accelerator_data) {
|
||||
_attach_accelerator_data (plan, plan->dest);
|
||||
}
|
||||
|
||||
end:
|
||||
return success ? hb_face_reference (plan->dest) : nullptr;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,14 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
|
|||
* in the final subset.
|
||||
* @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
|
||||
* OS/2 will not be recalculated.
|
||||
* @HB_SUBSET_FLAGS_PATCH_MODE: If set the subsetter behaviour will be modified
|
||||
* to produce a subset that is better suited to patching. For example cmap
|
||||
* subtable format will be kept stable.
|
||||
* @HB_SUBSET_FLAGS_OMIT_GLYF: If set the subsetter won't actually produce the final
|
||||
* glyf table bytes. The table directory will include and entry as if the table was
|
||||
* there but the actual final font blob will be truncated prior to the glyf data. This
|
||||
* is a useful performance optimization when a font aware binary patching algorithm
|
||||
* is being used to diff two subsets.
|
||||
*
|
||||
* List of boolean properties that can be configured on the subset input.
|
||||
*
|
||||
|
@ -86,6 +94,8 @@ typedef enum { /*< flags >*/
|
|||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u,
|
||||
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
|
||||
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
|
||||
// Not supported yet: HB_SUBSET_FLAGS_PATCH_MODE = 0x00000200u,
|
||||
// Not supported yet: HB_SUBSET_FLAGS_OMIT_GLYF = 0x00000400u,
|
||||
} hb_subset_flags_t;
|
||||
|
||||
/**
|
||||
|
@ -169,6 +179,13 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset_preprocess (hb_face_t *source);
|
||||
|
||||
#endif
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
|
||||
|
||||
|
|
|
@ -47,20 +47,20 @@ HB_BEGIN_DECLS
|
|||
*
|
||||
* The minor component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MINOR 1
|
||||
#define HB_VERSION_MINOR 3
|
||||
/**
|
||||
* HB_VERSION_MICRO:
|
||||
*
|
||||
* The micro component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MICRO 0
|
||||
#define HB_VERSION_MICRO 1
|
||||
|
||||
/**
|
||||
* HB_VERSION_STRING:
|
||||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "5.1.0"
|
||||
#define HB_VERSION_STRING "5.3.1"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
|
|
@ -334,6 +334,7 @@ hb_subset_sources = files(
|
|||
'hb-ot-cff1-table.cc',
|
||||
'hb-ot-cff2-table.cc',
|
||||
'hb-static.cc',
|
||||
'hb-subset-accelerator.hh',
|
||||
'hb-subset-cff-common.cc',
|
||||
'hb-subset-cff-common.hh',
|
||||
'hb-subset-cff1.cc',
|
||||
|
@ -656,8 +657,8 @@ endif
|
|||
have_gobject = conf.get('HAVE_GOBJECT', 0) == 1
|
||||
|
||||
cmake_config = configuration_data()
|
||||
cmake_config.set('libdir', '${prefix}/@0@'.format(get_option('libdir')))
|
||||
cmake_config.set('includedir', '${prefix}/@0@'.format(get_option('includedir')))
|
||||
cmake_config.set('libdir', get_option('prefix') / get_option('libdir'))
|
||||
cmake_config.set('includedir', get_option('prefix') / get_option('includedir'))
|
||||
cmake_config.set('HB_LIBTOOL_VERSION_INFO', hb_libtool_version_info)
|
||||
cmake_config.set('have_gobject', '@0@'.format(have_gobject))
|
||||
configure_file(input: 'harfbuzz-config.cmake.in',
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
# Updated for Unicode 12.1 by Andrew Glass 2019-05-30
|
||||
# Updated for Unicode 13.0 by Andrew Glass 2020-07-28
|
||||
# Updated for Unicode 14.0 by Andrew Glass 2021-09-28
|
||||
# Updated for Unicode 15.0 by Andrew Glass 2022-09-16
|
||||
|
||||
# ================================================
|
||||
# ================================================
|
||||
|
@ -19,9 +20,12 @@
|
|||
0F7A..0F7D ; Bottom # Mn [4] TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN OO # Not really below, but need to override to fit into Universal model
|
||||
0F80 ; Bottom # Mn TIBETAN VOWEL SIGN REVERSED I # Not really below, but need to override to fit into Universal model
|
||||
A9BF ; Bottom # Mc JAVANESE CONSONANT SIGN CAKRA
|
||||
10A38 ; Bottom # Mn KHAROSHTHI SIGN BAR ABOVE # Overriden, ccc controls order USE issue #26
|
||||
11127..11129 ; Bottom # Mn [3] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN II
|
||||
1112D ; Bottom # Mn CHAKMA VOWEL SIGN AI
|
||||
11130 ; Bottom # Mn CHAKMA VOWEL SIGN OI
|
||||
1BF2..1BF3 ; Bottom # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN # see USE issue #20
|
||||
|
||||
|
||||
# ================================================
|
||||
|
||||
|
@ -42,12 +46,15 @@ A9BE ; Right # Mc JAVANESE CONSONANT SIGN PENGKAL # Reduced from
|
|||
0F74 ; Top # Mn TIBETAN VOWEL SIGN U # Not really above, but need to override to fit into Universal model
|
||||
1A18 ; Top # Mn BUGINESE VOWEL SIGN U # Workaround to allow below to occur before above by treating all below marks as above
|
||||
AA35 ; Top # Mn CHAM CONSONANT SIGN
|
||||
1112A..1112B ; Top # Mn [2] CHAKMA VOWEL SIGN U..CHAKMA VOWEL SIGN UU # see USE issue #25
|
||||
11131..11132 ; Top # Mn [2] CHAKMA O MARK..CHAKMA AU MARK # see USE issue #25
|
||||
1E4EC..1E4EF ; Top # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH # 1E4EE is below, but made to for ccc
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Positional_Category=Top_And_Right
|
||||
0E33 ; Top_And_Right # Lo THAI CHARACTER SARA AM # IMC has Right, which seems to be a mistake.
|
||||
0EB3 ; Top_And_Right # Lo LAO VOWEL SIGN AM # IMC has Right, which seems to be a mistake.
|
||||
0E33 ; Top_And_Right # Lo THAI CHARACTER SARA AM # IPC has Right, which seems to be a mistake.
|
||||
0EB3 ; Top_And_Right # Lo LAO VOWEL SIGN AM # IPC has Right, which seems to be a mistake.
|
||||
|
||||
# ================================================
|
||||
# ================================================
|
||||
|
@ -72,6 +79,9 @@ AA35 ; Top # Mn CHAM CONSONANT SIGN
|
|||
16F4F ; Bottom # Mn MIAO SIGN CONSONANT MODIFIER BAR
|
||||
16F51..16F87 ; Bottom # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
|
||||
16F8F..16F92 ; Bottom # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
|
||||
#HIEROGLYPHS defined here while ISC is being used as a proxy for dedicated Hieroglyph cluster
|
||||
13440 ; Bottom # Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY
|
||||
13447..13455 ; Bottom # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED
|
||||
|
||||
# ================================================
|
||||
|
||||
|
@ -84,6 +94,7 @@ AA35 ; Top # Mn CHAM CONSONANT SIGN
|
|||
07EB..07F3 ; Top # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
|
||||
07FD ; Top # Mn NKO DANTAYALAN # Not really top, but assigned here to allow ccc to control mark order
|
||||
1885..1886 ; Top # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
|
||||
1CF8..1CF9 ; Top # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
|
||||
10D24..10D27 ; Top # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
|
||||
10EAB..10EAC ; Top # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
|
||||
16B30..16B36 ; Top # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
|
||||
|
|
|
@ -8,98 +8,106 @@
|
|||
#
|
||||
# Scope: This file enumerates sequences of characters that should be treated as invalid clusters
|
||||
|
||||
0905 0946 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT E
|
||||
0905 093E ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA
|
||||
0930 094D 0907 ; # DEVANAGARI LETTER RA, DEVANAGARI SIGN VIRAMA, DEVANAGARI LETTER I
|
||||
0909 0941 ; # DEVANAGARI LETTER U, DEVANAGARI VOWEL SIGN U
|
||||
090F 0945 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN CANDRA E
|
||||
090F 0946 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN SHORT E
|
||||
090F 0947 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN E
|
||||
0905 0949 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA O
|
||||
0906 0945 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN CANDRA E
|
||||
0905 094A ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT O
|
||||
0906 0946 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN SHORT E
|
||||
0905 094B ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN O
|
||||
0906 0947 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN E
|
||||
0905 094C ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AU
|
||||
0906 0948 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN AI
|
||||
0905 0945 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA E
|
||||
0905 093A ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN OE
|
||||
0905 093B ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN OOE
|
||||
0906 093A ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN OE
|
||||
0905 094F ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AW
|
||||
0905 0956 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN UE
|
||||
0905 0957 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN UUE
|
||||
0985 09BE ; # BENGALI LETTER A, BENGALI VOWEL SIGN AA
|
||||
098B 09C3 ; # BENGALI LETTER VOCALIC R, BENGALI VOWEL SIGN VOCALIC R
|
||||
098C 09E2 ; # BENGALI LETTER VOCALIC L, BENGALI VOWEL SIGN VOCALIC L
|
||||
0A05 0A3E ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AA
|
||||
0A72 0A3F ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN I
|
||||
0A72 0A40 ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN II
|
||||
0A73 0A41 ; # GURMUKHI URA, GURMUKHI VOWEL SIGN U
|
||||
0A73 0A42 ; # GURMUKHI URA, GURMUKHI VOWEL SIGN UU
|
||||
0A72 0A47 ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN EE
|
||||
0A05 0A48 ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AI
|
||||
0A73 0A4B ; # GURMUKHI URA, GURMUKHI VOWEL SIGN OO
|
||||
0A05 0A4C ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AU
|
||||
0A85 0ABE ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA
|
||||
0A85 0AC5 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA E
|
||||
0A85 0AC7 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN E
|
||||
0A85 0AC8 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AI
|
||||
0A85 0AC9 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA O
|
||||
0A85 0ACB ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN O
|
||||
0A85 0ABE 0AC5 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN CANDRA E
|
||||
0A85 0ACC ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AU
|
||||
0A85 0ABE 0AC8 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN AI
|
||||
0AC5 0ABE ; # GUJARATI VOWEL SIGN CANDRA E, GUJARATI VOWEL SIGN AA
|
||||
0B05 0B3E ; # ORIYA LETTER A, ORIYA VOWEL SIGN AA
|
||||
0B0F 0B57 ; # ORIYA LETTER E, ORIYA AU LENGTH MARK
|
||||
0B13 0B57 ; # ORIYA LETTER O, ORIYA AU LENGTH MARK
|
||||
0B85 0BC2 ; # TAMIL LETTER A, TAMIL VOWEL SIGN UU
|
||||
0C12 0C55 ; # TELUGU LETTER O, TELUGU LENGTH MARK
|
||||
0C12 0C4C ; # TELUGU LETTER O, TELUGU VOWEL SIGN AU
|
||||
0C3F 0C55 ; # TELUGU VOWEL SIGN I, TELUGU LENGTH MARK
|
||||
0C46 0C55 ; # TELUGU VOWEL SIGN E, TELUGU LENGTH MARK
|
||||
0C4A 0C55 ; # TELUGU VOWEL SIGN O, TELUGU LENGTH MARK
|
||||
0C89 0CBE ; # KANNADA LETTER U, KANNADA VOWEL SIGN AA
|
||||
0C92 0CCC ; # KANNADA LETTER O, KANNADA VOWEL SIGN AU
|
||||
0C8B 0CBE ; # KANNADA LETTER VOCALIC R, KANNADA VOWEL SIGN AA
|
||||
0D07 0D57 ; # MALAYALAM LETTER I, MALAYALAM AU LENGTH MARK
|
||||
0D09 0D57 ; # MALAYALAM LETTER U, MALAYALAM AU LENGTH MARK
|
||||
0D0E 0D46 ; # MALAYALAM LETTER E, MALAYALAM VOWEL SIGN E
|
||||
0D12 0D3E ; # MALAYALAM LETTER O, MALAYALAM VOWEL SIGN AA
|
||||
0D12 0D57 ; # MALAYALAM LETTER O, MALAYALAM AU LENGTH MARK
|
||||
0D85 0DCF ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN AELA-PILLA
|
||||
0D85 0DD0 ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN KETTI AEDA-PILLA
|
||||
0D85 0DD1 ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN DIGA AEDA-PILLA
|
||||
0D8B 0DDF ; # SINHALA LETTER UYANNA, SINHALA VOWEL SIGN GAYANUKITTA
|
||||
0D8D 0DD8 ; # SINHALA LETTER IRUYANNA, SINHALA VOWEL SIGN GAETTA-PILLA
|
||||
0D8F 0DDF ; # SINHALA LETTER ILUYANNA, SINHALA VOWEL SIGN GAYANUKITTA
|
||||
0D91 0DCA ; # SINHALA LETTER EYANNA, SINHALA SIGN AL-LAKUNA
|
||||
0D91 0DD9 ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA
|
||||
0D91 0DDA ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN DIGA KOMBUVA
|
||||
0D91 0DDC ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA
|
||||
0D91 0DDD ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA
|
||||
0D91 0DDE ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA
|
||||
0D94 0DDF ; # SINHALA LETTER OYANNA, SINHALA VOWEL SIGN GAYANUKITTA
|
||||
11005 11038 ; # BRAHMI LETTER A, BRAHMI VOWEL SIGN AA
|
||||
1100B 1103E ; # BRAHMI LETTER VOCALIC R, BRAHMI VOWEL SIGN VOCALIC R
|
||||
1100F 11042 ; # BRAHMI LETTER E, BRAHMI VOWEL SIGN E
|
||||
11680 116AD ; # TAKRI LETTER A, TAKRI VOWEL SIGN AA
|
||||
11686 116B2 ; # TAKRI LETTER E, TAKRI VOWEL SIGN E
|
||||
11680 116B4 ; # TAKRI LETTER A, TAKRI VOWEL SIGN O
|
||||
11680 116B5 ; # TAKRI LETTER A, TAKRI VOWEL SIGN AU
|
||||
112B0 112E0 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AA
|
||||
112B0 112E5 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN E
|
||||
112B0 112E6 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AI
|
||||
112B0 112E7 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN O
|
||||
112B0 112E8 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AU
|
||||
11481 114B0 ; # TIRHUTA LETTER A, TIRHUTA VOWEL SIGN AA
|
||||
114AA 114B5 ; # TIRHUTA LETTER LA, TIRHUTA VOWEL SIGN VOCALIC R
|
||||
114AA 114B6 ; # TIRHUTA LETTER LA, TIRHUTA VOWEL SIGN VOCALIC RR
|
||||
1148B 114BA ; # TIRHUTA LETTER E, TIRHUTA VOWEL SIGN SHORT E
|
||||
1148D 114BA ; # TIRHUTA LETTER O, TIRHUTA VOWEL SIGN SHORT E
|
||||
11600 11639 ; # MODI LETTER A, MODI VOWEL SIGN E
|
||||
11600 1163A ; # MODI LETTER A, MODI VOWEL SIGN AI
|
||||
11601 11639 ; # MODI LETTER AA, MODI VOWEL SIGN E
|
||||
11601 1163A ; # MODI LETTER AA, MODI VOWEL SIGN AI
|
||||
0905 0946 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT E
|
||||
0905 093E ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA
|
||||
0930 094D 0907 ; # DEVANAGARI LETTER RA, DEVANAGARI SIGN VIRAMA, DEVANAGARI LETTER I
|
||||
0909 0941 ; # DEVANAGARI LETTER U, DEVANAGARI VOWEL SIGN U
|
||||
090F 0945 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN CANDRA E
|
||||
090F 0946 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN SHORT E
|
||||
090F 0947 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN E
|
||||
0905 0949 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA O
|
||||
0906 0945 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN CANDRA E
|
||||
0905 094A ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT O
|
||||
0906 0946 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN SHORT E
|
||||
0905 094B ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN O
|
||||
0906 0947 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN E
|
||||
0905 094C ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AU
|
||||
0906 0948 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN AI
|
||||
0905 0945 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA E
|
||||
0905 093A ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN OE
|
||||
0905 093B ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN OOE
|
||||
0906 093A ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN OE
|
||||
0905 094F ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AW
|
||||
0905 0956 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN UE
|
||||
0905 0957 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN UUE
|
||||
0985 09BE ; # BENGALI LETTER A, BENGALI VOWEL SIGN AA
|
||||
098B 09C3 ; # BENGALI LETTER VOCALIC R, BENGALI VOWEL SIGN VOCALIC R
|
||||
098C 09E2 ; # BENGALI LETTER VOCALIC L, BENGALI VOWEL SIGN VOCALIC L
|
||||
0A05 0A3E ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AA
|
||||
0A72 0A3F ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN I
|
||||
0A72 0A40 ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN II
|
||||
0A73 0A41 ; # GURMUKHI URA, GURMUKHI VOWEL SIGN U
|
||||
0A73 0A42 ; # GURMUKHI URA, GURMUKHI VOWEL SIGN UU
|
||||
0A72 0A47 ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN EE
|
||||
0A05 0A48 ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AI
|
||||
0A73 0A4B ; # GURMUKHI URA, GURMUKHI VOWEL SIGN OO
|
||||
0A05 0A4C ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AU
|
||||
0A85 0ABE ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA
|
||||
0A85 0AC5 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA E
|
||||
0A85 0AC7 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN E
|
||||
0A85 0AC8 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AI
|
||||
0A85 0AC9 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA O
|
||||
0A85 0ACB ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN O
|
||||
0A85 0ABE 0AC5 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN CANDRA E
|
||||
0A85 0ACC ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AU
|
||||
0A85 0ABE 0AC8 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN AI
|
||||
0AC5 0ABE ; # GUJARATI VOWEL SIGN CANDRA E, GUJARATI VOWEL SIGN AA
|
||||
0B05 0B3E ; # ORIYA LETTER A, ORIYA VOWEL SIGN AA
|
||||
0B0F 0B57 ; # ORIYA LETTER E, ORIYA AU LENGTH MARK
|
||||
0B13 0B57 ; # ORIYA LETTER O, ORIYA AU LENGTH MARK
|
||||
0B85 0BC2 ; # TAMIL LETTER A, TAMIL VOWEL SIGN UU
|
||||
0C12 0C55 ; # TELUGU LETTER O, TELUGU LENGTH MARK
|
||||
0C12 0C4C ; # TELUGU LETTER O, TELUGU VOWEL SIGN AU
|
||||
0C3F 0C55 ; # TELUGU VOWEL SIGN I, TELUGU LENGTH MARK
|
||||
0C46 0C55 ; # TELUGU VOWEL SIGN E, TELUGU LENGTH MARK
|
||||
0C4A 0C55 ; # TELUGU VOWEL SIGN O, TELUGU LENGTH MARK
|
||||
0C89 0CBE ; # KANNADA LETTER U, KANNADA VOWEL SIGN AA
|
||||
0C92 0CCC ; # KANNADA LETTER O, KANNADA VOWEL SIGN AU
|
||||
0C8B 0CBE ; # KANNADA LETTER VOCALIC R, KANNADA VOWEL SIGN AA
|
||||
0D07 0D57 ; # MALAYALAM LETTER I, MALAYALAM AU LENGTH MARK
|
||||
0D09 0D57 ; # MALAYALAM LETTER U, MALAYALAM AU LENGTH MARK
|
||||
0D0E 0D46 ; # MALAYALAM LETTER E, MALAYALAM VOWEL SIGN E
|
||||
0D12 0D3E ; # MALAYALAM LETTER O, MALAYALAM VOWEL SIGN AA
|
||||
0D12 0D57 ; # MALAYALAM LETTER O, MALAYALAM AU LENGTH MARK
|
||||
0D85 0DCF ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN AELA-PILLA
|
||||
0D85 0DD0 ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN KETTI AEDA-PILLA
|
||||
0D85 0DD1 ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN DIGA AEDA-PILLA
|
||||
0D8B 0DDF ; # SINHALA LETTER UYANNA, SINHALA VOWEL SIGN GAYANUKITTA
|
||||
0D8D 0DD8 ; # SINHALA LETTER IRUYANNA, SINHALA VOWEL SIGN GAETTA-PILLA
|
||||
0D8F 0DDF ; # SINHALA LETTER ILUYANNA, SINHALA VOWEL SIGN GAYANUKITTA
|
||||
0D91 0DCA ; # SINHALA LETTER EYANNA, SINHALA SIGN AL-LAKUNA
|
||||
0D91 0DD9 ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA
|
||||
0D91 0DDA ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN DIGA KOMBUVA
|
||||
0D91 0DDC ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA
|
||||
0D91 0DDD ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA
|
||||
0D91 0DDE ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA
|
||||
0D94 0DDF ; # SINHALA LETTER OYANNA, SINHALA VOWEL SIGN GAYANUKITTA
|
||||
11005 11038 ; # BRAHMI LETTER A, BRAHMI VOWEL SIGN AA
|
||||
1100B 1103E ; # BRAHMI LETTER VOCALIC R, BRAHMI VOWEL SIGN VOCALIC R
|
||||
1100F 11042 ; # BRAHMI LETTER E, BRAHMI VOWEL SIGN E
|
||||
11680 116AD ; # TAKRI LETTER A, TAKRI VOWEL SIGN AA
|
||||
11686 116B2 ; # TAKRI LETTER E, TAKRI VOWEL SIGN E
|
||||
11680 116B4 ; # TAKRI LETTER A, TAKRI VOWEL SIGN O
|
||||
11680 116B5 ; # TAKRI LETTER A, TAKRI VOWEL SIGN AU
|
||||
11200 1122C ; # KHOJKI LETTER A, KHOJKI VOWEL SIGN AA
|
||||
11240 1122E ; # KHOJKI LETTER SHORT I, KHOJKI VOWEL SIGN II
|
||||
11206 1122C ; # KHOJKI LETTER O, KHOJKI VOWEL SIGN AA
|
||||
11200 11231 ; # KHOJKI LETTER A, KHOJKI VOWEL SIGN AI
|
||||
11200 11233 ; # KHOJKI LETTER A, KHOJKI VOWEL SIGN AU
|
||||
11200 1122C 11231 ; # KHOJKI LETTER A, KHOJKI VOWEL SIGN AA, KHOJKI VOWEL SIGN AI
|
||||
1122C 11230 ; # KHOJKI VOWEL SIGN AA, KHOJKI VOWEL SIGN E
|
||||
1122C 11231 ; # KHOJKI VOWEL SIGN AA, KHOJKI VOWEL SIGN AI
|
||||
112B0 112E0 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AA
|
||||
112B0 112E5 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN E
|
||||
112B0 112E6 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AI
|
||||
112B0 112E7 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN O
|
||||
112B0 112E8 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AU
|
||||
11481 114B0 ; # TIRHUTA LETTER A, TIRHUTA VOWEL SIGN AA
|
||||
114AA 114B5 ; # TIRHUTA LETTER LA, TIRHUTA VOWEL SIGN VOCALIC R
|
||||
114AA 114B6 ; # TIRHUTA LETTER LA, TIRHUTA VOWEL SIGN VOCALIC RR
|
||||
1148B 114BA ; # TIRHUTA LETTER E, TIRHUTA VOWEL SIGN SHORT E
|
||||
1148D 114BA ; # TIRHUTA LETTER O, TIRHUTA VOWEL SIGN SHORT E
|
||||
11600 11639 ; # MODI LETTER A, MODI VOWEL SIGN E
|
||||
11600 1163A ; # MODI LETTER A, MODI VOWEL SIGN AI
|
||||
11601 11639 ; # MODI LETTER AA, MODI VOWEL SIGN E
|
||||
11601 1163A ; # MODI LETTER AA, MODI VOWEL SIGN AI
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
# Updated for Unicode 12.1 by Andrew Glass 2019-05-24
|
||||
# Updated for Unicode 13.0 by Andrew Glass 2020-07-28
|
||||
# Updated for Unicode 14.0 by Andrew Glass 2021-09-25
|
||||
# Updated for Unicode 15.0 by Andrew Glass 2022-09-16
|
||||
|
||||
# ================================================
|
||||
# OVERRIDES TO ASSIGNED VALUES
|
||||
|
@ -18,23 +19,13 @@ AA29 ; Bindu # Mn CHAM VOWEL SIGN AA
|
|||
# ================================================
|
||||
|
||||
# Indic_Syllabic_Category=Consonant
|
||||
0840..0858 ; Consonant # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
|
||||
0F00..0F01 ; Consonant # Lo [2] TIBETAN SYLLABLE OM..TIBETAN MARK GTER YIG MGO TRUNCATED
|
||||
0F04..0F06 ; Consonant # Po TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK CARET YIG MGO PHUR SHAD MA
|
||||
19C1..19C7 ; Consonant # Lo [7] NEW TAI LUE LETTER FINAL V..NEW TAI LUE LETTER FINAL B # Reassigned to avoid clustering with a base consonant
|
||||
25CC ; Consonant # So DOTTED CIRCLE
|
||||
25CC ; Consonant # So DOTTED CIRCLE #Reassigned to allow it to cluster as a generic base
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Syllabic_Category=Consonant_Dead
|
||||
0F7F ; Consonant_Dead # Mc TIBETAN SIGN RNAM BCAD # reassigned so that visarga will form an independent cluster
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Syllabic_Category=Consonant_Final
|
||||
0F35 ; Consonant_Final # Mn TIBETAN MARK NGAS BZUNG NYI ZLA
|
||||
0F37 ; Consonant_Final # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS
|
||||
0FC6 ; Consonant_Final # Mn TIBETAN SYMBOL PADMA GDAN
|
||||
0F7F ; Consonant_Dead # Mc TIBETAN SIGN RNAM BCAD # reassigned so that visarga can form an independent cluster, but see #19
|
||||
|
||||
# ================================================
|
||||
|
||||
|
@ -49,8 +40,8 @@ AA29 ; Bindu # Mn CHAM VOWEL SIGN AA
|
|||
# ================================================
|
||||
|
||||
# Indic_Syllabic_Category=Nukta
|
||||
0F71 ; Nukta # Mn TIBETAN VOWEL SIGN AA # Reassigned to get this before an above vowel
|
||||
10A38..10A3A ; Nukta # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
|
||||
0F71 ; Nukta # Mn TIBETAN VOWEL SIGN AA # Reassigned to get this before an above vowel, but see #22
|
||||
1BF2..1BF3 ; Nukta # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN # see USE issue #20
|
||||
|
||||
# ================================================
|
||||
|
||||
|
@ -73,6 +64,9 @@ AABD ; Vowel_Independent # Lo TAI VIET VOWEL AN
|
|||
|
||||
# Indic_Syllabic_Category=Consonant
|
||||
0800..0815 ; Consonant # Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
|
||||
0840..0858 ; Consonant # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
|
||||
0F00..0F01 ; Consonant # Lo [2] TIBETAN SYLLABLE OM..TIBETAN MARK GTER YIG MGO TRUNCATED
|
||||
0F04..0F06 ; Consonant # Po TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK CARET YIG MGO PHUR SHAD MA
|
||||
1800 ; Consonant # Po MONGOLIAN BIRGA # Reassigned so that legacy Birga + MFVS sequences still work
|
||||
1807 ; Consonant # Po MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER
|
||||
180A ; Consonant # Po MONGOLIAN NIRUGU
|
||||
|
@ -94,11 +88,13 @@ AABD ; Vowel_Independent # Lo TAI VIET VOWEL AN
|
|||
10E80..10EA9 ; Consonant # Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
|
||||
10EB0..10EB1 ; Consonant # Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
|
||||
10F30..10F45 ; Consonant # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
|
||||
10F70..10F81 ; Consonant # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH
|
||||
111DA ; Consonant # Lo SHARADA EKAM
|
||||
#HIEROGLYPHS to be moved to new category
|
||||
13000..1342E ; Consonant # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
|
||||
13000..1342F ; Consonant # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D
|
||||
#For the Begin and End segment to be handled fully correctly, the cluster model needs to be modified.
|
||||
13437..13438 ; Consonant # Lo [2] EGYPTIAN HIEROGLYPH BEGIN SEGMENT..EGYPTIAN HIEROGLYPH END SEGMENT
|
||||
13441..13446 ; Consonant # Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..HIEROGLYPH WIDE LOST SIGN
|
||||
16B00..16B2F ; Consonant # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
|
||||
16F00..16F4A ; Consonant # Lo [75] MIAO LETTER PA..MIAO LETTER RTE
|
||||
16FE4 ; Consonant # Mn KHITAN SMALL SCRIPT FILLER # Avoids Mn pushing this into VOWEL class
|
||||
|
@ -113,6 +109,8 @@ AABD ; Vowel_Independent # Lo TAI VIET VOWEL AN
|
|||
1E14F ; Consonant # So NYIAKENG PUACHUE HMONG CIRCLED CA
|
||||
1E290..1E2AD ; Consonant # Lo [30] TOTO LETTER PA..TOTO LETTER A
|
||||
1E2C0..1E2EB ; Consonant # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH
|
||||
1E4D0..1E4EA ; Consonant # Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL
|
||||
1E4EB ; Consonant # Lm NAG MUNDARI SIGN OJOD
|
||||
1E900..1E921 ; Consonant # Lu [34] ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA
|
||||
1E922..1E943 ; Consonant # Ll [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA
|
||||
1E94B ; Consonant # Lm ADLAM NASALIZATION MARK
|
||||
|
@ -140,7 +138,6 @@ FE00..FE0F ; Modifying_Letter # Mn [16] VARIATION SELECTOR-1..VARIATION SEL
|
|||
0F39 ; Nukta # Mn TIBETAN MARK TSA -PHRU # NOW IN UNICODE 10.0
|
||||
1885..1886 ; Nukta # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
|
||||
18A9 ; Nukta # Mn MONGOLIAN LETTER ALI GALI DAGALGA
|
||||
1B6B..1B73 ; Nukta # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
|
||||
10AE5..10AE6 ; Nukta # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
|
||||
16F4F ; Nukta # Mn MIAO SIGN CONSONANT MODIFIER BAR
|
||||
1BC9D..1BC9E ; Nukta # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
|
||||
|
@ -155,6 +152,7 @@ FE00..FE0F ; Modifying_Letter # Mn [16] VARIATION SELECTOR-1..VARIATION SEL
|
|||
16AC0..16AC9 ; Number # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE
|
||||
1E140..1E149 ; Number # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
|
||||
1E2F0..1E2F9 ; Number # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE
|
||||
1E4F0..1E4F9 ; Number # Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE
|
||||
1E950..1E959 ; Number # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
|
||||
|
||||
# ================================================
|
||||
|
@ -176,7 +174,9 @@ FE00..FE0F ; Modifying_Letter # Mn [16] VARIATION SELECTOR-1..VARIATION SEL
|
|||
|
||||
# Indic_Syllabic_Category=Virama
|
||||
2D7F ; Virama # Mn TIFINAGH CONSONANT JOINER
|
||||
#HIEROGLYPHS to be moved to new category
|
||||
13430..13436 ; Virama # Cf [7] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE
|
||||
13439..1343B ; Virama # Cf [3] EGYPTIAN HIEROGLYPH INSERT AT MIDDLE..EGYPTIAN HIEROGLYPH INSERT AT BOTTOM
|
||||
|
||||
# ================================================
|
||||
|
||||
|
@ -191,6 +191,21 @@ AABD ; Vowel_Independent # Lo TAI VIET VOWEL AN
|
|||
0B55 ; Vowel_Dependent # Mn ORIYA SIGN OVERLINE
|
||||
10EAB..10EAC ; Vowel_Dependent # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
|
||||
16F51..16F87 ; Vowel_Dependent # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
|
||||
1E4EC..1E4EF ; Vowel_Dependent # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Syllabic_Category=Cantillation_Mark
|
||||
|
||||
1CF8..1CF9 ; Cantillation_Mark # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
|
||||
#HIEROGLYPHS to be moved to new category
|
||||
13440 ; Cantillation_Mark # Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY
|
||||
13447..13455 ; Cantillation_Mark # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Syllabic_Category=Symbol_Modifier
|
||||
1B6B..1B73 ; Symbol_Modifier # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
|
||||
|
||||
# ================================================
|
||||
# ================================================
|
||||
|
@ -198,24 +213,56 @@ AABD ; Vowel_Independent # Lo TAI VIET VOWEL AN
|
|||
# ================================================
|
||||
# ================================================
|
||||
|
||||
# USE_Syllabic_Category=Hieroglyph
|
||||
# 13000..1342E ; Hieroglyph # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph
|
||||
# 13000..1342F ; Hieroglyph # Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D
|
||||
# 13441..13446 ; Hieroglyph # Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..HIEROGLYPH WIDE LOST SIGN
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE_Syllabic_Category=Hieroglyph_Joiner
|
||||
# 13430..13436 ; Hieroglyph_Joiner # Cf EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Joiner
|
||||
# 13430..13436 ; Hieroglyph_Joiner # Cf [7] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE
|
||||
# 13439..1343B ; Hieroglyph_Joiner # Cf [3] EGYPTIAN HIEROGLYPH INSERT AT MIDDLE..EGYPTIAN HIEROGLYPH INSERT AT BOTTOM
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE_Syllabic_Category= Hieroglyph_Segment_Begin
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Mark_Begin
|
||||
# 005B ; Hieroglyph_Mark_Begin # Ps LEFT SQUARE BRACKET
|
||||
# 007B ; Hieroglyph_Mark_Begin # Ps LEFT CURLY BRACKET
|
||||
# 27E6 ; Hieroglyph_Mark_Begin # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET
|
||||
# 27E8 ; Hieroglyph_Mark_Begin # Ps MATHEMATICAL LEFT ANGLE BRACKET
|
||||
# 2E22 ; Hieroglyph_Mark_Begin # Ps TOP LEFT HALF BRACKET
|
||||
# 2E24 ; Hieroglyph_Mark_Begin # Ps BOTTOM LEFT HALF BRACKET
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Mark_End
|
||||
# 005D ; Hieroglyph_Mark_Begin # Pe RIGHT SQUARE BRACKET
|
||||
# 007D ; Hieroglyph_Mark_Begin # Pe RIGHT CURLY BRACKET
|
||||
# 27E7 ; Hieroglyph_Mark_Begin # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET
|
||||
# 27E9 ; Hieroglyph_Mark_Begin # Pe MATHEMATICAL RIGHT ANGLE BRACKET
|
||||
# 2E23 ; Hieroglyph_Mark_Begin # Pe TOP RIGHT HALF BRACKET
|
||||
# 2E25 ; Hieroglyph_Mark_Begin # Pe BOTTOM RIGHT HALF BRACKET
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Segment_Begin
|
||||
# 13437 ; Hieroglyph_Segment_Begin # Cf EGYPTIAN HIEROGLYPH BEGIN SEGMENT
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE_Syllabic_Category= Hieroglyph_Segment_End
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Segment_End
|
||||
# 13438 ; Hieroglyph_Segment_End # Cf EGYPTIAN HIEROGLYPH END SEGMENT
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Mirror
|
||||
# 13440 ; Hieroglyph_Mirror # Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY
|
||||
|
||||
# ================================================
|
||||
|
||||
# USE, Extended_Syllabic_Category=Hieroglyph_Modifier
|
||||
# 13447..13455 ; Hieroglyph_Modifier # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED
|
||||
|
||||
# ================================================
|
||||
|
||||
# eof
|
||||
|
|
|
@ -222,6 +222,23 @@ main (int argc, char **argv)
|
|||
hb::unique_ptr<hb_hashmap_t<int, int>> *v2;
|
||||
m.has (0, &v2);
|
||||
}
|
||||
/* Test hashmap with complex shared_ptrs as keys. */
|
||||
{
|
||||
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> m;
|
||||
|
||||
hb_map_t *m1 = hb_map_create ();
|
||||
hb_map_t *m2 = hb_map_create ();
|
||||
m1->set (1,3);
|
||||
m2->set (1,3);
|
||||
|
||||
hb::shared_ptr<hb_map_t> p1 {m1};
|
||||
hb::shared_ptr<hb_map_t> p2 {m2};
|
||||
m.set (p1,1);
|
||||
|
||||
assert (m.has (p2));
|
||||
|
||||
m1->set (2,4);
|
||||
assert (!m.has (p2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ emoji-data.txt:
|
|||
emoji-test.txt:
|
||||
curl -O https://www.unicode.org/Public/emoji/latest/emoji-test.txt
|
||||
languagetags:
|
||||
curl -O https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
|
||||
curl -O https://learn.microsoft.com/en-us/typography/opentype/spec/languagetags
|
||||
language-subtag-registry:
|
||||
curl -O https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
|
||||
ucd.nounihan.grouped.zip:
|
||||
|
|
Binary file not shown.
|
@ -129,6 +129,8 @@
|
|||
/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334;--font-funcs ot;U+0631,U+0628;[u0628.beh=1+1415|u0631.reh=0@-202,0+700]
|
||||
/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334;--font-funcs ot;U+0628,U+064F;[u064f.damma=0@250,-250+250|u0628.beh=0@-250,0+1165]
|
||||
/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334;--font-funcs ot;U+0644,U+064E,U+0645,U+064E,U+0651,U+0627;[u0627.final.alef=5+647|u064e.fatha=0@-80,160+-80|u064e_u0651.shaddaFatha=0@490,250+490|u0644_u0645.initial.lamMeem=0@-410,0+415]
|
||||
/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334;--font-funcs ot;U+0644,U+0627;[u0644_u0627.isolated.lamAlef=0+1162]
|
||||
/System/Library/Fonts/GeezaPro.ttc@ab26ea45dcaa5e1c5a958e42af10e10d330e7334;--font-funcs ot --features rlig=0;U+0644,U+0627;[u0627.final.alef=1+647|u0644.initial.lam=0+515]
|
||||
# SFNS uses opsz variation axis which isn't invoked here, see https;//crbug.com/1005969#c37
|
||||
/System/Library/Fonts/SFNS.ttf@253b4b28662acc1de4a86350fd2b26d620ea213c;--font-funcs ot;U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064;[T=0+920|e=1+1049|space=2+420|A=3+1162|V=4+1292|space=5+420|T=6+960|r=7+631|space=8+420|V=9+1142|a=10+1028|space=11+420|r=12+461|T=13+1190|space=14+420|e=15+779|T=16+1190|space=17+420|T=18+920|d=19+1134]
|
||||
/System/Library/Fonts/SFNS.ttf@253b4b28662acc1de4a86350fd2b26d620ea213c;--font-ptem 9 --font-funcs ot;U+0054,U+0065,U+0020,U+0041,U+0056,U+0020,U+0054,U+0072,U+0020,U+0056,U+0061,U+0020,U+0072,U+0054,U+0020,U+0065,U+0054,U+0020,U+0054,U+0064;[T=0@19,0+958|e=1@19,0+1087|space=2@19,0+458|A=3@19,0+1200|V=4@19,0+1330|space=5@19,0+458|T=6@19,0+998|r=7@19,0+669|space=8@19,0+458|V=9@19,0+1180|a=10@19,0+1066|space=11@19,0+458|r=12@19,0+499|T=13@19,0+1228|space=14@19,0+458|e=15@19,0+817|T=16@19,0+1228|space=17@19,0+458|T=18@19,0+958|d=19@19,0+1172]
|
||||
|
|
|
@ -39,7 +39,6 @@ EXTRA_DIST += \
|
|||
expected/layout.gdef-attachlist \
|
||||
expected/layout.notonastaliqurdu \
|
||||
expected/layout.tinos \
|
||||
expected/layout.default_features \
|
||||
expected/layout.duplicate_features \
|
||||
expected/layout.unsorted_featurelist \
|
||||
expected/layout.drop_feature \
|
||||
|
|
|
@ -38,7 +38,6 @@ TESTS = \
|
|||
tests/layout.notonastaliqurdu.tests \
|
||||
tests/layout.tests \
|
||||
tests/layout.tinos.tests \
|
||||
tests/layout.default_features.tests \
|
||||
tests/layout.duplicate_features.tests \
|
||||
tests/layout.unsorted_featurelist.tests \
|
||||
tests/layout.drop_feature.tests \
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
FONTS:
|
||||
MPLUS1-Variable.ttf
|
||||
|
||||
PROFILES:
|
||||
default.txt
|
||||
notdef-outline.txt
|
||||
|
||||
SUBSETS:
|
||||
*
|
||||
|
||||
INSTANCES:
|
||||
wght=400
|
|
@ -1,11 +0,0 @@
|
|||
FONTS:
|
||||
FranklinGothic-Regular.ttf
|
||||
|
||||
PROFILES:
|
||||
layout-test.txt
|
||||
default.txt
|
||||
retain-gids.txt
|
||||
|
||||
SUBSETS:
|
||||
achi
|
||||
*
|
|
@ -28,15 +28,7 @@ def strip_check_sum (ttx_string):
|
|||
|
||||
|
||||
def generate_expected_output(input_file, unicodes, profile_flags, instance_flags, output_directory, font_name):
|
||||
fonttools_path = os.path.join(tempfile.mkdtemp (), font_name)
|
||||
args = ["fonttools", "subset", input_file]
|
||||
args.extend(["--drop-tables+=DSIG",
|
||||
"--drop-tables-=sbix",
|
||||
"--unicodes=%s" % unicodes,
|
||||
"--output-file=%s" % fonttools_path])
|
||||
args.extend(profile_flags)
|
||||
check_call(args)
|
||||
|
||||
input_path = input_file
|
||||
if instance_flags:
|
||||
instance_path = os.path.join(tempfile.mkdtemp (), font_name)
|
||||
args = ["fonttools", "varLib.instancer",
|
||||
|
@ -44,10 +36,19 @@ def generate_expected_output(input_file, unicodes, profile_flags, instance_flags
|
|||
"--no-recalc-bounds",
|
||||
"--no-recalc-timestamp",
|
||||
"--output=%s" % instance_path,
|
||||
fonttools_path]
|
||||
input_file]
|
||||
args.extend(instance_flags)
|
||||
check_call(args)
|
||||
fonttools_path = instance_path
|
||||
input_path = instance_path
|
||||
|
||||
fonttools_path = os.path.join(tempfile.mkdtemp (), font_name)
|
||||
args = ["fonttools", "subset", input_path]
|
||||
args.extend(["--drop-tables+=DSIG",
|
||||
"--drop-tables-=sbix",
|
||||
"--unicodes=%s" % unicodes,
|
||||
"--output-file=%s" % fonttools_path])
|
||||
args.extend(profile_flags)
|
||||
check_call(args)
|
||||
|
||||
with io.StringIO () as fp:
|
||||
with TTFont (fonttools_path) as font:
|
||||
|
|
|
@ -33,7 +33,6 @@ tests = [
|
|||
'layout.duplicate_features',
|
||||
'layout.unsorted_featurelist',
|
||||
'layout.drop_feature',
|
||||
'layout.default_features',
|
||||
'cmap',
|
||||
'cmap14',
|
||||
'sbix',
|
||||
|
@ -54,6 +53,7 @@ tests = [
|
|||
# 'pin_all_at_default',
|
||||
# 'instantiate_glyf',
|
||||
# 'full_instance',
|
||||
# 'instance_feature_variations',
|
||||
]
|
||||
|
||||
repack_tests = [
|
||||
|
|
|
@ -52,6 +52,7 @@ def run_test (test, should_check_ots):
|
|||
cli_args = ["--font-file=" + test.font_path,
|
||||
"--output-file=" + out_file,
|
||||
"--unicodes=%s" % test.unicodes (),
|
||||
"--preprocess-face",
|
||||
"--drop-tables+=DSIG",
|
||||
"--drop-tables-=sbix"]
|
||||
cli_args.extend (test.get_profile_flags ())
|
||||
|
|
|
@ -32,6 +32,15 @@
|
|||
|
||||
#include <hb-subset.h>
|
||||
|
||||
static hb_face_t* preprocess_face(hb_face_t* face)
|
||||
{
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
return hb_subset_preprocess (face);
|
||||
#else
|
||||
return hb_face_reference(face);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Command line interface to the harfbuzz font subsetter.
|
||||
*/
|
||||
|
@ -103,6 +112,10 @@ struct subset_main_t : option_parser_t, face_options_t, output_options_t<false>
|
|||
{
|
||||
parse (argc, argv);
|
||||
|
||||
hb_face_t* orig_face = face;
|
||||
if (preprocess)
|
||||
orig_face = preprocess_face (face);
|
||||
|
||||
hb_face_t *new_face = nullptr;
|
||||
for (unsigned i = 0; i < num_iterations; i++)
|
||||
{
|
||||
|
@ -119,6 +132,8 @@ struct subset_main_t : option_parser_t, face_options_t, output_options_t<false>
|
|||
}
|
||||
|
||||
hb_face_destroy (new_face);
|
||||
if (preprocess)
|
||||
hb_face_destroy (orig_face);
|
||||
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
|
@ -160,6 +175,7 @@ struct subset_main_t : option_parser_t, face_options_t, output_options_t<false>
|
|||
public:
|
||||
|
||||
unsigned num_iterations = 1;
|
||||
gboolean preprocess;
|
||||
hb_subset_input_t *input = nullptr;
|
||||
};
|
||||
|
||||
|
@ -915,6 +931,8 @@ subset_main_t::add_options ()
|
|||
{"no-prune-unicode-ranges", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag<HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES>, "Don't change the 'OS/2 ulUnicodeRange*' bits.", nullptr},
|
||||
{"glyph-names", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag<HB_SUBSET_FLAGS_GLYPH_NAMES>, "Keep PS glyph names in TT-flavored fonts. ", nullptr},
|
||||
{"passthrough-tables", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &set_flag<HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED>, "Do not drop tables that the tool does not know how to subset.", nullptr},
|
||||
{"preprocess-face", 0, 0, G_OPTION_ARG_NONE, &this->preprocess,
|
||||
"If set preprocesses the face with the add accelerator option before actually subsetting.", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
add_group (flag_entries,
|
||||
|
|
Loading…
Reference in New Issue