Upgrade Harfbuzz to 11.0.0
[ChangeLog][Third-Party Code] Upgraded Harfbuzz to version 11.0.0. Pick-to: 6.8 6.5 5.15 Fixes: QTBUG-135373 Change-Id: If4a530ec43f5992141945d7ad86268e838cc0230 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> (cherry picked from commit 98e0a7e0a067c6aacf9d61295bd36d290b150d51) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
53a687e5c3
commit
a1b4480c53
1
src/3rdparty/harfbuzz-ng/CMakeLists.txt
vendored
1
src/3rdparty/harfbuzz-ng/CMakeLists.txt
vendored
@ -15,6 +15,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
|
||||
src/hb-aat-map.cc
|
||||
src/hb-algs.hh
|
||||
src/hb-atomic.hh
|
||||
src/hb-bit-vector.hh
|
||||
src/hb-blob.cc src/hb-blob.h
|
||||
src/hb-buffer.cc src/hb-buffer.h src/hb-buffer.hh
|
||||
src/hb-buffer-deserialize-json.hh
|
||||
|
2
src/3rdparty/harfbuzz-ng/README.md
vendored
2
src/3rdparty/harfbuzz-ng/README.md
vendored
@ -51,6 +51,8 @@ For custom configurations, see [CONFIG.md](CONFIG.md).
|
||||
|
||||
For testing and profiling, see [TESTING.md](TESTING.md).
|
||||
|
||||
For cross-compiling to Windows from Linux or macOS, see [README.mingw.md](README.mingw.md).
|
||||
|
||||
To get a better idea of where HarfBuzz stands in the text rendering stack you
|
||||
may want to read [State of Text Rendering 2024][6].
|
||||
Here are a few presentation slides about HarfBuzz at the
|
||||
|
4
src/3rdparty/harfbuzz-ng/qt_attribution.json
vendored
4
src/3rdparty/harfbuzz-ng/qt_attribution.json
vendored
@ -7,8 +7,8 @@
|
||||
|
||||
"Description": "HarfBuzz is an OpenType text shaping engine.",
|
||||
"Homepage": "http://harfbuzz.org",
|
||||
"Version": "10.4.0",
|
||||
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/10.4.0",
|
||||
"Version": "11.0.0",
|
||||
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.0.0",
|
||||
"PURL": "pkg:github/harfbuzz/harfbuzz@$<VERSION>",
|
||||
"CPE": "cpe:2.3:a:harfbuzz_project:harfbuzz:$<VERSION>:*:*:*:*:*:*:*",
|
||||
"License": "MIT License",
|
||||
|
127
src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
vendored
127
src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
vendored
@ -47,6 +47,11 @@ namespace OT {
|
||||
struct hb_paint_context_t;
|
||||
}
|
||||
|
||||
struct hb_colr_scratch_t
|
||||
{
|
||||
hb_paint_extents_context_t paint_extents;
|
||||
};
|
||||
|
||||
namespace OT {
|
||||
|
||||
struct COLR;
|
||||
@ -90,7 +95,8 @@ public:
|
||||
font (font_),
|
||||
palette (
|
||||
#ifndef HB_NO_COLOR
|
||||
font->face->table.CPAL->get_palette_colors (palette_)
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5116
|
||||
font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0)
|
||||
#endif
|
||||
),
|
||||
foreground (foreground_),
|
||||
@ -932,9 +938,9 @@ struct PaintGlyph
|
||||
void paint_glyph (hb_paint_context_t *c) const
|
||||
{
|
||||
TRACE_PAINT (this);
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->funcs->push_inverse_font_transform (c->data, c->font);
|
||||
c->funcs->push_clip_glyph (c->data, gid, c->font);
|
||||
c->funcs->push_root_transform (c->data, c->font);
|
||||
c->funcs->push_font_transform (c->data, c->font);
|
||||
c->recurse (this+paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_clip (c->data);
|
||||
@ -1511,10 +1517,12 @@ struct PaintComposite
|
||||
void paint_glyph (hb_paint_context_t *c) const
|
||||
{
|
||||
TRACE_PAINT (this);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (this+backdrop);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (this+src);
|
||||
c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode);
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 32 */
|
||||
@ -2079,6 +2087,8 @@ struct COLR
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
|
||||
|
||||
bool has_data () const { return has_v0_data () || version; }
|
||||
|
||||
bool has_v0_data () const { return numBaseGlyphs; }
|
||||
bool has_v1_data () const
|
||||
{
|
||||
@ -2112,7 +2122,53 @@ struct COLR
|
||||
{
|
||||
accelerator_t (hb_face_t *face)
|
||||
{ colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
|
||||
~accelerator_t () { this->colr.destroy (); }
|
||||
|
||||
~accelerator_t ()
|
||||
{
|
||||
auto *scratch = cached_scratch.get_relaxed ();
|
||||
if (scratch)
|
||||
{
|
||||
scratch->~hb_colr_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
|
||||
colr.destroy ();
|
||||
}
|
||||
|
||||
|
||||
bool has_data () const { return colr->has_data (); }
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (unlikely (!has_data ())) return false;
|
||||
|
||||
hb_colr_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = colr->get_extents (font, glyph, extents, *scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool paint_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *funcs, void *data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
bool clip = true) const
|
||||
{
|
||||
if (unlikely (!has_data ())) return false;
|
||||
|
||||
hb_colr_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_valid () { return colr.get_blob ()->length; }
|
||||
|
||||
@ -2148,7 +2204,33 @@ struct COLR
|
||||
{ return colr->get_delta_set_index_map_ptr (); }
|
||||
|
||||
private:
|
||||
|
||||
hb_colr_scratch_t *acquire_scratch () const
|
||||
{
|
||||
hb_colr_scratch_t *scratch = cached_scratch.get_acquire ();
|
||||
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_colr_scratch_t *) hb_calloc (1, sizeof (hb_colr_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scratch;
|
||||
}
|
||||
void release_scratch (hb_colr_scratch_t *scratch) const
|
||||
{
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_colr_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
hb_blob_ptr_t<COLR> colr;
|
||||
private:
|
||||
hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
void closure_glyphs (hb_codepoint_t glyph,
|
||||
@ -2520,7 +2602,10 @@ struct COLR
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
hb_colr_scratch_t &scratch) const
|
||||
{
|
||||
|
||||
ItemVarStoreInstancer instancer (get_var_store_ptr (),
|
||||
@ -2534,10 +2619,10 @@ struct COLR
|
||||
}
|
||||
|
||||
auto *extents_funcs = hb_paint_extents_get_funcs ();
|
||||
hb_paint_extents_context_t extents_data;
|
||||
bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0));
|
||||
scratch.paint_extents.clear ();
|
||||
bool ret = paint_glyph (font, glyph, extents_funcs, &scratch.paint_extents, 0, HB_COLOR(0,0,0,0), true, scratch);
|
||||
|
||||
hb_extents_t e = extents_data.get_extents ();
|
||||
auto e = scratch.paint_extents.get_extents ();
|
||||
if (e.is_void ())
|
||||
{
|
||||
extents->x_bearing = 0;
|
||||
@ -2547,6 +2632,7 @@ struct COLR
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ugh. We need to undo the synthetic slant here. Leave it for now. :-(.
|
||||
extents->x_bearing = e.xmin;
|
||||
extents->y_bearing = e.ymax;
|
||||
extents->width = e.xmax - e.xmin;
|
||||
@ -2583,7 +2669,12 @@ struct COLR
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
|
||||
paint_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *funcs, void *data,
|
||||
unsigned int palette_index, hb_color_t foreground,
|
||||
bool clip,
|
||||
hb_colr_scratch_t &scratch) const
|
||||
{
|
||||
ItemVarStoreInstancer instancer (get_var_store_ptr (),
|
||||
get_delta_set_index_map_ptr (),
|
||||
@ -2609,6 +2700,7 @@ struct COLR
|
||||
if (get_clip (glyph, &extents, instancer))
|
||||
{
|
||||
font->scale_glyph_extents (&extents);
|
||||
font->synthetic_glyph_extents (&extents);
|
||||
c.funcs->push_clip_rectangle (c.data,
|
||||
extents.x_bearing,
|
||||
extents.y_bearing + extents.height,
|
||||
@ -2618,15 +2710,16 @@ struct COLR
|
||||
else
|
||||
{
|
||||
auto *extents_funcs = hb_paint_extents_get_funcs ();
|
||||
hb_paint_extents_context_t extents_data;
|
||||
scratch.paint_extents.clear ();
|
||||
|
||||
paint_glyph (font, glyph,
|
||||
extents_funcs, &extents_data,
|
||||
extents_funcs, &scratch.paint_extents,
|
||||
palette_index, foreground,
|
||||
false);
|
||||
false,
|
||||
scratch);
|
||||
|
||||
hb_extents_t extents = extents_data.get_extents ();
|
||||
is_bounded = extents_data.is_bounded ();
|
||||
auto extents = scratch.paint_extents.get_extents ();
|
||||
is_bounded = scratch.paint_extents.is_bounded ();
|
||||
|
||||
c.funcs->push_clip_rectangle (c.data,
|
||||
extents.xmin,
|
||||
@ -2636,7 +2729,7 @@ struct COLR
|
||||
}
|
||||
}
|
||||
|
||||
c.funcs->push_root_transform (c.data, font);
|
||||
c.funcs->push_font_transform (c.data, font);
|
||||
|
||||
if (is_bounded)
|
||||
c.recurse (*paint);
|
||||
@ -2714,9 +2807,7 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
|
||||
return;
|
||||
|
||||
const Paint &paint = paint_offset_lists.get_paint (i);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (paint);
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2728,7 +2819,7 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
|
||||
if (unlikely (!node.visit (gid)))
|
||||
return;
|
||||
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->funcs->push_inverse_font_transform (c->data, c->font);
|
||||
if (c->funcs->color_glyph (c->data, gid, c->font))
|
||||
{
|
||||
c->funcs->pop_transform (c->data);
|
||||
|
105
src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.cc
vendored
105
src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.cc
vendored
@ -126,24 +126,18 @@ hb_transforming_pen_get_funcs ()
|
||||
return static_transforming_pen_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
|
||||
hb_ubytes_t
|
||||
VarComponent::get_path_at (hb_font_t *font,
|
||||
VarComponent::get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t parent_gid,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t total_transform,
|
||||
hb_ubytes_t total_record,
|
||||
hb_decycler_t *decycler,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
VarRegionList::cache_t *cache) const
|
||||
{
|
||||
const unsigned char *end = total_record.arrayZ + total_record.length;
|
||||
const unsigned char *record = total_record.arrayZ;
|
||||
|
||||
auto &VARC = *font->face->table.VARC->table;
|
||||
auto &VARC = *c.font->face->table.VARC->table;
|
||||
auto &varStore = &VARC+VARC.varStore;
|
||||
|
||||
#define READ_UINT32VAR(name) \
|
||||
@ -193,9 +187,9 @@ VarComponent::get_path_at (hb_font_t *font,
|
||||
|
||||
// Axis values
|
||||
|
||||
auto &axisIndices = scratch.axisIndices;
|
||||
auto &axisIndices = c.scratch.axisIndices;
|
||||
axisIndices.clear ();
|
||||
auto &axisValues = scratch.axisValues;
|
||||
auto &axisValues = c.scratch.axisValues;
|
||||
axisValues.clear ();
|
||||
if (flags & (unsigned) flags_t::HAVE_AXES)
|
||||
{
|
||||
@ -222,7 +216,7 @@ VarComponent::get_path_at (hb_font_t *font,
|
||||
* limit on the max number of coords for now. */
|
||||
if ((flags & (unsigned) flags_t::RESET_UNSPECIFIED_AXES) ||
|
||||
coords.length > HB_VAR_COMPOSITE_MAX_AXES)
|
||||
component_coords = hb_array<int> (font->coords, font->num_coords);
|
||||
component_coords = hb_array<int> (c.font->coords, c.font->num_coords);
|
||||
|
||||
// Transform
|
||||
|
||||
@ -316,14 +310,18 @@ VarComponent::get_path_at (hb_font_t *font,
|
||||
transform.scaleY = transform.scaleX;
|
||||
|
||||
total_transform.transform (transform.to_transform ());
|
||||
total_transform.scale (font->x_mult ? 1.f / font->x_multf : 0.f,
|
||||
font->y_mult ? 1.f / font->y_multf : 0.f);
|
||||
total_transform.scale (c.font->x_mult ? 1.f / c.font->x_multf : 0.f,
|
||||
c.font->y_mult ? 1.f / c.font->y_multf : 0.f);
|
||||
|
||||
VARC.get_path_at (font, gid,
|
||||
draw_session, component_coords, total_transform,
|
||||
bool same_coords = component_coords.length == coords.length &&
|
||||
component_coords.arrayZ == coords.arrayZ;
|
||||
|
||||
c.depth_left--;
|
||||
VARC.get_path_at (c, gid,
|
||||
component_coords, total_transform,
|
||||
parent_gid,
|
||||
decycler, edges_left, depth_left - 1,
|
||||
scratch);
|
||||
same_coords ? cache : nullptr);
|
||||
c.depth_left++;
|
||||
}
|
||||
|
||||
#undef PROCESS_TRANSFORM_COMPONENTS
|
||||
@ -333,16 +331,12 @@ VarComponent::get_path_at (hb_font_t *font,
|
||||
}
|
||||
|
||||
bool
|
||||
VARC::get_path_at (hb_font_t *font,
|
||||
VARC::get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_codepoint_t parent_glyph,
|
||||
hb_decycler_t *decycler,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
hb_glyf_scratch_t &scratch) const
|
||||
VarRegionList::cache_t *parent_cache) const
|
||||
{
|
||||
// Don't recurse on the same glyph.
|
||||
unsigned idx = glyph == parent_glyph ?
|
||||
@ -350,50 +344,69 @@ VARC::get_path_at (hb_font_t *font,
|
||||
(this+coverage).get_coverage (glyph);
|
||||
if (idx == NOT_COVERED)
|
||||
{
|
||||
// Build a transforming pen to apply the transform.
|
||||
hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs ();
|
||||
hb_transforming_pen_context_t context {transform,
|
||||
draw_session.funcs,
|
||||
draw_session.draw_data,
|
||||
&draw_session.st};
|
||||
hb_draw_session_t transformer_session {transformer_funcs, &context};
|
||||
hb_draw_session_t &shape_draw_session = transform.is_identity () ? draw_session : transformer_session;
|
||||
if (c.draw_session)
|
||||
{
|
||||
// Build a transforming pen to apply the transform.
|
||||
hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs ();
|
||||
hb_transforming_pen_context_t context {transform,
|
||||
c.draw_session->funcs,
|
||||
c.draw_session->draw_data,
|
||||
&c.draw_session->st};
|
||||
hb_draw_session_t transformer_session {transformer_funcs, &context};
|
||||
hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session;
|
||||
|
||||
if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords, scratch))
|
||||
if (!c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch))
|
||||
#ifndef HB_NO_CFF
|
||||
if (!font->face->table.cff2->get_path_at (font, glyph, shape_draw_session, coords))
|
||||
if (!font->face->table.cff1->get_path (font, glyph, shape_draw_session)) // Doesn't have variations
|
||||
if (!c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords))
|
||||
if (!c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) // Doesn't have variations
|
||||
#endif
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
else if (c.extents)
|
||||
{
|
||||
hb_glyph_extents_t glyph_extents;
|
||||
if (!c.font->face->table.glyf->get_extents_at (c.font, glyph, &glyph_extents, coords))
|
||||
#ifndef HB_NO_CFF
|
||||
if (!c.font->face->table.cff2->get_extents_at (c.font, glyph, &glyph_extents, coords))
|
||||
if (!c.font->face->table.cff1->get_extents (c.font, glyph, &glyph_extents)) // Doesn't have variations
|
||||
#endif
|
||||
return false;
|
||||
|
||||
hb_extents_t comp_extents (glyph_extents);
|
||||
transform.transform_extents (comp_extents);
|
||||
c.extents->union_ (comp_extents);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (depth_left <= 0)
|
||||
if (c.depth_left <= 0)
|
||||
return true;
|
||||
|
||||
if (*edges_left <= 0)
|
||||
if (c.edges_left <= 0)
|
||||
return true;
|
||||
(*edges_left)--;
|
||||
(c.edges_left)--;
|
||||
|
||||
hb_decycler_node_t node (*decycler);
|
||||
hb_decycler_node_t node (c.decycler);
|
||||
if (unlikely (!node.visit (glyph)))
|
||||
return true;
|
||||
|
||||
hb_ubytes_t record = (this+glyphRecords)[idx];
|
||||
|
||||
float static_cache[sizeof (void *) * 16];
|
||||
VarRegionList::cache_t *cache = (this+varStore).create_cache (hb_array (static_cache));
|
||||
VarRegionList::cache_t *cache = parent_cache ?
|
||||
parent_cache :
|
||||
(this+varStore).create_cache (hb_array (static_cache));
|
||||
|
||||
transform.scale (font->x_multf, font->y_multf);
|
||||
transform.scale (c.font->x_multf, c.font->y_multf);
|
||||
|
||||
VarCompositeGlyph::get_path_at (font, glyph,
|
||||
draw_session, coords, transform,
|
||||
VarCompositeGlyph::get_path_at (c,
|
||||
glyph,
|
||||
coords, transform,
|
||||
record,
|
||||
decycler, edges_left, depth_left,
|
||||
scratch,
|
||||
cache);
|
||||
|
||||
(this+varStore).destroy_cache (cache, hb_array (static_cache));
|
||||
if (cache != parent_cache)
|
||||
(this+varStore).destroy_cache (cache, hb_array (static_cache));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
166
src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.hh
vendored
166
src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.hh
vendored
@ -21,6 +21,24 @@ namespace OT {
|
||||
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
|
||||
struct hb_varc_scratch_t
|
||||
{
|
||||
hb_vector_t<unsigned> axisIndices;
|
||||
hb_vector_t<float> axisValues;
|
||||
hb_glyf_scratch_t glyf_scratch;
|
||||
};
|
||||
|
||||
struct hb_varc_context_t
|
||||
{
|
||||
hb_font_t *font;
|
||||
hb_draw_session_t *draw_session;
|
||||
hb_extents_t *extents;
|
||||
mutable hb_decycler_t decycler;
|
||||
mutable signed edges_left;
|
||||
mutable signed depth_left;
|
||||
hb_varc_scratch_t &scratch;
|
||||
};
|
||||
|
||||
struct VarComponent
|
||||
{
|
||||
enum class flags_t : uint32_t
|
||||
@ -44,41 +62,32 @@ struct VarComponent
|
||||
};
|
||||
|
||||
HB_INTERNAL hb_ubytes_t
|
||||
get_path_at (hb_font_t *font,
|
||||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t parent_gid,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_ubytes_t record,
|
||||
hb_decycler_t *decycler,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
VarRegionList::cache_t *cache = nullptr) const;
|
||||
};
|
||||
|
||||
struct VarCompositeGlyph
|
||||
{
|
||||
static void
|
||||
get_path_at (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_session_t &draw_session,
|
||||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_ubytes_t record,
|
||||
hb_decycler_t *decycler,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
VarRegionList::cache_t *cache = nullptr)
|
||||
VarRegionList::cache_t *cache)
|
||||
{
|
||||
while (record)
|
||||
{
|
||||
const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
|
||||
record = comp.get_path_at (font, glyph,
|
||||
draw_session, coords, transform,
|
||||
record = comp.get_path_at (c,
|
||||
gid,
|
||||
coords, transform,
|
||||
record,
|
||||
decycler, edges_left, depth_left, scratch, cache);
|
||||
cache);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -92,36 +101,47 @@ struct VARC
|
||||
static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C');
|
||||
|
||||
HB_INTERNAL bool
|
||||
get_path_at (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_session_t &draw_session,
|
||||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_codepoint_t parent_glyph,
|
||||
hb_decycler_t *decycler,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
hb_glyf_scratch_t &scratch) const;
|
||||
hb_transform_t transform = HB_TRANSFORM_IDENTITY,
|
||||
hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID,
|
||||
VarRegionList::cache_t *parent_cache = nullptr) const;
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_glyf_scratch_t &scratch) const
|
||||
hb_varc_scratch_t &scratch) const
|
||||
{
|
||||
hb_decycler_t decycler;
|
||||
signed edges = HB_MAX_GRAPH_EDGE_COUNT;
|
||||
hb_varc_context_t c {font,
|
||||
&draw_session,
|
||||
nullptr,
|
||||
hb_decycler_t {},
|
||||
HB_MAX_GRAPH_EDGE_COUNT,
|
||||
HB_MAX_NESTING_LEVEL,
|
||||
scratch};
|
||||
|
||||
return get_path_at (font,
|
||||
gid,
|
||||
draw_session,
|
||||
hb_array (font->coords, font->num_coords),
|
||||
HB_TRANSFORM_IDENTITY,
|
||||
HB_CODEPOINT_INVALID,
|
||||
&decycler,
|
||||
&edges,
|
||||
HB_MAX_NESTING_LEVEL,
|
||||
scratch);
|
||||
return get_path_at (c, gid,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
}
|
||||
|
||||
bool
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_extents_t *extents,
|
||||
hb_varc_scratch_t &scratch) const
|
||||
{
|
||||
hb_varc_context_t c {font,
|
||||
nullptr,
|
||||
extents,
|
||||
hb_decycler_t {},
|
||||
HB_MAX_GRAPH_EDGE_COUNT,
|
||||
HB_MAX_NESTING_LEVEL,
|
||||
scratch};
|
||||
|
||||
return get_path_at (c, gid,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
@ -150,7 +170,7 @@ struct VARC
|
||||
auto *scratch = cached_scratch.get_relaxed ();
|
||||
if (scratch)
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
scratch->~hb_varc_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
|
||||
@ -162,34 +182,60 @@ struct VARC
|
||||
{
|
||||
if (!table->has_data ()) return false;
|
||||
|
||||
hb_glyf_scratch_t *scratch;
|
||||
|
||||
// Borrow the cached strach buffer.
|
||||
{
|
||||
scratch = cached_scratch.get_acquire ();
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
auto *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = table->get_path (font, gid, draw_session, *scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Put it back.
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
bool
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (!table->has_data ()) return false;
|
||||
|
||||
hb_extents_t f_extents;
|
||||
|
||||
auto *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = table->get_extents (font, gid, &f_extents, *scratch);
|
||||
release_scratch (scratch);
|
||||
|
||||
if (ret)
|
||||
*extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
hb_varc_scratch_t *acquire_scratch () const
|
||||
{
|
||||
hb_varc_scratch_t *scratch = cached_scratch.get_acquire ();
|
||||
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scratch;
|
||||
}
|
||||
void release_scratch (hb_varc_scratch_t *scratch) const
|
||||
{
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_varc_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<VARC> table;
|
||||
hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
|
||||
hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
bool has_data () const { return version.major != 0; }
|
||||
|
21
src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
vendored
21
src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh
vendored
@ -429,16 +429,27 @@ struct glyf_accelerator_t
|
||||
}
|
||||
|
||||
public:
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||
|
||||
bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{ return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); }
|
||||
|
||||
bool get_extents_at (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents,
|
||||
hb_array_t<const int> coords) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (font->num_coords)
|
||||
if (coords)
|
||||
{
|
||||
hb_glyf_scratch_t scratch;
|
||||
return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
return get_points (font,
|
||||
gid,
|
||||
points_aggregator_t (font, extents, nullptr, true),
|
||||
coords,
|
||||
scratch);
|
||||
}
|
||||
#endif
|
||||
@ -532,7 +543,7 @@ struct glyf_accelerator_t
|
||||
unsigned int num_glyphs;
|
||||
hb_blob_ptr_t<loca> loca_table;
|
||||
hb_blob_ptr_t<glyf> glyf_table;
|
||||
hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
|
||||
hb_atomic_t<hb_glyf_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
|
||||
|
3
src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
vendored
3
src/3rdparty/harfbuzz-ng/src/harfbuzz.cc
vendored
@ -8,6 +8,9 @@
|
||||
#include "hb-common.cc"
|
||||
#include "hb-coretext-font.cc"
|
||||
#include "hb-coretext-shape.cc"
|
||||
#include "hb-coretext.cc"
|
||||
#include "hb-directwrite-font.cc"
|
||||
#include "hb-directwrite-shape.cc"
|
||||
#include "hb-directwrite.cc"
|
||||
#include "hb-draw.cc"
|
||||
#include "hb-face-builder.cc"
|
||||
|
141
src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
vendored
141
src/3rdparty/harfbuzz-ng/src/hb-aat-layout-common.hh
vendored
@ -29,6 +29,8 @@
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-aat-map.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-cache.hh"
|
||||
#include "hb-bit-set.hh"
|
||||
@ -48,6 +50,61 @@ struct ankr;
|
||||
using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
|
||||
|
||||
struct hb_aat_scratch_t
|
||||
{
|
||||
hb_aat_scratch_t () = default;
|
||||
hb_aat_scratch_t (const hb_aat_scratch_t &) = delete;
|
||||
|
||||
hb_aat_scratch_t (hb_aat_scratch_t &&o)
|
||||
{
|
||||
buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
|
||||
o.buffer_glyph_set.set_relaxed (nullptr);
|
||||
}
|
||||
hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o)
|
||||
{
|
||||
buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
|
||||
o.buffer_glyph_set.set_relaxed (nullptr);
|
||||
return *this;
|
||||
}
|
||||
~hb_aat_scratch_t ()
|
||||
{
|
||||
auto *s = buffer_glyph_set.get_relaxed ();
|
||||
if (unlikely (!s))
|
||||
return;
|
||||
s->fini ();
|
||||
hb_free (s);
|
||||
}
|
||||
|
||||
hb_bit_set_t *create_buffer_glyph_set () const
|
||||
{
|
||||
hb_bit_set_t *s = buffer_glyph_set.get_acquire ();
|
||||
if (s && buffer_glyph_set.cmpexch (s, nullptr))
|
||||
return s;
|
||||
|
||||
s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t));
|
||||
if (unlikely (!s))
|
||||
return nullptr;
|
||||
s->init ();
|
||||
|
||||
return s;
|
||||
}
|
||||
void destroy_buffer_glyph_set (hb_bit_set_t *s) const
|
||||
{
|
||||
if (unlikely (!s))
|
||||
return;
|
||||
if (buffer_glyph_set.cmpexch (nullptr, s))
|
||||
return;
|
||||
s->fini ();
|
||||
hb_free (s);
|
||||
}
|
||||
|
||||
mutable hb_atomic_t<hb_bit_set_t *> buffer_glyph_set;
|
||||
};
|
||||
|
||||
enum { DELETED_GLYPH = 0xFFFF };
|
||||
|
||||
#define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0
|
||||
|
||||
struct hb_aat_apply_context_t :
|
||||
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
|
||||
{
|
||||
@ -64,10 +121,11 @@ struct hb_aat_apply_context_t :
|
||||
hb_buffer_t *buffer;
|
||||
hb_sanitize_context_t sanitizer;
|
||||
const ankr *ankr_table;
|
||||
const OT::GDEF *gdef_table;
|
||||
const OT::GDEF &gdef;
|
||||
bool has_glyph_classes;
|
||||
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
|
||||
bool using_buffer_glyph_set = false;
|
||||
hb_bit_set_t buffer_glyph_set;
|
||||
hb_bit_set_t *buffer_glyph_set = nullptr;
|
||||
const hb_bit_set_t *left_set = nullptr;
|
||||
const hb_bit_set_t *right_set = nullptr;
|
||||
const hb_bit_set_t *machine_glyph_set = nullptr;
|
||||
@ -90,15 +148,15 @@ struct hb_aat_apply_context_t :
|
||||
|
||||
void setup_buffer_glyph_set ()
|
||||
{
|
||||
using_buffer_glyph_set = buffer->len >= 4;
|
||||
using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set;
|
||||
|
||||
if (using_buffer_glyph_set)
|
||||
buffer->collect_codepoints (buffer_glyph_set);
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer->collect_codepoints (*buffer_glyph_set);
|
||||
}
|
||||
bool buffer_intersects_machine () const
|
||||
{
|
||||
if (using_buffer_glyph_set)
|
||||
return buffer_glyph_set.intersects (*machine_glyph_set);
|
||||
if (likely (using_buffer_glyph_set))
|
||||
return buffer_glyph_set->intersects (*machine_glyph_set);
|
||||
|
||||
// Faster for shorter buffers.
|
||||
for (unsigned i = 0; i < buffer->len; i++)
|
||||
@ -106,6 +164,66 @@ struct hb_aat_apply_context_t :
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HB_NODISCARD bool output_glyphs (unsigned int count,
|
||||
const T *glyphs)
|
||||
{
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer_glyph_set->add_array (glyphs, count);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphs[i] == DELETED_GLYPH)
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
|
||||
_hb_glyph_info_set_aat_deleted (&buffer->cur());
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->cur(),
|
||||
gdef.get_glyph_props (glyphs[i]));
|
||||
#endif
|
||||
}
|
||||
if (unlikely (!buffer->output_glyph (glyphs[i]))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph)
|
||||
{
|
||||
if (glyph == DELETED_GLYPH)
|
||||
return delete_glyph ();
|
||||
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer_glyph_set->add (glyph);
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->cur(),
|
||||
gdef.get_glyph_props (glyph));
|
||||
#endif
|
||||
return buffer->replace_glyph (glyph);
|
||||
}
|
||||
|
||||
HB_NODISCARD bool delete_glyph ()
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
|
||||
_hb_glyph_info_set_aat_deleted (&buffer->cur());
|
||||
return buffer->replace_glyph (DELETED_GLYPH);
|
||||
}
|
||||
|
||||
void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph)
|
||||
{
|
||||
buffer->info[i].codepoint = glyph;
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer_glyph_set->add (glyph);
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[i],
|
||||
gdef.get_glyph_props (glyph));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -113,8 +231,6 @@ struct hb_aat_apply_context_t :
|
||||
* Lookup Table
|
||||
*/
|
||||
|
||||
enum { DELETED_GLYPH = 0xFFFF };
|
||||
|
||||
template <typename T> struct Lookup;
|
||||
|
||||
template <typename T>
|
||||
@ -179,6 +295,7 @@ struct LookupSegmentSingle
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
if (first == DELETED_GLYPH) return;
|
||||
if (!filter (value)) return;
|
||||
glyphs.add_range (first, last);
|
||||
}
|
||||
@ -268,6 +385,7 @@ struct LookupSegmentArray
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
|
||||
{
|
||||
if (first == DELETED_GLYPH) return;
|
||||
const auto &values = base+valuesZ;
|
||||
for (hb_codepoint_t i = first; i <= last; i++)
|
||||
if (filter (values[i - first]))
|
||||
@ -368,6 +486,7 @@ struct LookupSingle
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
if (glyph == DELETED_GLYPH) return;
|
||||
if (!filter (value)) return;
|
||||
glyphs.add (glyph);
|
||||
}
|
||||
@ -746,6 +865,10 @@ struct StateTable
|
||||
}
|
||||
|
||||
// And glyphs in those classes.
|
||||
|
||||
if (filter (CLASS_DELETED_GLYPH))
|
||||
glyphs.add (DELETED_GLYPH);
|
||||
|
||||
(this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,9 @@ struct Format1Entry<true>
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
static bool initiateAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Push; }
|
||||
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.data.kernActionIndex != 0xFFFF; }
|
||||
|
||||
@ -325,8 +328,9 @@ struct KerxSubTableFormat1
|
||||
}
|
||||
else if (buffer->info[idx].mask & kern_mask)
|
||||
{
|
||||
o.x_advance += c->font->em_scale_x (v);
|
||||
o.x_offset += c->font->em_scale_x (v);
|
||||
auto scaled = c->font->em_scale_x (v);
|
||||
o.x_advance += scaled;
|
||||
o.x_offset += scaled;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -394,10 +398,8 @@ struct KerxSubTableFormat1
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
{
|
||||
set_t set;
|
||||
machine.collect_glyphs (set, num_glyphs);
|
||||
left_set.union_ (set);
|
||||
right_set.union_ (set);
|
||||
machine.collect_initial_glyphs (left_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -671,10 +673,8 @@ struct KerxSubTableFormat4
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
{
|
||||
set_t set;
|
||||
machine.collect_glyphs (set, num_glyphs);
|
||||
left_set.union_ (set);
|
||||
right_set.union_ (set);
|
||||
machine.collect_initial_glyphs (left_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -921,7 +921,18 @@ struct KerxSubTable
|
||||
* The 'kerx' Table
|
||||
*/
|
||||
|
||||
using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_bit_set_t, hb_bit_set_t>>;
|
||||
struct kern_subtable_accelerator_data_t
|
||||
{
|
||||
hb_bit_set_t left_set;
|
||||
hb_bit_set_t right_set;
|
||||
mutable hb_aat_class_cache_t class_cache;
|
||||
};
|
||||
|
||||
struct kern_accelerator_data_t
|
||||
{
|
||||
hb_vector_t<kern_subtable_accelerator_data_t> subtable_accels;
|
||||
hb_aat_scratch_t scratch;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct KerxTable
|
||||
@ -985,6 +996,8 @@ struct KerxTable
|
||||
{
|
||||
c->buffer->unsafe_to_concat ();
|
||||
|
||||
c->setup_buffer_glyph_set ();
|
||||
|
||||
typedef typename T::SubTable SubTable;
|
||||
|
||||
bool ret = false;
|
||||
@ -996,12 +1009,25 @@ struct KerxTable
|
||||
{
|
||||
bool reverse;
|
||||
|
||||
auto &subtable_accel = accel_data.subtable_accels[i];
|
||||
|
||||
if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
|
||||
goto skip;
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
|
||||
goto skip;
|
||||
|
||||
c->left_set = &subtable_accel.left_set;
|
||||
c->right_set = &subtable_accel.right_set;
|
||||
c->machine_glyph_set = &subtable_accel.left_set;
|
||||
c->machine_class_cache = &subtable_accel.class_cache;
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped subtable %u because no glyph matches", c->lookup_index);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
|
||||
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
|
||||
|
||||
@ -1028,9 +1054,6 @@ struct KerxTable
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
c->left_set = &accel_data[i].first;
|
||||
c->right_set = &accel_data[i].second;
|
||||
|
||||
{
|
||||
/* See comment in sanitize() for conditional here. */
|
||||
hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
|
||||
@ -1106,9 +1129,13 @@ struct KerxTable
|
||||
unsigned int count = thiz()->tableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
hb_bit_set_t left_set, right_set;
|
||||
st->collect_glyphs (left_set, right_set, num_glyphs);
|
||||
accel_data.push (hb_pair (left_set, right_set));
|
||||
auto &subtable_accel = *accel_data.subtable_accels.push ();
|
||||
if (unlikely (accel_data.subtable_accels.in_error ()))
|
||||
return accel_data;
|
||||
|
||||
st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs);
|
||||
subtable_accel.class_cache.clear ();
|
||||
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
}
|
||||
|
||||
@ -1137,6 +1164,7 @@ struct KerxTable
|
||||
|
||||
hb_blob_ptr_t<T> table;
|
||||
kern_accelerator_data_t accel_data;
|
||||
hb_aat_scratch_t scratch;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -30,8 +30,6 @@
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-aat-map.hh"
|
||||
|
||||
/*
|
||||
@ -178,12 +176,6 @@ struct RearrangementSubtable
|
||||
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
return_trace (dc.ret);
|
||||
@ -242,9 +234,7 @@ struct ContextualSubtable
|
||||
ret (false),
|
||||
c (c_),
|
||||
table (table_),
|
||||
gdef (*c->gdef_table),
|
||||
mark_set (false),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
mark (0),
|
||||
subs (table+table->substitutionTables) {}
|
||||
|
||||
@ -281,12 +271,7 @@ struct ContextualSubtable
|
||||
if (replacement)
|
||||
{
|
||||
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
|
||||
hb_codepoint_t glyph = *replacement;
|
||||
buffer->info[mark].codepoint = glyph;
|
||||
c->buffer_glyph_set.add (glyph);
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[mark],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
c->replace_glyph_inplace (mark, *replacement);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
@ -312,12 +297,7 @@ struct ContextualSubtable
|
||||
}
|
||||
if (replacement)
|
||||
{
|
||||
hb_codepoint_t glyph = *replacement;
|
||||
buffer->info[idx].codepoint = glyph;
|
||||
c->buffer_glyph_set.add (glyph);
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[idx],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
c->replace_glyph_inplace (idx, *replacement);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
@ -333,9 +313,7 @@ struct ContextualSubtable
|
||||
hb_aat_apply_context_t *c;
|
||||
const ContextualSubtable *table;
|
||||
private:
|
||||
const OT::GDEF &gdef;
|
||||
bool mark_set;
|
||||
bool has_glyph_classes;
|
||||
unsigned int mark;
|
||||
const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false> &subs;
|
||||
};
|
||||
@ -348,12 +326,6 @@ struct ContextualSubtable
|
||||
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
return_trace (dc.ret);
|
||||
@ -581,7 +553,7 @@ struct LigatureSubtable
|
||||
hb_codepoint_t lig = ligatureData;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
|
||||
if (unlikely (!buffer->replace_glyph (lig))) return;
|
||||
if (unlikely (!c->replace_glyph (lig))) return;
|
||||
|
||||
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
|
||||
/* Now go and delete all subsequent components. */
|
||||
@ -589,8 +561,7 @@ struct LigatureSubtable
|
||||
{
|
||||
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
|
||||
if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
|
||||
_hb_glyph_info_set_default_ignorable (&buffer->cur());
|
||||
if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
|
||||
if (!c->delete_glyph ()) return;
|
||||
}
|
||||
|
||||
if (unlikely (!buffer->move_to (lig_end))) return;
|
||||
@ -624,12 +595,6 @@ struct LigatureSubtable
|
||||
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
return_trace (dc.ret);
|
||||
@ -665,15 +630,6 @@ struct NoncontextualSubtable
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
const OT::GDEF &gdef (*c->gdef_table);
|
||||
bool has_glyph_classes = gdef.has_glyph_classes ();
|
||||
|
||||
bool ret = false;
|
||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||
|
||||
@ -703,12 +659,7 @@ struct NoncontextualSubtable
|
||||
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
|
||||
if (replacement)
|
||||
{
|
||||
hb_codepoint_t glyph = *replacement;
|
||||
info[i].codepoint = glyph;
|
||||
c->buffer_glyph_set.add (glyph);
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&info[i],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
c->replace_glyph_inplace (i, *replacement);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
@ -850,9 +801,7 @@ struct InsertionSubtable
|
||||
if (buffer->idx < buffer->len && !before)
|
||||
if (unlikely (!buffer->copy_glyph ())) return;
|
||||
/* TODO We ignore KashidaLike setting. */
|
||||
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->buffer_glyph_set.add (glyphs[i]);
|
||||
if (unlikely (!c->output_glyphs (count, glyphs))) return;
|
||||
ret = true;
|
||||
if (buffer->idx < buffer->len && !before)
|
||||
buffer->skip_glyph ();
|
||||
@ -881,7 +830,8 @@ struct InsertionSubtable
|
||||
if (buffer->idx < buffer->len && !before)
|
||||
if (unlikely (!buffer->copy_glyph ())) return;
|
||||
/* TODO We ignore KashidaLike setting. */
|
||||
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
|
||||
if (unlikely (!c->output_glyphs (count, glyphs))) return;
|
||||
ret = true;
|
||||
if (buffer->idx < buffer->len && !before)
|
||||
buffer->skip_glyph ();
|
||||
|
||||
@ -921,12 +871,6 @@ struct InsertionSubtable
|
||||
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
return_trace (dc.ret);
|
||||
@ -1224,6 +1168,7 @@ struct Chain
|
||||
if (hb_none (hb_iter (c->range_flags) |
|
||||
hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
|
||||
goto skip;
|
||||
|
||||
c->subtable_flags = subtable_flags;
|
||||
c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
|
||||
c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
|
||||
@ -1233,6 +1178,12 @@ struct Chain
|
||||
bool (coverage & ChainSubtable<Types>::Vertical))
|
||||
goto skip;
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* Buffer contents is always in logical direction. Determine if
|
||||
* we need to reverse before applying this subtable. We reverse
|
||||
* back after if we did reverse indeed.
|
||||
@ -1376,7 +1327,7 @@ struct mortmorx
|
||||
|
||||
this->chain_count = table->get_chain_count ();
|
||||
|
||||
this->accels = (hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *) hb_calloc (this->chain_count, sizeof (*accels));
|
||||
this->accels = (hb_atomic_t<hb_aat_layout_chain_accelerator_t *> *) hb_calloc (this->chain_count, sizeof (*accels));
|
||||
if (unlikely (!this->accels))
|
||||
{
|
||||
this->chain_count = 0;
|
||||
@ -1423,7 +1374,8 @@ struct mortmorx
|
||||
|
||||
hb_blob_ptr_t<T> table;
|
||||
unsigned int chain_count;
|
||||
hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *accels;
|
||||
hb_atomic_t<hb_aat_layout_chain_accelerator_t *> *accels;
|
||||
hb_aat_scratch_t scratch;
|
||||
};
|
||||
|
||||
|
||||
|
@ -142,9 +142,9 @@ struct TrackData
|
||||
unsigned j = count - 1;
|
||||
|
||||
// Find the two entries that track is between.
|
||||
while (i + 1 < count && trackTable[i + 1].get_track_value () < track)
|
||||
while (i + 1 < count && trackTable[i + 1].get_track_value () <= track)
|
||||
i++;
|
||||
while (j > 0 && trackTable[j - 1].get_track_value () > track)
|
||||
while (j > 0 && trackTable[j - 1].get_track_value () >= track)
|
||||
j--;
|
||||
|
||||
// Exact match.
|
||||
|
46
src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
vendored
46
src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc
vendored
@ -58,13 +58,14 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
|
||||
buffer (buffer_),
|
||||
sanitizer (),
|
||||
ankr_table (&Null (AAT::ankr)),
|
||||
gdef_table (
|
||||
gdef (
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
face->table.GDEF->table
|
||||
*face->table.GDEF->table
|
||||
#else
|
||||
&Null (GDEF)
|
||||
Null (GDEF)
|
||||
#endif
|
||||
),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
lookup_index (0)
|
||||
{
|
||||
sanitizer.init (blob);
|
||||
@ -203,7 +204,7 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
|
||||
/*
|
||||
* mort/morx/kerx/trak
|
||||
@ -287,11 +288,14 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
||||
const hb_feature_t *features,
|
||||
unsigned num_features)
|
||||
{
|
||||
hb_aat_map_builder_t builder (font->face, plan->props);
|
||||
for (unsigned i = 0; i < num_features; i++)
|
||||
builder.add_feature (features[i]);
|
||||
hb_aat_map_t map;
|
||||
builder.compile (map);
|
||||
if (num_features)
|
||||
{
|
||||
hb_aat_map_builder_t builder (font->face, plan->props);
|
||||
for (unsigned i = 0; i < num_features; i++)
|
||||
builder.add_feature (features[i]);
|
||||
builder.compile (map);
|
||||
}
|
||||
|
||||
{
|
||||
auto &accel = *font->face->table.morx;
|
||||
@ -300,7 +304,10 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
||||
{
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
|
||||
if (!buffer->message (font, "start table morx")) return;
|
||||
morx.apply (&c, map, accel);
|
||||
c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
|
||||
morx.apply (&c, num_features ? map : plan->aat_map, accel);
|
||||
accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
|
||||
c.buffer_glyph_set = nullptr;
|
||||
(void) buffer->message (font, "end table morx");
|
||||
return;
|
||||
}
|
||||
@ -313,34 +320,24 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
||||
{
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
|
||||
if (!buffer->message (font, "start table mort")) return;
|
||||
mort.apply (&c, map, accel);
|
||||
mort.apply (&c, num_features ? map : plan->aat_map, accel);
|
||||
(void) buffer->message (font, "end table mort");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
|
||||
pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_deleted_glyph (const hb_glyph_info_t *info)
|
||||
{
|
||||
return info->codepoint == AAT::DELETED_GLYPH;
|
||||
return _hb_glyph_info_is_aat_deleted (info);
|
||||
}
|
||||
|
||||
void
|
||||
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
buffer->delete_glyphs_inplace (is_deleted_glyph);
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED)
|
||||
buffer->delete_glyphs_inplace (is_deleted_glyph);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -371,8 +368,11 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
|
||||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
|
||||
if (!buffer->message (font, "start table kerx")) return;
|
||||
c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
|
||||
c.set_ankr_table (font->face->table.ankr.get ());
|
||||
accel.apply (&c);
|
||||
accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
|
||||
c.buffer_glyph_set = nullptr;
|
||||
(void) buffer->message (font, "end table kerx");
|
||||
}
|
||||
|
||||
|
@ -60,9 +60,6 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
||||
const hb_feature_t *features,
|
||||
unsigned num_features);
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
|
||||
|
||||
|
5
src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc
vendored
5
src/3rdparty/harfbuzz-ng/src/hb-aat-map.cc
vendored
@ -85,6 +85,11 @@ void
|
||||
hb_aat_map_builder_t::compile (hb_aat_map_t &m)
|
||||
{
|
||||
/* Compute active features per range, and compile each. */
|
||||
if (!features.length)
|
||||
{
|
||||
hb_aat_layout_compile_map (this, &m);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort features by start/end events. */
|
||||
hb_vector_t<feature_event_t> feature_events;
|
||||
|
67
src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
vendored
67
src/3rdparty/harfbuzz-ng/src/hb-atomic.hh
vendored
@ -149,62 +149,47 @@ static inline void _hb_compiler_memory_r_barrier () {}
|
||||
#define hb_atomic_ptr_impl_get_relaxed(P) (*(P))
|
||||
#endif
|
||||
#ifndef hb_atomic_int_impl_set
|
||||
inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; }
|
||||
inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; }
|
||||
template <typename T>
|
||||
inline void hb_atomic_int_impl_set (T *AI, T v) { _hb_memory_w_barrier (); *AI = v; }
|
||||
#endif
|
||||
#ifndef hb_atomic_int_impl_get
|
||||
inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; }
|
||||
inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; }
|
||||
template <typename T>
|
||||
inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier (); return v; }
|
||||
#endif
|
||||
#ifndef hb_atomic_ptr_impl_get
|
||||
inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; }
|
||||
#endif
|
||||
|
||||
|
||||
struct hb_atomic_short_t
|
||||
template <typename T>
|
||||
struct hb_atomic_t
|
||||
{
|
||||
hb_atomic_short_t () = default;
|
||||
constexpr hb_atomic_short_t (short v) : v (v) {}
|
||||
hb_atomic_t () = default;
|
||||
constexpr hb_atomic_t (T v) : v (v) {}
|
||||
|
||||
hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; }
|
||||
operator short () const { return get_relaxed (); }
|
||||
hb_atomic_t& operator = (T v_) { set_relaxed (v_); return *this; }
|
||||
operator T () const { return get_relaxed (); }
|
||||
|
||||
void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
short get_acquire () const { return hb_atomic_int_impl_get (&v); }
|
||||
short inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
short dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
void set_relaxed (T v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (T v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
T get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
T get_acquire () const { return hb_atomic_int_impl_get (&v); }
|
||||
T inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
T dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
|
||||
short v = 0;
|
||||
int operator ++ (int) { return inc (); }
|
||||
int operator -- (int) { return dec (); }
|
||||
long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; }
|
||||
|
||||
T v = 0;
|
||||
};
|
||||
|
||||
struct hb_atomic_int_t
|
||||
template <typename T>
|
||||
struct hb_atomic_t<T*>
|
||||
{
|
||||
hb_atomic_int_t () = default;
|
||||
constexpr hb_atomic_int_t (int v) : v (v) {}
|
||||
|
||||
hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; }
|
||||
operator int () const { return get_relaxed (); }
|
||||
|
||||
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
int get_acquire () const { return hb_atomic_int_impl_get (&v); }
|
||||
int inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
int dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
|
||||
int v = 0;
|
||||
};
|
||||
|
||||
template <typename P>
|
||||
struct hb_atomic_ptr_t
|
||||
{
|
||||
typedef hb_remove_pointer<P> T;
|
||||
|
||||
hb_atomic_ptr_t () = default;
|
||||
constexpr hb_atomic_ptr_t (T* v) : v (v) {}
|
||||
hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete;
|
||||
hb_atomic_t () = default;
|
||||
constexpr hb_atomic_t (T* v) : v (v) {}
|
||||
hb_atomic_t (const hb_atomic_t &other) = delete;
|
||||
|
||||
void init (T* v_ = nullptr) { set_relaxed (v_); }
|
||||
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
|
||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
vendored
@ -77,7 +77,7 @@ struct hb_bit_set_t
|
||||
|
||||
bool successful = true; /* Allocations successful */
|
||||
mutable unsigned int population = 0;
|
||||
mutable hb_atomic_int_t last_page_lookup = 0;
|
||||
mutable hb_atomic_t<unsigned> last_page_lookup = 0;
|
||||
hb_sorted_vector_t<page_map_t> page_map;
|
||||
hb_vector_t<page_t> pages;
|
||||
|
||||
@ -88,7 +88,7 @@ struct hb_bit_set_t
|
||||
{
|
||||
if (unlikely (!successful)) return false;
|
||||
|
||||
if (pages.length < count && count <= 2)
|
||||
if (pages.length < count && (unsigned) pages.allocated < count && count <= 2)
|
||||
exact_size = true; // Most sets are small and local
|
||||
|
||||
if (unlikely (!pages.resize (count, clear, exact_size) ||
|
||||
|
195
src/3rdparty/harfbuzz-ng/src/hb-bit-vector.hh
vendored
Normal file
195
src/3rdparty/harfbuzz-ng/src/hb-bit-vector.hh
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_BIT_VECTOR_HH
|
||||
#define HB_BIT_VECTOR_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-atomic.hh"
|
||||
|
||||
struct hb_min_max_t
|
||||
{
|
||||
void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
min_v = hb_min (min_v, a);
|
||||
max_v = hb_max (max_v, b);
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void union_ (const set_t &set)
|
||||
{
|
||||
hb_codepoint_t set_min = set.get_min ();
|
||||
if (unlikely (set_min == HB_CODEPOINT_INVALID))
|
||||
return;
|
||||
hb_codepoint_t set_max = set.get_max ();
|
||||
min_v = hb_min (min_v, set_min);
|
||||
max_v = hb_max (max_v, set_max);
|
||||
}
|
||||
|
||||
hb_codepoint_t get_min () const { return min_v; }
|
||||
hb_codepoint_t get_max () const { return max_v; }
|
||||
|
||||
private:
|
||||
hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
|
||||
hb_codepoint_t max_v = 0;
|
||||
};
|
||||
|
||||
template <bool atomic = false>
|
||||
struct hb_bit_vector_t
|
||||
{
|
||||
using int_t = uint64_t;
|
||||
using elt_t = typename std::conditional<atomic, hb_atomic_t<int_t>, int_t>::type;
|
||||
|
||||
hb_bit_vector_t () = delete;
|
||||
hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
|
||||
hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;
|
||||
|
||||
// Move
|
||||
hb_bit_vector_t (hb_bit_vector_t &&other)
|
||||
: min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
|
||||
{
|
||||
other.min_v = other.max_v = other.count = 0;
|
||||
other.elts = nullptr;
|
||||
}
|
||||
hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
|
||||
{
|
||||
hb_swap (min_v, other.min_v);
|
||||
hb_swap (max_v, other.max_v);
|
||||
hb_swap (count, other.count);
|
||||
hb_swap (elts, other.elts);
|
||||
return *this;
|
||||
}
|
||||
|
||||
hb_bit_vector_t (unsigned min_v, unsigned max_v)
|
||||
: min_v (min_v), max_v (max_v)
|
||||
{
|
||||
if (unlikely (min_v >= max_v))
|
||||
{
|
||||
min_v = max_v = count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8);
|
||||
elts = (elt_t *) hb_calloc (num, sizeof (int_t));
|
||||
if (unlikely (!elts))
|
||||
{
|
||||
min_v = max_v = count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
count = max_v - min_v + 1;
|
||||
}
|
||||
~hb_bit_vector_t ()
|
||||
{
|
||||
hb_free (elts);
|
||||
}
|
||||
|
||||
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
|
||||
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
|
||||
void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
|
||||
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
|
||||
bool has (hb_codepoint_t g) const { return get (g); }
|
||||
bool may_have (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
bool operator [] (hb_codepoint_t g) const { return get (g); }
|
||||
bool operator () (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!count || a > b || a < min_v || b > max_v))
|
||||
return;
|
||||
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la |= (mask (b) << 1) - mask(a);
|
||||
else
|
||||
{
|
||||
*la |= ~(mask (a) - 1llu);
|
||||
la++;
|
||||
|
||||
hb_memset (la, 0xff, (char *) lb - (char *) la);
|
||||
|
||||
*lb |= ((mask (b) << 1) - 1llu);
|
||||
}
|
||||
}
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!count || a > b || a < min_v || b > max_v))
|
||||
return;
|
||||
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la &= ~((mask (b) << 1llu) - mask(a));
|
||||
else
|
||||
{
|
||||
*la &= mask (a) - 1;
|
||||
la++;
|
||||
|
||||
hb_memset (la, 0, (char *) lb - (char *) la);
|
||||
|
||||
*lb &= ~((mask (b) << 1) - 1llu);
|
||||
}
|
||||
}
|
||||
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
|
||||
{ if (v) add_range (a, b); else del_range (a, b); }
|
||||
|
||||
template <typename set_t>
|
||||
void union_ (const set_t &set)
|
||||
{
|
||||
for (hb_codepoint_t g : set)
|
||||
add (g);
|
||||
}
|
||||
|
||||
static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
|
||||
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
|
||||
|
||||
static constexpr elt_t zero = 0;
|
||||
|
||||
elt_t &elt (hb_codepoint_t g)
|
||||
{
|
||||
g -= min_v;
|
||||
if (unlikely (g >= count))
|
||||
return Crap(elt_t);
|
||||
return elts[g / ELT_BITS];
|
||||
}
|
||||
const elt_t& elt (hb_codepoint_t g) const
|
||||
{
|
||||
g -= min_v;
|
||||
if (unlikely (g >= count))
|
||||
return Null(elt_t);
|
||||
return elts[g / ELT_BITS];
|
||||
}
|
||||
|
||||
static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
|
||||
|
||||
hb_codepoint_t min_v = 0, max_v = 0, count = 0;
|
||||
elt_t *elts = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_BIT_VECTOR_HH */
|
File diff suppressed because it is too large
Load Diff
@ -34,285 +34,247 @@
|
||||
|
||||
#line 36 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
static const unsigned char _deserialize_text_glyphs_trans_keys[] = {
|
||||
0u, 0u, 48u, 57u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
|
||||
48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u,
|
||||
9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
|
||||
9u, 124u, 9u, 124u, 9u, 124u, 0
|
||||
0u, 0u, 35u, 124u, 48u, 57u, 93u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 45u, 57u,
|
||||
48u, 57u, 35u, 124u, 35u, 124u, 35u, 124u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u,
|
||||
44u, 44u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, 44u, 57u, 35u, 124u, 43u, 124u,
|
||||
48u, 124u, 35u, 124u, 35u, 124u, 35u, 124u, 0
|
||||
};
|
||||
|
||||
static const char _deserialize_text_glyphs_key_spans[] = {
|
||||
0, 10, 13, 10, 13, 10, 10, 13,
|
||||
10, 1, 13, 10, 14, 82, 116, 116,
|
||||
116, 116, 116, 116, 116, 116, 116, 116,
|
||||
116, 116, 116
|
||||
0, 90, 10, 32, 13, 10, 90, 13,
|
||||
10, 90, 90, 90, 10, 90, 13, 10,
|
||||
1, 13, 10, 90, 90, 14, 90, 82,
|
||||
77, 90, 90, 90
|
||||
};
|
||||
|
||||
static const short _deserialize_text_glyphs_index_offsets[] = {
|
||||
0, 0, 11, 25, 36, 50, 61, 72,
|
||||
86, 97, 99, 113, 124, 139, 222, 339,
|
||||
456, 573, 690, 807, 924, 1041, 1158, 1275,
|
||||
1392, 1509, 1626
|
||||
0, 0, 91, 102, 135, 149, 160, 251,
|
||||
265, 276, 367, 458, 549, 560, 651, 665,
|
||||
676, 678, 692, 703, 794, 885, 900, 991,
|
||||
1074, 1152, 1243, 1334
|
||||
};
|
||||
|
||||
static const char _deserialize_text_glyphs_indicies[] = {
|
||||
0, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 1, 3, 1, 1, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 1, 6, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 1, 8, 1, 1,
|
||||
9, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 1, 11, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 1, 13, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14,
|
||||
1, 15, 1, 1, 16, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 1, 18,
|
||||
19, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 1, 20, 1, 21, 1, 1, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 1, 24, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 1, 20, 1, 1,
|
||||
1, 19, 19, 19, 19, 19, 19, 19,
|
||||
19, 19, 19, 1, 26, 26, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 26, 1,
|
||||
1, 26, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 26, 26, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 26, 1, 28,
|
||||
28, 28, 28, 28, 27, 27, 27, 27,
|
||||
1, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 4, 0, 0, 5, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 6, 7, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 7, 0, 8, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 3, 10,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 10, 3,
|
||||
11, 3, 3, 12, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 3, 14, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15,
|
||||
3, 16, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 17, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 18, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 18, 3, 19, 3, 3, 20,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 3, 22, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 3, 24, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 25,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 25, 3,
|
||||
24, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 25, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 25, 3, 16, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 17, 3, 3, 3,
|
||||
15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 18, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 18, 3, 26, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 28, 27,
|
||||
27, 29, 27, 27, 27, 27, 27, 27,
|
||||
27, 30, 1, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 31, 27, 27, 32, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 33, 1, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 28, 27, 34, 34, 34, 34,
|
||||
34, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 34, 26, 26, 35, 26,
|
||||
26, 26, 26, 26, 26, 26, 36, 1,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
37, 26, 26, 38, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 39,
|
||||
1, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 40,
|
||||
26, 41, 41, 41, 41, 41, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
41, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 42, 1, 43, 43,
|
||||
43, 43, 43, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 43, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 44, 1, 41, 41, 41, 41, 41,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 41, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 42, 1,
|
||||
46, 46, 46, 46, 46, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 46,
|
||||
1, 1, 47, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 48, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 49, 1, 50, 50, 50,
|
||||
50, 50, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 50, 1, 1, 51,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
52, 1, 50, 50, 50, 50, 50, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 50, 1, 1, 51, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 52, 1, 46,
|
||||
46, 46, 46, 46, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 46, 1,
|
||||
1, 47, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 48, 1, 1, 1, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 49, 1, 53, 53, 53, 53,
|
||||
53, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 53, 1, 1, 54, 1,
|
||||
1, 1, 1, 1, 1, 1, 55, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 56, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 57,
|
||||
1, 58, 58, 58, 58, 58, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
58, 1, 1, 59, 1, 1, 1, 1,
|
||||
1, 1, 1, 60, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 61, 1, 58, 58,
|
||||
58, 58, 58, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 58, 1, 1,
|
||||
59, 1, 1, 1, 1, 1, 1, 1,
|
||||
60, 1, 1, 1, 1, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 61, 1, 53, 53, 53, 53, 53,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 53, 1, 1, 54, 1, 1,
|
||||
1, 1, 1, 1, 1, 55, 1, 1,
|
||||
1, 1, 62, 62, 62, 62, 62, 62,
|
||||
62, 62, 62, 62, 1, 1, 1, 1,
|
||||
1, 1, 56, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 57, 1,
|
||||
0
|
||||
3, 28, 3, 3, 3, 3, 3, 3,
|
||||
3, 29, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 30, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 31, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 31, 3, 32, 3, 3, 33,
|
||||
34, 34, 34, 34, 34, 34, 34, 34,
|
||||
34, 3, 35, 36, 36, 36, 36, 36,
|
||||
36, 36, 36, 36, 3, 37, 3, 38,
|
||||
3, 3, 39, 40, 40, 40, 40, 40,
|
||||
40, 40, 40, 40, 3, 41, 42, 42,
|
||||
42, 42, 42, 42, 42, 42, 42, 3,
|
||||
43, 3, 3, 3, 3, 3, 3, 3,
|
||||
44, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 45, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 45, 3, 43, 3, 3, 3, 3,
|
||||
3, 3, 3, 44, 3, 3, 3, 3,
|
||||
42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 45, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 45, 3, 37, 3,
|
||||
3, 3, 36, 36, 36, 36, 36, 36,
|
||||
36, 36, 36, 36, 3, 28, 3, 3,
|
||||
3, 3, 3, 3, 3, 29, 3, 3,
|
||||
3, 3, 46, 46, 46, 46, 46, 46,
|
||||
46, 46, 46, 46, 3, 3, 3, 3,
|
||||
3, 3, 30, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 31,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 31, 3,
|
||||
0, 0, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 0, 3, 3, 0, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 0, 0, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 0, 3, 47, 47, 47, 47, 47,
|
||||
47, 47, 47, 47, 47, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
10, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 10,
|
||||
3, 49, 48, 48, 48, 48, 48, 48,
|
||||
48, 50, 3, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 51, 48, 48, 52, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 53, 54, 55, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 55, 48, 57, 56, 56, 56,
|
||||
56, 56, 56, 56, 58, 3, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 59, 56,
|
||||
56, 60, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 61, 62, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 56, 56, 56,
|
||||
56, 56, 56, 56, 56, 62, 56, 63,
|
||||
48, 48, 48, 48, 48, 48, 48, 64,
|
||||
3, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 65, 48, 48, 66, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
54, 67, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
67, 48, 0
|
||||
};
|
||||
|
||||
static const char _deserialize_text_glyphs_trans_targs[] = {
|
||||
16, 0, 18, 3, 19, 22, 19, 22,
|
||||
5, 20, 21, 20, 21, 23, 26, 8,
|
||||
9, 12, 9, 12, 10, 11, 24, 25,
|
||||
24, 25, 15, 15, 14, 1, 2, 6,
|
||||
7, 13, 15, 1, 2, 6, 7, 13,
|
||||
14, 17, 14, 17, 14, 18, 17, 1,
|
||||
4, 14, 17, 1, 14, 17, 1, 2,
|
||||
7, 14, 17, 1, 2, 14, 26
|
||||
1, 2, 4, 0, 12, 14, 23, 26,
|
||||
3, 24, 26, 5, 6, 11, 6, 11,
|
||||
2, 7, 26, 8, 9, 10, 9, 10,
|
||||
2, 26, 13, 22, 2, 4, 14, 26,
|
||||
15, 16, 21, 16, 21, 17, 18, 19,
|
||||
20, 19, 20, 2, 4, 26, 22, 24,
|
||||
1, 2, 4, 12, 14, 27, 23, 26,
|
||||
1, 2, 4, 12, 14, 23, 26, 2,
|
||||
4, 12, 14, 26
|
||||
};
|
||||
|
||||
static const char _deserialize_text_glyphs_trans_actions[] = {
|
||||
1, 0, 1, 1, 1, 1, 0, 0,
|
||||
1, 1, 1, 0, 0, 1, 1, 1,
|
||||
1, 1, 0, 0, 2, 1, 1, 1,
|
||||
0, 0, 0, 4, 3, 5, 5, 5,
|
||||
5, 4, 6, 7, 7, 7, 7, 0,
|
||||
6, 8, 8, 0, 0, 0, 9, 10,
|
||||
10, 9, 11, 12, 11, 13, 14, 14,
|
||||
14, 13, 15, 16, 16, 15, 0
|
||||
0, 1, 1, 0, 1, 1, 0, 1,
|
||||
2, 2, 3, 2, 2, 2, 0, 0,
|
||||
4, 4, 4, 2, 2, 2, 0, 0,
|
||||
5, 5, 2, 2, 6, 6, 6, 6,
|
||||
2, 2, 2, 0, 0, 7, 2, 2,
|
||||
2, 0, 0, 8, 8, 8, 0, 0,
|
||||
9, 10, 10, 10, 10, 9, 9, 10,
|
||||
12, 13, 13, 13, 13, 12, 13, 14,
|
||||
14, 14, 14, 14
|
||||
};
|
||||
|
||||
static const char _deserialize_text_glyphs_eof_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 3, 6,
|
||||
8, 0, 8, 9, 11, 11, 9, 13,
|
||||
15, 15, 13
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 11, 0
|
||||
};
|
||||
|
||||
static const int deserialize_text_glyphs_start = 14;
|
||||
static const int deserialize_text_glyphs_first_final = 14;
|
||||
static const int deserialize_text_glyphs_start = 25;
|
||||
static const int deserialize_text_glyphs_first_final = 25;
|
||||
static const int deserialize_text_glyphs_error = 0;
|
||||
|
||||
static const int deserialize_text_glyphs_en_main = 14;
|
||||
static const int deserialize_text_glyphs_en_main = 25;
|
||||
|
||||
|
||||
#line 98 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
#line 99 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
|
||||
|
||||
static hb_bool_t
|
||||
@ -322,39 +284,22 @@ _hb_buffer_deserialize_text_glyphs (hb_buffer_t *buffer,
|
||||
const char **end_ptr,
|
||||
hb_font_t *font)
|
||||
{
|
||||
const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
|
||||
const char *p = buf, *pe = buf + buf_len, *eof = pe;
|
||||
|
||||
/* Ensure we have positions. */
|
||||
(void) hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||
|
||||
while (p < pe && ISSPACE (*p))
|
||||
p++;
|
||||
if (p < pe && *p == (buffer->len ? '|' : '['))
|
||||
*end_ptr = ++p;
|
||||
|
||||
const char *end = strchr ((char *) p, ']');
|
||||
if (end)
|
||||
pe = eof = end;
|
||||
else
|
||||
{
|
||||
end = strrchr ((char *) p, '|');
|
||||
if (end)
|
||||
pe = eof = end;
|
||||
else
|
||||
pe = eof = p;
|
||||
}
|
||||
|
||||
const char *tok = nullptr;
|
||||
int cs;
|
||||
hb_glyph_info_t info = {0};
|
||||
hb_glyph_position_t pos = {0};
|
||||
|
||||
#line 353 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
#line 298 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
{
|
||||
cs = deserialize_text_glyphs_start;
|
||||
}
|
||||
|
||||
#line 358 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
#line 303 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
@ -379,13 +324,13 @@ _resume:
|
||||
goto _again;
|
||||
|
||||
switch ( _deserialize_text_glyphs_trans_actions[_trans] ) {
|
||||
case 1:
|
||||
case 2:
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
case 1:
|
||||
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
/* TODO Unescape delimiters. */
|
||||
@ -393,40 +338,53 @@ _resume:
|
||||
tok, p - tok,
|
||||
&info.codepoint))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
#line 63 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||
break;
|
||||
case 2:
|
||||
#line 64 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
|
||||
break;
|
||||
case 16:
|
||||
#line 65 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||
break;
|
||||
case 10:
|
||||
#line 66 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||
break;
|
||||
case 12:
|
||||
#line 67 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||
break;
|
||||
case 4:
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
#line 63 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||
break;
|
||||
case 7:
|
||||
#line 64 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
|
||||
break;
|
||||
case 8:
|
||||
#line 65 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||
break;
|
||||
case 4:
|
||||
#line 66 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||
break;
|
||||
case 5:
|
||||
#line 67 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||
break;
|
||||
case 3:
|
||||
#line 68 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.mask )) return false; }
|
||||
break;
|
||||
case 9:
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
/* TODO Unescape delimiters. */
|
||||
@ -435,6 +393,8 @@ _resume:
|
||||
&info.codepoint))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
@ -442,11 +402,37 @@ _resume:
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
/* TODO Unescape delimiters. */
|
||||
if (!hb_font_glyph_from_string (font,
|
||||
tok, p - tok,
|
||||
&info.codepoint))
|
||||
return false;
|
||||
}
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
#line 63 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
@ -455,56 +441,6 @@ _resume:
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
#line 65 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
#line 66 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
#line 67 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
#line 68 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.mask )) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
@ -523,34 +459,7 @@ _resume:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
/* TODO Unescape delimiters. */
|
||||
if (!hb_font_glyph_from_string (font,
|
||||
tok, p - tok,
|
||||
&info.codepoint))
|
||||
return false;
|
||||
}
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
#line 554 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
#line 463 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
@ -562,63 +471,7 @@ _again:
|
||||
if ( p == eof )
|
||||
{
|
||||
switch ( _deserialize_text_glyphs_eof_actions[cs] ) {
|
||||
case 6:
|
||||
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
/* TODO Unescape delimiters. */
|
||||
if (!hb_font_glyph_from_string (font,
|
||||
tok, p - tok,
|
||||
&info.codepoint))
|
||||
return false;
|
||||
}
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
#line 63 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
#line 65 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
#line 66 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
#line 67 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
@ -628,62 +481,16 @@ _again:
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
#line 68 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{ if (!parse_uint (tok, p, &info.mask )) return false; }
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
#line 38 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
hb_memset (&pos , 0, sizeof (pos ));
|
||||
}
|
||||
#line 51 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
#line 55 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
/* TODO Unescape delimiters. */
|
||||
if (!hb_font_glyph_from_string (font,
|
||||
tok, p - tok,
|
||||
&info.codepoint))
|
||||
return false;
|
||||
}
|
||||
#line 43 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
#line 671 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
#line 485 "hb-buffer-deserialize-text-glyphs.hh"
|
||||
}
|
||||
}
|
||||
|
||||
_out: {}
|
||||
}
|
||||
|
||||
#line 136 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
#line 120 "hb-buffer-deserialize-text-glyphs.rl"
|
||||
|
||||
|
||||
if (pe < orig_pe && *pe == ']')
|
||||
{
|
||||
pe++;
|
||||
if (p == pe)
|
||||
p++;
|
||||
}
|
||||
|
||||
*end_ptr = p;
|
||||
|
||||
return p == pe;
|
||||
|
@ -34,135 +34,106 @@
|
||||
|
||||
#line 36 "hb-buffer-deserialize-text-unicode.hh"
|
||||
static const unsigned char _deserialize_text_unicode_trans_keys[] = {
|
||||
0u, 0u, 9u, 117u, 43u, 102u, 48u, 102u, 48u, 57u, 9u, 124u, 9u, 124u, 9u, 124u,
|
||||
9u, 124u, 0
|
||||
0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u,
|
||||
85u, 117u, 85u, 117u, 0
|
||||
};
|
||||
|
||||
static const char _deserialize_text_unicode_key_spans[] = {
|
||||
0, 109, 60, 55, 10, 116, 116, 116,
|
||||
116
|
||||
0, 60, 55, 77, 10, 63, 77, 58,
|
||||
33, 33
|
||||
};
|
||||
|
||||
static const short _deserialize_text_unicode_index_offsets[] = {
|
||||
0, 0, 110, 171, 227, 238, 355, 472,
|
||||
589
|
||||
0, 0, 61, 117, 195, 206, 270, 348,
|
||||
407, 441
|
||||
};
|
||||
|
||||
static const char _deserialize_text_unicode_indicies[] = {
|
||||
0, 0, 0, 0, 0, 1, 1,
|
||||
0, 1, 1, 1, 1, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 1, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 1, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
1, 1, 1, 4, 5, 1, 1, 3,
|
||||
3, 3, 3, 3, 3, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 3,
|
||||
3, 3, 3, 3, 3, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 5, 1, 6, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 1, 8,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 2, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 8, 1, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 1, 1, 1, 1, 8, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 2, 1, 3,
|
||||
1, 1, 1, 1, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 1, 1,
|
||||
1, 1, 1, 1, 1, 4, 4, 4,
|
||||
4, 4, 4, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 4, 4, 4,
|
||||
4, 4, 4, 1, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 1, 1,
|
||||
1, 1, 1, 1, 1, 4, 4, 4,
|
||||
4, 4, 4, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 4, 4, 4,
|
||||
4, 4, 4, 1, 5, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 1, 7,
|
||||
7, 7, 7, 7, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 7, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
1, 1, 1, 9, 1, 1, 1, 8,
|
||||
8, 8, 8, 8, 8, 1, 1, 1,
|
||||
1, 1, 1, 8, 1, 10, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 8,
|
||||
8, 8, 8, 8, 8, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 11, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 10, 1, 11, 11, 11, 11,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 11, 1,
|
||||
11, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 11, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
11, 1, 12, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 0,
|
||||
1, 12, 12, 12, 12, 12, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
12, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 13, 1, 12, 12,
|
||||
12, 12, 12, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 12, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 13, 1, 0
|
||||
1, 1, 12, 1, 0
|
||||
};
|
||||
|
||||
static const char _deserialize_text_unicode_trans_targs[] = {
|
||||
1, 0, 2, 3, 5, 7, 8, 6,
|
||||
5, 4, 1, 6, 6, 1, 8
|
||||
2, 0, 3, 3, 4, 9, 5, 6,
|
||||
9, 6, 8, 1, 1
|
||||
};
|
||||
|
||||
static const char _deserialize_text_unicode_trans_actions[] = {
|
||||
0, 0, 1, 0, 2, 2, 2, 3,
|
||||
0, 4, 3, 0, 5, 5, 0
|
||||
0, 0, 1, 0, 2, 2, 1, 1,
|
||||
3, 0, 0, 4, 6
|
||||
};
|
||||
|
||||
static const char _deserialize_text_unicode_eof_actions[] = {
|
||||
0, 0, 0, 0, 0, 3, 0, 5,
|
||||
5
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 5
|
||||
};
|
||||
|
||||
static const int deserialize_text_unicode_start = 1;
|
||||
static const int deserialize_text_unicode_first_final = 5;
|
||||
static const int deserialize_text_unicode_start = 7;
|
||||
static const int deserialize_text_unicode_first_final = 7;
|
||||
static const int deserialize_text_unicode_error = 0;
|
||||
|
||||
static const int deserialize_text_unicode_en_main = 1;
|
||||
static const int deserialize_text_unicode_en_main = 7;
|
||||
|
||||
|
||||
#line 79 "hb-buffer-deserialize-text-unicode.rl"
|
||||
#line 80 "hb-buffer-deserialize-text-unicode.rl"
|
||||
|
||||
|
||||
static hb_bool_t
|
||||
@ -172,37 +143,19 @@ _hb_buffer_deserialize_text_unicode (hb_buffer_t *buffer,
|
||||
const char **end_ptr,
|
||||
hb_font_t *font)
|
||||
{
|
||||
const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe;
|
||||
|
||||
while (p < pe && ISSPACE (*p))
|
||||
p++;
|
||||
if (p < pe && *p == (buffer->len ? '|' : '<'))
|
||||
*end_ptr = ++p;
|
||||
|
||||
const char *end = strchr ((char *) p, '>');
|
||||
if (end)
|
||||
pe = eof = end;
|
||||
else
|
||||
{
|
||||
end = strrchr ((char *) p, '|');
|
||||
if (end)
|
||||
pe = eof = end;
|
||||
else
|
||||
pe = eof = p;
|
||||
}
|
||||
|
||||
const char *p = buf, *pe = buf + buf_len, *eof = pe;
|
||||
|
||||
const char *tok = nullptr;
|
||||
int cs;
|
||||
hb_glyph_info_t info = {0};
|
||||
const hb_glyph_position_t pos = {0};
|
||||
|
||||
#line 201 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 154 "hb-buffer-deserialize-text-unicode.hh"
|
||||
{
|
||||
cs = deserialize_text_unicode_start;
|
||||
}
|
||||
|
||||
#line 206 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 159 "hb-buffer-deserialize-text-unicode.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
@ -227,38 +180,27 @@ _resume:
|
||||
goto _again;
|
||||
|
||||
switch ( _deserialize_text_unicode_trans_actions[_trans] ) {
|
||||
case 1:
|
||||
case 4:
|
||||
#line 38 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
#line 51 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
tok = p;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
case 2:
|
||||
#line 55 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
|
||||
break;
|
||||
case 3:
|
||||
#line 55 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
|
||||
#line 42 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
if (buffer->have_positions)
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
#line 57 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||
break;
|
||||
case 6:
|
||||
#line 42 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
@ -267,9 +209,13 @@ _resume:
|
||||
if (buffer->have_positions)
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
#line 38 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
hb_memset (&info, 0, sizeof (info));
|
||||
}
|
||||
break;
|
||||
#line 273 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 219 "hb-buffer-deserialize-text-unicode.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
@ -281,22 +227,7 @@ _again:
|
||||
if ( p == eof )
|
||||
{
|
||||
switch ( _deserialize_text_unicode_eof_actions[cs] ) {
|
||||
case 3:
|
||||
#line 55 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
|
||||
#line 42 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
if (unlikely (!buffer->successful))
|
||||
return false;
|
||||
if (buffer->have_positions)
|
||||
buffer->pos[buffer->len - 1] = pos;
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
#line 57 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
|
||||
#line 42 "hb-buffer-deserialize-text-unicode.rl"
|
||||
{
|
||||
buffer->add_info (info);
|
||||
@ -307,23 +238,16 @@ _again:
|
||||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
#line 311 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 242 "hb-buffer-deserialize-text-unicode.hh"
|
||||
}
|
||||
}
|
||||
|
||||
_out: {}
|
||||
}
|
||||
|
||||
#line 115 "hb-buffer-deserialize-text-unicode.rl"
|
||||
#line 98 "hb-buffer-deserialize-text-unicode.rl"
|
||||
|
||||
|
||||
if (pe < orig_pe && *pe == '>')
|
||||
{
|
||||
pe++;
|
||||
if (p == pe)
|
||||
p++;
|
||||
}
|
||||
|
||||
*end_ptr = p;
|
||||
|
||||
return p == pe;
|
||||
|
@ -169,11 +169,13 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
|
||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
||||
{
|
||||
hb_glyph_extents_t extents;
|
||||
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
|
||||
extents.x_bearing, extents.y_bearing));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
||||
extents.width, extents.height));
|
||||
if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents))
|
||||
{
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
|
||||
extents.x_bearing, extents.y_bearing));
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
|
||||
extents.width, extents.height));
|
||||
}
|
||||
}
|
||||
|
||||
*p++ = '}';
|
||||
@ -318,8 +320,8 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
||||
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
|
||||
{
|
||||
hb_glyph_extents_t extents;
|
||||
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
|
||||
if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents))
|
||||
p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
|
||||
}
|
||||
|
||||
if (i == end-1) {
|
||||
@ -737,8 +739,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
|
||||
* Deserializes glyphs @buffer from textual representation in the format
|
||||
* produced by hb_buffer_serialize_glyphs().
|
||||
*
|
||||
* Return value: `true` if parse was successful, `false` if an error
|
||||
* occurred.
|
||||
* Return value: `true` if the full string was parsed, `false` otherwise.
|
||||
*
|
||||
* Since: 0.9.7
|
||||
**/
|
||||
@ -810,8 +811,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
|
||||
* Deserializes Unicode @buffer from textual representation in the format
|
||||
* produced by hb_buffer_serialize_unicode().
|
||||
*
|
||||
* Return value: `true` if parse was successful, `false` if an error
|
||||
* occurred.
|
||||
* Return value: `true` if the full string was parsed, `false` otherwise.
|
||||
*
|
||||
* Since: 2.7.3
|
||||
**/
|
||||
|
37
src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
vendored
37
src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc
vendored
@ -63,24 +63,25 @@ static bool
|
||||
buffer_verify_monotone (hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
/* Check that clusters are monotone. */
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
|
||||
buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
|
||||
if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
|
||||
{
|
||||
bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
|
||||
|
||||
unsigned int num_glyphs;
|
||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
|
||||
|
||||
for (unsigned int i = 1; i < num_glyphs; i++)
|
||||
if (info[i-1].cluster != info[i].cluster &&
|
||||
(info[i-1].cluster < info[i].cluster) != is_forward)
|
||||
{
|
||||
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
|
||||
return false;
|
||||
}
|
||||
/* Cannot perform this check without monotone clusters. */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
|
||||
|
||||
unsigned int num_glyphs;
|
||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
|
||||
|
||||
for (unsigned int i = 1; i < num_glyphs; i++)
|
||||
if (info[i-1].cluster != info[i].cluster &&
|
||||
(info[i-1].cluster < info[i].cluster) != is_forward)
|
||||
{
|
||||
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -92,8 +93,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
|
||||
unsigned int num_features,
|
||||
const char * const *shapers)
|
||||
{
|
||||
if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
|
||||
buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
|
||||
if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
|
||||
{
|
||||
/* Cannot perform this check without monotone clusters. */
|
||||
return true;
|
||||
@ -207,8 +207,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
|
||||
unsigned int num_features,
|
||||
const char * const *shapers)
|
||||
{
|
||||
if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
|
||||
buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
|
||||
if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
|
||||
{
|
||||
/* Cannot perform this check without monotone clusters. */
|
||||
return true;
|
||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
@ -518,7 +518,7 @@ void
|
||||
hb_buffer_t::merge_clusters_impl (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||
if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level))
|
||||
{
|
||||
unsafe_to_break (start, end);
|
||||
return;
|
||||
@ -551,7 +551,7 @@ void
|
||||
hb_buffer_t::merge_out_clusters (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||
if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level))
|
||||
return;
|
||||
|
||||
if (unlikely (end - start < 2))
|
||||
|
65
src/3rdparty/harfbuzz-ng/src/hb-buffer.h
vendored
65
src/3rdparty/harfbuzz-ng/src/hb-buffer.h
vendored
@ -422,18 +422,34 @@ hb_buffer_get_flags (const hb_buffer_t *buffer);
|
||||
* @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
|
||||
* @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
|
||||
* equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
|
||||
*
|
||||
* @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: Only group clusters, but don't enforce monotone order.
|
||||
*
|
||||
* Data type for holding HarfBuzz's clustering behavior options. The cluster level
|
||||
* dictates one aspect of how HarfBuzz will treat non-base characters
|
||||
* dictates one aspect of how HarfBuzz will treat non-base characters
|
||||
* during shaping.
|
||||
*
|
||||
* In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES, non-base
|
||||
* characters are merged into the cluster of the base character that precedes them.
|
||||
* There is also cluster merging every time the clusters will otherwise become non-monotone.
|
||||
*
|
||||
* In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS, non-base characters are initially
|
||||
* assigned their own cluster values, which are not merged into preceding base
|
||||
* clusters. This allows HarfBuzz to perform additional operations like reorder
|
||||
* sequences of adjacent marks.
|
||||
* sequences of adjacent marks. The output is still monotone, but the cluster
|
||||
* values are more granular.
|
||||
*
|
||||
* In @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS, non-base characters are assigned their
|
||||
* own cluster values, which are not merged into preceding base clusters. Moreover,
|
||||
* the cluster values are not merged into monotone order. This is the most granular
|
||||
* cluster level, and it is useful for clients that need to know the exact cluster
|
||||
* values of each character, but is harder to use for clients, since clusters
|
||||
* might appear in any order.
|
||||
*
|
||||
* In @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES, non-base characters are merged into the
|
||||
* cluster of the base character that precedes them. This is similar to the Unicode
|
||||
* Grapheme Cluster algorithm, but it is not exactly the same. The output is
|
||||
* not forced to be monotone. This is useful for clients that want to use HarfBuzz
|
||||
* as a cheap implementation of the Unicode Grapheme Cluster algorithm.
|
||||
*
|
||||
* @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES is the default, because it maintains
|
||||
* backward compatibility with older versions of HarfBuzz. New client programs that
|
||||
@ -446,9 +462,52 @@ typedef enum {
|
||||
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
|
||||
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
|
||||
HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2,
|
||||
HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES = 3,
|
||||
HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
|
||||
} hb_buffer_cluster_level_t;
|
||||
|
||||
/**
|
||||
* HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE:
|
||||
* @level: #hb_buffer_cluster_level_t to test
|
||||
*
|
||||
* Tests whether a cluster level groups cluster values into monotone order.
|
||||
* Requires that the level be valid.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
#define HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE(level) \
|
||||
((bool) ((1u << (unsigned) (level)) & \
|
||||
((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \
|
||||
(1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS))))
|
||||
|
||||
/**
|
||||
* HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES:
|
||||
* @level: #hb_buffer_cluster_level_t to test
|
||||
*
|
||||
* Tests whether a cluster level groups cluster values by graphemes. Requires
|
||||
* that the level be valid.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
#define HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES(level) \
|
||||
((bool) ((1u << (unsigned) (level)) & \
|
||||
((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \
|
||||
(1u << HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES))))
|
||||
|
||||
/**
|
||||
* HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS
|
||||
* @level: #hb_buffer_cluster_level_t to test
|
||||
*
|
||||
* Tests whether a cluster level does not group cluster values by graphemes.
|
||||
* Requires that the level be valid.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
#define HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS(level) \
|
||||
((bool) ((1u << (unsigned) (level)) & \
|
||||
((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARCATERS) | \
|
||||
(1u << HB_BUFFER_CLUSTER_LEVEL_CHARACTERS))))
|
||||
|
||||
HB_EXTERN void
|
||||
hb_buffer_set_cluster_level (hb_buffer_t *buffer,
|
||||
hb_buffer_cluster_level_t cluster_level);
|
||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-cache.hh
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-cache.hh
vendored
@ -52,11 +52,11 @@ struct hb_cache_t
|
||||
{
|
||||
using item_t = typename std::conditional<thread_safe,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
|
||||
hb_atomic_short_t,
|
||||
hb_atomic_int_t>::type,
|
||||
hb_atomic_t<unsigned short>,
|
||||
hb_atomic_t<unsigned int>>::type,
|
||||
typename std::conditional<key_bits + value_bits - cache_bits <= 16,
|
||||
short,
|
||||
int>::type
|
||||
unsigned short,
|
||||
unsigned int>::type
|
||||
>::type;
|
||||
|
||||
static_assert ((key_bits >= cache_bits), "");
|
||||
|
@ -726,6 +726,9 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||
float span;
|
||||
|
||||
span = angles[n_stops - 1] - angles[0];
|
||||
if (!span)
|
||||
goto done;
|
||||
|
||||
k = 0;
|
||||
if (angles[0] >= 0)
|
||||
{
|
||||
|
@ -71,7 +71,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
|
||||
template <typename ACC>
|
||||
cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
|
||||
const int *coords_=nullptr, unsigned int num_coords_=0)
|
||||
: SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
|
||||
: SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs),
|
||||
cached_scalars_vector (&acc.cached_scalars_vector)
|
||||
{
|
||||
coords = coords_;
|
||||
num_coords = num_coords_;
|
||||
@ -80,9 +81,39 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
|
||||
set_ivs (acc.privateDicts[fd].ivs);
|
||||
}
|
||||
|
||||
void fini ()
|
||||
~cff2_cs_interp_env_t ()
|
||||
{
|
||||
SUPER::fini ();
|
||||
release_scalars_vector (scalars);
|
||||
}
|
||||
|
||||
hb_vector_t<float> *acquire_scalars_vector () const
|
||||
{
|
||||
hb_vector_t<float> *scalars = cached_scalars_vector->get_acquire ();
|
||||
|
||||
if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr))
|
||||
{
|
||||
scalars = (hb_vector_t<float> *) hb_calloc (1, sizeof (hb_vector_t<float>));
|
||||
if (unlikely (!scalars))
|
||||
return nullptr;
|
||||
scalars->init ();
|
||||
}
|
||||
|
||||
return scalars;
|
||||
}
|
||||
|
||||
void release_scalars_vector (hb_vector_t<float> *scalars) const
|
||||
{
|
||||
if (!scalars)
|
||||
return;
|
||||
|
||||
scalars->clear ();
|
||||
|
||||
if (!cached_scalars_vector->cmpexch (nullptr, scalars))
|
||||
{
|
||||
scalars->fini ();
|
||||
hb_free (scalars);
|
||||
}
|
||||
scalars = nullptr;
|
||||
}
|
||||
|
||||
op_code_t fetch_op ()
|
||||
@ -111,14 +142,20 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
|
||||
{
|
||||
if (!seen_blend)
|
||||
{
|
||||
region_count = varStore->varStore.get_region_index_count (get_ivs ());
|
||||
if (do_blend)
|
||||
scalars = acquire_scalars_vector ();
|
||||
if (unlikely (!scalars))
|
||||
SUPER::set_error ();
|
||||
else
|
||||
{
|
||||
if (unlikely (!scalars.resize_exact (region_count)))
|
||||
SUPER::set_error ();
|
||||
else
|
||||
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
region_count = varStore->varStore.get_region_index_count (get_ivs ());
|
||||
if (do_blend)
|
||||
{
|
||||
if (unlikely (!scalars->resize_exact (region_count)))
|
||||
SUPER::set_error ();
|
||||
else
|
||||
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
|
||||
&(*scalars)[0], region_count);
|
||||
}
|
||||
}
|
||||
seen_blend = true;
|
||||
}
|
||||
@ -149,11 +186,11 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
|
||||
double v = 0;
|
||||
if (do_blend)
|
||||
{
|
||||
if (likely (scalars.length == deltas.length))
|
||||
if (likely (scalars && scalars->length == deltas.length))
|
||||
{
|
||||
unsigned count = scalars.length;
|
||||
unsigned count = scalars->length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
|
||||
v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real ();
|
||||
}
|
||||
}
|
||||
return v;
|
||||
@ -167,7 +204,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
|
||||
const CFF2ItemVariationStore *varStore;
|
||||
unsigned int region_count;
|
||||
unsigned int ivs;
|
||||
hb_vector_t<float> scalars;
|
||||
hb_vector_t<float> *scalars = nullptr;
|
||||
hb_atomic_t<hb_vector_t<float> *> *cached_scalars_vector = nullptr;
|
||||
bool do_blend;
|
||||
bool seen_vsindex_ = false;
|
||||
bool seen_blend = false;
|
||||
|
63
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
63
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
@ -42,7 +42,7 @@
|
||||
|
||||
/* hb_options_t */
|
||||
|
||||
hb_atomic_int_t _hb_options;
|
||||
hb_atomic_t<unsigned> _hb_options;
|
||||
|
||||
void
|
||||
_hb_options_init ()
|
||||
@ -273,7 +273,7 @@ struct hb_language_item_t {
|
||||
|
||||
/* Thread-safe lockfree language list */
|
||||
|
||||
static hb_atomic_ptr_t <hb_language_item_t> langs;
|
||||
static hb_atomic_t<hb_language_item_t *> langs;
|
||||
|
||||
static inline void
|
||||
free_langs ()
|
||||
@ -403,7 +403,7 @@ hb_language_to_string (hb_language_t language)
|
||||
hb_language_t
|
||||
hb_language_get_default ()
|
||||
{
|
||||
static hb_atomic_ptr_t <hb_language_t> default_language;
|
||||
static hb_atomic_t<hb_language_t> default_language;
|
||||
|
||||
hb_language_t language = default_language;
|
||||
if (unlikely (language == HB_LANGUAGE_INVALID))
|
||||
@ -968,6 +968,9 @@ hb_feature_from_string (const char *str, int len,
|
||||
* understood by hb_feature_from_string(). The client in responsible for
|
||||
* allocating big enough size for @buf, 128 bytes is more than enough.
|
||||
*
|
||||
* Note that the feature value will be omitted if it is '1', but the
|
||||
* string won't include any whitespace.
|
||||
*
|
||||
* Since: 0.9.5
|
||||
**/
|
||||
void
|
||||
@ -1121,6 +1124,8 @@ get_C_locale ()
|
||||
* understood by hb_variation_from_string(). The client in responsible for
|
||||
* allocating big enough size for @buf, 128 bytes is more than enough.
|
||||
*
|
||||
* Note that the string won't include any whitespace.
|
||||
*
|
||||
* Since: 1.4.2
|
||||
*/
|
||||
void
|
||||
@ -1212,6 +1217,58 @@ uint8_t
|
||||
return hb_color_get_blue (color);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_malloc:
|
||||
* @size: The size of the memory to allocate.
|
||||
*
|
||||
* Allocates @size bytes of memory, using the allocator set at
|
||||
* compile-time. Typically just malloc().
|
||||
*
|
||||
* Return value: A pointer to the allocated memory.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
void* hb_malloc(size_t size) { return hb_malloc_impl (size); }
|
||||
|
||||
/**
|
||||
* hb_calloc:
|
||||
* @nmemb: The number of elements to allocate.
|
||||
* @size: The size of each element.
|
||||
*
|
||||
* Allocates @nmemb elements of @size bytes each, initialized to zero,
|
||||
* using the allocator set at compile-time. Typically just calloc().
|
||||
*
|
||||
* Return value: A pointer to the allocated memory.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
void* hb_calloc(size_t nmemb, size_t size) { return hb_calloc_impl (nmemb, size); }
|
||||
|
||||
/**
|
||||
* hb_realloc:
|
||||
* @ptr: The pointer to the memory to reallocate.
|
||||
* @size: The new size of the memory.
|
||||
*
|
||||
* Reallocates the memory pointed to by @ptr to @size bytes, using the
|
||||
* allocator set at compile-time. Typically just realloc().
|
||||
*
|
||||
* Return value: A pointer to the reallocated memory.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
void* hb_realloc(void *ptr, size_t size) { return hb_realloc_impl (ptr, size); }
|
||||
|
||||
/**
|
||||
* hb_free:
|
||||
* @ptr: The pointer to the memory to free.
|
||||
*
|
||||
* Frees the memory pointed to by @ptr, using the allocator set at
|
||||
* compile-time. Typically just free().
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
void hb_free(void *ptr) { hb_free_impl (ptr); }
|
||||
|
||||
|
||||
/* If there is no visibility control, then hb-static.cc will NOT
|
||||
* define anything. Instead, we get it to define one set in here
|
||||
|
11
src/3rdparty/harfbuzz-ng/src/hb-common.h
vendored
11
src/3rdparty/harfbuzz-ng/src/hb-common.h
vendored
@ -65,6 +65,7 @@ typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
#define HB_DEPRECATED __attribute__((__deprecated__))
|
||||
@ -948,6 +949,16 @@ typedef struct hb_glyph_extents_t {
|
||||
*/
|
||||
typedef struct hb_font_t hb_font_t;
|
||||
|
||||
/* Not of much use to clients. */
|
||||
HB_EXTERN void*
|
||||
hb_malloc (size_t size);
|
||||
HB_EXTERN void*
|
||||
hb_calloc (size_t nmemb, size_t size);
|
||||
HB_EXTERN void*
|
||||
hb_realloc (void *ptr, size_t size);
|
||||
HB_EXTERN void
|
||||
hb_free (void *ptr);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_COMMON_H */
|
||||
|
80
src/3rdparty/harfbuzz-ng/src/hb-coretext-font.cc
vendored
80
src/3rdparty/harfbuzz-ng/src/hb-coretext-font.cc
vendored
@ -28,7 +28,7 @@
|
||||
|
||||
#ifdef HAVE_CORETEXT
|
||||
|
||||
#include "hb-coretext.h"
|
||||
#include "hb-coretext.hh"
|
||||
|
||||
#include "hb-draw.hh"
|
||||
#include "hb-font.hh"
|
||||
@ -42,24 +42,17 @@
|
||||
# define kCTFontOrientationVertical kCTFontVerticalOrientation
|
||||
#endif
|
||||
|
||||
#define MAX_GLYPHS 64u
|
||||
|
||||
static void
|
||||
_hb_coretext_font_destroy (void *font_data)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
|
||||
CFRelease (ct_font);
|
||||
}
|
||||
#define MAX_GLYPHS 256u
|
||||
|
||||
static hb_bool_t
|
||||
hb_coretext_get_nominal_glyph (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_coretext_get_nominal_glyph (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
UniChar ch[2];
|
||||
CGGlyph cg_glyph[2];
|
||||
unsigned count = 0;
|
||||
@ -85,7 +78,7 @@ hb_coretext_get_nominal_glyph (hb_font_t *font HB_UNUSED,
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hb_coretext_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
||||
hb_coretext_get_nominal_glyphs (hb_font_t *font,
|
||||
void *font_data,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_unicode,
|
||||
@ -94,6 +87,8 @@ hb_coretext_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
||||
unsigned int glyph_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
// If any non-BMP codepoint is requested, use the slow path.
|
||||
bool slow_path = false;
|
||||
auto *unicode = first_unicode;
|
||||
@ -119,8 +114,6 @@ hb_coretext_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
||||
return count;
|
||||
}
|
||||
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
|
||||
UniChar ch[MAX_GLYPHS];
|
||||
CGGlyph cg_glyph[MAX_GLYPHS];
|
||||
for (unsigned i = 0; i < count; i += MAX_GLYPHS)
|
||||
@ -152,14 +145,14 @@ hb_coretext_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_coretext_get_variation_glyph (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_coretext_get_variation_glyph (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
UniChar ch[4];
|
||||
CGGlyph cg_glyph[4];
|
||||
@ -194,12 +187,17 @@ hb_coretext_get_variation_glyph (hb_font_t *font HB_UNUSED,
|
||||
if (cg_glyph[i])
|
||||
return false;
|
||||
|
||||
// Humm. CoreText falls back to the default glyph if the variation selector
|
||||
// is not supported. We cannot truly detect that case. So, in essence,
|
||||
// we are always returning true here...
|
||||
|
||||
*glyph = cg_glyph[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_coretext_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
hb_coretext_get_glyph_h_advances (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
@ -207,7 +205,7 @@ hb_coretext_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
|
||||
@ -233,7 +231,8 @@ hb_coretext_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static void
|
||||
hb_coretext_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
hb_coretext_get_glyph_v_advances (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
@ -241,7 +240,7 @@ hb_coretext_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||
CGFloat y_mult = (CGFloat) -font->y_scale / ct_font_size;
|
||||
@ -264,18 +263,16 @@ hb_coretext_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static hb_bool_t
|
||||
hb_coretext_get_glyph_v_origin (hb_font_t *font,
|
||||
void *font_data,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||
CGFloat x_mult = (CGFloat) -font->x_scale / ct_font_size;
|
||||
@ -294,12 +291,12 @@ hb_coretext_get_glyph_v_origin (hb_font_t *font,
|
||||
|
||||
static hb_bool_t
|
||||
hb_coretext_get_glyph_extents (hb_font_t *font,
|
||||
void *font_data,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
|
||||
@ -310,20 +307,21 @@ hb_coretext_get_glyph_extents (hb_font_t *font,
|
||||
kCTFontOrientationDefault, glyphs, NULL, 1);
|
||||
|
||||
extents->x_bearing = round (bounds.origin.x * x_mult);
|
||||
extents->y_bearing = round (bounds.origin.y * y_mult);
|
||||
extents->y_bearing = round ((bounds.origin.y + bounds.size.height) * y_mult);
|
||||
extents->width = round (bounds.size.width * x_mult);
|
||||
extents->height = round (bounds.size.height * y_mult);
|
||||
extents->height = round (bounds.origin.y * y_mult) - extents->y_bearing;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_coretext_get_font_h_extents (hb_font_t *font,
|
||||
void *font_data,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
|
||||
|
||||
@ -371,7 +369,7 @@ hb_coretext_draw_glyph (hb_font_t *font,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
CGFloat ct_font_size = CTFontGetSize (ct_font);
|
||||
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
|
||||
@ -415,17 +413,20 @@ hb_coretext_get_glyph_name (hb_font_t *font,
|
||||
(UInt8 *) name, size, &len);
|
||||
|
||||
name[len] = '\0';
|
||||
|
||||
CFRelease (cf_name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_coretext_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_coretext_get_glyph_from_name (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
const char *name, int len,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) font_data;
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
|
||||
if (len == -1)
|
||||
len = strlen (name);
|
||||
@ -458,10 +459,8 @@ static struct hb_coretext_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_coretext_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_coretext_get_glyph_h_advances, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_coretext_get_glyph_h_origin, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
//hb_font_funcs_set_font_v_extents_func (funcs, hb_coretext_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_coretext_get_glyph_v_advances, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_coretext_get_glyph_v_origin, nullptr, nullptr);
|
||||
#endif
|
||||
@ -530,8 +529,7 @@ hb_coretext_font_set_funcs (hb_font_t *font)
|
||||
|
||||
hb_font_set_funcs (font,
|
||||
_hb_coretext_get_font_funcs (),
|
||||
(void *) CFRetain (ct_font),
|
||||
_hb_coretext_font_destroy);
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
#undef MAX_GLYPHS
|
||||
|
475
src/3rdparty/harfbuzz-ng/src/hb-coretext-shape.cc
vendored
475
src/3rdparty/harfbuzz-ng/src/hb-coretext-shape.cc
vendored
@ -32,279 +32,9 @@
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include "hb-coretext.h"
|
||||
#include "hb-coretext.hh"
|
||||
#include "hb-aat-layout.hh"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-coretext
|
||||
* @title: hb-coretext
|
||||
* @short_description: CoreText integration
|
||||
* @include: hb-coretext.h
|
||||
*
|
||||
* Functions for using HarfBuzz with the CoreText fonts.
|
||||
**/
|
||||
|
||||
static CTFontRef create_ct_font (CGFontRef cg_font, CGFloat font_size);
|
||||
|
||||
static void
|
||||
release_table_data (void *user_data)
|
||||
{
|
||||
CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
|
||||
CFRelease(cf_data);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
||||
if (unlikely (!cf_data))
|
||||
return nullptr;
|
||||
|
||||
const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
|
||||
const size_t length = CFDataGetLength (cf_data);
|
||||
if (!data || !length)
|
||||
{
|
||||
CFRelease (cf_data);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
|
||||
reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
|
||||
release_table_data);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
_hb_cg_get_table_tags (const hb_face_t *face HB_UNUSED,
|
||||
unsigned int start_offset,
|
||||
unsigned int *table_count,
|
||||
hb_tag_t *table_tags,
|
||||
void *user_data)
|
||||
{
|
||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||
|
||||
CTFontRef ct_font = create_ct_font (cg_font, (CGFloat) HB_CORETEXT_DEFAULT_FONT_SIZE);
|
||||
|
||||
auto arr = CTFontCopyAvailableTables (ct_font, kCTFontTableOptionNoOptions);
|
||||
|
||||
unsigned population = (unsigned) CFArrayGetCount (arr);
|
||||
unsigned end_offset;
|
||||
|
||||
if (!table_count)
|
||||
goto done;
|
||||
|
||||
if (unlikely (start_offset >= population))
|
||||
{
|
||||
*table_count = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
end_offset = start_offset + *table_count;
|
||||
if (unlikely (end_offset < start_offset))
|
||||
{
|
||||
*table_count = 0;
|
||||
goto done;
|
||||
}
|
||||
end_offset= hb_min (end_offset, (unsigned) population);
|
||||
|
||||
*table_count = end_offset - start_offset;
|
||||
for (unsigned i = start_offset; i < end_offset; i++)
|
||||
{
|
||||
CTFontTableTag tag = (CTFontTableTag)(uintptr_t) CFArrayGetValueAtIndex (arr, i);
|
||||
table_tags[i - start_offset] = tag;
|
||||
}
|
||||
|
||||
done:
|
||||
CFRelease (arr);
|
||||
CFRelease (ct_font);
|
||||
return population;
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_cg_font_release (void *data)
|
||||
{
|
||||
CGFontRelease ((CGFontRef) data);
|
||||
}
|
||||
|
||||
|
||||
static CTFontDescriptorRef
|
||||
get_last_resort_font_desc ()
|
||||
{
|
||||
// TODO Handle allocation failures?
|
||||
CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
|
||||
CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
|
||||
(const void **) &last_resort,
|
||||
1,
|
||||
&kCFTypeArrayCallBacks);
|
||||
CFRelease (last_resort);
|
||||
CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) &kCTFontCascadeListAttribute,
|
||||
(const void **) &cascade_list,
|
||||
1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease (cascade_list);
|
||||
|
||||
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
|
||||
CFRelease (attributes);
|
||||
return font_desc;
|
||||
}
|
||||
|
||||
static void
|
||||
release_data (void *info, const void *data, size_t size)
|
||||
{
|
||||
assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
|
||||
hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
|
||||
|
||||
hb_blob_destroy ((hb_blob_t *) info);
|
||||
}
|
||||
|
||||
static CGFontRef
|
||||
create_cg_font (hb_face_t *face)
|
||||
{
|
||||
CGFontRef cg_font = nullptr;
|
||||
if (face->destroy == _hb_cg_font_release)
|
||||
{
|
||||
cg_font = CGFontRetain ((CGFontRef) face->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
unsigned int blob_length;
|
||||
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
||||
if (unlikely (!blob_length))
|
||||
DEBUG_MSG (CORETEXT, face, "Face has empty blob");
|
||||
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
|
||||
if (likely (provider))
|
||||
{
|
||||
cg_font = CGFontCreateWithDataProvider (provider);
|
||||
if (unlikely (!cg_font))
|
||||
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
|
||||
CGDataProviderRelease (provider);
|
||||
}
|
||||
}
|
||||
return cg_font;
|
||||
}
|
||||
|
||||
static CTFontRef
|
||||
create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
||||
{
|
||||
CTFontRef ct_font = nullptr;
|
||||
|
||||
/* CoreText does not enable trak table usage / tracking when creating a CTFont
|
||||
* using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
|
||||
* to be through the CTFontCreateUIFontForLanguage call. */
|
||||
CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
|
||||
if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
|
||||
CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
|
||||
{
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
# define kCTFontUIFontSystem kCTFontSystemFontType
|
||||
# define kCTFontUIFontEmphasizedSystem kCTFontEmphasizedSystemFontType
|
||||
#endif
|
||||
CTFontUIFontType font_type = kCTFontUIFontSystem;
|
||||
if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
|
||||
font_type = kCTFontUIFontEmphasizedSystem;
|
||||
|
||||
ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr);
|
||||
CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
|
||||
if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
|
||||
{
|
||||
CFRelease(ct_font);
|
||||
ct_font = nullptr;
|
||||
}
|
||||
CFRelease (ct_result_name);
|
||||
}
|
||||
CFRelease (cg_postscript_name);
|
||||
|
||||
if (!ct_font)
|
||||
ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr);
|
||||
|
||||
if (unlikely (!ct_font)) {
|
||||
DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
|
||||
* bug indicate that the cascade list reconfiguration occasionally causes
|
||||
* crashes in CoreText on OS X 10.9, thus let's skip this step on older
|
||||
* operating system versions. Except for the emoji font, where _not_
|
||||
* reconfiguring the cascade list causes CoreText crashes. For details, see
|
||||
* crbug.com/549610 */
|
||||
// 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
|
||||
#pragma GCC diagnostic pop
|
||||
CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
|
||||
bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
|
||||
CFRelease (fontName);
|
||||
if (!isEmojiFont)
|
||||
return ct_font;
|
||||
}
|
||||
|
||||
CFURLRef original_url = nullptr;
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
ATSFontRef atsFont;
|
||||
FSRef fsref;
|
||||
OSStatus status;
|
||||
atsFont = CTFontGetPlatformFont (ct_font, NULL);
|
||||
status = ATSFontGetFileReference (atsFont, &fsref);
|
||||
if (status == noErr)
|
||||
original_url = CFURLCreateFromFSRef (NULL, &fsref);
|
||||
#else
|
||||
original_url = (CFURLRef) CTFontCopyAttribute (ct_font, kCTFontURLAttribute);
|
||||
#endif
|
||||
|
||||
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
|
||||
* font fallback which we don't need anyway. */
|
||||
{
|
||||
CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
|
||||
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc);
|
||||
CFRelease (last_resort_font_desc);
|
||||
if (new_ct_font)
|
||||
{
|
||||
/* The CTFontCreateCopyWithAttributes call fails to stay on the same font
|
||||
* when reconfiguring the cascade list and may switch to a different font
|
||||
* when there are fonts that go by the same name, since the descriptor is
|
||||
* just name and size.
|
||||
*
|
||||
* Avoid reconfiguring the cascade lists if the new font is outside the
|
||||
* system locations that we cannot access from the sandboxed renderer
|
||||
* process in Blink. This can be detected by the new file URL location
|
||||
* that the newly found font points to. */
|
||||
CFURLRef new_url = nullptr;
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
|
||||
status = ATSFontGetFileReference (atsFont, &fsref);
|
||||
if (status == noErr)
|
||||
new_url = CFURLCreateFromFSRef (NULL, &fsref);
|
||||
#else
|
||||
new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
|
||||
#endif
|
||||
// Keep reconfigured font if URL cannot be retrieved (seems to be the case
|
||||
// on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
|
||||
if (!original_url || !new_url || CFEqual (original_url, new_url)) {
|
||||
CFRelease (ct_font);
|
||||
ct_font = new_ct_font;
|
||||
} else {
|
||||
CFRelease (new_ct_font);
|
||||
DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
|
||||
}
|
||||
if (new_url)
|
||||
CFRelease (new_url);
|
||||
}
|
||||
else
|
||||
DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
|
||||
}
|
||||
|
||||
if (original_url)
|
||||
CFRelease (original_url);
|
||||
return ct_font;
|
||||
}
|
||||
|
||||
hb_coretext_face_data_t *
|
||||
_hb_coretext_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
@ -325,102 +55,6 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
|
||||
CFRelease ((CGFontRef) data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_create:
|
||||
* @cg_font: The CGFontRef to work upon
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* CGFontRef.
|
||||
*
|
||||
* Return value: (transfer full): The new face object
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font)
|
||||
{
|
||||
hb_face_t *face = hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||
hb_face_set_get_table_tags_func (face, _hb_cg_get_table_tags, cg_font, nullptr);
|
||||
return face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_create_from_file_or_fail:
|
||||
* @file_name: A font filename
|
||||
* @index: The index of the face within the file
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* font file and face index.
|
||||
*
|
||||
* This is similar in functionality to hb_face_create_from_file_or_fail(),
|
||||
* but uses the CoreText library for loading the font file.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* no face is found at the specified index or the file cannot be read.
|
||||
*
|
||||
* Since: 10.1.0
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_coretext_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index)
|
||||
{
|
||||
auto url = CFURLCreateFromFileSystemRepresentation (nullptr,
|
||||
(const UInt8 *) file_name,
|
||||
strlen (file_name),
|
||||
false);
|
||||
if (unlikely (!url))
|
||||
return nullptr;
|
||||
|
||||
auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromURL (url);
|
||||
if (unlikely (!ct_font_desc_array))
|
||||
{
|
||||
CFRelease (url);
|
||||
return nullptr;
|
||||
}
|
||||
auto ct_font_desc = (CFArrayGetCount (ct_font_desc_array) > index) ?
|
||||
(CTFontDescriptorRef) CFArrayGetValueAtIndex (ct_font_desc_array, index) : nullptr;
|
||||
if (unlikely (!ct_font_desc))
|
||||
{
|
||||
CFRelease (ct_font_desc_array);
|
||||
CFRelease (url);
|
||||
return nullptr;
|
||||
}
|
||||
CFRelease (url);
|
||||
auto ct_font = ct_font_desc ? CTFontCreateWithFontDescriptor (ct_font_desc, 0, nullptr) : nullptr;
|
||||
CFRelease (ct_font_desc_array);
|
||||
if (unlikely (!ct_font))
|
||||
return nullptr;
|
||||
|
||||
auto cg_font = ct_font ? CTFontCopyGraphicsFont (ct_font, nullptr) : nullptr;
|
||||
CFRelease (ct_font);
|
||||
if (unlikely (!cg_font))
|
||||
return nullptr;
|
||||
|
||||
hb_face_t *face = hb_coretext_face_create (cg_font);
|
||||
CFRelease (cg_font);
|
||||
if (unlikely (hb_face_is_immutable (face)))
|
||||
return nullptr;
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_get_cg_font:
|
||||
* @face: The #hb_face_t to work upon
|
||||
*
|
||||
* Fetches the CGFontRef associated with an #hb_face_t
|
||||
* face object
|
||||
*
|
||||
* Return value: the CGFontRef found
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
CGFontRef
|
||||
hb_coretext_face_get_cg_font (hb_face_t *face)
|
||||
{
|
||||
return (CGFontRef) (const void *) face->data.coretext;
|
||||
}
|
||||
|
||||
|
||||
hb_coretext_font_data_t *
|
||||
_hb_coretext_shaper_font_data_create (hb_font_t *font)
|
||||
@ -439,7 +73,9 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (font->num_coords)
|
||||
unsigned num_axes = hb_ot_var_get_axis_count (face);
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5163
|
||||
if (num_axes)
|
||||
{
|
||||
CFMutableDictionaryRef variations =
|
||||
CFDictionaryCreateMutable (kCFAllocatorDefault,
|
||||
@ -447,14 +83,15 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
for (unsigned i = 0; i < font->num_coords; i++)
|
||||
unsigned count = hb_max (num_axes, font->num_coords);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_ot_var_axis_info_t info;
|
||||
unsigned int c = 1;
|
||||
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
|
||||
if (font->design_coords[i] == info.default_value)
|
||||
continue;
|
||||
float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value);
|
||||
float v = i < font->num_coords ?
|
||||
hb_clamp (font->design_coords[i], info.min_value, info.max_value) :
|
||||
info.default_value;
|
||||
|
||||
CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
|
||||
CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v);
|
||||
@ -489,94 +126,6 @@ _hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
|
||||
CFRelease ((CTFontRef) data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_font_create:
|
||||
* @ct_font: The CTFontRef to work upon
|
||||
*
|
||||
* Creates an #hb_font_t font object from the specified
|
||||
* CTFontRef.
|
||||
*
|
||||
* The created font uses the default font functions implemented
|
||||
* natively by HarfBuzz. If you want to use the CoreText font functions
|
||||
* instead (rarely needed), you can do so by calling
|
||||
* by hb_coretext_font_set_funcs().
|
||||
*
|
||||
* Return value: (transfer full): The new font object
|
||||
*
|
||||
* Since: 1.7.2
|
||||
**/
|
||||
hb_font_t *
|
||||
hb_coretext_font_create (CTFontRef ct_font)
|
||||
{
|
||||
CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
|
||||
hb_face_t *face = hb_coretext_face_create (cg_font);
|
||||
CFRelease (cg_font);
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
|
||||
if (unlikely (hb_object_is_immutable (font)))
|
||||
return font;
|
||||
|
||||
hb_font_set_ptem (font, CTFontGetSize (ct_font));
|
||||
|
||||
/* Copy font variations */
|
||||
CFDictionaryRef variations = CTFontCopyVariation (ct_font);
|
||||
if (variations)
|
||||
{
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
hb_vector_t<CFTypeRef> keys;
|
||||
hb_vector_t<CFTypeRef> values;
|
||||
|
||||
CFIndex count = CFDictionaryGetCount (variations);
|
||||
if (unlikely (!vars.alloc_exact (count) || !keys.resize_exact (count) || !values.resize_exact (count)))
|
||||
goto done;
|
||||
|
||||
// Fetch them one by one and collect in a vector of our own.
|
||||
CFDictionaryGetKeysAndValues (variations, keys.arrayZ, values.arrayZ);
|
||||
for (CFIndex i = 0; i < count; i++)
|
||||
{
|
||||
int tag;
|
||||
float value;
|
||||
CFNumberGetValue ((CFNumberRef) keys.arrayZ[i], kCFNumberIntType, &tag);
|
||||
CFNumberGetValue ((CFNumberRef) values.arrayZ[i], kCFNumberFloatType, &value);
|
||||
|
||||
hb_variation_t var = {tag, value};
|
||||
vars.push (var);
|
||||
}
|
||||
hb_font_set_variations (font, vars.arrayZ, vars.length);
|
||||
|
||||
done:
|
||||
CFRelease (variations);
|
||||
}
|
||||
|
||||
/* Let there be dragons here... */
|
||||
font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
|
||||
|
||||
// https://github.com/harfbuzz/harfbuzz/pull/4895#issuecomment-2408471254
|
||||
//hb_coretext_font_set_funcs (font);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_font_get_ct_font:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Fetches the CTFontRef associated with the specified
|
||||
* #hb_font_t font object.
|
||||
*
|
||||
* Return value: the CTFontRef found
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
CTFontRef
|
||||
hb_coretext_font_get_ct_font (hb_font_t *font)
|
||||
{
|
||||
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
|
||||
return ct_font ? (CTFontRef) ct_font : nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
@ -646,7 +195,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
* B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
|
||||
* continue pointing to B2 even though B2 was merged into B1's
|
||||
* cluster... */
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
if (HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (buffer->cluster_level))
|
||||
{
|
||||
hb_unicode_funcs_t *unicode = buffer->unicode;
|
||||
unsigned int count = buffer->len;
|
||||
@ -1010,7 +559,7 @@ resize_and_retry:
|
||||
|
||||
CFArrayRef glyph_runs = CTLineGetGlyphRuns (line);
|
||||
unsigned int num_runs = CFArrayGetCount (glyph_runs);
|
||||
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
|
||||
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %u", num_runs);
|
||||
|
||||
buffer->len = 0;
|
||||
uint32_t status_or = 0;
|
||||
@ -1292,7 +841,7 @@ resize_and_retry:
|
||||
* or the native OT backend, only that the cluster indices will be
|
||||
* monotonic in the output buffer. */
|
||||
if (count > 1 && (status_or & kCTRunStatusNonMonotonic) &&
|
||||
buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||
HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level))
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
|
||||
|
572
src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
vendored
Normal file
572
src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
vendored
Normal file
@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright © 2012,2013 Mozilla Foundation.
|
||||
* Copyright © 2012,2013 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Mozilla Author(s): Jonathan Kew
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_CORETEXT
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include "hb-coretext.hh"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-coretext
|
||||
* @title: hb-coretext
|
||||
* @short_description: CoreText integration
|
||||
* @include: hb-coretext.h
|
||||
*
|
||||
* Functions for using HarfBuzz with the CoreText fonts.
|
||||
**/
|
||||
|
||||
static void
|
||||
release_table_data (void *user_data)
|
||||
{
|
||||
CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
|
||||
CFRelease(cf_data);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
||||
if (unlikely (!cf_data))
|
||||
return nullptr;
|
||||
|
||||
const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
|
||||
const size_t length = CFDataGetLength (cf_data);
|
||||
if (!data || !length)
|
||||
{
|
||||
CFRelease (cf_data);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
|
||||
reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
|
||||
release_table_data);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
_hb_cg_get_table_tags (const hb_face_t *face HB_UNUSED,
|
||||
unsigned int start_offset,
|
||||
unsigned int *table_count,
|
||||
hb_tag_t *table_tags,
|
||||
void *user_data)
|
||||
{
|
||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||
|
||||
CTFontRef ct_font = create_ct_font (cg_font, (CGFloat) HB_CORETEXT_DEFAULT_FONT_SIZE);
|
||||
|
||||
auto arr = CTFontCopyAvailableTables (ct_font, kCTFontTableOptionNoOptions);
|
||||
|
||||
unsigned population = (unsigned) CFArrayGetCount (arr);
|
||||
unsigned end_offset;
|
||||
|
||||
if (!table_count)
|
||||
goto done;
|
||||
|
||||
if (unlikely (start_offset >= population))
|
||||
{
|
||||
*table_count = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
end_offset = start_offset + *table_count;
|
||||
if (unlikely (end_offset < start_offset))
|
||||
{
|
||||
*table_count = 0;
|
||||
goto done;
|
||||
}
|
||||
end_offset= hb_min (end_offset, (unsigned) population);
|
||||
|
||||
*table_count = end_offset - start_offset;
|
||||
for (unsigned i = start_offset; i < end_offset; i++)
|
||||
{
|
||||
CTFontTableTag tag = (CTFontTableTag)(uintptr_t) CFArrayGetValueAtIndex (arr, i);
|
||||
table_tags[i - start_offset] = tag;
|
||||
}
|
||||
|
||||
done:
|
||||
CFRelease (arr);
|
||||
CFRelease (ct_font);
|
||||
return population;
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_cg_font_release (void *data)
|
||||
{
|
||||
CGFontRelease ((CGFontRef) data);
|
||||
}
|
||||
|
||||
|
||||
static CTFontDescriptorRef
|
||||
get_last_resort_font_desc ()
|
||||
{
|
||||
// TODO Handle allocation failures?
|
||||
CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
|
||||
CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
|
||||
(const void **) &last_resort,
|
||||
1,
|
||||
&kCFTypeArrayCallBacks);
|
||||
CFRelease (last_resort);
|
||||
CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) &kCTFontCascadeListAttribute,
|
||||
(const void **) &cascade_list,
|
||||
1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease (cascade_list);
|
||||
|
||||
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
|
||||
CFRelease (attributes);
|
||||
return font_desc;
|
||||
}
|
||||
|
||||
static void
|
||||
release_data (void *info, const void *data, size_t size)
|
||||
{
|
||||
assert (hb_blob_get_length ((hb_blob_t *) info) == size &&
|
||||
hb_blob_get_data ((hb_blob_t *) info, nullptr) == data);
|
||||
|
||||
hb_blob_destroy ((hb_blob_t *) info);
|
||||
}
|
||||
|
||||
CGFontRef
|
||||
create_cg_font (CFArrayRef ct_font_desc_array, unsigned int named_instance_index)
|
||||
{
|
||||
if (named_instance_index == 0)
|
||||
{
|
||||
// Default instance. We don't know which one is it. Return the first one.
|
||||
// We will set the correct variations on it later.
|
||||
}
|
||||
else
|
||||
named_instance_index--;
|
||||
auto ct_font_desc = (CFArrayGetCount (ct_font_desc_array) > named_instance_index) ?
|
||||
(CTFontDescriptorRef) CFArrayGetValueAtIndex (ct_font_desc_array, named_instance_index) : nullptr;
|
||||
if (unlikely (!ct_font_desc))
|
||||
{
|
||||
CFRelease (ct_font_desc_array);
|
||||
return nullptr;
|
||||
}
|
||||
auto ct_font = ct_font_desc ? CTFontCreateWithFontDescriptor (ct_font_desc, 0, nullptr) : nullptr;
|
||||
CFRelease (ct_font_desc_array);
|
||||
if (unlikely (!ct_font))
|
||||
return nullptr;
|
||||
|
||||
auto cg_font = ct_font ? CTFontCopyGraphicsFont (ct_font, nullptr) : nullptr;
|
||||
CFRelease (ct_font);
|
||||
|
||||
return cg_font;
|
||||
}
|
||||
|
||||
CGFontRef
|
||||
create_cg_font (hb_blob_t *blob, unsigned int index)
|
||||
{
|
||||
hb_blob_make_immutable (blob);
|
||||
unsigned int blob_length;
|
||||
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
||||
if (unlikely (!blob_length))
|
||||
DEBUG_MSG (CORETEXT, blob, "Empty blob");
|
||||
|
||||
unsigned ttc_index = index & 0xFFFF;
|
||||
unsigned named_instance_index = index >> 16;
|
||||
|
||||
if (ttc_index != 0)
|
||||
{
|
||||
DEBUG_MSG (CORETEXT, blob, "TTC index %d not supported", ttc_index);
|
||||
return nullptr; // CoreText does not support TTCs
|
||||
}
|
||||
|
||||
if (unlikely (named_instance_index != 0))
|
||||
{
|
||||
auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromData (CFDataCreate (kCFAllocatorDefault, (const UInt8 *) blob_data, blob_length));
|
||||
if (unlikely (!ct_font_desc_array))
|
||||
return nullptr;
|
||||
return create_cg_font (ct_font_desc_array, named_instance_index);
|
||||
}
|
||||
|
||||
hb_blob_reference (blob);
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
|
||||
CGFontRef cg_font = nullptr;
|
||||
if (likely (provider))
|
||||
{
|
||||
cg_font = CGFontCreateWithDataProvider (provider);
|
||||
if (unlikely (!cg_font))
|
||||
DEBUG_MSG (CORETEXT, blob, "CGFontCreateWithDataProvider() failed");
|
||||
CGDataProviderRelease (provider);
|
||||
}
|
||||
return cg_font;
|
||||
}
|
||||
|
||||
CGFontRef
|
||||
create_cg_font (hb_face_t *face)
|
||||
{
|
||||
CGFontRef cg_font = nullptr;
|
||||
if (face->destroy == _hb_cg_font_release)
|
||||
cg_font = CGFontRetain ((CGFontRef) face->user_data);
|
||||
else
|
||||
{
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
cg_font = create_cg_font (blob, face->index);
|
||||
hb_blob_destroy (blob);
|
||||
}
|
||||
return cg_font;
|
||||
}
|
||||
|
||||
CTFontRef
|
||||
create_ct_font (CGFontRef cg_font, CGFloat font_size)
|
||||
{
|
||||
CTFontRef ct_font = nullptr;
|
||||
|
||||
/* CoreText does not enable trak table usage / tracking when creating a CTFont
|
||||
* using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
|
||||
* to be through the CTFontCreateUIFontForLanguage call. */
|
||||
CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
|
||||
if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
|
||||
CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
|
||||
{
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
# define kCTFontUIFontSystem kCTFontSystemFontType
|
||||
# define kCTFontUIFontEmphasizedSystem kCTFontEmphasizedSystemFontType
|
||||
#endif
|
||||
CTFontUIFontType font_type = kCTFontUIFontSystem;
|
||||
if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
|
||||
font_type = kCTFontUIFontEmphasizedSystem;
|
||||
|
||||
ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr);
|
||||
CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
|
||||
if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
|
||||
{
|
||||
CFRelease(ct_font);
|
||||
ct_font = nullptr;
|
||||
}
|
||||
CFRelease (ct_result_name);
|
||||
}
|
||||
CFRelease (cg_postscript_name);
|
||||
|
||||
if (!ct_font)
|
||||
ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr);
|
||||
|
||||
if (unlikely (!ct_font)) {
|
||||
DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
|
||||
* bug indicate that the cascade list reconfiguration occasionally causes
|
||||
* crashes in CoreText on OS X 10.9, thus let's skip this step on older
|
||||
* operating system versions. Except for the emoji font, where _not_
|
||||
* reconfiguring the cascade list causes CoreText crashes. For details, see
|
||||
* crbug.com/549610 */
|
||||
// 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) {
|
||||
#pragma GCC diagnostic pop
|
||||
CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
|
||||
bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
|
||||
CFRelease (fontName);
|
||||
if (!isEmojiFont)
|
||||
return ct_font;
|
||||
}
|
||||
|
||||
CFURLRef original_url = nullptr;
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
ATSFontRef atsFont;
|
||||
FSRef fsref;
|
||||
OSStatus status;
|
||||
atsFont = CTFontGetPlatformFont (ct_font, NULL);
|
||||
status = ATSFontGetFileReference (atsFont, &fsref);
|
||||
if (status == noErr)
|
||||
original_url = CFURLCreateFromFSRef (NULL, &fsref);
|
||||
#else
|
||||
original_url = (CFURLRef) CTFontCopyAttribute (ct_font, kCTFontURLAttribute);
|
||||
#endif
|
||||
|
||||
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
|
||||
* font fallback which we don't need anyway. */
|
||||
{
|
||||
CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc ();
|
||||
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc);
|
||||
CFRelease (last_resort_font_desc);
|
||||
if (new_ct_font)
|
||||
{
|
||||
/* The CTFontCreateCopyWithAttributes call fails to stay on the same font
|
||||
* when reconfiguring the cascade list and may switch to a different font
|
||||
* when there are fonts that go by the same name, since the descriptor is
|
||||
* just name and size.
|
||||
*
|
||||
* Avoid reconfiguring the cascade lists if the new font is outside the
|
||||
* system locations that we cannot access from the sandboxed renderer
|
||||
* process in Blink. This can be detected by the new file URL location
|
||||
* that the newly found font points to. */
|
||||
CFURLRef new_url = nullptr;
|
||||
#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
|
||||
status = ATSFontGetFileReference (atsFont, &fsref);
|
||||
if (status == noErr)
|
||||
new_url = CFURLCreateFromFSRef (NULL, &fsref);
|
||||
#else
|
||||
new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute);
|
||||
#endif
|
||||
// Keep reconfigured font if URL cannot be retrieved (seems to be the case
|
||||
// on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606
|
||||
if (!original_url || !new_url || CFEqual (original_url, new_url)) {
|
||||
CFRelease (ct_font);
|
||||
ct_font = new_ct_font;
|
||||
} else {
|
||||
CFRelease (new_ct_font);
|
||||
DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed.");
|
||||
}
|
||||
if (new_url)
|
||||
CFRelease (new_url);
|
||||
}
|
||||
else
|
||||
DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
|
||||
}
|
||||
|
||||
if (original_url)
|
||||
CFRelease (original_url);
|
||||
return ct_font;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_create:
|
||||
* @cg_font: The CGFontRef to work upon
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* CGFontRef.
|
||||
*
|
||||
* Return value: (transfer full): The new face object
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font)
|
||||
{
|
||||
hb_face_t *face = hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||
hb_face_set_get_table_tags_func (face, _hb_cg_get_table_tags, cg_font, nullptr);
|
||||
return face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_create_from_file_or_fail:
|
||||
* @file_name: A font filename
|
||||
* @index: The index of the face within the file
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* font file and face index.
|
||||
*
|
||||
* This is similar in functionality to hb_face_create_from_file_or_fail(),
|
||||
* but uses the CoreText library for loading the font file.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* no face is found at the specified index or the file cannot be read.
|
||||
*
|
||||
* Since: 10.1.0
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_coretext_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index)
|
||||
{
|
||||
auto url = CFURLCreateFromFileSystemRepresentation (nullptr,
|
||||
(const UInt8 *) file_name,
|
||||
strlen (file_name),
|
||||
false);
|
||||
if (unlikely (!url))
|
||||
return nullptr;
|
||||
|
||||
auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromURL (url);
|
||||
if (unlikely (!ct_font_desc_array))
|
||||
{
|
||||
CFRelease (url);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned ttc_index = index & 0xFFFF;
|
||||
unsigned named_instance_index = index >> 16;
|
||||
|
||||
if (ttc_index != 0)
|
||||
{
|
||||
DEBUG_MSG (CORETEXT, nullptr, "TTC index %d not supported", ttc_index);
|
||||
return nullptr; // CoreText does not support TTCs
|
||||
}
|
||||
|
||||
auto cg_font = create_cg_font (ct_font_desc_array, named_instance_index);
|
||||
CFRelease (url);
|
||||
|
||||
hb_face_t *face = hb_coretext_face_create (cg_font);
|
||||
CFRelease (cg_font);
|
||||
if (unlikely (hb_face_is_immutable (face)))
|
||||
return nullptr;
|
||||
|
||||
hb_face_set_index (face, index);
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_create_from_blob_or_fail:
|
||||
* @blob: A blob containing the font data
|
||||
* @index: The index of the face within the blob
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* blob and face index.
|
||||
*
|
||||
* This is similar in functionality to hb_face_create_from_blob_or_fail(),
|
||||
* but uses the CoreText library for loading the font data.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* no face is found at the specified index or the blob cannot be read.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_coretext_face_create_from_blob_or_fail (hb_blob_t *blob,
|
||||
unsigned int index)
|
||||
{
|
||||
auto cg_font = create_cg_font (blob, index);
|
||||
if (unlikely (!cg_font))
|
||||
return nullptr;
|
||||
|
||||
hb_face_t *face = hb_coretext_face_create (cg_font);
|
||||
CFRelease (cg_font);
|
||||
if (unlikely (hb_face_is_immutable (face)))
|
||||
return nullptr;
|
||||
|
||||
hb_face_set_index (face, index);
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_get_cg_font:
|
||||
* @face: The #hb_face_t to work upon
|
||||
*
|
||||
* Fetches the CGFontRef associated with an #hb_face_t
|
||||
* face object
|
||||
*
|
||||
* Return value: the CGFontRef found
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
CGFontRef
|
||||
hb_coretext_face_get_cg_font (hb_face_t *face)
|
||||
{
|
||||
return (CGFontRef) (const void *) face->data.coretext;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_font_create:
|
||||
* @ct_font: The CTFontRef to work upon
|
||||
*
|
||||
* Creates an #hb_font_t font object from the specified
|
||||
* CTFontRef.
|
||||
*
|
||||
* The created font uses the default font functions implemented
|
||||
* natively by HarfBuzz. If you want to use the CoreText font functions
|
||||
* instead (rarely needed), you can do so by calling
|
||||
* by hb_coretext_font_set_funcs().
|
||||
*
|
||||
* Return value: (transfer full): The new font object
|
||||
*
|
||||
* Since: 1.7.2
|
||||
**/
|
||||
hb_font_t *
|
||||
hb_coretext_font_create (CTFontRef ct_font)
|
||||
{
|
||||
CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
|
||||
hb_face_t *face = hb_coretext_face_create (cg_font);
|
||||
CFRelease (cg_font);
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
|
||||
if (unlikely (hb_object_is_immutable (font)))
|
||||
return font;
|
||||
|
||||
hb_font_set_ptem (font, CTFontGetSize (ct_font));
|
||||
|
||||
/* Copy font variations */
|
||||
CFDictionaryRef variations = CTFontCopyVariation (ct_font);
|
||||
if (variations)
|
||||
{
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
hb_vector_t<CFTypeRef> keys;
|
||||
hb_vector_t<CFTypeRef> values;
|
||||
|
||||
CFIndex count = CFDictionaryGetCount (variations);
|
||||
if (unlikely (!vars.alloc_exact (count) || !keys.resize_exact (count) || !values.resize_exact (count)))
|
||||
goto done;
|
||||
|
||||
// Fetch them one by one and collect in a vector of our own.
|
||||
CFDictionaryGetKeysAndValues (variations, keys.arrayZ, values.arrayZ);
|
||||
for (CFIndex i = 0; i < count; i++)
|
||||
{
|
||||
int tag;
|
||||
float value;
|
||||
CFNumberGetValue ((CFNumberRef) keys.arrayZ[i], kCFNumberIntType, &tag);
|
||||
CFNumberGetValue ((CFNumberRef) values.arrayZ[i], kCFNumberFloatType, &value);
|
||||
|
||||
hb_variation_t var = {tag, value};
|
||||
vars.push (var);
|
||||
}
|
||||
hb_font_set_variations (font, vars.arrayZ, vars.length);
|
||||
|
||||
done:
|
||||
CFRelease (variations);
|
||||
}
|
||||
|
||||
/* Let there be dragons here... */
|
||||
font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
|
||||
|
||||
// https://github.com/harfbuzz/harfbuzz/pull/4895#issuecomment-2408471254
|
||||
//hb_coretext_font_set_funcs (font);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_font_get_ct_font:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Fetches the CTFontRef associated with the specified
|
||||
* #hb_font_t font object.
|
||||
*
|
||||
* Return value: the CTFontRef found
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
CTFontRef
|
||||
hb_coretext_font_get_ct_font (hb_font_t *font)
|
||||
{
|
||||
return (CTFontRef) (const void *) font->data.coretext;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
4
src/3rdparty/harfbuzz-ng/src/hb-coretext.h
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-coretext.h
vendored
@ -84,6 +84,10 @@ HB_EXTERN hb_face_t *
|
||||
hb_coretext_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_coretext_face_create_from_blob_or_fail (hb_blob_t *blob,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_font_t *
|
||||
hb_coretext_font_create (CTFontRef ct_font);
|
||||
|
||||
|
53
src/3rdparty/harfbuzz-ng/src/hb-coretext.hh
vendored
Normal file
53
src/3rdparty/harfbuzz-ng/src/hb-coretext.hh
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright © 2012,2013 Mozilla Foundation.
|
||||
* Copyright © 2012,2013 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Mozilla Author(s): Jonathan Kew
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HB_CORETEXT_HH
|
||||
#define HB_CORETEXT_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-coretext.h"
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
|
||||
|
||||
HB_INTERNAL CGFontRef
|
||||
create_cg_font (CFArrayRef ct_font_desc_array, unsigned int index);
|
||||
|
||||
HB_INTERNAL CGFontRef
|
||||
create_cg_font (hb_blob_t *blob, unsigned int index);
|
||||
|
||||
HB_INTERNAL CGFontRef
|
||||
create_cg_font (hb_face_t *face);
|
||||
|
||||
HB_INTERNAL CTFontRef
|
||||
create_ct_font (CGFontRef cg_font, CGFloat font_size);
|
||||
|
||||
|
||||
#endif /* HB_CORETEXT_HH */
|
6
src/3rdparty/harfbuzz-ng/src/hb-debug.hh
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-debug.hh
vendored
@ -49,15 +49,15 @@ struct hb_options_t
|
||||
};
|
||||
|
||||
union hb_options_union_t {
|
||||
int i;
|
||||
unsigned i;
|
||||
hb_options_t opts;
|
||||
};
|
||||
static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
|
||||
static_assert ((sizeof (hb_atomic_t<unsigned>) >= sizeof (hb_options_union_t)), "");
|
||||
|
||||
HB_INTERNAL void
|
||||
_hb_options_init ();
|
||||
|
||||
extern HB_INTERNAL hb_atomic_int_t _hb_options;
|
||||
extern HB_INTERNAL hb_atomic_t<unsigned> _hb_options;
|
||||
|
||||
static inline hb_options_t
|
||||
hb_options ()
|
||||
|
388
src/3rdparty/harfbuzz-ng/src/hb-directwrite-font.cc
vendored
Normal file
388
src/3rdparty/harfbuzz-ng/src/hb-directwrite-font.cc
vendored
Normal file
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright © 2025 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.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
#include <d2d1.h>
|
||||
|
||||
#include "hb-draw.hh"
|
||||
#include "hb-font.hh"
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
#define MAX_GLYPHS 256u
|
||||
|
||||
static unsigned int
|
||||
hb_directwrite_get_nominal_glyphs (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_unicode,
|
||||
unsigned int unicode_stride,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
for (unsigned i = 0; i < count;)
|
||||
{
|
||||
UINT32 unicodes[MAX_GLYPHS];
|
||||
UINT16 gids[MAX_GLYPHS];
|
||||
|
||||
unsigned n = hb_min (MAX_GLYPHS, count - i);
|
||||
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
unicodes[j] = *first_unicode;
|
||||
first_unicode = &StructAtOffset<const hb_codepoint_t> (first_unicode, unicode_stride);
|
||||
}
|
||||
|
||||
if (!SUCCEEDED (dw_face->GetGlyphIndices (unicodes, n, gids)))
|
||||
return i;
|
||||
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
if (!gids[j])
|
||||
return i + j;
|
||||
*first_glyph = gids[j];
|
||||
first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
}
|
||||
|
||||
i += n;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_directwrite_get_font_h_extents (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
DWRITE_FONT_METRICS dw_metrics;
|
||||
dw_face->GetMetrics (&dw_metrics);
|
||||
|
||||
metrics->ascender = font->em_scale_y (dw_metrics.ascent);
|
||||
metrics->descender = -font->em_scale_y (dw_metrics.descent);
|
||||
metrics->line_gap = font->em_scale_y (dw_metrics.lineGap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_directwrite_get_glyph_h_advances (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
IDWriteFontFace1 *dw_face1 = nullptr;
|
||||
dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1);
|
||||
assert (dw_face1);
|
||||
|
||||
for (unsigned i = 0; i < count;)
|
||||
{
|
||||
UINT16 gids[MAX_GLYPHS];
|
||||
INT32 advances[MAX_GLYPHS];
|
||||
|
||||
unsigned n = hb_min (MAX_GLYPHS, count - i);
|
||||
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
gids[j] = *first_glyph;
|
||||
advances[j] = 0;
|
||||
first_glyph = &StructAtOffset<const hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
}
|
||||
dw_face1->GetDesignGlyphAdvances (n, gids, advances, false);
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
*first_advance = font->em_scale_x (advances[j]);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
i += n;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
||||
static void
|
||||
hb_directwrite_get_glyph_v_advances (hb_font_t* font,
|
||||
void* font_data HB_UNUSED,
|
||||
unsigned count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
IDWriteFontFace1 *dw_face1 = nullptr;
|
||||
dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1);
|
||||
assert (dw_face1);
|
||||
|
||||
for (unsigned i = 0; i < count;)
|
||||
{
|
||||
UINT16 gids[MAX_GLYPHS];
|
||||
INT32 advances[MAX_GLYPHS];
|
||||
|
||||
unsigned n = hb_min (MAX_GLYPHS, count - i);
|
||||
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
gids[j] = *first_glyph;
|
||||
advances[j] = 0;
|
||||
first_glyph = &StructAtOffset<const hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
}
|
||||
dw_face1->GetDesignGlyphAdvances (n, gids, advances, true);
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
*first_advance = -font->em_scale_y (advances[j]);
|
||||
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
i += n;
|
||||
}
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_directwrite_get_glyph_v_origin (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
UINT16 gid = glyph;
|
||||
DWRITE_GLYPH_METRICS metrics;
|
||||
|
||||
if (FAILED (dw_face->GetDesignGlyphMetrics (&gid, 1, &metrics)))
|
||||
return false;
|
||||
|
||||
*x = font->em_scale_x (metrics.advanceWidth / 2);
|
||||
*y = font->em_scale_y (metrics.verticalOriginY); // Untested
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_bool_t
|
||||
hb_directwrite_get_glyph_extents (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
UINT16 gid = glyph;
|
||||
DWRITE_GLYPH_METRICS metrics;
|
||||
|
||||
if (FAILED (dw_face->GetDesignGlyphMetrics (&gid, 1, &metrics)))
|
||||
return false;
|
||||
|
||||
extents->x_bearing = font->em_scale_x (metrics.leftSideBearing);
|
||||
extents->y_bearing = font->em_scale_y (metrics.verticalOriginY - metrics.topSideBearing);
|
||||
extents->width = font->em_scale_x (metrics.advanceWidth - metrics.rightSideBearing) - extents->x_bearing;
|
||||
extents->height = font->em_scale_y (metrics.verticalOriginY - metrics.advanceHeight + metrics.bottomSideBearing) - extents->y_bearing; // Magic
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
|
||||
class GeometrySink : public IDWriteGeometrySink
|
||||
{
|
||||
hb_font_t *font;
|
||||
hb_draw_session_t drawing;
|
||||
|
||||
public:
|
||||
GeometrySink(hb_font_t *font,
|
||||
hb_draw_funcs_t *draw_funcs,
|
||||
void *draw_data)
|
||||
: font (font), drawing ({draw_funcs, draw_data, font->slant}) {}
|
||||
|
||||
virtual ~GeometrySink() {}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Close() override { return S_OK; }
|
||||
void STDMETHODCALLTYPE SetFillMode(D2D1_FILL_MODE) override {}
|
||||
void STDMETHODCALLTYPE SetSegmentFlags(D2D1_PATH_SEGMENT) override {}
|
||||
|
||||
IFACEMETHOD(QueryInterface)(REFIID, void **) override { return E_NOINTERFACE; }
|
||||
IFACEMETHOD_(ULONG, AddRef)() override { return 1; }
|
||||
IFACEMETHOD_(ULONG, Release)() override { return 1; }
|
||||
|
||||
void STDMETHODCALLTYPE BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN) override
|
||||
{
|
||||
drawing.move_to (font->em_scalef_x (startPoint.x), -font->em_scalef_y (startPoint.y));
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) override
|
||||
{
|
||||
for (unsigned i = 0; i < beziersCount; ++i)
|
||||
drawing.cubic_to (font->em_scalef_x (beziers[i].point1.x), -font->em_scalef_y (beziers[i].point1.y),
|
||||
font->em_scalef_x (beziers[i].point2.x), -font->em_scalef_y (beziers[i].point2.y),
|
||||
font->em_scalef_x (beziers[i].point3.x), -font->em_scalef_y (beziers[i].point3.y));
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE AddLines(const D2D1_POINT_2F *points, UINT pointsCount) override
|
||||
{
|
||||
for (unsigned i = 0; i < pointsCount; ++i)
|
||||
drawing.line_to (font->em_scalef_x (points[i].x), -font->em_scalef_y (points[i].y));
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE EndFigure(D2D1_FIGURE_END) override
|
||||
{
|
||||
drawing.close_path ();
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
hb_directwrite_draw_glyph (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
|
||||
GeometrySink sink (font, draw_funcs, draw_data);
|
||||
UINT16 gid = static_cast<UINT16>(glyph);
|
||||
unsigned upem = font->face->get_upem();
|
||||
|
||||
(void) dw_face->GetGlyphRunOutline (upem,
|
||||
&gid, nullptr, nullptr,
|
||||
1,
|
||||
false, false,
|
||||
&sink);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline void free_static_directwrite_funcs ();
|
||||
|
||||
static struct hb_directwrite_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_directwrite_font_funcs_lazy_loader_t>
|
||||
{
|
||||
static hb_font_funcs_t *create ()
|
||||
{
|
||||
hb_font_funcs_t *funcs = hb_font_funcs_create ();
|
||||
|
||||
hb_font_funcs_set_nominal_glyphs_func (funcs, hb_directwrite_get_nominal_glyphs, nullptr, nullptr);
|
||||
//hb_font_funcs_set_variation_glyph_func (funcs, hb_directwrite_get_variation_glyph, nullptr, nullptr);
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_directwrite_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_directwrite_get_glyph_h_advances, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_directwrite_get_glyph_v_advances, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_directwrite_get_glyph_v_origin, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
hb_font_funcs_set_draw_glyph_func (funcs, hb_directwrite_draw_glyph, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_directwrite_get_glyph_extents, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
|
||||
//hb_font_funcs_set_glyph_name_func (funcs, hb_directwrite_get_glyph_name, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_from_name_func (funcs, hb_directwrite_get_glyph_from_name, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
hb_atexit (free_static_directwrite_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_directwrite_funcs;
|
||||
|
||||
static inline
|
||||
void free_static_directwrite_funcs ()
|
||||
{
|
||||
static_directwrite_funcs.free_instance ();
|
||||
}
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_directwrite_get_font_funcs ()
|
||||
{
|
||||
return static_directwrite_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_directwrite_font_set_funcs:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Configures the font-functions structure of the specified
|
||||
* #hb_font_t font object to use DirectWrite font functions.
|
||||
*
|
||||
* In particular, you can use this function to configure an
|
||||
* existing #hb_face_t face object for use with DirectWrite font
|
||||
* functions even if that #hb_face_t face object was initially
|
||||
* created with hb_face_create(), and therefore was not
|
||||
* initially configured to use DirectWrite font functions.
|
||||
*
|
||||
* <note>Note: Internally, this function creates a DirectWrite font.
|
||||
* </note>
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
void
|
||||
hb_directwrite_font_set_funcs (hb_font_t *font)
|
||||
{
|
||||
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
if (unlikely (!dw_face))
|
||||
{
|
||||
hb_font_set_funcs (font,
|
||||
hb_font_funcs_get_empty (),
|
||||
nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
dw_face->AddRef ();
|
||||
hb_font_set_funcs (font,
|
||||
_hb_directwrite_get_font_funcs (),
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
#undef MAX_GLYPHS
|
||||
|
||||
#endif
|
656
src/3rdparty/harfbuzz-ng/src/hb-directwrite-shape.cc
vendored
Normal file
656
src/3rdparty/harfbuzz-ng/src/hb-directwrite-shape.cc
vendored
Normal file
@ -0,0 +1,656 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include "hb-directwrite.hh"
|
||||
|
||||
#include "hb-ms-feature-ranges.hh"
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
|
||||
hb_directwrite_face_data_t *
|
||||
_hb_directwrite_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
|
||||
hb_directwrite_face_data_t *data = (hb_directwrite_face_data_t *) dw_face_create (blob, face->index);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
|
||||
{
|
||||
((IDWriteFontFace *) data)->Release ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper font data
|
||||
*/
|
||||
|
||||
struct hb_directwrite_font_data_t {};
|
||||
|
||||
hb_directwrite_font_data_t *
|
||||
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
|
||||
{
|
||||
IDWriteFontFace *fontFace = (IDWriteFontFace *) (const void *) font->face->data.directwrite;
|
||||
|
||||
/*
|
||||
* Set up variations.
|
||||
*/
|
||||
IDWriteFontFace5 *fontFaceVariations = nullptr;
|
||||
{
|
||||
IDWriteFontFace5 *fontFace5;
|
||||
if (SUCCEEDED (fontFace->QueryInterface (__uuidof (IDWriteFontFace5), (void **) &fontFace5)))
|
||||
{
|
||||
IDWriteFontResource *fontResource;
|
||||
if (SUCCEEDED (fontFace5->GetFontResource (&fontResource)))
|
||||
{
|
||||
hb_vector_t<DWRITE_FONT_AXIS_VALUE> axis_values;
|
||||
if (likely (axis_values.resize_exact (font->num_coords)))
|
||||
{
|
||||
for (unsigned int i = 0; i < font->num_coords; i++)
|
||||
{
|
||||
hb_ot_var_axis_info_t info;
|
||||
unsigned int c = 1;
|
||||
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
|
||||
axis_values[i].axisTag = (DWRITE_FONT_AXIS_TAG) hb_uint32_swap (info.tag);
|
||||
axis_values[i].value = i < font->num_coords ?
|
||||
hb_clamp (font->design_coords[i], info.min_value, info.max_value) :
|
||||
info.default_value;
|
||||
}
|
||||
|
||||
fontResource->CreateFontFace (DWRITE_FONT_SIMULATIONS::DWRITE_FONT_SIMULATIONS_NONE,
|
||||
axis_values.arrayZ, axis_values.length, &fontFaceVariations);
|
||||
}
|
||||
fontResource->Release ();
|
||||
}
|
||||
fontFace5->Release ();
|
||||
}
|
||||
}
|
||||
|
||||
return (hb_directwrite_font_data_t *) fontFaceVariations;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
|
||||
{
|
||||
((IDWriteFontFace *) data)->Release ();
|
||||
}
|
||||
|
||||
|
||||
// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project
|
||||
// but now is relicensed to MIT for HarfBuzz use
|
||||
class TextAnalysis : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink
|
||||
{
|
||||
private:
|
||||
hb_reference_count_t mRefCount;
|
||||
public:
|
||||
IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
|
||||
{ return S_OK; }
|
||||
IFACEMETHOD_ (ULONG, AddRef) ()
|
||||
{
|
||||
return mRefCount.inc () + 1;
|
||||
}
|
||||
IFACEMETHOD_ (ULONG, Release) ()
|
||||
{
|
||||
signed refCount = mRefCount.dec () - 1;
|
||||
assert (refCount >= 0);
|
||||
if (refCount)
|
||||
return refCount;
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A single contiguous run of characters containing the same analysis
|
||||
// results.
|
||||
struct Run
|
||||
{
|
||||
uint32_t mTextStart; // starting text position of this run
|
||||
uint32_t mTextLength; // number of contiguous code units covered
|
||||
uint32_t mGlyphStart; // starting glyph in the glyphs array
|
||||
uint32_t mGlyphCount; // number of glyphs associated with this run
|
||||
// text
|
||||
DWRITE_SCRIPT_ANALYSIS mScript;
|
||||
uint8_t mBidiLevel;
|
||||
bool mIsSideways;
|
||||
|
||||
bool ContainsTextPosition (uint32_t aTextPosition) const
|
||||
{
|
||||
return aTextPosition >= mTextStart &&
|
||||
aTextPosition < mTextStart + mTextLength;
|
||||
}
|
||||
|
||||
Run *nextRun;
|
||||
};
|
||||
|
||||
public:
|
||||
TextAnalysis (const wchar_t* text, uint32_t textLength,
|
||||
const wchar_t* localeName, DWRITE_READING_DIRECTION readingDirection)
|
||||
: mTextLength (textLength), mText (text), mLocaleName (localeName),
|
||||
mReadingDirection (readingDirection), mCurrentRun (nullptr)
|
||||
{
|
||||
mRefCount.init ();
|
||||
}
|
||||
virtual ~TextAnalysis ()
|
||||
{
|
||||
// delete runs, except mRunHead which is part of the TextAnalysis object
|
||||
for (Run *run = mRunHead.nextRun; run;)
|
||||
{
|
||||
Run *origRun = run;
|
||||
run = run->nextRun;
|
||||
delete origRun;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
GenerateResults (IDWriteTextAnalyzer* textAnalyzer, Run **runHead)
|
||||
{
|
||||
// Analyzes the text using the script analyzer and returns
|
||||
// the result as a series of runs.
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// Initially start out with one result that covers the entire range.
|
||||
// This result will be subdivided by the analysis processes.
|
||||
mRunHead.mTextStart = 0;
|
||||
mRunHead.mTextLength = mTextLength;
|
||||
mRunHead.mBidiLevel =
|
||||
(mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
|
||||
mRunHead.nextRun = nullptr;
|
||||
mCurrentRun = &mRunHead;
|
||||
|
||||
// Call each of the analyzers in sequence, recording their results.
|
||||
if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this)))
|
||||
*runHead = &mRunHead;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// IDWriteTextAnalysisSource implementation
|
||||
|
||||
IFACEMETHODIMP
|
||||
GetTextAtPosition (uint32_t textPosition,
|
||||
OUT wchar_t const** textString,
|
||||
OUT uint32_t* textLength)
|
||||
{
|
||||
if (textPosition >= mTextLength)
|
||||
{
|
||||
// No text at this position, valid query though.
|
||||
*textString = nullptr;
|
||||
*textLength = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*textString = mText + textPosition;
|
||||
*textLength = mTextLength - textPosition;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP
|
||||
GetTextBeforePosition (uint32_t textPosition,
|
||||
OUT wchar_t const** textString,
|
||||
OUT uint32_t* textLength)
|
||||
{
|
||||
if (textPosition == 0 || textPosition > mTextLength)
|
||||
{
|
||||
// Either there is no text before here (== 0), or this
|
||||
// is an invalid position. The query is considered valid though.
|
||||
*textString = nullptr;
|
||||
*textLength = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*textString = mText;
|
||||
*textLength = textPosition;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_ (DWRITE_READING_DIRECTION)
|
||||
GetParagraphReadingDirection () { return mReadingDirection; }
|
||||
|
||||
IFACEMETHODIMP GetLocaleName (uint32_t textPosition, uint32_t* textLength,
|
||||
wchar_t const** localeName)
|
||||
{ return S_OK; }
|
||||
|
||||
IFACEMETHODIMP
|
||||
GetNumberSubstitution (uint32_t textPosition,
|
||||
OUT uint32_t* textLength,
|
||||
OUT IDWriteNumberSubstitution** numberSubstitution)
|
||||
{
|
||||
// We do not support number substitution.
|
||||
*numberSubstitution = nullptr;
|
||||
*textLength = mTextLength - textPosition;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IDWriteTextAnalysisSink implementation
|
||||
|
||||
IFACEMETHODIMP
|
||||
SetScriptAnalysis (uint32_t textPosition, uint32_t textLength,
|
||||
DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
|
||||
{
|
||||
SetCurrentRun (textPosition);
|
||||
SplitCurrentRun (textPosition);
|
||||
while (textLength > 0)
|
||||
{
|
||||
Run *run = FetchNextRun (&textLength);
|
||||
run->mScript = *scriptAnalysis;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP
|
||||
SetLineBreakpoints (uint32_t textPosition,
|
||||
uint32_t textLength,
|
||||
const DWRITE_LINE_BREAKPOINT* lineBreakpoints)
|
||||
{ return S_OK; }
|
||||
|
||||
IFACEMETHODIMP SetBidiLevel (uint32_t textPosition, uint32_t textLength,
|
||||
uint8_t explicitLevel, uint8_t resolvedLevel)
|
||||
{ return S_OK; }
|
||||
|
||||
IFACEMETHODIMP
|
||||
SetNumberSubstitution (uint32_t textPosition, uint32_t textLength,
|
||||
IDWriteNumberSubstitution* numberSubstitution)
|
||||
{ return S_OK; }
|
||||
|
||||
protected:
|
||||
Run *FetchNextRun (IN OUT uint32_t* textLength)
|
||||
{
|
||||
// Used by the sink setters, this returns a reference to the next run.
|
||||
// Position and length are adjusted to now point after the current run
|
||||
// being returned.
|
||||
|
||||
Run *origRun = mCurrentRun;
|
||||
// Split the tail if needed (the length remaining is less than the
|
||||
// current run's size).
|
||||
if (*textLength < mCurrentRun->mTextLength)
|
||||
SplitCurrentRun (mCurrentRun->mTextStart + *textLength);
|
||||
else
|
||||
// Just advance the current run.
|
||||
mCurrentRun = mCurrentRun->nextRun;
|
||||
*textLength -= origRun->mTextLength;
|
||||
|
||||
// Return a reference to the run that was just current.
|
||||
return origRun;
|
||||
}
|
||||
|
||||
void SetCurrentRun (uint32_t textPosition)
|
||||
{
|
||||
// Move the current run to the given position.
|
||||
// Since the analyzers generally return results in a forward manner,
|
||||
// this will usually just return early. If not, find the
|
||||
// corresponding run for the text position.
|
||||
|
||||
if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition))
|
||||
return;
|
||||
|
||||
for (Run *run = &mRunHead; run; run = run->nextRun)
|
||||
if (run->ContainsTextPosition (textPosition))
|
||||
{
|
||||
mCurrentRun = run;
|
||||
return;
|
||||
}
|
||||
assert (0); // We should always be able to find the text position in one of our runs
|
||||
}
|
||||
|
||||
void SplitCurrentRun (uint32_t splitPosition)
|
||||
{
|
||||
if (!mCurrentRun)
|
||||
{
|
||||
assert (0); // SplitCurrentRun called without current run
|
||||
// Shouldn't be calling this when no current run is set!
|
||||
return;
|
||||
}
|
||||
// Split the current run.
|
||||
if (splitPosition <= mCurrentRun->mTextStart)
|
||||
{
|
||||
// No need to split, already the start of a run
|
||||
// or before it. Usually the first.
|
||||
return;
|
||||
}
|
||||
Run *newRun = new Run;
|
||||
|
||||
*newRun = *mCurrentRun;
|
||||
|
||||
// Insert the new run in our linked list.
|
||||
newRun->nextRun = mCurrentRun->nextRun;
|
||||
mCurrentRun->nextRun = newRun;
|
||||
|
||||
// Adjust runs' text positions and lengths.
|
||||
uint32_t splitPoint = splitPosition - mCurrentRun->mTextStart;
|
||||
newRun->mTextStart += splitPoint;
|
||||
newRun->mTextLength -= splitPoint;
|
||||
mCurrentRun->mTextLength = splitPoint;
|
||||
mCurrentRun = newRun;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Input
|
||||
// (weak references are fine here, since this class is a transient
|
||||
// stack-based helper that doesn't need to copy data)
|
||||
uint32_t mTextLength;
|
||||
const wchar_t* mText;
|
||||
const wchar_t* mLocaleName;
|
||||
DWRITE_READING_DIRECTION mReadingDirection;
|
||||
|
||||
// Current processing state.
|
||||
Run *mCurrentRun;
|
||||
|
||||
// Output is a list of runs starting here
|
||||
Run mRunHead;
|
||||
};
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
|
||||
hb_bool_t
|
||||
_hb_directwrite_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
{
|
||||
IDWriteFontFace *fontFace = (IDWriteFontFace *) (const void *) font->data.directwrite;
|
||||
auto *global = get_directwrite_global ();
|
||||
if (unlikely (!global))
|
||||
return false;
|
||||
IDWriteFactory *dwriteFactory = global->dwriteFactory;
|
||||
|
||||
IDWriteTextAnalyzer* analyzer;
|
||||
dwriteFactory->CreateTextAnalyzer (&analyzer);
|
||||
|
||||
unsigned int scratch_size;
|
||||
hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
|
||||
#define ALLOCATE_ARRAY(Type, name, len) \
|
||||
Type *name = (Type *) scratch; \
|
||||
do { \
|
||||
unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
|
||||
assert (_consumed <= scratch_size); \
|
||||
scratch += _consumed; \
|
||||
scratch_size -= _consumed; \
|
||||
} while (0)
|
||||
|
||||
#define utf16_index() var1.u32
|
||||
|
||||
ALLOCATE_ARRAY (wchar_t, textString, buffer->len * 2);
|
||||
|
||||
unsigned int chars_len = 0;
|
||||
for (unsigned int i = 0; i < buffer->len; i++)
|
||||
{
|
||||
hb_codepoint_t c = buffer->info[i].codepoint;
|
||||
buffer->info[i].utf16_index () = chars_len;
|
||||
if (likely (c <= 0xFFFFu))
|
||||
textString[chars_len++] = c;
|
||||
else if (unlikely (c > 0x10FFFFu))
|
||||
textString[chars_len++] = 0xFFFDu;
|
||||
else
|
||||
{
|
||||
textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
|
||||
textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
|
||||
}
|
||||
}
|
||||
|
||||
ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
|
||||
/* Need log_clusters to assign features. */
|
||||
chars_len = 0;
|
||||
for (unsigned int i = 0; i < buffer->len; i++)
|
||||
{
|
||||
hb_codepoint_t c = buffer->info[i].codepoint;
|
||||
unsigned int cluster = buffer->info[i].cluster;
|
||||
log_clusters[chars_len++] = cluster;
|
||||
if (hb_in_range (c, 0x10000u, 0x10FFFFu))
|
||||
log_clusters[chars_len++] = cluster; /* Surrogates. */
|
||||
}
|
||||
|
||||
DWRITE_READING_DIRECTION readingDirection;
|
||||
readingDirection = buffer->props.direction ?
|
||||
DWRITE_READING_DIRECTION_RIGHT_TO_LEFT :
|
||||
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
|
||||
|
||||
/*
|
||||
* There's an internal 16-bit limit on some things inside the analyzer,
|
||||
* but we never attempt to shape a word longer than 64K characters
|
||||
* in a single gfxShapedWord, so we cannot exceed that limit.
|
||||
*/
|
||||
uint32_t textLength = chars_len;
|
||||
|
||||
TextAnalysis analysis (textString, textLength, nullptr, readingDirection);
|
||||
TextAnalysis::Run *runHead;
|
||||
HRESULT hr;
|
||||
hr = analysis.GenerateResults (analyzer, &runHead);
|
||||
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||
return false; \
|
||||
} HB_STMT_END
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to generate results.");
|
||||
|
||||
uint32_t maxGlyphCount = 3 * textLength / 2 + 16;
|
||||
uint32_t glyphCount;
|
||||
bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
|
||||
const wchar_t localeName[20] = {0};
|
||||
if (buffer->props.language)
|
||||
mbstowcs ((wchar_t*) localeName,
|
||||
hb_language_to_string (buffer->props.language), 20);
|
||||
|
||||
/*
|
||||
* Set up features.
|
||||
*/
|
||||
static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), "");
|
||||
static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), "");
|
||||
hb_vector_t<hb_ms_features_t *> range_features;
|
||||
hb_vector_t<uint32_t> range_char_counts;
|
||||
|
||||
// https://github.com/harfbuzz/harfbuzz/pull/5114
|
||||
// The data allocated by these two vectors are used by the above two, so they
|
||||
// should remain alive as long as the above two are.
|
||||
hb_vector_t<hb_ms_feature_t> feature_records;
|
||||
hb_vector_t<hb_ms_range_record_t> range_records;
|
||||
if (num_features)
|
||||
{
|
||||
if (hb_ms_setup_features (features, num_features, feature_records, range_records))
|
||||
{
|
||||
hb_ms_make_feature_ranges (feature_records,
|
||||
range_records,
|
||||
0,
|
||||
chars_len,
|
||||
log_clusters,
|
||||
range_features,
|
||||
range_char_counts);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t* clusterMap;
|
||||
clusterMap = new uint16_t[textLength];
|
||||
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
|
||||
textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength];
|
||||
|
||||
retry_getglyphs:
|
||||
uint16_t* glyphIndices = new uint16_t[maxGlyphCount];
|
||||
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
|
||||
glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
|
||||
|
||||
hr = analyzer->GetGlyphs (textString,
|
||||
chars_len,
|
||||
fontFace,
|
||||
false,
|
||||
isRightToLeft,
|
||||
&runHead->mScript,
|
||||
localeName,
|
||||
nullptr,
|
||||
(const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
|
||||
range_char_counts.arrayZ,
|
||||
range_features.length,
|
||||
maxGlyphCount,
|
||||
clusterMap,
|
||||
textProperties,
|
||||
glyphIndices,
|
||||
glyphProperties,
|
||||
&glyphCount);
|
||||
|
||||
if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
|
||||
{
|
||||
delete [] glyphIndices;
|
||||
delete [] glyphProperties;
|
||||
|
||||
maxGlyphCount *= 2;
|
||||
|
||||
goto retry_getglyphs;
|
||||
}
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to get glyphs.");
|
||||
|
||||
float* glyphAdvances = new float[maxGlyphCount];
|
||||
DWRITE_GLYPH_OFFSET* glyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount];
|
||||
|
||||
/* The -2 in the following is to compensate for possible
|
||||
* alignment needed after the WORD array. sizeof (WORD) == 2. */
|
||||
unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
|
||||
/ (sizeof (WORD) +
|
||||
sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES) +
|
||||
sizeof (int) +
|
||||
sizeof (DWRITE_GLYPH_OFFSET) +
|
||||
sizeof (uint32_t));
|
||||
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
|
||||
|
||||
#undef ALLOCATE_ARRAY
|
||||
|
||||
unsigned fontEmSize = font->face->get_upem ();
|
||||
|
||||
float x_mult = font->x_multf;
|
||||
float y_mult = font->y_multf;
|
||||
|
||||
hr = analyzer->GetGlyphPlacements (textString,
|
||||
clusterMap,
|
||||
textProperties,
|
||||
chars_len,
|
||||
glyphIndices,
|
||||
glyphProperties,
|
||||
glyphCount,
|
||||
fontFace,
|
||||
fontEmSize,
|
||||
false,
|
||||
isRightToLeft,
|
||||
&runHead->mScript,
|
||||
localeName,
|
||||
(const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
|
||||
range_char_counts.arrayZ,
|
||||
range_features.length,
|
||||
glyphAdvances,
|
||||
glyphOffsets);
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to get glyph placements.");
|
||||
|
||||
/* Ok, we've got everything we need, now compose output buffer,
|
||||
* very, *very*, carefully! */
|
||||
|
||||
/* Calculate visual-clusters. That's what we ship. */
|
||||
for (unsigned int i = 0; i < glyphCount; i++)
|
||||
vis_clusters[i] = (uint32_t) -1;
|
||||
for (unsigned int i = 0; i < buffer->len; i++)
|
||||
{
|
||||
uint32_t *p =
|
||||
&vis_clusters[log_clusters[buffer->info[i].utf16_index ()]];
|
||||
*p = hb_min (*p, buffer->info[i].cluster);
|
||||
}
|
||||
for (unsigned int i = 1; i < glyphCount; i++)
|
||||
if (vis_clusters[i] == (uint32_t) -1)
|
||||
vis_clusters[i] = vis_clusters[i - 1];
|
||||
|
||||
#undef utf16_index
|
||||
|
||||
if (unlikely (!buffer->ensure (glyphCount)))
|
||||
FAIL ("Buffer in error");
|
||||
|
||||
#undef FAIL
|
||||
|
||||
/* Set glyph infos */
|
||||
buffer->len = 0;
|
||||
for (unsigned int i = 0; i < glyphCount; i++)
|
||||
{
|
||||
hb_glyph_info_t *info = &buffer->info[buffer->len++];
|
||||
|
||||
info->codepoint = glyphIndices[i];
|
||||
info->cluster = vis_clusters[i];
|
||||
|
||||
/* The rest is crap. Let's store position info there for now. */
|
||||
info->mask = glyphAdvances[i];
|
||||
info->var1.i32 = glyphOffsets[i].advanceOffset;
|
||||
info->var2.i32 = glyphOffsets[i].ascenderOffset;
|
||||
}
|
||||
|
||||
/* Set glyph positions */
|
||||
buffer->clear_positions ();
|
||||
for (unsigned int i = 0; i < glyphCount; i++)
|
||||
{
|
||||
hb_glyph_info_t *info = &buffer->info[i];
|
||||
hb_glyph_position_t *pos = &buffer->pos[i];
|
||||
|
||||
/* TODO vertical */
|
||||
pos->x_advance = round (x_mult * (int32_t) info->mask);
|
||||
pos->x_offset = round (x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32));
|
||||
pos->y_offset = round (y_mult * info->var2.i32);
|
||||
}
|
||||
|
||||
if (isRightToLeft) hb_buffer_reverse (buffer);
|
||||
|
||||
buffer->clear_glyph_flags ();
|
||||
buffer->unsafe_to_break ();
|
||||
|
||||
delete [] clusterMap;
|
||||
delete [] glyphIndices;
|
||||
delete [] textProperties;
|
||||
delete [] glyphProperties;
|
||||
delete [] glyphAdvances;
|
||||
delete [] glyphOffsets;
|
||||
|
||||
/* Wow, done! */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
945
src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
vendored
945
src/3rdparty/harfbuzz-ng/src/hb-directwrite.cc
vendored
File diff suppressed because it is too large
Load Diff
23
src/3rdparty/harfbuzz-ng/src/hb-directwrite.h
vendored
23
src/3rdparty/harfbuzz-ng/src/hb-directwrite.h
vendored
@ -27,19 +27,32 @@
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include <dwrite_3.h>
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_directwrite_face_create (IDWriteFontFace *dw_face);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_directwrite_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_directwrite_face_create_from_blob_or_fail (hb_blob_t *blob,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN IDWriteFontFace *
|
||||
hb_directwrite_face_get_dw_font_face (hb_face_t *face);
|
||||
|
||||
HB_EXTERN hb_font_t *
|
||||
hb_directwrite_font_create (IDWriteFont *dw_font);
|
||||
hb_directwrite_font_create (IDWriteFontFace *dw_face);
|
||||
|
||||
HB_EXTERN IDWriteFont *
|
||||
hb_directwrite_font_get_dw_font (hb_font_t *font);
|
||||
HB_EXTERN IDWriteFontFace *
|
||||
hb_directwrite_font_get_dw_font_face (hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_directwrite_font_set_funcs (hb_font_t *font);
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
|
||||
@ -47,6 +60,10 @@ HB_DEPRECATED_FOR (hb_directwrite_face_get_dw_font_face)
|
||||
HB_EXTERN IDWriteFontFace *
|
||||
hb_directwrite_face_get_font_face (hb_face_t *face);
|
||||
|
||||
HB_DEPRECATED
|
||||
HB_EXTERN IDWriteFont *
|
||||
hb_directwrite_font_get_dw_font (hb_font_t *font);
|
||||
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
243
src/3rdparty/harfbuzz-ng/src/hb-directwrite.hh
vendored
Normal file
243
src/3rdparty/harfbuzz-ng/src/hb-directwrite.hh
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HB_DIRECTWRITE_HH
|
||||
#define HB_DIRECTWRITE_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
#include "hb-mutex.hh"
|
||||
#include "hb-map.hh"
|
||||
|
||||
/*
|
||||
* DirectWrite font stream helpers
|
||||
*/
|
||||
|
||||
// Have a look at to NativeFontResourceDWrite.cpp in Mozilla
|
||||
|
||||
|
||||
/* Declare object creator for dynamic support of DWRITE */
|
||||
typedef HRESULT (WINAPI *t_DWriteCreateFactory)(
|
||||
DWRITE_FACTORY_TYPE factoryType,
|
||||
REFIID iid,
|
||||
IUnknown **factory
|
||||
);
|
||||
|
||||
class DWriteFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
private:
|
||||
hb_reference_count_t mRefCount;
|
||||
hb_mutex_t mutex;
|
||||
hb_hashmap_t<uint64_t, IDWriteFontFileStream *> mFontStreams;
|
||||
uint64_t mNextFontFileKey = 0;
|
||||
public:
|
||||
DWriteFontFileLoader ()
|
||||
{
|
||||
mRefCount.init ();
|
||||
}
|
||||
|
||||
uint64_t RegisterFontFileStream (IDWriteFontFileStream *fontFileStream)
|
||||
{
|
||||
fontFileStream->AddRef ();
|
||||
auto lock = hb_lock_t (mutex);
|
||||
mFontStreams.set (mNextFontFileKey, fontFileStream);
|
||||
return mNextFontFileKey++;
|
||||
}
|
||||
void UnregisterFontFileStream (uint64_t fontFileKey)
|
||||
{
|
||||
auto lock = hb_lock_t (mutex);
|
||||
IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey);
|
||||
if (stream)
|
||||
{
|
||||
mFontStreams.del (fontFileKey);
|
||||
stream->Release ();
|
||||
}
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
|
||||
{ return S_OK; }
|
||||
IFACEMETHOD_ (ULONG, AddRef) ()
|
||||
{
|
||||
return mRefCount.inc () + 1;
|
||||
}
|
||||
IFACEMETHOD_ (ULONG, Release) ()
|
||||
{
|
||||
signed refCount = mRefCount.dec () - 1;
|
||||
assert (refCount >= 0);
|
||||
if (refCount)
|
||||
return refCount;
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDWriteFontFileLoader methods
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
CreateStreamFromKey (void const* fontFileReferenceKey,
|
||||
uint32_t fontFileReferenceKeySize,
|
||||
OUT IDWriteFontFileStream** fontFileStream)
|
||||
{
|
||||
if (fontFileReferenceKeySize != sizeof (uint64_t))
|
||||
return E_INVALIDARG;
|
||||
uint64_t fontFileKey = * (uint64_t *) fontFileReferenceKey;
|
||||
IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey);
|
||||
if (!stream)
|
||||
return E_FAIL;
|
||||
stream->AddRef ();
|
||||
*fontFileStream = stream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual ~DWriteFontFileLoader()
|
||||
{
|
||||
for (auto v : mFontStreams.values ())
|
||||
v->Release ();
|
||||
}
|
||||
};
|
||||
|
||||
class DWriteFontFileStream : public IDWriteFontFileStream
|
||||
{
|
||||
private:
|
||||
hb_reference_count_t mRefCount;
|
||||
hb_blob_t *mBlob;
|
||||
uint8_t *mData;
|
||||
unsigned mSize;
|
||||
DWriteFontFileLoader *mLoader;
|
||||
public:
|
||||
uint64_t fontFileKey;
|
||||
public:
|
||||
DWriteFontFileStream (hb_blob_t *blob);
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject)
|
||||
{ return S_OK; }
|
||||
IFACEMETHOD_ (ULONG, AddRef) ()
|
||||
{
|
||||
return mRefCount.inc () + 1;
|
||||
}
|
||||
IFACEMETHOD_ (ULONG, Release) ()
|
||||
{
|
||||
signed refCount = mRefCount.dec () - 1;
|
||||
assert (refCount >= 0);
|
||||
if (refCount)
|
||||
return refCount;
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDWriteFontFileStream methods
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
ReadFileFragment (void const** fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
OUT void** fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > mSize) return E_FAIL;
|
||||
|
||||
// truncate the 64 bit fileOffset to size_t sized index into mData
|
||||
size_t index = static_cast<size_t> (fileOffset);
|
||||
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[index];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual void STDMETHODCALLTYPE
|
||||
ReleaseFileFragment (void* fragmentContext) {}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
GetFileSize (OUT UINT64* fileSize)
|
||||
{
|
||||
*fileSize = mSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; }
|
||||
|
||||
virtual ~DWriteFontFileStream();
|
||||
};
|
||||
|
||||
struct hb_directwrite_global_t
|
||||
{
|
||||
hb_directwrite_global_t ()
|
||||
{
|
||||
dwrite_dll = LoadLibraryW (L"DWrite.dll");
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
|
||||
t_DWriteCreateFactory p_DWriteCreateFactory = (t_DWriteCreateFactory)
|
||||
GetProcAddress (dwrite_dll, "DWriteCreateFactory");
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
if (unlikely (!p_DWriteCreateFactory))
|
||||
return;
|
||||
|
||||
HRESULT hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
|
||||
if (unlikely (hr != S_OK))
|
||||
return;
|
||||
|
||||
fontFileLoader = new DWriteFontFileLoader ();
|
||||
dwriteFactory->RegisterFontFileLoader (fontFileLoader);
|
||||
|
||||
success = true;
|
||||
}
|
||||
~hb_directwrite_global_t ()
|
||||
{
|
||||
if (fontFileLoader)
|
||||
fontFileLoader->Release ();
|
||||
if (dwriteFactory)
|
||||
dwriteFactory->Release ();
|
||||
if (dwrite_dll)
|
||||
FreeLibrary (dwrite_dll);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
HMODULE dwrite_dll;
|
||||
IDWriteFactory *dwriteFactory;
|
||||
DWriteFontFileLoader *fontFileLoader;
|
||||
};
|
||||
|
||||
|
||||
HB_INTERNAL hb_directwrite_global_t *
|
||||
get_directwrite_global ();
|
||||
|
||||
HB_INTERNAL IDWriteFontFace *
|
||||
dw_face_create (hb_blob_t *blob, unsigned index);
|
||||
|
||||
|
||||
#endif /* HB_DIRECTWRITE_HH */
|
12
src/3rdparty/harfbuzz-ng/src/hb-draw.h
vendored
12
src/3rdparty/harfbuzz-ng/src/hb-draw.h
vendored
@ -41,9 +41,16 @@ HB_BEGIN_DECLS
|
||||
* @path_start_y: Y component of the start of current path
|
||||
* @current_x: X component of current point
|
||||
* @current_y: Y component of current point
|
||||
* @slant_xy: (Since: 11.0.0): Slanting factor for synthetic oblique
|
||||
*
|
||||
* Current drawing state.
|
||||
*
|
||||
* The @slant_xy is a slanting factor for synthetic oblique. If the font's
|
||||
* oblique angle is not 0, this factor is used to slant the drawing. For
|
||||
* fonts with uniform x and y scales, this factor is calculated as
|
||||
* tan(oblique_angle). For fonts with non-uniform scales, this factor is
|
||||
* calculated as tan(oblique_angle) * x_scale / y_scale, or 0 if y_scale is 0.
|
||||
*
|
||||
* Since: 4.0.0
|
||||
**/
|
||||
typedef struct hb_draw_state_t {
|
||||
@ -55,6 +62,8 @@ typedef struct hb_draw_state_t {
|
||||
float current_x;
|
||||
float current_y;
|
||||
|
||||
float slant_xy;
|
||||
|
||||
/*< private >*/
|
||||
hb_var_num_t reserved1;
|
||||
hb_var_num_t reserved2;
|
||||
@ -62,7 +71,6 @@ typedef struct hb_draw_state_t {
|
||||
hb_var_num_t reserved4;
|
||||
hb_var_num_t reserved5;
|
||||
hb_var_num_t reserved6;
|
||||
hb_var_num_t reserved7;
|
||||
} hb_draw_state_t;
|
||||
|
||||
/**
|
||||
@ -70,7 +78,7 @@ typedef struct hb_draw_state_t {
|
||||
*
|
||||
* The default #hb_draw_state_t at the start of glyph drawing.
|
||||
*/
|
||||
#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
|
||||
#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
|
||||
|
||||
|
||||
/**
|
||||
|
76
src/3rdparty/harfbuzz-ng/src/hb-draw.hh
vendored
76
src/3rdparty/harfbuzz-ng/src/hb-draw.hh
vendored
@ -99,6 +99,10 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (st.path_open)) close_path (draw_data, st);
|
||||
|
||||
if (st.slant_xy)
|
||||
to_x += to_y * st.slant_xy;
|
||||
|
||||
st.current_x = to_x;
|
||||
st.current_y = to_y;
|
||||
}
|
||||
@ -109,7 +113,12 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (!st.path_open)) start_path (draw_data, st);
|
||||
|
||||
if (st.slant_xy)
|
||||
to_x += to_y * st.slant_xy;
|
||||
|
||||
emit_line_to (draw_data, st, to_x, to_y);
|
||||
|
||||
st.current_x = to_x;
|
||||
st.current_y = to_y;
|
||||
}
|
||||
@ -121,7 +130,15 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (!st.path_open)) start_path (draw_data, st);
|
||||
|
||||
if (st.slant_xy)
|
||||
{
|
||||
control_x += control_y * st.slant_xy;
|
||||
to_x += to_y * st.slant_xy;
|
||||
}
|
||||
|
||||
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
|
||||
|
||||
st.current_x = to_x;
|
||||
st.current_y = to_y;
|
||||
}
|
||||
@ -134,7 +151,16 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (!st.path_open)) start_path (draw_data, st);
|
||||
|
||||
if (st.slant_xy)
|
||||
{
|
||||
control1_x += control1_y * st.slant_xy;
|
||||
control2_x += control2_y * st.slant_xy;
|
||||
to_x += to_y * st.slant_xy;
|
||||
}
|
||||
|
||||
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
|
||||
|
||||
st.current_x = to_x;
|
||||
st.current_y = to_y;
|
||||
}
|
||||
@ -168,46 +194,32 @@ DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
|
||||
|
||||
struct hb_draw_session_t
|
||||
{
|
||||
hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
|
||||
: slant {slant_}, not_slanted {slant == 0.f},
|
||||
funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
|
||||
{}
|
||||
hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_xy = 0.f)
|
||||
: funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
|
||||
{ st.slant_xy = slant_xy; }
|
||||
|
||||
~hb_draw_session_t () { close_path (); }
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
void move_to (float to_x, float to_y)
|
||||
{
|
||||
if (likely (not_slanted))
|
||||
funcs->move_to (draw_data, st,
|
||||
to_x, to_y);
|
||||
else
|
||||
funcs->move_to (draw_data, st,
|
||||
to_x + to_y * slant, to_y);
|
||||
funcs->move_to (draw_data, st,
|
||||
to_x, to_y);
|
||||
}
|
||||
HB_ALWAYS_INLINE
|
||||
void line_to (float to_x, float to_y)
|
||||
{
|
||||
if (likely (not_slanted))
|
||||
funcs->line_to (draw_data, st,
|
||||
to_x, to_y);
|
||||
else
|
||||
funcs->line_to (draw_data, st,
|
||||
to_x + to_y * slant, to_y);
|
||||
funcs->line_to (draw_data, st,
|
||||
to_x, to_y);
|
||||
}
|
||||
void
|
||||
HB_ALWAYS_INLINE
|
||||
quadratic_to (float control_x, float control_y,
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (likely (not_slanted))
|
||||
funcs->quadratic_to (draw_data, st,
|
||||
control_x, control_y,
|
||||
to_x, to_y);
|
||||
else
|
||||
funcs->quadratic_to (draw_data, st,
|
||||
control_x + control_y * slant, control_y,
|
||||
to_x + to_y * slant, to_y);
|
||||
funcs->quadratic_to (draw_data, st,
|
||||
control_x, control_y,
|
||||
to_x, to_y);
|
||||
}
|
||||
void
|
||||
HB_ALWAYS_INLINE
|
||||
@ -215,16 +227,10 @@ struct hb_draw_session_t
|
||||
float control2_x, float control2_y,
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (likely (not_slanted))
|
||||
funcs->cubic_to (draw_data, st,
|
||||
control1_x, control1_y,
|
||||
control2_x, control2_y,
|
||||
to_x, to_y);
|
||||
else
|
||||
funcs->cubic_to (draw_data, st,
|
||||
control1_x + control1_y * slant, control1_y,
|
||||
control2_x + control2_y * slant, control2_y,
|
||||
to_x + to_y * slant, to_y);
|
||||
funcs->cubic_to (draw_data, st,
|
||||
control1_x, control1_y,
|
||||
control2_x, control2_y,
|
||||
to_x, to_y);
|
||||
}
|
||||
HB_ALWAYS_INLINE
|
||||
void close_path ()
|
||||
@ -233,8 +239,6 @@ struct hb_draw_session_t
|
||||
}
|
||||
|
||||
public:
|
||||
float slant;
|
||||
bool not_slanted;
|
||||
hb_draw_funcs_t *funcs;
|
||||
void *draw_data;
|
||||
hb_draw_state_t st;
|
||||
|
226
src/3rdparty/harfbuzz-ng/src/hb-face.cc
vendored
226
src/3rdparty/harfbuzz-ng/src/hb-face.cc
vendored
@ -34,6 +34,16 @@
|
||||
#include "hb-ot-face.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include "hb-coretext.h"
|
||||
#endif
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
#include "hb-directwrite.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-face
|
||||
@ -72,14 +82,14 @@ hb_face_count (hb_blob_t *blob)
|
||||
if (unlikely (!blob))
|
||||
return 0;
|
||||
|
||||
/* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
|
||||
/* Make API signature const after. */
|
||||
hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
|
||||
const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
|
||||
unsigned int ret = ot.get_face_count ();
|
||||
hb_blob_destroy (sanitized);
|
||||
hb_sanitize_context_t c (blob);
|
||||
|
||||
return ret;
|
||||
const char *start = hb_blob_get_data (blob, nullptr);
|
||||
auto *ot = reinterpret_cast<OT::OpenTypeFontFile *> (const_cast<char *> (start));
|
||||
if (unlikely (!ot->sanitize (&c)))
|
||||
return 0;
|
||||
|
||||
return ot->get_face_count ();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -318,7 +328,209 @@ hb_face_create_from_file_or_fail (const char *file_name,
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
static struct supported_face_loaders_t {
|
||||
char name[16];
|
||||
hb_face_t * (*from_file) (const char *font_file, unsigned face_index);
|
||||
hb_face_t * (*from_blob) (hb_blob_t *blob, unsigned face_index);
|
||||
} supported_face_loaders[] =
|
||||
{
|
||||
{"ot",
|
||||
#ifndef HB_NO_OPEN
|
||||
hb_face_create_from_file_or_fail,
|
||||
#else
|
||||
nullptr,
|
||||
#endif
|
||||
hb_face_create_or_fail
|
||||
},
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft",
|
||||
hb_ft_face_create_from_file_or_fail,
|
||||
hb_ft_face_create_from_blob_or_fail
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
{"coretext",
|
||||
hb_coretext_face_create_from_file_or_fail,
|
||||
hb_coretext_face_create_from_blob_or_fail
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
{"directwrite",
|
||||
hb_directwrite_face_create_from_file_or_fail,
|
||||
hb_directwrite_face_create_from_blob_or_fail
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char *get_default_loader_name ()
|
||||
{
|
||||
static hb_atomic_t<const char *> static_loader_name;
|
||||
const char *loader_name = static_loader_name.get_acquire ();
|
||||
if (!loader_name)
|
||||
{
|
||||
loader_name = getenv ("HB_FACE_LOADER");
|
||||
if (!loader_name)
|
||||
loader_name = "";
|
||||
if (!static_loader_name.cmpexch (nullptr, loader_name))
|
||||
loader_name = static_loader_name.get_acquire ();
|
||||
}
|
||||
return loader_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_create_from_file_or_fail_using:
|
||||
* @file_name: A font filename
|
||||
* @index: The index of the face within the file
|
||||
* @loader_name: (nullable): The name of the loader to use, or `NULL`
|
||||
*
|
||||
* A thin wrapper around the face loader functions registered with HarfBuzz.
|
||||
* If @loader_name is `NULL` or the empty string, the first available loader
|
||||
* is used.
|
||||
*
|
||||
* For example, the FreeType ("ft") loader might be able to load
|
||||
* WOFF and WOFF2 files if FreeType is built with those features,
|
||||
* whereas the OpenType ("ot") loader will not.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* the file cannot be read or the loader fails to load the face.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
hb_face_t *
|
||||
hb_face_create_from_file_or_fail_using (const char *file_name,
|
||||
unsigned int index,
|
||||
const char *loader_name)
|
||||
{
|
||||
// Duplicated in hb_face_create_or_fail_using
|
||||
bool retry = false;
|
||||
if (!loader_name || !*loader_name)
|
||||
{
|
||||
loader_name = get_default_loader_name ();
|
||||
retry = true;
|
||||
}
|
||||
if (loader_name && !*loader_name) loader_name = nullptr;
|
||||
|
||||
retry:
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
{
|
||||
if (!loader_name || (supported_face_loaders[i].from_file && !strcmp (supported_face_loaders[i].name, loader_name)))
|
||||
return supported_face_loaders[i].from_file (file_name, index);
|
||||
}
|
||||
|
||||
if (retry)
|
||||
{
|
||||
retry = false;
|
||||
loader_name = nullptr;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_create_or_fail_using:
|
||||
* @blob: #hb_blob_t to work upon
|
||||
* @index: The index of the face within @blob
|
||||
* @loader_name: (nullable): The name of the loader to use, or `NULL`
|
||||
*
|
||||
* A thin wrapper around the face loader functions registered with HarfBuzz.
|
||||
* If @loader_name is `NULL` or the empty string, the first available loader
|
||||
* is used.
|
||||
*
|
||||
* For example, the FreeType ("ft") loader might be able to load
|
||||
* WOFF and WOFF2 files if FreeType is built with those features,
|
||||
* whereas the OpenType ("ot") loader will not.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* the loader fails to load the face.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
hb_face_t *
|
||||
hb_face_create_or_fail_using (hb_blob_t *blob,
|
||||
unsigned int index,
|
||||
const char *loader_name)
|
||||
{
|
||||
// Duplicated in hb_face_create_from_file_or_fail_using
|
||||
bool retry = false;
|
||||
if (!loader_name || !*loader_name)
|
||||
{
|
||||
loader_name = get_default_loader_name ();
|
||||
retry = true;
|
||||
}
|
||||
if (loader_name && !*loader_name) loader_name = nullptr;
|
||||
|
||||
retry:
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
{
|
||||
if (!loader_name || (supported_face_loaders[i].from_blob && !strcmp (supported_face_loaders[i].name, loader_name)))
|
||||
return supported_face_loaders[i].from_blob (blob, index);
|
||||
}
|
||||
|
||||
if (retry)
|
||||
{
|
||||
retry = false;
|
||||
loader_name = nullptr;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static inline void free_static_face_loader_list ();
|
||||
|
||||
static const char * const nil_face_loader_list[] = {nullptr};
|
||||
|
||||
static struct hb_face_loader_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
||||
hb_face_loader_list_lazy_loader_t>
|
||||
{
|
||||
static const char ** create ()
|
||||
{
|
||||
const char **face_loader_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_face_loaders), sizeof (const char *));
|
||||
if (unlikely (!face_loader_list))
|
||||
return nullptr;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
face_loader_list[i] = supported_face_loaders[i].name;
|
||||
face_loader_list[i] = nullptr;
|
||||
|
||||
hb_atexit (free_static_face_loader_list);
|
||||
|
||||
return face_loader_list;
|
||||
}
|
||||
static void destroy (const char **l)
|
||||
{ hb_free (l); }
|
||||
static const char * const * get_null ()
|
||||
{ return nil_face_loader_list; }
|
||||
} static_face_loader_list;
|
||||
|
||||
static inline
|
||||
void free_static_face_loader_list ()
|
||||
{
|
||||
static_face_loader_list.free_instance ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_list_loaders:
|
||||
*
|
||||
* Retrieves the list of face loaders supported by HarfBuzz.
|
||||
*
|
||||
* Return value: (transfer none) (array zero-terminated=1): a
|
||||
* `NULL`-terminated array of supported face loaders
|
||||
* constant strings. The returned array is owned by HarfBuzz
|
||||
* and should not be modified or freed.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
const char **
|
||||
hb_face_list_loaders ()
|
||||
{
|
||||
return static_face_loader_list.get_unconst ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* hb_face_get_empty:
|
||||
|
14
src/3rdparty/harfbuzz-ng/src/hb-face.h
vendored
14
src/3rdparty/harfbuzz-ng/src/hb-face.h
vendored
@ -63,10 +63,24 @@ HB_EXTERN hb_face_t *
|
||||
hb_face_create_or_fail (hb_blob_t *blob,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_face_create_or_fail_using (hb_blob_t *blob,
|
||||
unsigned int index,
|
||||
const char *loader_name);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_face_create_from_file_or_fail_using (const char *file_name,
|
||||
unsigned int index,
|
||||
const char *loader_name);
|
||||
|
||||
HB_EXTERN const char **
|
||||
hb_face_list_loaders (void);
|
||||
|
||||
|
||||
/**
|
||||
* hb_reference_table_func_t:
|
||||
* @face: an #hb_face_t to reference table for
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-face.hh
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-face.hh
vendored
@ -49,8 +49,8 @@ struct hb_face_t
|
||||
hb_object_header_t header;
|
||||
|
||||
unsigned int index; /* Face index in a collection, zero-based. */
|
||||
mutable hb_atomic_int_t upem; /* Units-per-EM. */
|
||||
mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */
|
||||
mutable hb_atomic_t<unsigned> upem; /* Units-per-EM. */
|
||||
mutable hb_atomic_t<unsigned> num_glyphs;/* Number of glyphs. */
|
||||
|
||||
hb_reference_table_func_t reference_table_func;
|
||||
void *user_data;
|
||||
@ -70,7 +70,7 @@ struct hb_face_t
|
||||
plan_node_t *next;
|
||||
};
|
||||
#ifndef HB_NO_SHAPER
|
||||
hb_atomic_ptr_t<plan_node_t> shape_plans;
|
||||
hb_atomic_t<plan_node_t *> shape_plans;
|
||||
#endif
|
||||
|
||||
hb_blob_t *reference_table (hb_tag_t tag) const
|
||||
|
221
src/3rdparty/harfbuzz-ng/src/hb-font.cc
vendored
221
src/3rdparty/harfbuzz-ng/src/hb-font.cc
vendored
@ -38,6 +38,22 @@
|
||||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
|
||||
#ifndef HB_NO_OT_FONT
|
||||
#include "hb-ot.h"
|
||||
#endif
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
#include "hb-fontations.h"
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include "hb-coretext.h"
|
||||
#endif
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
#include "hb-directwrite.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-font
|
||||
@ -1854,10 +1870,7 @@ hb_font_create (hb_face_t *face)
|
||||
{
|
||||
hb_font_t *font = _hb_font_create (face);
|
||||
|
||||
#ifndef HB_NO_OT_FONT
|
||||
/* Install our in-house, very lightweight, funcs. */
|
||||
hb_ot_font_set_funcs (font);
|
||||
#endif
|
||||
hb_font_set_funcs_using (font, nullptr);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (face && face->index >> 16)
|
||||
@ -1880,7 +1893,7 @@ _hb_font_adopt_var_coords (hb_font_t *font,
|
||||
font->design_coords = design_coords;
|
||||
font->num_coords = coords_length;
|
||||
|
||||
font->mults_changed (); // Easiest to call this to drop cached data
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1935,7 +1948,8 @@ hb_font_create_sub_font (hb_font_t *parent)
|
||||
}
|
||||
}
|
||||
|
||||
font->mults_changed ();
|
||||
font->changed ();
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
return font;
|
||||
}
|
||||
@ -2023,7 +2037,7 @@ hb_font_set_user_data (hb_font_t *font,
|
||||
hb_bool_t replace)
|
||||
{
|
||||
if (!hb_object_is_immutable (font))
|
||||
font->serial++;
|
||||
font->changed ();
|
||||
|
||||
return hb_object_set_user_data (font, key, data, destroy, replace);
|
||||
}
|
||||
@ -2098,7 +2112,7 @@ hb_font_is_immutable (hb_font_t *font)
|
||||
unsigned int
|
||||
hb_font_get_serial (hb_font_t *font)
|
||||
{
|
||||
return font->serial;
|
||||
return font->serial.get_acquire ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2117,9 +2131,7 @@ hb_font_changed (hb_font_t *font)
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->mults_changed ();
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2141,8 +2153,6 @@ hb_font_set_parent (hb_font_t *font,
|
||||
if (parent == font->parent)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
if (!parent)
|
||||
parent = hb_font_get_empty ();
|
||||
|
||||
@ -2151,6 +2161,8 @@ hb_font_set_parent (hb_font_t *font,
|
||||
font->parent = hb_font_reference (parent);
|
||||
|
||||
hb_font_destroy (old);
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2188,8 +2200,6 @@ hb_font_set_face (hb_font_t *font,
|
||||
if (face == font->face)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
if (unlikely (!face))
|
||||
face = hb_face_get_empty ();
|
||||
|
||||
@ -2197,9 +2207,11 @@ hb_font_set_face (hb_font_t *font,
|
||||
|
||||
hb_face_make_immutable (face);
|
||||
font->face = hb_face_reference (face);
|
||||
font->mults_changed ();
|
||||
font->changed ();
|
||||
|
||||
hb_face_destroy (old);
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2244,8 +2256,6 @@ hb_font_set_funcs (hb_font_t *font,
|
||||
return;
|
||||
}
|
||||
|
||||
font->serial++;
|
||||
|
||||
if (font->destroy)
|
||||
font->destroy (font->user_data);
|
||||
|
||||
@ -2257,6 +2267,8 @@ hb_font_set_funcs (hb_font_t *font,
|
||||
font->klass = klass;
|
||||
font->user_data = font_data;
|
||||
font->destroy = destroy;
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2283,15 +2295,151 @@ hb_font_set_funcs_data (hb_font_t *font,
|
||||
return;
|
||||
}
|
||||
|
||||
font->serial++;
|
||||
|
||||
if (font->destroy)
|
||||
font->destroy (font->user_data);
|
||||
|
||||
font->user_data = font_data;
|
||||
font->destroy = destroy;
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
static struct supported_font_funcs_t {
|
||||
char name[16];
|
||||
void (*func) (hb_font_t *);
|
||||
} supported_font_funcs[] =
|
||||
{
|
||||
#ifndef HB_NO_OT_FONT
|
||||
{"ot", hb_ot_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft", hb_ft_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
{"fontations",hb_fontations_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
{"coretext", hb_coretext_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_DIRECTWRITE
|
||||
{"directwrite",hb_directwrite_font_set_funcs},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char *get_default_funcs_name ()
|
||||
{
|
||||
static hb_atomic_t<const char *> static_funcs_name;
|
||||
const char *name = static_funcs_name.get_acquire ();
|
||||
if (!name)
|
||||
{
|
||||
name = getenv ("HB_FONT_FUNCS");
|
||||
if (!name)
|
||||
name = "";
|
||||
if (!static_funcs_name.cmpexch (nullptr, name))
|
||||
name = static_funcs_name.get_acquire ();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_funcs_using:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @name: The name of the font-functions structure to use, or `NULL`
|
||||
*
|
||||
* Sets the font-functions structure to use for a font, based on the
|
||||
* specified name.
|
||||
*
|
||||
* If @name is `NULL` or the empty string, the default (first) functioning font-functions
|
||||
* are used. This default can be changed by setting the `HB_FONT_FUNCS` environment
|
||||
* variable to the name of the desired font-functions.
|
||||
*
|
||||
* Return value: `true` if the font-functions was found and set, `false` otherwise
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_set_funcs_using (hb_font_t *font,
|
||||
const char *name)
|
||||
{
|
||||
bool retry = false;
|
||||
|
||||
if (!name || !*name)
|
||||
{
|
||||
name = get_default_funcs_name ();
|
||||
retry = true;
|
||||
}
|
||||
if (name && !*name) name = nullptr;
|
||||
|
||||
retry:
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
if (!name || strcmp (supported_font_funcs[i].name, name) == 0)
|
||||
{
|
||||
supported_font_funcs[i].func (font);
|
||||
if (name || font->klass != hb_font_funcs_get_empty ())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (retry)
|
||||
{
|
||||
retry = false;
|
||||
name = nullptr;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void free_static_font_funcs_list ();
|
||||
|
||||
static const char * const nil_font_funcs_list[] = {nullptr};
|
||||
|
||||
static struct hb_font_funcs_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
||||
hb_font_funcs_list_lazy_loader_t>
|
||||
{
|
||||
static const char ** create ()
|
||||
{
|
||||
const char **font_funcs_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_font_funcs), sizeof (const char *));
|
||||
if (unlikely (!font_funcs_list))
|
||||
return nullptr;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
font_funcs_list[i] = supported_font_funcs[i].name;
|
||||
font_funcs_list[i] = nullptr;
|
||||
|
||||
hb_atexit (free_static_font_funcs_list);
|
||||
|
||||
return font_funcs_list;
|
||||
}
|
||||
static void destroy (const char **l)
|
||||
{ hb_free (l); }
|
||||
static const char * const * get_null ()
|
||||
{ return nil_font_funcs_list; }
|
||||
} static_font_funcs_list;
|
||||
|
||||
static inline
|
||||
void free_static_font_funcs_list ()
|
||||
{
|
||||
static_font_funcs_list.free_instance ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_list_funcs:
|
||||
*
|
||||
* Retrieves the list of font functions supported by HarfBuzz.
|
||||
*
|
||||
* Return value: (transfer none) (array zero-terminated=1): a
|
||||
* `NULL`-terminated array of supported font functions
|
||||
* constant strings. The returned array is owned by HarfBuzz
|
||||
* and should not be modified or freed.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
const char **
|
||||
hb_font_list_funcs ()
|
||||
{
|
||||
return static_font_funcs_list.get_unconst ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_scale:
|
||||
@ -2339,11 +2487,10 @@ hb_font_set_scale (hb_font_t *font,
|
||||
if (font->x_scale == x_scale && font->y_scale == y_scale)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->x_scale = x_scale;
|
||||
font->y_scale = y_scale;
|
||||
font->mults_changed ();
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2390,10 +2537,10 @@ hb_font_set_ppem (hb_font_t *font,
|
||||
if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->x_ppem = x_ppem;
|
||||
font->y_ppem = y_ppem;
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2437,9 +2584,9 @@ hb_font_set_ptem (hb_font_t *font,
|
||||
if (font->ptem == ptem)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->ptem = ptem;
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2499,12 +2646,11 @@ hb_font_set_synthetic_bold (hb_font_t *font,
|
||||
font->embolden_in_place == (bool) in_place)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->x_embolden = x_embolden;
|
||||
font->y_embolden = y_embolden;
|
||||
font->embolden_in_place = in_place;
|
||||
font->mults_changed ();
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2558,10 +2704,9 @@ hb_font_set_synthetic_slant (hb_font_t *font, float slant)
|
||||
if (font->slant == slant)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->slant = slant;
|
||||
font->mults_changed ();
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2607,8 +2752,6 @@ hb_font_set_variations (hb_font_t *font,
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
|
||||
if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
|
||||
{
|
||||
hb_font_set_var_coords_normalized (font, nullptr, 0);
|
||||
@ -2677,8 +2820,6 @@ hb_font_set_variation (hb_font_t *font,
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
|
||||
// TODO Share some of this code with set_variations()
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
@ -2749,8 +2890,6 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
@ -2787,8 +2926,6 @@ hb_font_set_var_named_instance (hb_font_t *font,
|
||||
if (font->instance_index == instance_index)
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
|
||||
font->instance_index = instance_index;
|
||||
hb_font_set_variations (font, nullptr, 0);
|
||||
}
|
||||
@ -2834,8 +2971,6 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
|
||||
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-font.h
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-font.h
vendored
@ -1052,6 +1052,12 @@ hb_font_set_funcs_data (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_set_funcs_using (hb_font_t *font,
|
||||
const char *name);
|
||||
|
||||
HB_EXTERN const char **
|
||||
hb_font_list_funcs (void);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_scale (hb_font_t *font,
|
||||
|
54
src/3rdparty/harfbuzz-ng/src/hb-font.hh
vendored
54
src/3rdparty/harfbuzz-ng/src/hb-font.hh
vendored
@ -32,6 +32,7 @@
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-face.hh"
|
||||
#include "hb-atomic.hh"
|
||||
#include "hb-shaper.hh"
|
||||
|
||||
|
||||
@ -105,8 +106,8 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
|
||||
struct hb_font_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
unsigned int serial;
|
||||
unsigned int serial_coords;
|
||||
hb_atomic_t<unsigned> serial;
|
||||
hb_atomic_t<unsigned> serial_coords;
|
||||
|
||||
hb_font_t *parent;
|
||||
hb_face_t *face;
|
||||
@ -191,22 +192,33 @@ struct hb_font_t
|
||||
|
||||
void scale_glyph_extents (hb_glyph_extents_t *extents)
|
||||
{
|
||||
float x1 = em_fscale_x (extents->x_bearing);
|
||||
float y1 = em_fscale_y (extents->y_bearing);
|
||||
float x2 = em_fscale_x (extents->x_bearing + extents->width);
|
||||
float y2 = em_fscale_y (extents->y_bearing + extents->height);
|
||||
|
||||
/* Apply slant. */
|
||||
if (slant_xy)
|
||||
{
|
||||
x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
|
||||
x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
|
||||
}
|
||||
float x1 = em_scale_x (extents->x_bearing);
|
||||
float y1 = em_scale_y (extents->y_bearing);
|
||||
float x2 = em_scale_x (extents->x_bearing + extents->width);
|
||||
float y2 = em_scale_y (extents->y_bearing + extents->height);
|
||||
|
||||
extents->x_bearing = floorf (x1);
|
||||
extents->y_bearing = floorf (y1);
|
||||
extents->width = ceilf (x2) - extents->x_bearing;
|
||||
extents->height = ceilf (y2) - extents->y_bearing;
|
||||
}
|
||||
|
||||
void synthetic_glyph_extents (hb_glyph_extents_t *extents)
|
||||
{
|
||||
/* Apply slant. */
|
||||
if (slant_xy)
|
||||
{
|
||||
hb_position_t x1 = extents->x_bearing;
|
||||
hb_position_t y1 = extents->y_bearing;
|
||||
hb_position_t x2 = extents->x_bearing + extents->width;
|
||||
hb_position_t y2 = extents->y_bearing + extents->height;
|
||||
|
||||
x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy));
|
||||
x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy));
|
||||
|
||||
extents->x_bearing = x1;
|
||||
extents->width = x2 - extents->x_bearing;
|
||||
}
|
||||
|
||||
if (x_strength || y_strength)
|
||||
{
|
||||
@ -389,10 +401,14 @@ struct hb_font_t
|
||||
hb_glyph_extents_t *extents)
|
||||
{
|
||||
hb_memset (extents, 0, sizeof (*extents));
|
||||
return klass->get.f.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_extents);
|
||||
bool ret = klass->get.f.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_extents);
|
||||
if (ret)
|
||||
synthetic_glyph_extents (extents);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
|
||||
@ -686,7 +702,7 @@ struct hb_font_t
|
||||
return false;
|
||||
}
|
||||
|
||||
void mults_changed ()
|
||||
void changed ()
|
||||
{
|
||||
float upem = face->get_upem ();
|
||||
|
||||
@ -703,6 +719,8 @@ struct hb_font_t
|
||||
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
|
||||
|
||||
data.fini ();
|
||||
|
||||
serial++;
|
||||
}
|
||||
|
||||
hb_position_t em_mult (int16_t v, int64_t mult)
|
||||
|
56
src/3rdparty/harfbuzz-ng/src/hb-fontations.h
vendored
Normal file
56
src/3rdparty/harfbuzz-ng/src/hb-fontations.h
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_FONTATIONS_H
|
||||
#define HB_FONTATIONS_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
/**
|
||||
* SECTION: hb-fontations
|
||||
* @title: hb-fontations
|
||||
* @short_description: Fontations integration
|
||||
* @include: hb-fontations.h
|
||||
*
|
||||
* Functions for using HarfBuzz with
|
||||
* [Fontations](https://github.com/googlefonts/fontations/) fonts.
|
||||
**/
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* hb_fontations_font_set_funcs:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Configures the font-functions structure of the specified #hb_font_t font
|
||||
* object to use Fontations font functions.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_fontations_font_set_funcs (hb_font_t *font);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FONTATIONS_H */
|
43
src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh
vendored
43
src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh
vendored
@ -83,7 +83,7 @@ struct hb_ft_paint_context_t
|
||||
hb_ft_paint_context_t (const hb_ft_font_t *ft_font,
|
||||
hb_font_t *font,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
FT_Color *palette,
|
||||
hb_array_t<const FT_Color> palette,
|
||||
unsigned palette_index,
|
||||
hb_color_t foreground) :
|
||||
ft_font (ft_font), font(font),
|
||||
@ -103,7 +103,7 @@ struct hb_ft_paint_context_t
|
||||
hb_font_t *font;
|
||||
hb_paint_funcs_t *funcs;
|
||||
void *data;
|
||||
FT_Color *palette;
|
||||
hb_array_t<const FT_Color> palette;
|
||||
unsigned palette_index;
|
||||
hb_color_t foreground;
|
||||
hb_decycler_t glyphs_decycler;
|
||||
@ -167,7 +167,7 @@ _hb_ft_color_line_get_color_stops (hb_color_line_t *color_line,
|
||||
hb_color_get_red (color),
|
||||
(hb_color_get_alpha (color) * stop.color.alpha) >> 14);
|
||||
}
|
||||
else
|
||||
else if (c->palette)
|
||||
{
|
||||
FT_Color ft_color = c->palette[stop.color.palette_index];
|
||||
color_stops->color = HB_COLOR (ft_color.blue,
|
||||
@ -175,6 +175,8 @@ _hb_ft_color_line_get_color_stops (hb_color_line_t *color_line,
|
||||
ft_color.red,
|
||||
(ft_color.alpha * stop.color.alpha) >> 14);
|
||||
}
|
||||
else
|
||||
color_stops->color = HB_COLOR (0, 0, 0, 0);
|
||||
}
|
||||
|
||||
color_stops++;
|
||||
@ -229,9 +231,7 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
||||
if (unlikely (!node.visit ((uintptr_t) other_paint.p)))
|
||||
continue;
|
||||
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (other_paint);
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -316,11 +316,11 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_GLYPH:
|
||||
{
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->funcs->push_inverse_font_transform (c->data, c->font);
|
||||
c->ft_font->lock.unlock ();
|
||||
c->funcs->push_clip_glyph (c->data, paint.u.glyph.glyphID, c->font);
|
||||
c->ft_font->lock.lock ();
|
||||
c->funcs->push_root_transform (c->data, c->font);
|
||||
c->funcs->push_font_transform (c->data, c->font);
|
||||
c->recurse (paint.u.glyph.paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_clip (c->data);
|
||||
@ -335,7 +335,7 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
||||
if (unlikely (!node.visit (gid)))
|
||||
return;
|
||||
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->funcs->push_inverse_font_transform (c->data, c->font);
|
||||
c->ft_font->lock.unlock ();
|
||||
if (c->funcs->color_glyph (c->data, gid, c->font))
|
||||
{
|
||||
@ -451,10 +451,12 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_COMPOSITE:
|
||||
{
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (paint.u.composite.backdrop_paint);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (paint.u.composite.source_paint);
|
||||
c->funcs->pop_group (c->data, _hb_ft_paint_composite_mode (paint.u.composite.composite_mode));
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -479,17 +481,24 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
||||
|
||||
/* Face is locked. */
|
||||
|
||||
FT_Error error;
|
||||
FT_Color* palette;
|
||||
FT_Palette_Data palette_data = {};
|
||||
FT_Color* palette = NULL;
|
||||
FT_LayerIterator iterator;
|
||||
|
||||
FT_Bool have_layers;
|
||||
FT_UInt layer_glyph_index;
|
||||
FT_UInt layer_color_index;
|
||||
|
||||
error = FT_Palette_Select(ft_face, palette_index, &palette);
|
||||
if (error)
|
||||
palette = NULL;
|
||||
(void) FT_Palette_Data_Get(ft_face, &palette_data);
|
||||
(void) FT_Palette_Select(ft_face, palette_index, &palette);
|
||||
if (!palette)
|
||||
{
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5116
|
||||
(void) FT_Palette_Select(ft_face, 0, &palette);
|
||||
}
|
||||
|
||||
auto palette_array = hb_array ((const FT_Color *) palette,
|
||||
palette ? palette_data.num_palette_entries : 0);
|
||||
|
||||
/* COLRv1 */
|
||||
FT_OpaquePaint paint = {0};
|
||||
@ -499,7 +508,7 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
||||
{
|
||||
hb_ft_paint_context_t c (ft_font, font,
|
||||
paint_funcs, paint_data,
|
||||
palette, palette_index, foreground);
|
||||
palette_array, palette_index, foreground);
|
||||
hb_decycler_node_t node (c.glyphs_decycler);
|
||||
node.visit (gid);
|
||||
|
||||
@ -524,10 +533,10 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
||||
hb_paint_extents_context_t extents_data;
|
||||
hb_ft_paint_context_t ce (ft_font, font,
|
||||
extents_funcs, &extents_data,
|
||||
palette, palette_index, foreground);
|
||||
palette_array, palette_index, foreground);
|
||||
hb_decycler_node_t node2 (ce.glyphs_decycler);
|
||||
node2.visit (gid);
|
||||
ce.funcs->push_root_transform (ce.data, font);
|
||||
ce.funcs->push_font_transform (ce.data, font);
|
||||
ce.recurse (paint);
|
||||
ce.funcs->pop_transform (ce.data);
|
||||
hb_extents_t extents = extents_data.get_extents ();
|
||||
@ -540,7 +549,7 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
||||
extents.ymax);
|
||||
}
|
||||
|
||||
c.funcs->push_root_transform (c.data, font);
|
||||
c.funcs->push_font_transform (c.data, font);
|
||||
|
||||
if (is_bounded)
|
||||
{
|
||||
|
129
src/3rdparty/harfbuzz-ng/src/hb-ft.cc
vendored
129
src/3rdparty/harfbuzz-ng/src/hb-ft.cc
vendored
@ -101,7 +101,7 @@ struct hb_ft_font_t
|
||||
|
||||
mutable hb_mutex_t lock; /* Protects members below. */
|
||||
FT_Face ft_face;
|
||||
mutable unsigned cached_serial;
|
||||
mutable hb_atomic_t<unsigned> cached_serial;
|
||||
mutable hb_ft_advance_cache_t advance_cache;
|
||||
};
|
||||
|
||||
@ -118,7 +118,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
|
||||
|
||||
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
|
||||
|
||||
ft_font->cached_serial = (unsigned) -1;
|
||||
ft_font->cached_serial = UINT_MAX;
|
||||
new (&ft_font->advance_cache) hb_ft_advance_cache_t;
|
||||
|
||||
return ft_font;
|
||||
@ -213,9 +213,10 @@ _hb_ft_hb_font_check_changed (hb_font_t *font,
|
||||
{
|
||||
if (font->serial != ft_font->cached_serial)
|
||||
{
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
_hb_ft_hb_font_changed (font, ft_font->ft_face);
|
||||
ft_font->advance_cache.clear ();
|
||||
ft_font->cached_serial = font->serial;
|
||||
ft_font->cached_serial.set_release (font->serial.get_acquire ());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -478,6 +479,8 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
@ -561,6 +564,8 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Fixed v;
|
||||
float y_mult;
|
||||
@ -614,6 +619,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
float x_mult, y_mult;
|
||||
@ -658,6 +665,8 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Vector kerningv;
|
||||
|
||||
@ -677,10 +686,12 @@ hb_ft_get_glyph_extents (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
float x_mult, y_mult;
|
||||
float slant_xy = font->slant_xy;
|
||||
|
||||
#ifdef HAVE_FT_GET_TRANSFORM
|
||||
if (ft_font->transform)
|
||||
{
|
||||
@ -708,34 +719,11 @@ hb_ft_get_glyph_extents (hb_font_t *font,
|
||||
float x2 = x1 + x_mult * ft_face->glyph->metrics.width;
|
||||
float y2 = y1 + y_mult * -ft_face->glyph->metrics.height;
|
||||
|
||||
/* Apply slant. */
|
||||
if (slant_xy)
|
||||
{
|
||||
x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
|
||||
x2 += hb_max (y1 * slant_xy, y2 * slant_xy);
|
||||
}
|
||||
|
||||
extents->x_bearing = floorf (x1);
|
||||
extents->y_bearing = floorf (y1);
|
||||
extents->width = ceilf (x2) - extents->x_bearing;
|
||||
extents->height = ceilf (y2) - extents->y_bearing;
|
||||
|
||||
if (font->x_strength || font->y_strength)
|
||||
{
|
||||
/* Y */
|
||||
int y_shift = font->y_strength;
|
||||
if (font->y_scale < 0) y_shift = -y_shift;
|
||||
extents->y_bearing += y_shift;
|
||||
extents->height -= y_shift;
|
||||
|
||||
/* X */
|
||||
int x_shift = font->x_strength;
|
||||
if (font->x_scale < 0) x_shift = -x_shift;
|
||||
if (font->embolden_in_place)
|
||||
extents->x_bearing -= x_shift / 2;
|
||||
extents->width += x_shift;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -749,6 +737,8 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
@ -826,6 +816,8 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
float y_mult;
|
||||
@ -916,6 +908,8 @@ hb_ft_draw_glyph (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
@ -990,6 +984,8 @@ hb_ft_paint_glyph (hb_font_t *font,
|
||||
void *user_data)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
@ -1079,10 +1075,8 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
|
||||
#endif
|
||||
@ -1090,7 +1084,6 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
||||
#ifndef HB_NO_OT_SHAPE_FALLBACK
|
||||
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
|
||||
#endif
|
||||
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
|
||||
@ -1456,6 +1449,10 @@ hb_ft_font_changed (hb_font_t *font)
|
||||
* variation-axis settings on the @font.
|
||||
* This call is fast if nothing has changed on @font.
|
||||
*
|
||||
* Note that as of version 11.0.0, calling this function is not necessary,
|
||||
* as HarfBuzz will automatically detect changes to the font and update
|
||||
* the underlying FT_Face as needed.
|
||||
*
|
||||
* Return value: true if changed, false otherwise
|
||||
*
|
||||
* Since: 4.4.0
|
||||
@ -1587,7 +1584,8 @@ destroy_ft_library (void *arg)
|
||||
* font file and face index.
|
||||
*
|
||||
* This is similar in functionality to hb_face_create_from_file_or_fail(),
|
||||
* but uses the FreeType library for loading the font file.
|
||||
* but uses the FreeType library for loading the font file. This can
|
||||
* be useful, for example, to load WOFF and WOFF2 font data.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* no face is found at the specified index or the file cannot be read.
|
||||
@ -1624,6 +1622,75 @@ hb_ft_face_create_from_file_or_fail (const char *file_name,
|
||||
return face;
|
||||
}
|
||||
|
||||
static hb_user_data_key_t ft_blob_key = {0};
|
||||
|
||||
static void
|
||||
_destroy_blob (void *p)
|
||||
{
|
||||
hb_blob_destroy ((hb_blob_t *) p);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ft_face_create_from_blob_or_fail:
|
||||
* @blob: A blob
|
||||
* @index: The index of the face within the blob
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* font blob and face index.
|
||||
*
|
||||
* This is similar in functionality to hb_face_create_from_blob_or_fail(),
|
||||
* but uses the FreeType library for loading the font blob. This can
|
||||
* be useful, for example, to load WOFF and WOFF2 font data.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* loading fails (eg. blob does not contain valid font data).
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob,
|
||||
unsigned int index)
|
||||
{
|
||||
FT_Library ft_library = reference_ft_library ();
|
||||
if (unlikely (!ft_library))
|
||||
{
|
||||
DEBUG_MSG (FT, ft_library, "reference_ft_library failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hb_blob_make_immutable (blob);
|
||||
unsigned blob_size;
|
||||
const char *blob_data = hb_blob_get_data (blob, &blob_size);
|
||||
|
||||
FT_Face ft_face;
|
||||
if (unlikely (FT_New_Memory_Face (ft_library,
|
||||
(const FT_Byte *) blob_data,
|
||||
blob_size,
|
||||
index,
|
||||
&ft_face)))
|
||||
return nullptr;
|
||||
|
||||
hb_face_t *face = hb_ft_face_create_referenced (ft_face);
|
||||
FT_Done_Face (ft_face);
|
||||
|
||||
ft_face->generic.data = ft_library;
|
||||
ft_face->generic.finalizer = finalize_ft_library;
|
||||
|
||||
if (hb_face_is_immutable (face))
|
||||
return nullptr;
|
||||
|
||||
// Hook the blob to the hb_face_t, since FT_Face still needs it.
|
||||
hb_blob_reference (blob);
|
||||
if (!hb_face_set_user_data (face, &ft_blob_key, blob, _destroy_blob, true))
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
hb_face_destroy (face);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
static void
|
||||
_release_blob (void *arg)
|
||||
{
|
||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-ft.h
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-ft.h
vendored
@ -88,6 +88,10 @@ HB_EXTERN hb_face_t *
|
||||
hb_ft_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob,
|
||||
unsigned int index);
|
||||
|
||||
/*
|
||||
* hb-font from ft-face.
|
||||
*/
|
||||
|
30
src/3rdparty/harfbuzz-ng/src/hb-geometry.hh
vendored
30
src/3rdparty/harfbuzz-ng/src/hb-geometry.hh
vendored
@ -30,6 +30,11 @@
|
||||
struct hb_extents_t
|
||||
{
|
||||
hb_extents_t () {}
|
||||
hb_extents_t (const hb_glyph_extents_t &extents) :
|
||||
xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)),
|
||||
ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)),
|
||||
xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)),
|
||||
ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {}
|
||||
hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
|
||||
xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
|
||||
|
||||
@ -38,6 +43,12 @@ struct hb_extents_t
|
||||
|
||||
void union_ (const hb_extents_t &o)
|
||||
{
|
||||
if (o.is_empty ()) return;
|
||||
if (is_empty ())
|
||||
{
|
||||
*this = o;
|
||||
return;
|
||||
}
|
||||
xmin = hb_min (xmin, o.xmin);
|
||||
ymin = hb_min (ymin, o.ymin);
|
||||
xmax = hb_max (xmax, o.xmax);
|
||||
@ -46,6 +57,11 @@ struct hb_extents_t
|
||||
|
||||
void intersect (const hb_extents_t &o)
|
||||
{
|
||||
if (o.is_empty () || is_empty ())
|
||||
{
|
||||
*this = hb_extents_t {};
|
||||
return;
|
||||
}
|
||||
xmin = hb_max (xmin, o.xmin);
|
||||
ymin = hb_max (ymin, o.ymin);
|
||||
xmax = hb_min (xmax, o.xmax);
|
||||
@ -69,6 +85,18 @@ struct hb_extents_t
|
||||
}
|
||||
}
|
||||
|
||||
hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const
|
||||
{
|
||||
hb_position_t x0 = (hb_position_t) roundf (xmin);
|
||||
hb_position_t y0 = (hb_position_t) roundf (ymin);
|
||||
hb_position_t x1 = (hb_position_t) roundf (xmax);
|
||||
hb_position_t y1 = (hb_position_t) roundf (ymax);
|
||||
return hb_glyph_extents_t {xneg ? x1 : x0,
|
||||
yneg ? y0 : y1,
|
||||
xneg ? x0 - x1 : x1 - x0,
|
||||
yneg ? y1 - y0 : y0 - y1};
|
||||
}
|
||||
|
||||
float xmin = 0.f;
|
||||
float ymin = 0.f;
|
||||
float xmax = -1.f;
|
||||
@ -218,7 +246,7 @@ struct hb_bounds_t
|
||||
EMPTY,
|
||||
};
|
||||
|
||||
hb_bounds_t (status_t status) : status (status) {}
|
||||
hb_bounds_t (status_t status = UNBOUNDED) : status (status) {}
|
||||
hb_bounds_t (const hb_extents_t &extents) :
|
||||
status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
|
||||
|
||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc
vendored
@ -68,7 +68,7 @@ struct hb_graphite2_face_data_t
|
||||
{
|
||||
hb_face_t *face;
|
||||
gr_face *grface;
|
||||
hb_atomic_ptr_t<hb_graphite2_tablelist_t> tlist;
|
||||
hb_atomic_t<hb_graphite2_tablelist_t *> tlist;
|
||||
};
|
||||
|
||||
static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
|
||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-machinery.hh
vendored
@ -273,7 +273,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
|
||||
|
||||
private:
|
||||
/* Must only have one pointer. */
|
||||
hb_atomic_ptr_t<Stored *> instance;
|
||||
hb_atomic_t<Stored *> instance;
|
||||
};
|
||||
|
||||
/* Specializations. */
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-object.hh
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-object.hh
vendored
@ -142,7 +142,7 @@ struct hb_lockable_set_t
|
||||
|
||||
struct hb_reference_count_t
|
||||
{
|
||||
mutable hb_atomic_int_t ref_count;
|
||||
mutable hb_atomic_t<int> ref_count;
|
||||
|
||||
void init (int v = 1) { ref_count = v; }
|
||||
int get_relaxed () const { return ref_count; }
|
||||
@ -213,8 +213,8 @@ struct hb_user_data_array_t
|
||||
struct hb_object_header_t
|
||||
{
|
||||
hb_reference_count_t ref_count;
|
||||
mutable hb_atomic_int_t writable = 0;
|
||||
hb_atomic_ptr_t<hb_user_data_array_t> user_data;
|
||||
mutable hb_atomic_t<bool> writable = false;
|
||||
hb_atomic_t<hb_user_data_array_t *> user_data;
|
||||
|
||||
bool is_inert () const { return !ref_count.get_relaxed (); }
|
||||
};
|
||||
|
14
src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
vendored
14
src/3rdparty/harfbuzz-ng/src/hb-open-type.hh
vendored
@ -1888,7 +1888,7 @@ struct TupleValues
|
||||
|
||||
bool ensure_run ()
|
||||
{
|
||||
if (likely (run_count > 0)) return true;
|
||||
if (run_count > 0) return true;
|
||||
|
||||
if (unlikely (p >= end))
|
||||
{
|
||||
@ -1943,6 +1943,11 @@ struct TupleValues
|
||||
unsigned count = hb_min (n - i, (unsigned) run_count);
|
||||
switch (width)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
arrayZ += count;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const auto *pp = (const HBINT8 *) p;
|
||||
@ -1958,6 +1963,8 @@ struct TupleValues
|
||||
#endif
|
||||
for (; j < count; j++)
|
||||
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
|
||||
|
||||
p = (const unsigned char *) pp;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@ -1975,6 +1982,8 @@ struct TupleValues
|
||||
#endif
|
||||
for (; j < count; j++)
|
||||
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
|
||||
|
||||
p = (const unsigned char *) pp;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@ -1982,10 +1991,11 @@ struct TupleValues
|
||||
const auto *pp = (const HBINT32 *) p;
|
||||
for (unsigned j = 0; j < count; j++)
|
||||
*arrayZ++ += scaled ? *pp++ * scale : *pp++;
|
||||
|
||||
p = (const unsigned char *) pp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
p += count * width;
|
||||
run_count -= count;
|
||||
i += count;
|
||||
}
|
||||
|
@ -1176,7 +1176,8 @@ struct cff1
|
||||
if (unlikely (!font_interp.interpret (*font))) goto fail;
|
||||
PRIVDICTVAL *priv = &privateDicts[i];
|
||||
const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
|
||||
if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
|
||||
if (unlikely (font->privateDictInfo.size &&
|
||||
privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
|
||||
num_interp_env_t env2 (privDictStr);
|
||||
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
|
||||
priv->init ();
|
||||
@ -1191,7 +1192,8 @@ struct cff1
|
||||
PRIVDICTVAL *priv = &privateDicts[0];
|
||||
|
||||
const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
|
||||
if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
|
||||
if (font->privateDictInfo.size &&
|
||||
unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
|
||||
num_interp_env_t env (privDictStr);
|
||||
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
|
||||
priv->init ();
|
||||
@ -1483,7 +1485,7 @@ struct cff1
|
||||
int cmp (const gname_t &a) const { return cmp (&a, this); }
|
||||
};
|
||||
|
||||
mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
|
||||
mutable hb_atomic_t<hb_sorted_vector_t<gname_t> *> glyph_names;
|
||||
|
||||
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
|
||||
};
|
||||
|
10
src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
vendored
10
src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.cc
vendored
@ -102,6 +102,14 @@ struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_e
|
||||
bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
return get_extents_at (font, glyph, extents, hb_array (font->coords, font->num_coords));
|
||||
}
|
||||
|
||||
bool OT::cff2::accelerator_t::get_extents_at (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
hb_array_t<const int> coords) const
|
||||
{
|
||||
#ifdef HB_NO_OT_FONT_CFF
|
||||
/* XXX Remove check when this code moves to .hh file. */
|
||||
@ -112,7 +120,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
|
||||
|
||||
unsigned int fd = fdSelect->get_fd (glyph);
|
||||
const hb_ubytes_t str = (*charStrings)[glyph];
|
||||
cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
|
||||
cff2_cs_interp_env_t<number_t> env (str, *this, fd, coords.arrayZ, coords.length);
|
||||
cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t> interp (env);
|
||||
cff2_extents_param_t param;
|
||||
if (unlikely (!interp.interpret (param))) return false;
|
||||
|
16
src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
vendored
16
src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh
vendored
@ -458,7 +458,8 @@ struct cff2
|
||||
if (unlikely (!font_interp.interpret (*font))) goto fail;
|
||||
|
||||
const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
|
||||
if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
|
||||
if (unlikely (font->privateDictInfo.size &&
|
||||
privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
|
||||
cff2_priv_dict_interp_env_t env2 (privDictStr);
|
||||
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
|
||||
privateDicts[i].init ();
|
||||
@ -481,6 +482,13 @@ struct cff2
|
||||
privateDicts.fini ();
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
|
||||
auto *scalars = cached_scalars_vector.get_acquire ();
|
||||
if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
|
||||
{
|
||||
scalars->fini ();
|
||||
hb_free (scalars);
|
||||
}
|
||||
}
|
||||
|
||||
hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
|
||||
@ -508,6 +516,8 @@ struct cff2
|
||||
hb_vector_t<cff2_font_dict_values_t> fontDicts;
|
||||
hb_vector_t<PRIVDICTVAL> privateDicts;
|
||||
|
||||
mutable hb_atomic_t<hb_vector_t<float> *> cached_scalars_vector;
|
||||
|
||||
unsigned int num_glyphs = 0;
|
||||
};
|
||||
|
||||
@ -518,6 +528,10 @@ struct cff2
|
||||
HB_INTERNAL bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const;
|
||||
HB_INTERNAL bool get_extents_at (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
hb_array_t<const int> coords) const;
|
||||
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
|
||||
HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const;
|
||||
};
|
||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-ot-color.cc
vendored
@ -204,7 +204,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
|
||||
hb_bool_t
|
||||
hb_ot_color_has_layers (hb_face_t *face)
|
||||
{
|
||||
return face->table.COLR->has_v0_data ();
|
||||
return face->table.COLR->colr->has_v0_data ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,7 +221,7 @@ hb_ot_color_has_layers (hb_face_t *face)
|
||||
hb_bool_t
|
||||
hb_ot_color_has_paint (hb_face_t *face)
|
||||
{
|
||||
return face->table.COLR->has_v1_data ();
|
||||
return face->table.COLR->colr->has_v1_data ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,7 +240,7 @@ hb_bool_t
|
||||
hb_ot_color_glyph_has_paint (hb_face_t *face,
|
||||
hb_codepoint_t glyph)
|
||||
{
|
||||
return face->table.COLR->has_paint_for_glyph (glyph);
|
||||
return face->table.COLR->colr->has_paint_for_glyph (glyph);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,7 +266,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
|
||||
unsigned int *layer_count, /* IN/OUT. May be NULL. */
|
||||
hb_ot_color_layer_t *layers /* OUT. May be NULL. */)
|
||||
{
|
||||
return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
|
||||
return face->table.COLR->colr->get_glyph_layers (glyph, start_offset, layer_count, layers);
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,7 +136,7 @@ HB_OT_TABLE (AAT, feat)
|
||||
|
||||
/* OpenType color fonts. */
|
||||
#ifndef HB_NO_COLOR
|
||||
HB_OT_CORE_TABLE (OT, COLR)
|
||||
HB_OT_ACCELERATOR (OT, COLR)
|
||||
HB_OT_CORE_TABLE (OT, CPAL)
|
||||
HB_OT_ACCELERATOR (OT, CBDT)
|
||||
HB_OT_ACCELERATOR (OT, sbix)
|
||||
|
1
src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc
vendored
1
src/3rdparty/harfbuzz-ng/src/hb-ot-face.cc
vendored
@ -36,6 +36,7 @@
|
||||
#include "hb-ot-name-table.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
#include "OT/Color/CBDT/CBDT.hh"
|
||||
#include "OT/Color/COLR/COLR.hh"
|
||||
#include "OT/Color/sbix/sbix.hh"
|
||||
#include "OT/Color/svg/svg.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
|
7
src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
vendored
7
src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc
vendored
@ -85,8 +85,8 @@ struct hb_ot_font_t
|
||||
#endif
|
||||
|
||||
/* h_advance caching */
|
||||
mutable hb_atomic_int_t cached_coords_serial;
|
||||
mutable hb_atomic_ptr_t<hb_ot_font_advance_cache_t> advance_cache;
|
||||
mutable hb_atomic_t<int> cached_coords_serial;
|
||||
mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
|
||||
};
|
||||
|
||||
static hb_ot_font_t *
|
||||
@ -471,6 +471,9 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
#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;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#ifndef HB_OT_KERN_TABLE_HH
|
||||
#define HB_OT_KERN_TABLE_HH
|
||||
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-aat-layout-kerx-table.hh"
|
||||
|
||||
|
||||
@ -400,6 +401,7 @@ struct kern
|
||||
|
||||
hb_blob_ptr_t<kern> table;
|
||||
AAT::kern_accelerator_data_t accel_data;
|
||||
AAT::hb_aat_scratch_t scratch;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -2565,7 +2565,7 @@ struct VarRegionList
|
||||
if (cache)
|
||||
{
|
||||
cached_value = &(cache[region_index]);
|
||||
if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
|
||||
if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
|
||||
return *cached_value;
|
||||
}
|
||||
|
||||
@ -2743,7 +2743,7 @@ struct SparseVarRegionList
|
||||
if (cache)
|
||||
{
|
||||
cached_value = &(cache[region_index]);
|
||||
if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
|
||||
if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
|
||||
return *cached_value;
|
||||
}
|
||||
|
||||
|
@ -4900,7 +4900,7 @@ struct GSUBGPOS
|
||||
|
||||
this->lookup_count = table->get_lookup_count ();
|
||||
|
||||
this->accels = (hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *) hb_calloc (this->lookup_count, sizeof (*accels));
|
||||
this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
|
||||
if (unlikely (!this->accels))
|
||||
{
|
||||
this->lookup_count = 0;
|
||||
@ -4948,7 +4948,7 @@ struct GSUBGPOS
|
||||
|
||||
hb_blob_ptr_t<T> table;
|
||||
unsigned int lookup_count;
|
||||
hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *accels;
|
||||
hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *accels;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc
vendored
@ -131,13 +131,15 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_blob_t *blob = font->face->table.kern.get_blob ();
|
||||
const auto& kern = *font->face->table.kern;
|
||||
auto &accel = *font->face->table.kern;
|
||||
hb_blob_t *blob = accel.get_blob ();
|
||||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
|
||||
|
||||
if (!buffer->message (font, "start table kern")) return;
|
||||
kern.apply (&c);
|
||||
c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
|
||||
accel.apply (&c);
|
||||
accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
|
||||
(void) buffer->message (font, "end table kern");
|
||||
}
|
||||
#endif
|
||||
|
16
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
vendored
16
src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh
vendored
@ -202,7 +202,8 @@ enum hb_unicode_props_flags_t {
|
||||
/* If GEN_CAT=FORMAT, top byte masks: */
|
||||
UPROPS_MASK_Cf_ZWJ = 0x0100u,
|
||||
UPROPS_MASK_Cf_ZWNJ = 0x0200u,
|
||||
UPROPS_MASK_Cf_VS = 0x0400u
|
||||
UPROPS_MASK_Cf_VS = 0x0400u,
|
||||
UPROPS_MASK_Cf_AAT_DELETED = 0x0800u
|
||||
};
|
||||
HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
|
||||
|
||||
@ -386,6 +387,8 @@ _hb_grapheme_group_func (const hb_glyph_info_t& a HB_UNUSED,
|
||||
static inline void
|
||||
_hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer)
|
||||
{
|
||||
// MONOTONE_GRAPHEMES was already applied and is taken care of by _hb_grapheme_group_func.
|
||||
// So we just check for MONOTONE_CHARACTERS here.
|
||||
buffer->reverse_groups (_hb_grapheme_group_func,
|
||||
buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
|
||||
}
|
||||
@ -418,6 +421,17 @@ _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
|
||||
return;
|
||||
info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
|
||||
}
|
||||
static inline bool
|
||||
_hb_glyph_info_is_aat_deleted (const hb_glyph_info_t *info)
|
||||
{
|
||||
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_AAT_DELETED);
|
||||
}
|
||||
static inline void
|
||||
_hb_glyph_info_set_aat_deleted (hb_glyph_info_t *info)
|
||||
{
|
||||
_hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT);
|
||||
info->unicode_props() |= UPROPS_MASK_Cf_AAT_DELETED;
|
||||
}
|
||||
|
||||
/* lig_props: aka lig_id / lig_comp
|
||||
*
|
||||
|
@ -290,7 +290,7 @@ struct post
|
||||
const Array16Of<HBUINT16> *glyphNameIndex = nullptr;
|
||||
hb_vector_t<uint32_t> index_to_offset;
|
||||
const uint8_t *pool = nullptr;
|
||||
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
|
||||
hb_atomic_t<uint16_t *> gids_sorted_by_name;
|
||||
};
|
||||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
13
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
13
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
@ -84,6 +84,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
|
||||
props (props),
|
||||
map (face, props)
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
, aat_map (face, props)
|
||||
, apply_morx (_hb_apply_morx (face, props))
|
||||
#endif
|
||||
{
|
||||
@ -106,6 +107,10 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
||||
plan.props = props;
|
||||
plan.shaper = shaper;
|
||||
map.compile (plan.map, key);
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (apply_morx)
|
||||
aat_map.compile (plan.aat_map);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE_FRACTIONS
|
||||
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
|
||||
@ -551,7 +556,7 @@ hb_form_clusters (hb_buffer_t *buffer)
|
||||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
|
||||
return;
|
||||
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
if (HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (buffer->cluster_level))
|
||||
foreach_grapheme (buffer, start, end)
|
||||
buffer->merge_clusters (start, end);
|
||||
else
|
||||
@ -609,7 +614,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
|
||||
* Ogham fonts are supposed to be implemented BTT or not. Need to research that
|
||||
* first. */
|
||||
if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
|
||||
direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
|
||||
direction != horiz_dir && HB_DIRECTION_IS_VALID (horiz_dir)) ||
|
||||
(HB_DIRECTION_IS_VERTICAL (direction) &&
|
||||
direction != HB_DIRECTION_TTB))
|
||||
{
|
||||
@ -1109,10 +1114,6 @@ hb_ot_position_plan (const hb_ot_shape_context_t *c)
|
||||
/* Finish off. Has to follow a certain order. */
|
||||
hb_ot_layout_position_finish_advances (c->font, c->buffer);
|
||||
hb_ot_zero_width_default_ignorables (c->buffer);
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (c->plan->apply_morx)
|
||||
hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
|
||||
#endif
|
||||
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
|
||||
|
||||
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
|
||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.hh
vendored
@ -66,6 +66,7 @@ struct hb_ot_shape_plan_t
|
||||
hb_segment_properties_t props;
|
||||
const struct hb_ot_shaper_t *shaper;
|
||||
hb_ot_map_t map;
|
||||
hb_aat_map_t aat_map;
|
||||
const void *data;
|
||||
#ifndef HB_NO_OT_SHAPE_FRACTIONS
|
||||
hb_mask_t frac_mask, numr_mask, dnom_mask;
|
||||
@ -141,6 +142,7 @@ struct hb_ot_shape_planner_t
|
||||
hb_segment_properties_t props;
|
||||
hb_ot_map_builder_t map;
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
hb_aat_map_builder_t aat_map;
|
||||
bool apply_morx : 1;
|
||||
#else
|
||||
static constexpr bool apply_morx = false;
|
||||
|
@ -260,7 +260,7 @@ struct arabic_shape_plan_t
|
||||
* mask_array[NONE] == 0. */
|
||||
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
|
||||
|
||||
hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
|
||||
hb_atomic_t<arabic_fallback_plan_t *> fallback_plan;
|
||||
|
||||
unsigned int do_fallback : 1;
|
||||
unsigned int has_stch : 1;
|
||||
|
@ -298,8 +298,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
end = start + 2;
|
||||
if (unlikely (!buffer->successful))
|
||||
break;
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
buffer->merge_out_clusters (start, end);
|
||||
buffer->merge_out_clusters (start, end);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -372,8 +371,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
if (i < end)
|
||||
info[i++].hangul_shaping_feature() = TJMO;
|
||||
|
||||
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
buffer->merge_out_clusters (start, end);
|
||||
buffer->merge_out_clusters (start, end);
|
||||
continue;
|
||||
}
|
||||
else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint)))
|
||||
|
@ -301,7 +301,7 @@ struct indic_shape_plan_t
|
||||
#else
|
||||
static constexpr bool uniscribe_bug_compatible = false;
|
||||
#endif
|
||||
mutable hb_atomic_int_t virama_glyph;
|
||||
mutable hb_atomic_t<hb_codepoint_t> virama_glyph;
|
||||
|
||||
hb_indic_would_substitute_feature_t rphf;
|
||||
hb_indic_would_substitute_feature_t pref;
|
||||
|
@ -360,7 +360,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
|
||||
{
|
||||
/* Since we decomposed, and NIKHAHIT is combining, merge clusters with the
|
||||
* previous cluster. */
|
||||
if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
|
||||
if (start)
|
||||
buffer->merge_out_clusters (start - 1, end);
|
||||
}
|
||||
}
|
||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc
vendored
@ -326,7 +326,7 @@ hb_ot_tags_from_language (const char *lang_str,
|
||||
|
||||
hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len);
|
||||
|
||||
static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */
|
||||
static hb_atomic_t<unsigned> last_tag_idx = 0; /* Poor man's cache. */
|
||||
unsigned tag_idx = last_tag_idx;
|
||||
|
||||
if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) ||
|
||||
|
@ -53,10 +53,6 @@ struct hb_glyf_scratch_t
|
||||
contour_point_vector_t deltas;
|
||||
hb_vector_t<unsigned int> shared_indices;
|
||||
hb_vector_t<unsigned int> private_indices;
|
||||
|
||||
// VARC
|
||||
hb_vector_t<unsigned> axisIndices;
|
||||
hb_vector_t<float> axisValues;
|
||||
};
|
||||
|
||||
namespace OT {
|
||||
|
11
src/3rdparty/harfbuzz-ng/src/hb-paint-extents.hh
vendored
11
src/3rdparty/harfbuzz-ng/src/hb-paint-extents.hh
vendored
@ -35,13 +35,22 @@ typedef struct hb_paint_extents_context_t hb_paint_extents_context_t;
|
||||
|
||||
struct hb_paint_extents_context_t
|
||||
{
|
||||
hb_paint_extents_context_t ()
|
||||
void clear ()
|
||||
{
|
||||
transforms.clear ();
|
||||
clips.clear ();
|
||||
groups.clear ();
|
||||
|
||||
transforms.push (hb_transform_t{});
|
||||
clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED});
|
||||
groups.push (hb_bounds_t{hb_bounds_t::EMPTY});
|
||||
}
|
||||
|
||||
hb_paint_extents_context_t ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
hb_extents_t get_extents ()
|
||||
{
|
||||
return groups.tail().extents;
|
||||
|
38
src/3rdparty/harfbuzz-ng/src/hb-paint.cc
vendored
38
src/3rdparty/harfbuzz-ng/src/hb-paint.cc
vendored
@ -464,6 +464,42 @@ hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
funcs->push_transform (paint_data, xx, yx, xy, yy, dx, dy);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_paint_push_font_transform:
|
||||
* @funcs: paint functions
|
||||
* @paint_data: associated data passed by the caller
|
||||
* @font: a font
|
||||
*
|
||||
* Push the transform reflecting the font's scale and slant
|
||||
* settings onto the paint functions.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
void
|
||||
hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
const hb_font_t *font)
|
||||
{
|
||||
funcs->push_font_transform (paint_data, font);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_paint_push_inverse_font_transform:
|
||||
* @funcs: paint functions
|
||||
* @paint_data: associated data passed by the caller
|
||||
* @font: a font
|
||||
*
|
||||
* Push the inverse of the transform reflecting the font's
|
||||
* scale and slant settings onto the paint functions.
|
||||
*
|
||||
* Since: 11.0.0
|
||||
*/
|
||||
void
|
||||
hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
const hb_font_t *font)
|
||||
{
|
||||
funcs->push_inverse_font_transform (paint_data, font);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_paint_pop_transform:
|
||||
* @funcs: paint functions
|
||||
@ -646,7 +682,7 @@ hb_paint_radial_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
float x0, float y0, float r0,
|
||||
float x1, float y1, float r1)
|
||||
{
|
||||
funcs->radial_gradient (paint_data, color_line, x0, y0, r0, y1, x1, r1);
|
||||
funcs->radial_gradient (paint_data, color_line, x0, y0, r0, x1, y1, r1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-paint.h
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-paint.h
vendored
@ -956,6 +956,14 @@ hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
float xy, float yy,
|
||||
float dx, float dy);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
const hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
const hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data);
|
||||
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-paint.hh
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-paint.hh
vendored
@ -157,7 +157,7 @@ struct hb_paint_funcs_t
|
||||
|
||||
/* Internal specializations. */
|
||||
|
||||
void push_root_transform (void *paint_data,
|
||||
void push_font_transform (void *paint_data,
|
||||
const hb_font_t *font)
|
||||
{
|
||||
float upem = font->face->get_upem ();
|
||||
@ -168,8 +168,8 @@ struct hb_paint_funcs_t
|
||||
xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0);
|
||||
}
|
||||
|
||||
void push_inverse_root_transform (void *paint_data,
|
||||
hb_font_t *font)
|
||||
void push_inverse_font_transform (void *paint_data,
|
||||
const hb_font_t *font)
|
||||
{
|
||||
float upem = font->face->get_upem ();
|
||||
int xscale = font->x_scale ? font->x_scale : upem;
|
||||
|
1
src/3rdparty/harfbuzz-ng/src/hb-set.hh
vendored
1
src/3rdparty/harfbuzz-ng/src/hb-set.hh
vendored
@ -30,6 +30,7 @@
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-bit-set-invertible.hh"
|
||||
#include "hb-bit-vector.hh" // Just to include
|
||||
|
||||
|
||||
template <typename impl_t>
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-shape.cc
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-shape.cc
vendored
@ -91,8 +91,10 @@ void free_static_shaper_list ()
|
||||
*
|
||||
* Retrieves the list of shapers supported by HarfBuzz.
|
||||
*
|
||||
* Return value: (transfer none) (array zero-terminated=1): an array of
|
||||
* constant strings
|
||||
* Return value: (transfer none) (array zero-terminated=1): a
|
||||
* `NULL`-terminated array of supported shapers constant string.
|
||||
* The returned array is owned by HarfBuzz and should not be
|
||||
* modified or freed.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
1
src/3rdparty/harfbuzz-ng/src/hb-static.cc
vendored
1
src/3rdparty/harfbuzz-ng/src/hb-static.cc
vendored
@ -41,6 +41,7 @@
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
||||
#ifndef HB_NO_VISIBILITY
|
||||
|
||||
#include "hb-ot-name-language-static.hh"
|
||||
|
||||
uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
||||
|
@ -570,7 +570,7 @@ struct cff_subset_accelerator_t
|
||||
parsed_cs_str_vec_t parsed_charstrings;
|
||||
parsed_cs_str_vec_t parsed_global_subrs;
|
||||
hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs;
|
||||
mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map;
|
||||
mutable hb_atomic_t<glyph_to_sid_map_t *> glyph_to_sid_map;
|
||||
|
||||
private:
|
||||
hb_blob_t* original_blob;
|
||||
|
9
src/3rdparty/harfbuzz-ng/src/hb-vector.hh
vendored
9
src/3rdparty/harfbuzz-ng/src/hb-vector.hh
vendored
@ -90,7 +90,13 @@ struct hb_vector_t
|
||||
{
|
||||
auto iter = hb_iter (o);
|
||||
if (iter.is_random_access_iterator || iter.has_fast_len)
|
||||
alloc (hb_len (iter), true);
|
||||
{
|
||||
if (unlikely (!alloc (hb_len (iter), true)))
|
||||
return;
|
||||
unsigned count = hb_len (iter);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
push_has_room (*iter++);
|
||||
}
|
||||
while (iter)
|
||||
{
|
||||
if (unlikely (!alloc (length + 1)))
|
||||
@ -436,7 +442,6 @@ struct hb_vector_t
|
||||
new_allocated += (new_allocated >> 1) + 8;
|
||||
}
|
||||
|
||||
|
||||
/* Reallocate */
|
||||
|
||||
bool overflows =
|
||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
@ -41,13 +41,13 @@ HB_BEGIN_DECLS
|
||||
*
|
||||
* The major component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MAJOR 10
|
||||
#define HB_VERSION_MAJOR 11
|
||||
/**
|
||||
* HB_VERSION_MINOR:
|
||||
*
|
||||
* The minor component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MINOR 4
|
||||
#define HB_VERSION_MINOR 0
|
||||
/**
|
||||
* HB_VERSION_MICRO:
|
||||
*
|
||||
@ -60,7 +60,7 @@ HB_BEGIN_DECLS
|
||||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "10.4.0"
|
||||
#define HB_VERSION_STRING "11.0.0"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
@ -113,7 +113,7 @@ struct hb_wasm_shape_plan_t {
|
||||
struct hb_wasm_face_data_t {
|
||||
hb_blob_t *wasm_blob;
|
||||
wasm_module_t wasm_module;
|
||||
mutable hb_atomic_ptr_t<hb_wasm_shape_plan_t> plan;
|
||||
mutable hb_atomic_t<hb_wasm_shape_plan_t *> plan;
|
||||
};
|
||||
|
||||
static bool
|
||||
|
52
src/3rdparty/harfbuzz-ng/src/hb.hh
vendored
52
src/3rdparty/harfbuzz-ng/src/hb.hh
vendored
@ -230,33 +230,6 @@
|
||||
#define HB_PASTE(a,b) HB_PASTE1(a,b)
|
||||
|
||||
|
||||
/* Compile-time custom allocator support. */
|
||||
|
||||
#if !defined(HB_CUSTOM_MALLOC) \
|
||||
&& defined(hb_malloc_impl) \
|
||||
&& defined(hb_calloc_impl) \
|
||||
&& defined(hb_realloc_impl) \
|
||||
&& defined(hb_free_impl)
|
||||
#define HB_CUSTOM_MALLOC
|
||||
#endif
|
||||
|
||||
#ifdef HB_CUSTOM_MALLOC
|
||||
extern "C" void* hb_malloc_impl(size_t size);
|
||||
extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
|
||||
extern "C" void* hb_realloc_impl(void *ptr, size_t size);
|
||||
extern "C" void hb_free_impl(void *ptr);
|
||||
#define hb_malloc hb_malloc_impl
|
||||
#define hb_calloc hb_calloc_impl
|
||||
#define hb_realloc hb_realloc_impl
|
||||
#define hb_free hb_free_impl
|
||||
#else
|
||||
#define hb_malloc malloc
|
||||
#define hb_calloc calloc
|
||||
#define hb_realloc realloc
|
||||
#define hb_free free
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Compiler attributes
|
||||
*/
|
||||
@ -282,7 +255,7 @@ extern "C" void hb_free_impl(void *ptr);
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__) && (__GNUC__ >= 3)
|
||||
#if defined(__MINGW32__) && (__GNUC__ >= 3) && !defined(__clang__)
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (gnu_printf, format_idx, arg_idx)))
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
|
||||
@ -539,6 +512,29 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
|
||||
#define HB_PI 3.14159265358979f
|
||||
#define HB_2_PI (2.f * HB_PI)
|
||||
|
||||
/* Compile-time custom allocator support. */
|
||||
|
||||
#if !defined(HB_CUSTOM_MALLOC) \
|
||||
&& defined(hb_malloc_impl) \
|
||||
&& defined(hb_calloc_impl) \
|
||||
&& defined(hb_realloc_impl) \
|
||||
&& defined(hb_free_impl)
|
||||
#define HB_CUSTOM_MALLOC
|
||||
#endif
|
||||
|
||||
#ifdef HB_CUSTOM_MALLOC
|
||||
extern "C" void* hb_malloc_impl(size_t size);
|
||||
extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
|
||||
extern "C" void* hb_realloc_impl(void *ptr, size_t size);
|
||||
extern "C" void hb_free_impl(void *ptr);
|
||||
#else
|
||||
#define hb_malloc_impl malloc
|
||||
#define hb_calloc_impl calloc
|
||||
#define hb_realloc_impl realloc
|
||||
#define hb_free_impl free
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Headers we include for everyone. Keep topologically sorted by dependency.
|
||||
* They express dependency amongst themselves, but no other file should include
|
||||
|
Loading…
x
Reference in New Issue
Block a user