mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-11 16:33:42 +00:00
8355528: Update HarfBuzz to 11.2.0
Reviewed-by: dnguyen, prr
This commit is contained in:
parent
a6995a3d42
commit
b21b3a38a5
@ -1,4 +1,4 @@
|
||||
## Harfbuzz v10.4.0
|
||||
## Harfbuzz 11.2.0
|
||||
|
||||
### Harfbuzz License
|
||||
|
||||
|
||||
@ -949,25 +949,25 @@ struct CBDT
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_glyph_extents_t pixel_extents;
|
||||
hb_blob_t *blob = reference_png (font, glyph);
|
||||
|
||||
if (unlikely (blob == hb_blob_get_empty ()))
|
||||
return false;
|
||||
|
||||
if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents)))
|
||||
if (unlikely (!font->get_glyph_extents (glyph, &extents, false)))
|
||||
return false;
|
||||
|
||||
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
|
||||
return false;
|
||||
|
||||
hb_blob_t *blob = reference_png (font, glyph);
|
||||
if (unlikely (hb_blob_is_immutable (blob)))
|
||||
return false;
|
||||
|
||||
bool ret = funcs->image (data,
|
||||
blob,
|
||||
pixel_extents.width, -pixel_extents.height,
|
||||
HB_PAINT_IMAGE_FORMAT_PNG,
|
||||
font->slant_xy,
|
||||
0.f,
|
||||
&extents);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-ot-var-common.hh"
|
||||
#include "../../../hb-paint.hh"
|
||||
#include "../../../hb-paint-bounded.hh"
|
||||
#include "../../../hb-paint-extents.hh"
|
||||
|
||||
#include "../CPAL/CPAL.hh"
|
||||
@ -47,6 +48,12 @@ namespace OT {
|
||||
struct hb_paint_context_t;
|
||||
}
|
||||
|
||||
struct hb_colr_scratch_t
|
||||
{
|
||||
hb_paint_bounded_context_t paint_bounded;
|
||||
hb_paint_extents_context_t paint_extents;
|
||||
};
|
||||
|
||||
namespace OT {
|
||||
|
||||
struct COLR;
|
||||
@ -90,12 +97,27 @@ 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_),
|
||||
instancer (instancer_)
|
||||
{ }
|
||||
{
|
||||
if (font->is_synthetic ())
|
||||
{
|
||||
font = hb_font_create_sub_font (font);
|
||||
hb_font_set_synthetic_bold (font, 0, 0, true);
|
||||
hb_font_set_synthetic_slant (font, 0);
|
||||
}
|
||||
else
|
||||
hb_font_reference (font);
|
||||
}
|
||||
|
||||
~hb_paint_context_t ()
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground)
|
||||
{
|
||||
@ -932,9 +954,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 +1533,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 */
|
||||
@ -1612,7 +1636,7 @@ struct ClipBox
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 2: u.format2.closurev1 (c);
|
||||
case 2: u.format2.closurev1 (c); return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
@ -2079,6 +2103,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 +2138,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 +2220,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:
|
||||
mutable hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
void closure_glyphs (hb_codepoint_t glyph,
|
||||
@ -2520,7 +2618,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 +2635,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;
|
||||
@ -2583,7 +2684,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 (),
|
||||
@ -2617,26 +2723,26 @@ struct COLR
|
||||
}
|
||||
else
|
||||
{
|
||||
auto *extents_funcs = hb_paint_extents_get_funcs ();
|
||||
hb_paint_extents_context_t extents_data;
|
||||
clip = false;
|
||||
is_bounded = false;
|
||||
}
|
||||
|
||||
if (!is_bounded)
|
||||
{
|
||||
auto *bounded_funcs = hb_paint_bounded_get_funcs ();
|
||||
scratch.paint_bounded.clear ();
|
||||
|
||||
paint_glyph (font, glyph,
|
||||
extents_funcs, &extents_data,
|
||||
bounded_funcs, &scratch.paint_bounded,
|
||||
palette_index, foreground,
|
||||
false);
|
||||
false,
|
||||
scratch);
|
||||
|
||||
hb_extents_t extents = extents_data.get_extents ();
|
||||
is_bounded = extents_data.is_bounded ();
|
||||
|
||||
c.funcs->push_clip_rectangle (c.data,
|
||||
extents.xmin,
|
||||
extents.ymin,
|
||||
extents.xmax,
|
||||
extents.ymax);
|
||||
is_bounded = scratch.paint_bounded.is_bounded ();
|
||||
}
|
||||
}
|
||||
|
||||
c.funcs->push_root_transform (c.data, font);
|
||||
c.funcs->push_font_transform (c.data, font);
|
||||
|
||||
if (is_bounded)
|
||||
c.recurse (*paint);
|
||||
@ -2714,9 +2820,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 +2832,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);
|
||||
|
||||
@ -237,27 +237,28 @@ struct sbix
|
||||
|
||||
int x_offset = 0, y_offset = 0;
|
||||
unsigned int strike_ppem = 0;
|
||||
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
|
||||
hb_glyph_extents_t extents;
|
||||
hb_glyph_extents_t pixel_extents;
|
||||
|
||||
if (blob == hb_blob_get_empty ())
|
||||
return false;
|
||||
|
||||
if (!hb_font_get_glyph_extents (font, glyph, &extents))
|
||||
if (!font->get_glyph_extents (glyph, &extents, false))
|
||||
return false;
|
||||
|
||||
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
|
||||
return false;
|
||||
|
||||
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
|
||||
if (hb_blob_is_immutable (blob))
|
||||
return false;
|
||||
|
||||
bool ret = funcs->image (data,
|
||||
blob,
|
||||
pixel_extents.width, -pixel_extents.height,
|
||||
HB_PAINT_IMAGE_FORMAT_PNG,
|
||||
font->slant_xy,
|
||||
0.f,
|
||||
&extents);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -104,15 +104,16 @@ struct SVG
|
||||
if (blob == hb_blob_get_empty ())
|
||||
return false;
|
||||
|
||||
funcs->image (data,
|
||||
blob,
|
||||
0, 0,
|
||||
HB_PAINT_IMAGE_FORMAT_SVG,
|
||||
font->slant_xy,
|
||||
nullptr);
|
||||
bool ret = funcs->image (data,
|
||||
blob,
|
||||
0, 0,
|
||||
HB_PAINT_IMAGE_FORMAT_SVG,
|
||||
0.f,
|
||||
nullptr);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
return true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -77,7 +77,7 @@ struct CoverageFormat1_3
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
|
||||
@ -120,7 +120,7 @@ struct CoverageFormat2_4
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
|
||||
@ -205,20 +205,19 @@ struct CaretValueFormat3
|
||||
|
||||
unsigned varidx = (this+deviceTable).get_variation_index ();
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) {
|
||||
uint32_t new_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
uint32_t new_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
if (!c->serializer->embed (deviceTable))
|
||||
return_trace (false);
|
||||
|
||||
@ -1015,7 +1014,8 @@ struct GDEF
|
||||
hb_blob_ptr_t<GDEF> table;
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
hb_vector_t<hb_set_digest_t> mark_glyph_set_digests;
|
||||
mutable hb_cache_t<21, 3, 8> glyph_props_cache;
|
||||
mutable hb_cache_t<21, 3> glyph_props_cache;
|
||||
static_assert (sizeof (glyph_props_cache) == 512, "");
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -152,8 +152,11 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
|
||||
if (unlikely (font->slant))
|
||||
if (unlikely (font->slant_xy) &&
|
||||
HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
{
|
||||
/* Slanting shaping results is only supported for horizontal text,
|
||||
* as it gets weird otherwise. */
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (unlikely (pos[i].y_offset))
|
||||
pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset);
|
||||
|
||||
@ -54,7 +54,7 @@ struct PairPosFormat1_3
|
||||
{
|
||||
auto &cov = this+coverage;
|
||||
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len))
|
||||
{
|
||||
for (hb_codepoint_t g : glyphs->iter())
|
||||
{
|
||||
|
||||
@ -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;
|
||||
mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
bool has_data () const { return version.major != 0; }
|
||||
|
||||
@ -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;
|
||||
mutable hb_atomic_t<hb_glyf_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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,69 @@ 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)
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
|
||||
_hb_glyph_info_set_aat_deleted (&buffer->cur());
|
||||
}
|
||||
|
||||
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 +234,6 @@ struct hb_aat_apply_context_t :
|
||||
* Lookup Table
|
||||
*/
|
||||
|
||||
enum { DELETED_GLYPH = 0xFFFF };
|
||||
|
||||
template <typename T> struct Lookup;
|
||||
|
||||
template <typename T>
|
||||
@ -179,6 +298,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 +388,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 +489,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 +868,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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
|
||||
/*
|
||||
* trak -- Tracking
|
||||
@ -115,7 +116,7 @@ struct TrackTableEntry
|
||||
|
||||
protected:
|
||||
F16DOT16 track; /* Track value for this record. */
|
||||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
OT::NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
NNOffset16To<UnsizedArrayOf<FWORD>>
|
||||
@ -142,9 +143,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.
|
||||
@ -200,6 +201,46 @@ struct trak
|
||||
float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
|
||||
return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track));
|
||||
}
|
||||
hb_position_t get_tracking (hb_font_t *font, hb_direction_t dir, float track = 0.f) const
|
||||
{
|
||||
#ifndef HB_NO_STYLE
|
||||
if (!font->face->table.STAT->has_data ())
|
||||
return 0;
|
||||
return HB_DIRECTION_IS_HORIZONTAL (dir) ?
|
||||
get_h_tracking (font, track) :
|
||||
get_v_tracking (font, track);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool apply (hb_aat_apply_context_t *c, float track = 0.f) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
float ptem = c->font->ptem;
|
||||
if (unlikely (ptem <= 0.f))
|
||||
{
|
||||
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
|
||||
ptem = HB_CORETEXT_DEFAULT_FONT_SIZE;
|
||||
}
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
{
|
||||
hb_position_t advance_to_add = get_h_tracking (c->font, track);
|
||||
foreach_grapheme (buffer, start, end)
|
||||
buffer->pos[start].x_advance += advance_to_add;
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_position_t advance_to_add = get_v_tracking (c->font, track);
|
||||
foreach_grapheme (buffer, start, end)
|
||||
buffer->pos[start].y_advance += advance_to_add;
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-aat-layout-kerx-table.hh"
|
||||
#include "hb-aat-layout-morx-table.hh"
|
||||
#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-aat-layout-trak-table.hh"
|
||||
#include "hb-aat-ltag-table.hh"
|
||||
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -394,6 +394,17 @@ hb_aat_layout_has_tracking (hb_face_t *face)
|
||||
return face->table.trak->has_data ();
|
||||
}
|
||||
|
||||
void
|
||||
hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
const AAT::trak& trak = *font->face->table.trak;
|
||||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer);
|
||||
trak.apply (&c);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_aat_layout_get_feature_types:
|
||||
* @face: #hb_face_t to work upon
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -71,5 +68,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
|
||||
#endif /* HB_AAT_LAYOUT_HH */
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -80,15 +80,14 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#define _hb_memory_barrier() std::atomic_thread_fence(std::memory_order_ack_rel)
|
||||
#define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire)
|
||||
#define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release)
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
|
||||
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_release))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_acquire))
|
||||
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
|
||||
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_release))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_acquire))
|
||||
|
||||
#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> const *> (P)->load (std::memory_order_relaxed))
|
||||
@ -149,68 +148,53 @@ 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_); }
|
||||
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
|
||||
T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
|
||||
bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
|
||||
bool cmpexch (const T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
|
||||
|
||||
operator bool () const { return get_acquire () != nullptr; }
|
||||
T * operator -> () const { return get_acquire (); }
|
||||
|
||||
@ -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/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh
Normal file
195
src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh
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
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
**/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -370,6 +370,18 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
|
||||
|
||||
len++;
|
||||
}
|
||||
void
|
||||
hb_buffer_t::add_info_and_pos (const hb_glyph_info_t &glyph_info,
|
||||
const hb_glyph_position_t &glyph_pos)
|
||||
{
|
||||
if (unlikely (!ensure (len + 1))) return;
|
||||
|
||||
info[len] = glyph_info;
|
||||
assert (have_positions);
|
||||
pos[len] = glyph_pos;
|
||||
|
||||
len++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
@ -518,7 +530,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 +563,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))
|
||||
|
||||
@ -422,6 +422,7 @@ 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
|
||||
@ -429,11 +430,26 @@ hb_buffer_get_flags (const hb_buffer_t *buffer);
|
||||
*
|
||||
* 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);
|
||||
|
||||
@ -229,6 +229,8 @@ struct hb_buffer_t
|
||||
HB_INTERNAL void add (hb_codepoint_t codepoint,
|
||||
unsigned int cluster);
|
||||
HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
|
||||
HB_INTERNAL void add_info_and_pos (const hb_glyph_info_t &glyph_info,
|
||||
const hb_glyph_position_t &glyph_pos);
|
||||
|
||||
void reverse_range (unsigned start, unsigned end)
|
||||
{
|
||||
@ -410,6 +412,9 @@ struct hb_buffer_t
|
||||
{
|
||||
end = hb_min (end, len);
|
||||
|
||||
if (unlikely (end - start > 255))
|
||||
return;
|
||||
|
||||
if (interior && !from_out_buffer && end - start < 2)
|
||||
return;
|
||||
|
||||
|
||||
@ -30,18 +30,31 @@
|
||||
#include "hb.hh"
|
||||
|
||||
|
||||
/* Implements a lockfree cache for int->int functions.
|
||||
/* Implements a lockfree and thread-safe cache for int->int functions,
|
||||
* using (optionally) _relaxed_ atomic integer operations.
|
||||
*
|
||||
* The cache is a fixed-size array of 16-bit or 32-bit integers.
|
||||
* The key is split into two parts: the cache index and the rest.
|
||||
* The cache is a fixed-size array of 16-bit or 32-bit integers,
|
||||
* typically 256 elements.
|
||||
*
|
||||
* The cache index is used to index into the array. The rest is used
|
||||
* to store the key and the value.
|
||||
* The key is split into two parts: the cache index (high bits)
|
||||
* and the rest (low bits).
|
||||
*
|
||||
* The cache index is used to index into the array. The array
|
||||
* member is a 16-bit or 32-bit integer that is used *both*
|
||||
* to store the low bits of the key, and the value.
|
||||
*
|
||||
* The value is stored in the least significant bits of the integer.
|
||||
* The key is stored in the most significant bits of the integer.
|
||||
* The key is shifted by cache_bits to the left to make room for the
|
||||
* value.
|
||||
* The low bits of the key are stored in the most significant bits
|
||||
* of the integer.
|
||||
*
|
||||
* A cache hit is detected by comparing the low bits of the key
|
||||
* with the high bits of the integer at the array position indexed
|
||||
* by the high bits of the key. If they match, the value is extracted
|
||||
* from the least significant bits of the integer and returned.
|
||||
* Otherwise, a cache miss is reported.
|
||||
*
|
||||
* Cache operations (storage and retrieval) involve just a few
|
||||
* arithmetic operations and a single memory access.
|
||||
*/
|
||||
|
||||
template <unsigned int key_bits=16,
|
||||
@ -52,11 +65,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), "");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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__))
|
||||
@ -337,437 +338,7 @@ HB_EXTERN hb_bool_t
|
||||
hb_language_matches (hb_language_t language,
|
||||
hb_language_t specific);
|
||||
|
||||
/**
|
||||
* hb_script_t:
|
||||
* @HB_SCRIPT_COMMON: `Zyyy`
|
||||
* @HB_SCRIPT_INHERITED: `Zinh`
|
||||
* @HB_SCRIPT_UNKNOWN: `Zzzz`
|
||||
* @HB_SCRIPT_ARABIC: `Arab`
|
||||
* @HB_SCRIPT_ARMENIAN: `Armn`
|
||||
* @HB_SCRIPT_BENGALI: `Beng`
|
||||
* @HB_SCRIPT_CYRILLIC: `Cyrl`
|
||||
* @HB_SCRIPT_DEVANAGARI: `Deva`
|
||||
* @HB_SCRIPT_GEORGIAN: `Geor`
|
||||
* @HB_SCRIPT_GREEK: `Grek`
|
||||
* @HB_SCRIPT_GUJARATI: `Gujr`
|
||||
* @HB_SCRIPT_GURMUKHI: `Guru`
|
||||
* @HB_SCRIPT_HANGUL: `Hang`
|
||||
* @HB_SCRIPT_HAN: `Hani`
|
||||
* @HB_SCRIPT_HEBREW: `Hebr`
|
||||
* @HB_SCRIPT_HIRAGANA: `Hira`
|
||||
* @HB_SCRIPT_KANNADA: `Knda`
|
||||
* @HB_SCRIPT_KATAKANA: `Kana`
|
||||
* @HB_SCRIPT_LAO: `Laoo`
|
||||
* @HB_SCRIPT_LATIN: `Latn`
|
||||
* @HB_SCRIPT_MALAYALAM: `Mlym`
|
||||
* @HB_SCRIPT_ORIYA: `Orya`
|
||||
* @HB_SCRIPT_TAMIL: `Taml`
|
||||
* @HB_SCRIPT_TELUGU: `Telu`
|
||||
* @HB_SCRIPT_THAI: `Thai`
|
||||
* @HB_SCRIPT_TIBETAN: `Tibt`
|
||||
* @HB_SCRIPT_BOPOMOFO: `Bopo`
|
||||
* @HB_SCRIPT_BRAILLE: `Brai`
|
||||
* @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans`
|
||||
* @HB_SCRIPT_CHEROKEE: `Cher`
|
||||
* @HB_SCRIPT_ETHIOPIC: `Ethi`
|
||||
* @HB_SCRIPT_KHMER: `Khmr`
|
||||
* @HB_SCRIPT_MONGOLIAN: `Mong`
|
||||
* @HB_SCRIPT_MYANMAR: `Mymr`
|
||||
* @HB_SCRIPT_OGHAM: `Ogam`
|
||||
* @HB_SCRIPT_RUNIC: `Runr`
|
||||
* @HB_SCRIPT_SINHALA: `Sinh`
|
||||
* @HB_SCRIPT_SYRIAC: `Syrc`
|
||||
* @HB_SCRIPT_THAANA: `Thaa`
|
||||
* @HB_SCRIPT_YI: `Yiii`
|
||||
* @HB_SCRIPT_DESERET: `Dsrt`
|
||||
* @HB_SCRIPT_GOTHIC: `Goth`
|
||||
* @HB_SCRIPT_OLD_ITALIC: `Ital`
|
||||
* @HB_SCRIPT_BUHID: `Buhd`
|
||||
* @HB_SCRIPT_HANUNOO: `Hano`
|
||||
* @HB_SCRIPT_TAGALOG: `Tglg`
|
||||
* @HB_SCRIPT_TAGBANWA: `Tagb`
|
||||
* @HB_SCRIPT_CYPRIOT: `Cprt`
|
||||
* @HB_SCRIPT_LIMBU: `Limb`
|
||||
* @HB_SCRIPT_LINEAR_B: `Linb`
|
||||
* @HB_SCRIPT_OSMANYA: `Osma`
|
||||
* @HB_SCRIPT_SHAVIAN: `Shaw`
|
||||
* @HB_SCRIPT_TAI_LE: `Tale`
|
||||
* @HB_SCRIPT_UGARITIC: `Ugar`
|
||||
* @HB_SCRIPT_BUGINESE: `Bugi`
|
||||
* @HB_SCRIPT_COPTIC: `Copt`
|
||||
* @HB_SCRIPT_GLAGOLITIC: `Glag`
|
||||
* @HB_SCRIPT_KHAROSHTHI: `Khar`
|
||||
* @HB_SCRIPT_NEW_TAI_LUE: `Talu`
|
||||
* @HB_SCRIPT_OLD_PERSIAN: `Xpeo`
|
||||
* @HB_SCRIPT_SYLOTI_NAGRI: `Sylo`
|
||||
* @HB_SCRIPT_TIFINAGH: `Tfng`
|
||||
* @HB_SCRIPT_BALINESE: `Bali`
|
||||
* @HB_SCRIPT_CUNEIFORM: `Xsux`
|
||||
* @HB_SCRIPT_NKO: `Nkoo`
|
||||
* @HB_SCRIPT_PHAGS_PA: `Phag`
|
||||
* @HB_SCRIPT_PHOENICIAN: `Phnx`
|
||||
* @HB_SCRIPT_CARIAN: `Cari`
|
||||
* @HB_SCRIPT_CHAM: `Cham`
|
||||
* @HB_SCRIPT_KAYAH_LI: `Kali`
|
||||
* @HB_SCRIPT_LEPCHA: `Lepc`
|
||||
* @HB_SCRIPT_LYCIAN: `Lyci`
|
||||
* @HB_SCRIPT_LYDIAN: `Lydi`
|
||||
* @HB_SCRIPT_OL_CHIKI: `Olck`
|
||||
* @HB_SCRIPT_REJANG: `Rjng`
|
||||
* @HB_SCRIPT_SAURASHTRA: `Saur`
|
||||
* @HB_SCRIPT_SUNDANESE: `Sund`
|
||||
* @HB_SCRIPT_VAI: `Vaii`
|
||||
* @HB_SCRIPT_AVESTAN: `Avst`
|
||||
* @HB_SCRIPT_BAMUM: `Bamu`
|
||||
* @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp`
|
||||
* @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi`
|
||||
* @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli`
|
||||
* @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti`
|
||||
* @HB_SCRIPT_JAVANESE: `Java`
|
||||
* @HB_SCRIPT_KAITHI: `Kthi`
|
||||
* @HB_SCRIPT_LISU: `Lisu`
|
||||
* @HB_SCRIPT_MEETEI_MAYEK: `Mtei`
|
||||
* @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb`
|
||||
* @HB_SCRIPT_OLD_TURKIC: `Orkh`
|
||||
* @HB_SCRIPT_SAMARITAN: `Samr`
|
||||
* @HB_SCRIPT_TAI_THAM: `Lana`
|
||||
* @HB_SCRIPT_TAI_VIET: `Tavt`
|
||||
* @HB_SCRIPT_BATAK: `Batk`
|
||||
* @HB_SCRIPT_BRAHMI: `Brah`
|
||||
* @HB_SCRIPT_MANDAIC: `Mand`
|
||||
* @HB_SCRIPT_CHAKMA: `Cakm`
|
||||
* @HB_SCRIPT_MEROITIC_CURSIVE: `Merc`
|
||||
* @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero`
|
||||
* @HB_SCRIPT_MIAO: `Plrd`
|
||||
* @HB_SCRIPT_SHARADA: `Shrd`
|
||||
* @HB_SCRIPT_SORA_SOMPENG: `Sora`
|
||||
* @HB_SCRIPT_TAKRI: `Takr`
|
||||
* @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30
|
||||
* @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30
|
||||
* @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30
|
||||
* @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30
|
||||
* @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30
|
||||
* @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30
|
||||
* @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30
|
||||
* @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30
|
||||
* @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30
|
||||
* @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30
|
||||
* @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30
|
||||
* @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30
|
||||
* @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30
|
||||
* @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30
|
||||
* @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30
|
||||
* @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30
|
||||
* @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30
|
||||
* @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30
|
||||
* @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30
|
||||
* @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0
|
||||
* @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0
|
||||
* @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0
|
||||
* @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0
|
||||
* @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0
|
||||
* @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0
|
||||
* @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0
|
||||
* @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0
|
||||
* @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0
|
||||
* @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0
|
||||
* @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0
|
||||
* @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0
|
||||
* @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0
|
||||
* @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0
|
||||
* @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0
|
||||
* @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0
|
||||
* @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0
|
||||
* @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0
|
||||
* @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0
|
||||
* @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0
|
||||
* @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0
|
||||
* @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7
|
||||
* @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
|
||||
* @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
|
||||
* @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
|
||||
* @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0
|
||||
* @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
|
||||
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
|
||||
* @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
|
||||
* @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0
|
||||
* @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0
|
||||
* @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0
|
||||
* @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0
|
||||
* @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0
|
||||
* @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0
|
||||
* @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0
|
||||
* @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0
|
||||
* @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0
|
||||
* @HB_SCRIPT_INVALID: No script set
|
||||
*
|
||||
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
|
||||
* to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/).
|
||||
*
|
||||
* See also the Script (sc) property of the Unicode Character Database.
|
||||
*
|
||||
**/
|
||||
|
||||
/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
|
||||
typedef enum
|
||||
{
|
||||
HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/
|
||||
HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/
|
||||
HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/
|
||||
|
||||
HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/
|
||||
HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/
|
||||
HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/
|
||||
HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/
|
||||
HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/
|
||||
HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/
|
||||
HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/
|
||||
HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/
|
||||
HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/
|
||||
HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/
|
||||
HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/
|
||||
HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/
|
||||
HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/
|
||||
HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/
|
||||
HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/
|
||||
HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/
|
||||
HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/
|
||||
HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/
|
||||
HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/
|
||||
HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/
|
||||
HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/
|
||||
HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/
|
||||
|
||||
HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/
|
||||
|
||||
HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/
|
||||
HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/
|
||||
HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/
|
||||
HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/
|
||||
HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/
|
||||
HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/
|
||||
HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/
|
||||
HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/
|
||||
HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/
|
||||
HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/
|
||||
HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/
|
||||
HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/
|
||||
HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/
|
||||
HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/
|
||||
|
||||
HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/
|
||||
HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/
|
||||
HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/
|
||||
|
||||
HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/
|
||||
HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/
|
||||
HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/
|
||||
HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/
|
||||
|
||||
HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/
|
||||
HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/
|
||||
HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/
|
||||
HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/
|
||||
HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/
|
||||
HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/
|
||||
HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/
|
||||
|
||||
HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/
|
||||
HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/
|
||||
HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/
|
||||
HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/
|
||||
HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/
|
||||
HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/
|
||||
HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/
|
||||
HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/
|
||||
|
||||
HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/
|
||||
HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/
|
||||
HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/
|
||||
HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/
|
||||
HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/
|
||||
|
||||
HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/
|
||||
HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/
|
||||
HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/
|
||||
HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/
|
||||
HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/
|
||||
HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/
|
||||
HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/
|
||||
HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/
|
||||
HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/
|
||||
HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/
|
||||
HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/
|
||||
|
||||
HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/
|
||||
HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/
|
||||
HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/
|
||||
HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/
|
||||
HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/
|
||||
HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/
|
||||
HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/
|
||||
HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/
|
||||
HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/
|
||||
HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/
|
||||
HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/
|
||||
HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/
|
||||
HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/
|
||||
HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/
|
||||
HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/
|
||||
|
||||
HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/
|
||||
HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/
|
||||
HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/
|
||||
|
||||
HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/
|
||||
HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/
|
||||
HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/
|
||||
HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/
|
||||
HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/
|
||||
HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/
|
||||
HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/
|
||||
|
||||
/*
|
||||
* Since: 0.9.30
|
||||
*/
|
||||
HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/
|
||||
HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/
|
||||
HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/
|
||||
HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/
|
||||
HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/
|
||||
HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/
|
||||
HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/
|
||||
HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/
|
||||
HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/
|
||||
HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/
|
||||
HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/
|
||||
HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/
|
||||
HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/
|
||||
HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/
|
||||
HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/
|
||||
HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/
|
||||
HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/
|
||||
HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/
|
||||
HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/
|
||||
HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/
|
||||
HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/
|
||||
HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/
|
||||
HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/
|
||||
|
||||
HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/
|
||||
HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/
|
||||
HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/
|
||||
HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/
|
||||
HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/
|
||||
HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/
|
||||
|
||||
/*
|
||||
* Since 1.3.0
|
||||
*/
|
||||
HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/
|
||||
HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/
|
||||
HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/
|
||||
HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/
|
||||
HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/
|
||||
HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/
|
||||
|
||||
/*
|
||||
* Since 1.6.0
|
||||
*/
|
||||
HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/
|
||||
HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/
|
||||
HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/
|
||||
HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/
|
||||
|
||||
/*
|
||||
* Since 1.8.0
|
||||
*/
|
||||
HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/
|
||||
HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/
|
||||
HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/
|
||||
HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/
|
||||
HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/
|
||||
HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/
|
||||
HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/
|
||||
|
||||
/*
|
||||
* Since 2.4.0
|
||||
*/
|
||||
HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/
|
||||
HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/
|
||||
HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/
|
||||
HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/
|
||||
|
||||
/*
|
||||
* Since 2.6.7
|
||||
*/
|
||||
HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/
|
||||
HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/
|
||||
HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
|
||||
HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
|
||||
|
||||
/*
|
||||
* Since 3.0.0
|
||||
*/
|
||||
HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/
|
||||
HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/
|
||||
HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/
|
||||
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
|
||||
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
|
||||
|
||||
/*
|
||||
* Since 3.4.0
|
||||
*/
|
||||
HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
|
||||
|
||||
/*
|
||||
* Since 5.2.0
|
||||
*/
|
||||
HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/
|
||||
HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/
|
||||
|
||||
/*
|
||||
* Since 10.0.0
|
||||
*/
|
||||
HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/
|
||||
HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/
|
||||
HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/
|
||||
HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/
|
||||
HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/
|
||||
HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/
|
||||
HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/
|
||||
|
||||
/* No script set. */
|
||||
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
/*< private >*/
|
||||
|
||||
/* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
||||
* without risking undefined behavior. We have two, for historical reasons.
|
||||
* HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed
|
||||
* to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well.
|
||||
*
|
||||
* See this thread for technicalities:
|
||||
*
|
||||
* https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
|
||||
*/
|
||||
_HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/
|
||||
_HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
|
||||
} hb_script_t;
|
||||
|
||||
#include "hb-script-list.h"
|
||||
|
||||
/* Script functions */
|
||||
|
||||
@ -948,6 +519,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 */
|
||||
|
||||
@ -146,6 +146,7 @@
|
||||
|
||||
#ifdef HB_NO_DRAW
|
||||
#define HB_NO_OUTLINE
|
||||
#define HB_NO_PAINT
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_GETENV
|
||||
@ -191,7 +192,6 @@
|
||||
#ifdef HB_MINIMIZE_MEMORY_USAGE
|
||||
#define HB_NO_GDEF_CACHE
|
||||
#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
#define HB_NO_OT_FONT_ADVANCE_CACHE
|
||||
#define HB_NO_OT_FONT_CMAP_CACHE
|
||||
#endif
|
||||
|
||||
|
||||
@ -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 ()
|
||||
|
||||
@ -275,6 +275,48 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* hb_font_draw_glyph_func_t:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @font_data: @font user data pointer
|
||||
* @glyph: The glyph ID to query
|
||||
* @draw_funcs: The draw functions to send the shape data to
|
||||
* @draw_data: The data accompanying the draw functions
|
||||
* @user_data: User data pointer passed by the caller
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_draw_glyph_func_or_fail_t instead.
|
||||
**/
|
||||
typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* hb_font_paint_glyph_func_t:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @font_data: @font user data pointer
|
||||
* @glyph: The glyph ID to query
|
||||
* @paint_funcs: The paint functions to use
|
||||
* @paint_data: The data accompanying the paint functions
|
||||
* @palette_index: The color palette to use
|
||||
* @foreground: The foreground color
|
||||
* @user_data: User data pointer passed by the caller
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_paint_glyph_or_fail_func_t instead.
|
||||
*/
|
||||
typedef hb_bool_t (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_shape_func:
|
||||
* @ffuncs: A font-function structure
|
||||
@ -288,13 +330,49 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
|
||||
* Since: 4.0.0
|
||||
* Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
|
||||
**/
|
||||
HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func)
|
||||
HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_shape_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
HB_DEPRECATED_FOR (hb_font_draw_glyph)
|
||||
/**
|
||||
* hb_font_funcs_set_draw_glyph_func:
|
||||
* @ffuncs: A font-function structure
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||
* @user_data: Data to pass to @func
|
||||
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||
*
|
||||
* Sets the implementation function for #hb_font_draw_glyph_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_or_fail_func instead.
|
||||
**/
|
||||
HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_draw_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_paint_glyph_func:
|
||||
* @ffuncs: A font-function structure
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||
* @user_data: Data to pass to @func
|
||||
* @destroy: (nullable): The function to call when @user_data is no longer needed
|
||||
*
|
||||
* Sets the implementation function for #hb_font_paint_glyph_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead.
|
||||
*/
|
||||
HB_DEPRECATED_FOR (hb_font_funcs_set_paint_glyph_or_fail_func)
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_paint_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
HB_DEPRECATED_FOR (hb_font_draw_glyph_or_fail)
|
||||
HB_EXTERN void
|
||||
hb_font_get_glyph_shape (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
|
||||
@ -28,6 +28,11 @@
|
||||
|
||||
#include "hb-draw.hh"
|
||||
|
||||
#include "hb-geometry.hh"
|
||||
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-draw
|
||||
* @title: hb-draw
|
||||
@ -455,4 +460,92 @@ hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float control_x, float control_y,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (control_x, control_y);
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float control1_x, float control1_y,
|
||||
float control2_x, float control2_y,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (control1_x, control1_y);
|
||||
extents->add_point (control2_x, control2_y);
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static inline void free_static_draw_extents_funcs ();
|
||||
|
||||
static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
|
||||
{
|
||||
static hb_draw_funcs_t *create ()
|
||||
{
|
||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||
|
||||
hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
|
||||
|
||||
hb_draw_funcs_make_immutable (funcs);
|
||||
|
||||
hb_atexit (free_static_draw_extents_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_draw_extents_funcs;
|
||||
|
||||
static inline
|
||||
void free_static_draw_extents_funcs ()
|
||||
{
|
||||
static_draw_extents_funcs.free_instance ();
|
||||
}
|
||||
|
||||
hb_draw_funcs_t *
|
||||
hb_draw_extents_get_funcs ()
|
||||
{
|
||||
return static_draw_extents_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -70,7 +70,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}, {0}, {0}, {0}, {0}, {0}, {0}}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -99,6 +99,7 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (st.path_open)) close_path (draw_data, st);
|
||||
|
||||
st.current_x = to_x;
|
||||
st.current_y = to_y;
|
||||
}
|
||||
@ -109,7 +110,9 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (!st.path_open)) start_path (draw_data, st);
|
||||
|
||||
emit_line_to (draw_data, st, to_x, to_y);
|
||||
|
||||
st.current_x = to_x;
|
||||
st.current_y = to_y;
|
||||
}
|
||||
@ -121,7 +124,9 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (!st.path_open)) start_path (draw_data, st);
|
||||
|
||||
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 +139,9 @@ struct hb_draw_funcs_t
|
||||
float to_x, float to_y)
|
||||
{
|
||||
if (unlikely (!st.path_open)) start_path (draw_data, st);
|
||||
|
||||
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,9 +175,8 @@ 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_)
|
||||
: funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
|
||||
{}
|
||||
|
||||
~hb_draw_session_t () { close_path (); }
|
||||
@ -178,36 +184,23 @@ struct hb_draw_session_t
|
||||
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 +208,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,11 +220,14 @@ struct hb_draw_session_t
|
||||
}
|
||||
|
||||
public:
|
||||
float slant;
|
||||
bool not_slanted;
|
||||
hb_draw_funcs_t *funcs;
|
||||
void *draw_data;
|
||||
hb_draw_state_t st;
|
||||
};
|
||||
|
||||
|
||||
HB_INTERNAL hb_draw_funcs_t *
|
||||
hb_draw_extents_get_funcs ();
|
||||
|
||||
|
||||
#endif /* HB_DRAW_HH */
|
||||
|
||||
@ -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:
|
||||
@ -460,7 +672,7 @@ hb_face_make_immutable (hb_face_t *face)
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_face_is_immutable (const hb_face_t *face)
|
||||
hb_face_is_immutable (hb_face_t *face)
|
||||
{
|
||||
return hb_object_is_immutable (face);
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -117,7 +131,7 @@ HB_EXTERN void
|
||||
hb_face_make_immutable (hb_face_t *face);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_face_is_immutable (const hb_face_t *face);
|
||||
hb_face_is_immutable (hb_face_t *face);
|
||||
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -87,7 +103,7 @@ hb_font_get_font_h_extents_default (hb_font_t *font,
|
||||
hb_font_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_font_h_extents (extents);
|
||||
hb_bool_t ret = font->parent->get_font_h_extents (extents, false);
|
||||
if (ret) {
|
||||
extents->ascender = font->parent_scale_y_distance (extents->ascender);
|
||||
extents->descender = font->parent_scale_y_distance (extents->descender);
|
||||
@ -112,7 +128,7 @@ hb_font_get_font_v_extents_default (hb_font_t *font,
|
||||
hb_font_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_font_v_extents (extents);
|
||||
hb_bool_t ret = font->parent->get_font_v_extents (extents, false);
|
||||
if (ret) {
|
||||
extents->ascender = font->parent_scale_x_distance (extents->ascender);
|
||||
extents->descender = font->parent_scale_x_distance (extents->descender);
|
||||
@ -218,10 +234,10 @@ hb_font_get_glyph_h_advance_default (hb_font_t *font,
|
||||
if (font->has_glyph_h_advances_func_set ())
|
||||
{
|
||||
hb_position_t ret;
|
||||
font->get_glyph_h_advances (1, &glyph, 0, &ret, 0);
|
||||
font->get_glyph_h_advances (1, &glyph, 0, &ret, 0, false);
|
||||
return ret;
|
||||
}
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
|
||||
return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph, false));
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
@ -243,10 +259,10 @@ hb_font_get_glyph_v_advance_default (hb_font_t *font,
|
||||
if (font->has_glyph_v_advances_func_set ())
|
||||
{
|
||||
hb_position_t ret;
|
||||
font->get_glyph_v_advances (1, &glyph, 0, &ret, 0);
|
||||
font->get_glyph_v_advances (1, &glyph, 0, &ret, 0, false);
|
||||
return ret;
|
||||
}
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
|
||||
return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph, false));
|
||||
}
|
||||
|
||||
#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
|
||||
@ -265,7 +281,7 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_h_advance (*first_glyph);
|
||||
*first_advance = font->get_glyph_h_advance (*first_glyph, false);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
@ -274,7 +290,8 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
|
||||
|
||||
font->parent->get_glyph_h_advances (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride);
|
||||
first_advance, advance_stride,
|
||||
false);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->parent_scale_x_distance (*first_advance);
|
||||
@ -297,7 +314,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->get_glyph_v_advance (*first_glyph);
|
||||
*first_advance = font->get_glyph_v_advance (*first_glyph, false);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
@ -306,7 +323,8 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
|
||||
|
||||
font->parent->get_glyph_v_advances (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride);
|
||||
first_advance, advance_stride,
|
||||
false);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->parent_scale_y_distance (*first_advance);
|
||||
@ -426,7 +444,7 @@ hb_font_get_glyph_extents_default (hb_font_t *font,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
|
||||
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents, false);
|
||||
if (ret) {
|
||||
font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
|
||||
font->parent_scale_distance (&extents->width, &extents->height);
|
||||
@ -456,7 +474,7 @@ hb_font_get_glyph_contour_point_default (hb_font_t *font,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
|
||||
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y, false);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
@ -508,26 +526,28 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
|
||||
return font->parent->get_glyph_from_name (name, len, glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_font_draw_glyph_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs,
|
||||
void *draw_data,
|
||||
void *user_data HB_UNUSED)
|
||||
static hb_bool_t
|
||||
hb_font_draw_glyph_or_fail_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs,
|
||||
void *draw_data,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_font_paint_glyph_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
hb_paint_funcs_t *paint_funcs HB_UNUSED,
|
||||
void *paint_data HB_UNUSED,
|
||||
unsigned int palette HB_UNUSED,
|
||||
hb_color_t foreground HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
static hb_bool_t
|
||||
hb_font_paint_glyph_or_fail_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_codepoint_t glyph HB_UNUSED,
|
||||
hb_paint_funcs_t *paint_funcs HB_UNUSED,
|
||||
void *paint_data HB_UNUSED,
|
||||
unsigned int palette HB_UNUSED,
|
||||
hb_color_t foreground HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct hb_font_draw_glyph_default_adaptor_t {
|
||||
@ -535,7 +555,6 @@ typedef struct hb_font_draw_glyph_default_adaptor_t {
|
||||
void *draw_data;
|
||||
float x_scale;
|
||||
float y_scale;
|
||||
float slant;
|
||||
} hb_font_draw_glyph_default_adaptor_t;
|
||||
|
||||
static void
|
||||
@ -548,10 +567,9 @@ hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
|
||||
float x_scale = adaptor->x_scale;
|
||||
float y_scale = adaptor->y_scale;
|
||||
float slant = adaptor->slant;
|
||||
|
||||
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
|
||||
x_scale * to_x + slant * to_y, y_scale * to_y);
|
||||
x_scale * to_x, y_scale * to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -563,13 +581,12 @@ hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
|
||||
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
|
||||
float x_scale = adaptor->x_scale;
|
||||
float y_scale = adaptor->y_scale;
|
||||
float slant = adaptor->slant;
|
||||
|
||||
st->current_x = st->current_x * x_scale + st->current_y * slant;
|
||||
st->current_x = st->current_x * x_scale;
|
||||
st->current_y = st->current_y * y_scale;
|
||||
|
||||
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
|
||||
x_scale * to_x + slant * to_y, y_scale * to_y);
|
||||
x_scale * to_x, y_scale * to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -582,14 +599,13 @@ hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data
|
||||
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
|
||||
float x_scale = adaptor->x_scale;
|
||||
float y_scale = adaptor->y_scale;
|
||||
float slant = adaptor->slant;
|
||||
|
||||
st->current_x = st->current_x * x_scale + st->current_y * slant;
|
||||
st->current_x = st->current_x * x_scale;
|
||||
st->current_y = st->current_y * y_scale;
|
||||
|
||||
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
|
||||
x_scale * control_x + slant * control_y, y_scale * control_y,
|
||||
x_scale * to_x + slant * to_y, y_scale * to_y);
|
||||
x_scale * control_x, y_scale * control_y,
|
||||
x_scale * to_x, y_scale * to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -603,15 +619,14 @@ hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
|
||||
hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data;
|
||||
float x_scale = adaptor->x_scale;
|
||||
float y_scale = adaptor->y_scale;
|
||||
float slant = adaptor->slant;
|
||||
|
||||
st->current_x = st->current_x * x_scale + st->current_y * slant;
|
||||
st->current_x = st->current_x * x_scale;
|
||||
st->current_y = st->current_y * y_scale;
|
||||
|
||||
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
|
||||
x_scale * control1_x + slant * control1_y, y_scale * control1_y,
|
||||
x_scale * control2_x + slant * control2_y, y_scale * control2_y,
|
||||
x_scale * to_x + slant * to_y, y_scale * to_y);
|
||||
x_scale * control1_x, y_scale * control1_y,
|
||||
x_scale * control2_x, y_scale * control2_y,
|
||||
x_scale * to_x, y_scale * to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -634,49 +649,47 @@ static const hb_draw_funcs_t _hb_draw_funcs_default = {
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
hb_font_draw_glyph_default (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 HB_UNUSED)
|
||||
static hb_bool_t
|
||||
hb_font_draw_glyph_or_fail_default (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 HB_UNUSED)
|
||||
{
|
||||
hb_font_draw_glyph_default_adaptor_t adaptor = {
|
||||
draw_funcs,
|
||||
draw_data,
|
||||
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
|
||||
font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
|
||||
font->parent->y_scale ? (font->slant - font->parent->slant) *
|
||||
(float) font->x_scale / (float) font->parent->y_scale : 0.f
|
||||
font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f
|
||||
};
|
||||
|
||||
font->parent->draw_glyph (glyph,
|
||||
const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
|
||||
&adaptor);
|
||||
return font->parent->draw_glyph_or_fail (glyph,
|
||||
const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
|
||||
&adaptor,
|
||||
false);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_font_paint_glyph_default (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs,
|
||||
void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground,
|
||||
void *user_data)
|
||||
static hb_bool_t
|
||||
hb_font_paint_glyph_or_fail_default (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs,
|
||||
void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground,
|
||||
void *user_data)
|
||||
{
|
||||
paint_funcs->push_transform (paint_data,
|
||||
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f,
|
||||
font->parent->y_scale ? (font->slant - font->parent->slant) *
|
||||
(float) font->x_scale / (float) font->parent->y_scale : 0.f,
|
||||
0.f,
|
||||
font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f,
|
||||
0.f, 0.f);
|
||||
font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0, 0,
|
||||
0, font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0,
|
||||
0, 0);
|
||||
|
||||
font->parent->paint_glyph (glyph, paint_funcs, paint_data, palette, foreground);
|
||||
bool ret = font->parent->paint_glyph_or_fail (glyph, paint_funcs, paint_data, palette, foreground);
|
||||
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
|
||||
@ -1413,6 +1426,92 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_font_draw_glyph_or_fail:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @glyph: The glyph ID
|
||||
* @dfuncs: #hb_draw_funcs_t to draw to
|
||||
* @draw_data: User data to pass to draw callbacks
|
||||
*
|
||||
* Draws the outline that corresponds to a glyph in the specified @font.
|
||||
*
|
||||
* This is a newer name for hb_font_draw_glyph(), that returns `false`
|
||||
* if the font has no outlines for the glyph.
|
||||
*
|
||||
* The outline is returned by way of calls to the callbacks of the @dfuncs
|
||||
* objects, with @draw_data passed to them.
|
||||
*
|
||||
* Return value: `true` if glyph was drawn, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_draw_glyph_or_fail (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *dfuncs, void *draw_data)
|
||||
{
|
||||
return font->draw_glyph_or_fail (glyph, dfuncs, draw_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_paint_glyph_or_fail:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @glyph: The glyph ID
|
||||
* @pfuncs: #hb_paint_funcs_t to paint with
|
||||
* @paint_data: User data to pass to paint callbacks
|
||||
* @palette_index: The index of the font's color palette to use
|
||||
* @foreground: The foreground color, unpremultipled
|
||||
*
|
||||
* Paints a color glyph.
|
||||
*
|
||||
* This function is similar to, but lower-level than,
|
||||
* hb_font_paint_glyph(). It is suitable for clients that
|
||||
* need more control. If there are no color glyphs available,
|
||||
* it will return `false`. The client can then fall back to
|
||||
* hb_font_draw_glyph_or_fail() for the monochrome outline glyph.
|
||||
*
|
||||
* The painting instructions are returned by way of calls to
|
||||
* the callbacks of the @funcs object, with @paint_data passed
|
||||
* to them.
|
||||
*
|
||||
* If the font has color palettes (see hb_ot_color_has_palettes()),
|
||||
* then @palette_index selects the palette to use. If the font only
|
||||
* has one palette, this will be 0.
|
||||
*
|
||||
* Return value: `true` if glyph was painted, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_font_paint_glyph_or_fail (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *pfuncs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground)
|
||||
{
|
||||
return font->paint_glyph_or_fail (glyph, pfuncs, paint_data, palette_index, foreground);
|
||||
}
|
||||
|
||||
/* A bit higher-level, and with fallback */
|
||||
|
||||
void
|
||||
hb_font_t::paint_glyph (hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground)
|
||||
{
|
||||
if (paint_glyph_or_fail (glyph,
|
||||
paint_funcs, paint_data,
|
||||
palette, foreground))
|
||||
return;
|
||||
|
||||
/* Fallback for outline glyph. */
|
||||
paint_funcs->push_clip_glyph (paint_data, glyph, this);
|
||||
paint_funcs->color (paint_data, true, foreground);
|
||||
paint_funcs->pop_clip (paint_data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_font_draw_glyph:
|
||||
* @font: #hb_font_t to work upon
|
||||
@ -1422,6 +1521,9 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
||||
*
|
||||
* Draws the outline that corresponds to a glyph in the specified @font.
|
||||
*
|
||||
* This is an older name for hb_font_draw_glyph_or_fail(), with no
|
||||
* return value.
|
||||
*
|
||||
* The outline is returned by way of calls to the callbacks of the @dfuncs
|
||||
* objects, with @draw_data passed to them.
|
||||
*
|
||||
@ -1429,10 +1531,10 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
||||
**/
|
||||
void
|
||||
hb_font_draw_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *dfuncs, void *draw_data)
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *dfuncs, void *draw_data)
|
||||
{
|
||||
font->draw_glyph (glyph, dfuncs, draw_data);
|
||||
(void) hb_font_draw_glyph_or_fail (font, glyph, dfuncs, draw_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1444,7 +1546,10 @@ hb_font_draw_glyph (hb_font_t *font,
|
||||
* @palette_index: The index of the font's color palette to use
|
||||
* @foreground: The foreground color, unpremultipled
|
||||
*
|
||||
* Paints the glyph.
|
||||
* Paints the glyph. This function is similar to
|
||||
* hb_font_paint_glyph_or_fail(), but if painting a color glyph
|
||||
* failed, it will fall back to painting an outline monochrome
|
||||
* glyph.
|
||||
*
|
||||
* The painting instructions are returned by way of calls to
|
||||
* the callbacks of the @funcs object, with @paint_data passed
|
||||
@ -1466,8 +1571,6 @@ hb_font_paint_glyph (hb_font_t *font,
|
||||
font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground);
|
||||
}
|
||||
|
||||
/* A bit higher-level, and with fallback */
|
||||
|
||||
/**
|
||||
* hb_font_get_extents_for_direction:
|
||||
* @font: #hb_font_t to work upon
|
||||
@ -1854,10 +1957,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 +1980,8 @@ _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 ();
|
||||
font->serial_coords = font->serial;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1935,7 +2036,8 @@ hb_font_create_sub_font (hb_font_t *parent)
|
||||
}
|
||||
}
|
||||
|
||||
font->mults_changed ();
|
||||
font->changed ();
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
return font;
|
||||
}
|
||||
@ -2023,7 +2125,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 +2200,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 +2219,7 @@ hb_font_changed (hb_font_t *font)
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->mults_changed ();
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2141,8 +2241,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 +2249,8 @@ hb_font_set_parent (hb_font_t *font,
|
||||
font->parent = hb_font_reference (parent);
|
||||
|
||||
hb_font_destroy (old);
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2188,8 +2288,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 +2295,12 @@ 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 ();
|
||||
font->serial_coords = font->serial;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2244,8 +2345,6 @@ hb_font_set_funcs (hb_font_t *font,
|
||||
return;
|
||||
}
|
||||
|
||||
font->serial++;
|
||||
|
||||
if (font->destroy)
|
||||
font->destroy (font->user_data);
|
||||
|
||||
@ -2257,6 +2356,8 @@ hb_font_set_funcs (hb_font_t *font,
|
||||
font->klass = klass;
|
||||
font->user_data = font_data;
|
||||
font->destroy = destroy;
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2283,15 +2384,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 +2576,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 +2626,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 +2673,9 @@ hb_font_set_ptem (hb_font_t *font,
|
||||
if (font->ptem == ptem)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->ptem = ptem;
|
||||
|
||||
font->changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2459,6 +2695,23 @@ hb_font_get_ptem (hb_font_t *font)
|
||||
return font->ptem;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_is_synthetic:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Tests whether a font is synthetic. A synthetic font is one
|
||||
* that has either synthetic slant or synthetic bold set on it.
|
||||
*
|
||||
* Return value: `true` if the font is synthetic, `false` otherwise.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_font_is_synthetic (hb_font_t *font)
|
||||
{
|
||||
return font->is_synthetic ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_synthetic_bold:
|
||||
* @font: #hb_font_t to work upon
|
||||
@ -2476,7 +2729,7 @@ hb_font_get_ptem (hb_font_t *font)
|
||||
* points of the glyph shape.
|
||||
*
|
||||
* Synthetic boldness is applied when rendering a glyph via
|
||||
* hb_font_draw_glyph().
|
||||
* hb_font_draw_glyph_or_fail().
|
||||
*
|
||||
* If @in_place is `false`, then glyph advance-widths are also
|
||||
* adjusted, otherwise they are not. The in-place mode is
|
||||
@ -2499,12 +2752,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 ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2541,7 +2793,7 @@ hb_font_get_synthetic_bold (hb_font_t *font,
|
||||
* HarfBuzz needs to know this value to adjust shaping results,
|
||||
* metrics, and style values to match the slanted rendering.
|
||||
*
|
||||
* <note>Note: The glyph shape fetched via the hb_font_draw_glyph()
|
||||
* <note>Note: The glyph shape fetched via the hb_font_draw_glyph_or_fail()
|
||||
* function is slanted to reflect this value as well.</note>
|
||||
*
|
||||
* <note>Note: The slant value is a ratio. For example, a
|
||||
@ -2558,10 +2810,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 +2858,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 +2926,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 +2996,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 +3032,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 +3077,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;
|
||||
@ -3058,12 +3299,134 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
|
||||
struct hb_draw_glyph_closure_t
|
||||
{
|
||||
hb_font_draw_glyph_func_t func;
|
||||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
};
|
||||
static hb_bool_t
|
||||
hb_font_draw_glyph_trampoline (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs,
|
||||
void *draw_data,
|
||||
void *user_data)
|
||||
{
|
||||
hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data;
|
||||
closure->func (font, font_data, glyph, draw_funcs, draw_data, closure->user_data);
|
||||
return true;
|
||||
}
|
||||
static void
|
||||
hb_font_draw_glyph_closure_destroy (void *user_data)
|
||||
{
|
||||
hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data;
|
||||
|
||||
if (closure->destroy)
|
||||
closure->destroy (closure->user_data);
|
||||
hb_free (closure);
|
||||
}
|
||||
static void
|
||||
_hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_draw_glyph_func_t func,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy /* May be NULL. */)
|
||||
{
|
||||
if (hb_object_is_immutable (ffuncs))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return;
|
||||
}
|
||||
hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) hb_calloc (1, sizeof (hb_draw_glyph_closure_t));
|
||||
if (unlikely (!closure))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return;
|
||||
}
|
||||
closure->func = func;
|
||||
closure->user_data = user_data;
|
||||
closure->destroy = destroy;
|
||||
|
||||
hb_font_funcs_set_draw_glyph_or_fail_func (ffuncs,
|
||||
hb_font_draw_glyph_trampoline,
|
||||
closure,
|
||||
hb_font_draw_glyph_closure_destroy);
|
||||
}
|
||||
void
|
||||
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_draw_glyph_func_t func,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy /* May be NULL. */)
|
||||
{
|
||||
_hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
|
||||
}
|
||||
void
|
||||
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_shape_func_t func,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy /* May be NULL. */)
|
||||
{
|
||||
hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
|
||||
_hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy);
|
||||
}
|
||||
|
||||
struct hb_paint_glyph_closure_t
|
||||
{
|
||||
hb_font_paint_glyph_func_t func;
|
||||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
};
|
||||
static hb_bool_t
|
||||
hb_font_paint_glyph_trampoline (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs,
|
||||
void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground,
|
||||
void *user_data)
|
||||
{
|
||||
hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data;
|
||||
closure->func (font, font_data, glyph, paint_funcs, paint_data, palette, foreground, closure->user_data);
|
||||
return true;
|
||||
}
|
||||
static void
|
||||
hb_font_paint_glyph_closure_destroy (void *user_data)
|
||||
{
|
||||
hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data;
|
||||
|
||||
if (closure->destroy)
|
||||
closure->destroy (closure->user_data);
|
||||
hb_free (closure);
|
||||
}
|
||||
void
|
||||
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_paint_glyph_func_t func,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy /* May be NULL. */)
|
||||
{
|
||||
if (hb_object_is_immutable (ffuncs))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return;
|
||||
}
|
||||
hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) hb_calloc (1, sizeof (hb_paint_glyph_closure_t));
|
||||
if (unlikely (!closure))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return;
|
||||
}
|
||||
closure->func = func;
|
||||
closure->user_data = user_data;
|
||||
closure->destroy = destroy;
|
||||
|
||||
hb_font_funcs_set_paint_glyph_or_fail_func (ffuncs,
|
||||
hb_font_paint_glyph_trampoline,
|
||||
closure,
|
||||
hb_font_paint_glyph_closure_destroy);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -486,7 +486,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* hb_font_draw_glyph_func_t:
|
||||
* hb_font_draw_glyph_or_fail_func_t:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @font_data: @font user data pointer
|
||||
* @glyph: The glyph ID to query
|
||||
@ -496,16 +496,17 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Return value: `true` if glyph was drawn, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data);
|
||||
typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* hb_font_paint_glyph_func_t:
|
||||
* hb_font_paint_glyph_or_fail_func_t:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @font_data: @font user data pointer
|
||||
* @glyph: The glyph ID to query
|
||||
@ -517,14 +518,16 @@ typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Return value: `true` if glyph was painted, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
*/
|
||||
typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
void *user_data);
|
||||
typedef hb_bool_t (*hb_font_paint_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
void *user_data);
|
||||
|
||||
/* func setters */
|
||||
|
||||
@ -785,36 +788,36 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_draw_glyph_func:
|
||||
* hb_font_funcs_set_draw_glyph_or_fail_func:
|
||||
* @ffuncs: A font-function structure
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||
* @user_data: Data to pass to @func
|
||||
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||
*
|
||||
* Sets the implementation function for #hb_font_draw_glyph_func_t.
|
||||
* Sets the implementation function for #hb_font_draw_glyph_or_fail_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_draw_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_draw_glyph_or_fail_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_paint_glyph_func:
|
||||
* hb_font_funcs_set_paint_glyph_or_fail_func:
|
||||
* @ffuncs: A font-function structure
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||
* @user_data: Data to pass to @func
|
||||
* @destroy: (nullable): The function to call when @user_data is no longer needed
|
||||
*
|
||||
* Sets the implementation function for #hb_font_paint_glyph_func_t.
|
||||
* Sets the implementation function for #hb_font_paint_glyph_or_fail_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XSince: REPLACEME
|
||||
*/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_paint_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
hb_font_funcs_set_paint_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_paint_glyph_or_fail_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/* func dispatch */
|
||||
|
||||
@ -896,17 +899,17 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
||||
const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_draw_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *dfuncs, void *draw_data);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_draw_glyph_or_fail (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *dfuncs, void *draw_data);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_paint_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *pfuncs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_paint_glyph_or_fail (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *pfuncs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground);
|
||||
|
||||
/* high-level funcs, with fallback */
|
||||
|
||||
@ -979,6 +982,19 @@ hb_font_glyph_from_string (hb_font_t *font,
|
||||
const char *s, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph);
|
||||
|
||||
/* Older alias for hb_font_draw_glyph_or_fail() with no return value. */
|
||||
HB_EXTERN void
|
||||
hb_font_draw_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *dfuncs, void *draw_data);
|
||||
|
||||
/* Paints color glyph; if failed, draws outline glyph. */
|
||||
HB_EXTERN void
|
||||
hb_font_paint_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *pfuncs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground);
|
||||
|
||||
/*
|
||||
* hb_font_t
|
||||
@ -1052,6 +1068,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,
|
||||
@ -1086,6 +1108,9 @@ hb_font_set_ptem (hb_font_t *font, float ptem);
|
||||
HB_EXTERN float
|
||||
hb_font_get_ptem (hb_font_t *font);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_is_synthetic (hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_synthetic_bold (hb_font_t *font,
|
||||
float x_embolden, float y_embolden,
|
||||
|
||||
@ -32,7 +32,11 @@
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-face.hh"
|
||||
#include "hb-atomic.hh"
|
||||
#include "hb-draw.hh"
|
||||
#include "hb-paint-extents.hh"
|
||||
#include "hb-shaper.hh"
|
||||
#include "hb-outline.hh"
|
||||
|
||||
|
||||
/*
|
||||
@ -57,8 +61,8 @@
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \
|
||||
HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \
|
||||
HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \
|
||||
HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \
|
||||
HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \
|
||||
/* ^--- Add new callbacks here */
|
||||
|
||||
struct hb_font_funcs_t
|
||||
@ -105,8 +109,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,23 +195,35 @@ 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);
|
||||
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);
|
||||
|
||||
/* Apply slant. */
|
||||
extents->x_bearing = roundf (x1);
|
||||
extents->y_bearing = roundf (y1);
|
||||
extents->width = roundf (x2) - extents->x_bearing;
|
||||
extents->height = roundf (y2) - extents->y_bearing;
|
||||
}
|
||||
|
||||
void synthetic_glyph_extents (hb_glyph_extents_t *extents)
|
||||
{
|
||||
/* Slant. */
|
||||
if (slant_xy)
|
||||
{
|
||||
x1 += hb_min (y1 * slant_xy, y2 * slant_xy);
|
||||
x2 += hb_max (y1 * slant_xy, y2 * 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;
|
||||
}
|
||||
|
||||
extents->x_bearing = floorf (x1);
|
||||
extents->y_bearing = floorf (y1);
|
||||
extents->width = ceilf (x2) - extents->x_bearing;
|
||||
extents->height = ceilf (y2) - extents->y_bearing;
|
||||
|
||||
/* Embolden. */
|
||||
if (x_strength || y_strength)
|
||||
{
|
||||
/* Y */
|
||||
@ -250,19 +266,45 @@ struct hb_font_t
|
||||
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||
#undef HB_FONT_FUNC_IMPLEMENT
|
||||
|
||||
hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
|
||||
hb_bool_t get_font_h_extents (hb_font_extents_t *extents,
|
||||
bool synthetic = true)
|
||||
{
|
||||
hb_memset (extents, 0, sizeof (*extents));
|
||||
return klass->get.f.font_h_extents (this, user_data,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->font_h_extents);
|
||||
bool ret = klass->get.f.font_h_extents (this, user_data,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->font_h_extents);
|
||||
|
||||
if (synthetic && ret)
|
||||
{
|
||||
/* Embolden */
|
||||
int y_shift = y_scale < 0 ? -y_strength : y_strength;
|
||||
extents->ascender += y_shift;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
|
||||
hb_bool_t get_font_v_extents (hb_font_extents_t *extents,
|
||||
bool synthetic = true)
|
||||
{
|
||||
hb_memset (extents, 0, sizeof (*extents));
|
||||
return klass->get.f.font_v_extents (this, user_data,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->font_v_extents);
|
||||
bool ret = klass->get.f.font_v_extents (this, user_data,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->font_v_extents);
|
||||
|
||||
if (synthetic && ret)
|
||||
{
|
||||
/* Embolden */
|
||||
int x_shift = x_scale < 0 ? -x_strength : x_strength;
|
||||
if (embolden_in_place)
|
||||
{
|
||||
extents->ascender += x_shift / 2;
|
||||
extents->descender -= x_shift - x_shift / 2;
|
||||
}
|
||||
else
|
||||
extents->ascender += x_shift;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool has_glyph (hb_codepoint_t unicode)
|
||||
@ -303,44 +345,88 @@ struct hb_font_t
|
||||
!klass->user_data ? nullptr : klass->user_data->variation_glyph);
|
||||
}
|
||||
|
||||
hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
|
||||
hb_position_t get_glyph_h_advance (hb_codepoint_t glyph,
|
||||
bool synthetic = true)
|
||||
{
|
||||
return klass->get.f.glyph_h_advance (this, user_data,
|
||||
glyph,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
|
||||
hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data,
|
||||
glyph,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
|
||||
|
||||
if (synthetic && x_strength && !embolden_in_place)
|
||||
{
|
||||
/* Embolden */
|
||||
hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
|
||||
advance += advance ? strength : 0;
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
||||
|
||||
hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
|
||||
hb_position_t get_glyph_v_advance (hb_codepoint_t glyph,
|
||||
bool synthetic = true)
|
||||
{
|
||||
return klass->get.f.glyph_v_advance (this, user_data,
|
||||
glyph,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
|
||||
hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data,
|
||||
glyph,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
|
||||
|
||||
if (synthetic && y_strength && !embolden_in_place)
|
||||
{
|
||||
/* Embolden */
|
||||
hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
|
||||
advance += advance ? strength : 0;
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
||||
|
||||
void get_glyph_h_advances (unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride)
|
||||
unsigned int advance_stride,
|
||||
bool synthetic = true)
|
||||
{
|
||||
return klass->get.f.glyph_h_advances (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
|
||||
klass->get.f.glyph_h_advances (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
|
||||
|
||||
if (synthetic && x_strength && !embolden_in_place)
|
||||
{
|
||||
/* Embolden */
|
||||
hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void get_glyph_v_advances (unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_advance,
|
||||
unsigned int advance_stride)
|
||||
unsigned int advance_stride,
|
||||
bool synthetic = true)
|
||||
{
|
||||
return klass->get.f.glyph_v_advances (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
|
||||
klass->get.f.glyph_v_advances (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_advance, advance_stride,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
|
||||
|
||||
if (synthetic && y_strength && !embolden_in_place)
|
||||
{
|
||||
/* Embolden */
|
||||
hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
|
||||
@ -386,23 +472,82 @@ struct hb_font_t
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents)
|
||||
hb_glyph_extents_t *extents,
|
||||
bool synthetic = true)
|
||||
{
|
||||
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);
|
||||
|
||||
/* This is rather messy, but necessary. */
|
||||
|
||||
if (!synthetic)
|
||||
{
|
||||
return klass->get.f.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_extents);
|
||||
}
|
||||
if (!is_synthetic () &&
|
||||
klass->get.f.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_extents))
|
||||
return true;
|
||||
|
||||
/* Try getting extents from paint(), then draw(), *then* get_extents()
|
||||
* and apply synthetic settings in the last case. */
|
||||
|
||||
hb_paint_extents_context_t paint_extents;
|
||||
if (paint_glyph_or_fail (glyph,
|
||||
hb_paint_extents_get_funcs (), &paint_extents,
|
||||
0, 0))
|
||||
{
|
||||
*extents = paint_extents.get_extents ().to_glyph_extents ();
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_extents_t draw_extents;
|
||||
if (draw_glyph_or_fail (glyph,
|
||||
hb_draw_extents_get_funcs (), &draw_extents))
|
||||
{
|
||||
*extents = draw_extents.to_glyph_extents ();
|
||||
return true;
|
||||
}
|
||||
|
||||
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,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
hb_position_t *x, hb_position_t *y,
|
||||
bool synthetic = true)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_contour_point (this, user_data,
|
||||
glyph, point_index,
|
||||
x, y,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
|
||||
bool ret = klass->get.f.glyph_contour_point (this, user_data,
|
||||
glyph, point_index,
|
||||
x, y,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
|
||||
|
||||
if (synthetic && ret)
|
||||
{
|
||||
/* Slant */
|
||||
if (slant_xy)
|
||||
*x += roundf (*y * slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (!embolden_in_place)
|
||||
{
|
||||
int x_shift = x_scale < 0 ? -x_strength : x_strength;
|
||||
*x += x_shift;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_name (hb_codepoint_t glyph,
|
||||
@ -426,29 +571,88 @@ struct hb_font_t
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_from_name);
|
||||
}
|
||||
|
||||
void draw_glyph (hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data)
|
||||
bool draw_glyph_or_fail (hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
bool synthetic = true)
|
||||
{
|
||||
klass->get.f.draw_glyph (this, user_data,
|
||||
glyph,
|
||||
draw_funcs, draw_data,
|
||||
!klass->user_data ? nullptr : klass->user_data->draw_glyph);
|
||||
#ifndef HB_NO_OUTLINE
|
||||
bool embolden = x_strength || y_strength;
|
||||
bool slanted = slant_xy;
|
||||
synthetic = synthetic && (embolden || slanted);
|
||||
#else
|
||||
synthetic = false;
|
||||
#endif
|
||||
|
||||
if (!synthetic)
|
||||
{
|
||||
return klass->get.f.draw_glyph_or_fail (this, user_data,
|
||||
glyph,
|
||||
draw_funcs, draw_data,
|
||||
!klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_OUTLINE
|
||||
|
||||
hb_outline_t outline;
|
||||
if (!klass->get.f.draw_glyph_or_fail (this, user_data,
|
||||
glyph,
|
||||
hb_outline_recording_pen_get_funcs (), &outline,
|
||||
!klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail))
|
||||
return false;
|
||||
|
||||
// Slant before embolden; produces nicer results.
|
||||
|
||||
if (slanted)
|
||||
outline.slant (slant_xy);
|
||||
|
||||
if (embolden)
|
||||
{
|
||||
float x_shift = embolden_in_place ? 0 : (float) x_strength / 2;
|
||||
float y_shift = (float) y_strength / 2;
|
||||
if (x_scale < 0) x_shift = -x_shift;
|
||||
if (y_scale < 0) y_shift = -y_shift;
|
||||
outline.embolden (x_strength, y_strength, x_shift, y_shift);
|
||||
}
|
||||
|
||||
outline.replay (draw_funcs, draw_data);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void paint_glyph (hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground)
|
||||
bool paint_glyph_or_fail (hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground,
|
||||
bool synthetic = true)
|
||||
{
|
||||
klass->get.f.paint_glyph (this, user_data,
|
||||
glyph,
|
||||
paint_funcs, paint_data,
|
||||
palette, foreground,
|
||||
!klass->user_data ? nullptr : klass->user_data->paint_glyph);
|
||||
/* Slant */
|
||||
if (synthetic && slant_xy)
|
||||
hb_paint_push_transform (paint_funcs, paint_data,
|
||||
1.f, 0.f,
|
||||
slant_xy, 1.f,
|
||||
0.f, 0.f);
|
||||
|
||||
bool ret = klass->get.f.paint_glyph_or_fail (this, user_data,
|
||||
glyph,
|
||||
paint_funcs, paint_data,
|
||||
palette, foreground,
|
||||
!klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail);
|
||||
|
||||
if (synthetic && slant_xy)
|
||||
hb_paint_pop_transform (paint_funcs, paint_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* A bit higher-level, and with fallback */
|
||||
|
||||
HB_INTERNAL
|
||||
void paint_glyph (hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground);
|
||||
|
||||
void get_h_extents_with_fallback (hb_font_extents_t *extents)
|
||||
{
|
||||
if (!get_font_h_extents (extents))
|
||||
@ -686,7 +890,12 @@ struct hb_font_t
|
||||
return false;
|
||||
}
|
||||
|
||||
void mults_changed ()
|
||||
bool is_synthetic () const
|
||||
{
|
||||
return x_embolden || y_embolden || slant;
|
||||
}
|
||||
|
||||
void changed ()
|
||||
{
|
||||
float upem = face->get_upem ();
|
||||
|
||||
@ -697,12 +906,14 @@ struct hb_font_t
|
||||
bool y_neg = y_scale < 0;
|
||||
y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
|
||||
|
||||
x_strength = fabsf (roundf (x_scale * x_embolden));
|
||||
y_strength = fabsf (roundf (y_scale * y_embolden));
|
||||
x_strength = roundf (abs (x_scale) * x_embolden);
|
||||
y_strength = roundf (abs (y_scale) * y_embolden);
|
||||
|
||||
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)
|
||||
|
||||
@ -37,11 +37,7 @@
|
||||
#include "hb-draw.hh"
|
||||
#include "hb-font.hh"
|
||||
#include "hb-machinery.hh"
|
||||
#ifndef HB_NO_AAT
|
||||
#include "hb-aat-layout-trak-table.hh"
|
||||
#endif
|
||||
#include "hb-ot-os2-table.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
#include "hb-ot-shaper-arabic-pua.hh"
|
||||
#include "hb-paint.hh"
|
||||
|
||||
@ -101,7 +97,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 +114,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 +209,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,7 +475,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_position_t *orig_first_advance = first_advance;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
int load_flags = ft_font->load_flags;
|
||||
@ -519,38 +517,6 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
if (font->x_strength && !font->embolden_in_place)
|
||||
{
|
||||
/* Emboldening. */
|
||||
hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? x_strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
/* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
|
||||
#ifndef HB_NO_STYLE
|
||||
bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
|
||||
#else
|
||||
bool apply_trak = false;
|
||||
#endif
|
||||
if (apply_trak)
|
||||
{
|
||||
hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += tracking;
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
@ -561,6 +527,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;
|
||||
@ -581,26 +549,11 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
|
||||
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
|
||||
return 0;
|
||||
|
||||
v = (int) (y_mult * v);
|
||||
|
||||
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
|
||||
* have a Y growing upward. Hence the extra negation. */
|
||||
v = ((-v + (1<<9)) >> 10);
|
||||
|
||||
hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
|
||||
v = ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
/* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
|
||||
#ifndef HB_NO_STYLE
|
||||
bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
|
||||
#else
|
||||
bool apply_trak = false;
|
||||
#endif
|
||||
if (apply_trak)
|
||||
v += font->face->table.trak->get_v_tracking (font);
|
||||
#endif
|
||||
|
||||
return v;
|
||||
return (hb_position_t) (y_mult * v);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -614,6 +567,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 +613,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;
|
||||
|
||||
@ -669,6 +626,41 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
hb_ft_is_colr_glyph (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t gid)
|
||||
{
|
||||
#ifndef HB_NO_PAINT
|
||||
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
|
||||
/* COLRv1 */
|
||||
FT_OpaquePaint paint = {0};
|
||||
if (FT_Get_Color_Glyph_Paint (ft_face, gid,
|
||||
FT_COLOR_NO_ROOT_TRANSFORM,
|
||||
&paint))
|
||||
return true;
|
||||
|
||||
/* COLRv0 */
|
||||
FT_LayerIterator iterator;
|
||||
FT_UInt layer_glyph_index;
|
||||
FT_UInt layer_color_index;
|
||||
iterator.p = NULL;
|
||||
if (FT_Get_Color_Glyph_Layer (ft_face,
|
||||
gid,
|
||||
&layer_glyph_index,
|
||||
&layer_color_index,
|
||||
&iterator))
|
||||
return true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ft_get_glyph_extents (hb_font_t *font,
|
||||
void *font_data,
|
||||
@ -676,11 +668,17 @@ hb_ft_get_glyph_extents (hb_font_t *font,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
// FreeType doesn't return COLR glyph extents.
|
||||
if (hb_ft_is_colr_glyph (font, font_data, glyph))
|
||||
return false;
|
||||
|
||||
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,33 +706,10 @@ 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;
|
||||
}
|
||||
extents->x_bearing = roundf (x1);
|
||||
extents->y_bearing = roundf (y1);
|
||||
extents->width = roundf (x2) - extents->x_bearing;
|
||||
extents->height = roundf (y2) - extents->y_bearing;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -749,6 +724,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 +803,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;
|
||||
@ -857,7 +836,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
||||
metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
|
||||
}
|
||||
|
||||
metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength));
|
||||
metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
|
||||
metrics->descender = (hb_position_t) (y_mult * metrics->descender);
|
||||
metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
|
||||
|
||||
@ -908,23 +887,25 @@ _hb_ft_cubic_to (const FT_Vector *control1,
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_ft_draw_glyph (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data HB_UNUSED)
|
||||
static hb_bool_t
|
||||
hb_ft_draw_glyph_or_fail (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_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_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
if (unlikely (FT_Load_Glyph (ft_face, glyph,
|
||||
FT_LOAD_NO_BITMAP | ft_font->load_flags)))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const FT_Outline_Funcs outline_funcs = {
|
||||
_hb_ft_move_to,
|
||||
@ -935,43 +916,13 @@ hb_ft_draw_glyph (hb_font_t *font,
|
||||
0, /* delta */
|
||||
};
|
||||
|
||||
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (font->x_strength || font->y_strength)
|
||||
{
|
||||
FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength);
|
||||
|
||||
int x_shift = 0;
|
||||
int y_shift = 0;
|
||||
if (font->embolden_in_place)
|
||||
{
|
||||
/* Undo the FreeType shift. */
|
||||
x_shift = -font->x_strength / 2;
|
||||
y_shift = 0;
|
||||
if (font->y_scale < 0) y_shift = -font->y_strength;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FreeType applied things in the wrong direction for negative scale; fix up. */
|
||||
if (font->x_scale < 0) x_shift = -font->x_strength;
|
||||
if (font->y_scale < 0) y_shift = -font->y_strength;
|
||||
}
|
||||
if (x_shift || y_shift)
|
||||
{
|
||||
auto &outline = ft_face->glyph->outline;
|
||||
for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1))
|
||||
{
|
||||
point.x += x_shift;
|
||||
point.y += y_shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hb_draw_session_t draw_session {draw_funcs, draw_data};
|
||||
|
||||
FT_Outline_Decompose (&ft_face->glyph->outline,
|
||||
&outline_funcs,
|
||||
&draw_session);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -980,20 +931,22 @@ hb_ft_draw_glyph (hb_font_t *font,
|
||||
|
||||
#include "hb-ft-colr.hh"
|
||||
|
||||
static void
|
||||
hb_ft_paint_glyph (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t gid,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
void *user_data)
|
||||
static hb_bool_t
|
||||
hb_ft_paint_glyph_or_fail (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t gid,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
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;
|
||||
|
||||
FT_Long load_flags = ft_font->load_flags | FT_LOAD_NO_BITMAP | FT_LOAD_COLOR;
|
||||
FT_Long load_flags = ft_font->load_flags | FT_LOAD_COLOR;
|
||||
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301
|
||||
load_flags |= FT_LOAD_NO_SVG;
|
||||
#endif
|
||||
@ -1002,7 +955,7 @@ hb_ft_paint_glyph (hb_font_t *font,
|
||||
* eg. draw API can call back into the face.*/
|
||||
|
||||
if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags)))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
||||
{
|
||||
@ -1010,26 +963,21 @@ hb_ft_paint_glyph (hb_font_t *font,
|
||||
paint_funcs, paint_data,
|
||||
palette_index, foreground,
|
||||
user_data))
|
||||
return;
|
||||
return true;
|
||||
|
||||
/* Simple outline. */
|
||||
ft_font->lock.unlock ();
|
||||
paint_funcs->push_clip_glyph (paint_data, gid, font);
|
||||
ft_font->lock.lock ();
|
||||
paint_funcs->color (paint_data, true, foreground);
|
||||
paint_funcs->pop_clip (paint_data);
|
||||
|
||||
return;
|
||||
// Outline glyph
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *glyph = ft_face->glyph;
|
||||
if (glyph->format == FT_GLYPH_FORMAT_BITMAP)
|
||||
{
|
||||
bool ret = false;
|
||||
auto &bitmap = glyph->bitmap;
|
||||
if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
if (bitmap.pitch != (signed) bitmap.width * 4)
|
||||
return;
|
||||
return ret;
|
||||
|
||||
ft_font->lock.unlock ();
|
||||
|
||||
@ -1039,27 +987,26 @@ hb_ft_paint_glyph (hb_font_t *font,
|
||||
nullptr, nullptr);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
if (!hb_font_get_glyph_extents (font, gid, &extents))
|
||||
if (!font->get_glyph_extents (gid, &extents, false))
|
||||
goto out;
|
||||
|
||||
if (!paint_funcs->image (paint_data,
|
||||
blob,
|
||||
bitmap.width,
|
||||
bitmap.rows,
|
||||
HB_PAINT_IMAGE_FORMAT_BGRA,
|
||||
font->slant_xy,
|
||||
&extents))
|
||||
{
|
||||
/* TODO Try a forced outline load and paint? */
|
||||
}
|
||||
if (paint_funcs->image (paint_data,
|
||||
blob,
|
||||
bitmap.width,
|
||||
bitmap.rows,
|
||||
HB_PAINT_IMAGE_FORMAT_BGRA,
|
||||
0.f,
|
||||
&extents))
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
hb_blob_destroy (blob);
|
||||
ft_font->lock.lock ();
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -1079,10 +1026,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,19 +1035,18 @@ 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);
|
||||
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr);
|
||||
hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ft_draw_glyph_or_fail, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
|
||||
hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr);
|
||||
hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ft_paint_glyph_or_fail, nullptr, nullptr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1456,6 +1400,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 +1535,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 +1573,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)
|
||||
{
|
||||
|
||||
@ -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,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) {}
|
||||
|
||||
|
||||
@ -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;
|
||||
mutable hb_atomic_t<Stored *> instance;
|
||||
};
|
||||
|
||||
/* Specializations. */
|
||||
|
||||
@ -99,6 +99,8 @@ struct hb_mutex_t
|
||||
|
||||
hb_mutex_t () { init (); }
|
||||
~hb_mutex_t () { fini (); }
|
||||
hb_mutex_t (const hb_mutex_t &) = delete;
|
||||
hb_mutex_t &operator= (const hb_mutex_t &) = delete;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
@ -114,6 +116,10 @@ struct hb_lock_t
|
||||
hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); }
|
||||
hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); }
|
||||
~hb_lock_t () { if (mutex) mutex->unlock (); }
|
||||
|
||||
hb_lock_t (const hb_lock_t &) = delete;
|
||||
hb_lock_t &operator= (const hb_lock_t &) = delete;
|
||||
|
||||
private:
|
||||
hb_mutex_t *mutex;
|
||||
};
|
||||
|
||||
@ -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 (); }
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1073,7 +1073,7 @@ struct cff1
|
||||
|
||||
this->blob = sc.reference_table<cff1> (face);
|
||||
|
||||
/* setup for run-time santization */
|
||||
/* setup for run-time sanitization */
|
||||
sc.init (this->blob);
|
||||
sc.start_processing ();
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -405,7 +405,7 @@ struct cff2
|
||||
|
||||
this->blob = sc.reference_table<cff2> (face);
|
||||
|
||||
/* setup for run-time santization */
|
||||
/* setup for run-time sanitization */
|
||||
sc.init (this->blob);
|
||||
sc.start_processing ();
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -2014,7 +2014,8 @@ struct cmap
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
using cache_t = hb_cache_t<21, 16, 8, true>;
|
||||
using cache_t = hb_cache_t<21, 19>;
|
||||
static_assert (sizeof (cache_t) == 1024, "");
|
||||
|
||||
accelerator_t (hb_face_t *face)
|
||||
{
|
||||
@ -2028,6 +2029,14 @@ struct cmap
|
||||
subtable_uvs = &st->u.format14;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
cache = (cache_t *) hb_malloc (sizeof (cache_t));
|
||||
if (cache)
|
||||
new (cache) cache_t ();
|
||||
else
|
||||
return; // Such that get_glyph_funcZ remains null.
|
||||
#endif
|
||||
|
||||
this->get_glyph_data = subtable;
|
||||
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
if (unlikely (symbol))
|
||||
@ -2061,62 +2070,71 @@ struct cmap
|
||||
#endif
|
||||
{
|
||||
switch (subtable->u.format) {
|
||||
/* Accelerate format 4 and format 12. */
|
||||
default:
|
||||
this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
|
||||
break;
|
||||
case 12:
|
||||
this->get_glyph_funcZ = get_glyph_from<CmapSubtableFormat12>;
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
this->format4_accel.init (&subtable->u.format4);
|
||||
this->get_glyph_data = &this->format4_accel;
|
||||
this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
|
||||
break;
|
||||
}
|
||||
/* Accelerate format 4 and format 12. */
|
||||
default:
|
||||
this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
|
||||
break;
|
||||
case 12:
|
||||
this->get_glyph_funcZ = get_glyph_from<CmapSubtableFormat12>;
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
this->format4_accel.init (&subtable->u.format4);
|
||||
this->get_glyph_data = &this->format4_accel;
|
||||
this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
~accelerator_t () { this->table.destroy (); }
|
||||
~accelerator_t ()
|
||||
{
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
hb_free (cache);
|
||||
#endif
|
||||
table.destroy ();
|
||||
}
|
||||
|
||||
inline bool _cached_get (hb_codepoint_t unicode,
|
||||
hb_codepoint_t *glyph,
|
||||
cache_t *cache) const
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
// cache is always non-null if we have a get_glyph_funcZ
|
||||
unsigned v;
|
||||
if (cache && cache->get (unicode, &v))
|
||||
if (cache->get (unicode, &v))
|
||||
{
|
||||
*glyph = v;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
bool ret = this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
|
||||
|
||||
if (cache && ret)
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
if (ret)
|
||||
cache->set (unicode, *glyph);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool get_nominal_glyph (hb_codepoint_t unicode,
|
||||
hb_codepoint_t *glyph,
|
||||
cache_t *cache = nullptr) const
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
if (unlikely (!this->get_glyph_funcZ)) return false;
|
||||
return _cached_get (unicode, glyph, cache);
|
||||
return _cached_get (unicode, glyph);
|
||||
}
|
||||
|
||||
unsigned int get_nominal_glyphs (unsigned int count,
|
||||
const hb_codepoint_t *first_unicode,
|
||||
unsigned int unicode_stride,
|
||||
hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
cache_t *cache = nullptr) const
|
||||
unsigned int glyph_stride) const
|
||||
{
|
||||
if (unlikely (!this->get_glyph_funcZ)) return 0;
|
||||
|
||||
unsigned int done;
|
||||
for (done = 0;
|
||||
done < count && _cached_get (*first_unicode, first_glyph, cache);
|
||||
done < count && _cached_get (*first_unicode, first_glyph);
|
||||
done++)
|
||||
{
|
||||
first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
|
||||
@ -2127,8 +2145,7 @@ struct cmap
|
||||
|
||||
bool get_variation_glyph (hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
cache_t *cache = nullptr) const
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
switch (this->subtable_uvs->get_glyph_variant (unicode,
|
||||
variation_selector,
|
||||
@ -2139,7 +2156,7 @@ struct cmap
|
||||
case GLYPH_VARIANT_USE_DEFAULT: break;
|
||||
}
|
||||
|
||||
return get_nominal_glyph (unicode, glyph, cache);
|
||||
return get_nominal_glyph (unicode, glyph);
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
|
||||
@ -2209,11 +2226,15 @@ struct cmap
|
||||
hb_nonnull_ptr_t<const CmapSubtable> subtable;
|
||||
hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs;
|
||||
|
||||
hb_cmap_get_glyph_func_t get_glyph_funcZ;
|
||||
const void *get_glyph_data;
|
||||
hb_cmap_get_glyph_func_t get_glyph_funcZ = nullptr;
|
||||
const void *get_glyph_data = nullptr;
|
||||
|
||||
CmapSubtableFormat4::accelerator_t format4_accel;
|
||||
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
cache_t *cache = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
hb_blob_ptr_t<cmap> table;
|
||||
};
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -34,11 +34,7 @@
|
||||
#include "hb-font.hh"
|
||||
#include "hb-machinery.hh"
|
||||
#include "hb-ot-face.hh"
|
||||
#include "hb-outline.hh"
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
#include "hb-aat-layout-trak-table.hh"
|
||||
#endif
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
@ -65,28 +61,111 @@
|
||||
* never need to call these functions directly.
|
||||
**/
|
||||
|
||||
using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>;
|
||||
using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>;
|
||||
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key;
|
||||
#endif
|
||||
using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>;
|
||||
static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, "");
|
||||
|
||||
struct hb_ot_font_t
|
||||
{
|
||||
const hb_ot_face_t *ot_face;
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
bool apply_trak;
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
hb_ot_font_cmap_cache_t *cmap_cache;
|
||||
#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;
|
||||
struct advance_cache_t
|
||||
{
|
||||
mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
|
||||
mutable hb_atomic_t<OT::ItemVariationStore::cache_t *> varStore_cache;
|
||||
|
||||
~advance_cache_t ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
hb_ot_font_advance_cache_t *acquire_advance_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = advance_cache.get_acquire ();
|
||||
if (!cache)
|
||||
{
|
||||
cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
|
||||
if (!cache)
|
||||
return nullptr;
|
||||
new (cache) hb_ot_font_advance_cache_t;
|
||||
return cache;
|
||||
}
|
||||
if (advance_cache.cmpexch (cache, nullptr))
|
||||
return cache;
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
void release_advance_cache (hb_ot_font_advance_cache_t *cache) const
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
if (!advance_cache.cmpexch (nullptr, cache))
|
||||
hb_free (cache);
|
||||
}
|
||||
void clear_advance_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = advance_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return;
|
||||
if (advance_cache.cmpexch (cache, nullptr))
|
||||
hb_free (cache);
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
|
||||
{
|
||||
retry:
|
||||
auto *cache = varStore_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return varStore.create_cache ();
|
||||
if (varStore_cache.cmpexch (cache, nullptr))
|
||||
return cache;
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
if (!varStore_cache.cmpexch (nullptr, cache))
|
||||
OT::ItemVariationStore::destroy_cache (cache);
|
||||
}
|
||||
void clear_varStore_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = varStore_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return;
|
||||
if (varStore_cache.cmpexch (cache, nullptr))
|
||||
OT::ItemVariationStore::destroy_cache (cache);
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
void clear () const
|
||||
{
|
||||
clear_advance_cache ();
|
||||
clear_varStore_cache ();
|
||||
}
|
||||
|
||||
} h, v;
|
||||
|
||||
void check_serial (hb_font_t *font) const
|
||||
{
|
||||
int font_serial = font->serial_coords.get_acquire ();
|
||||
|
||||
if (cached_coords_serial.get_acquire () == font_serial)
|
||||
return;
|
||||
|
||||
h.clear ();
|
||||
v.clear ();
|
||||
|
||||
cached_coords_serial.set_release (font_serial);
|
||||
}
|
||||
};
|
||||
|
||||
static hb_ot_font_t *
|
||||
@ -98,44 +177,6 @@ _hb_ot_font_create (hb_font_t *font)
|
||||
|
||||
ot_font->ot_face = &font->face->table;
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
/* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
|
||||
#ifndef HB_NO_STYLE
|
||||
ot_font->apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
|
||||
#else
|
||||
ot_font->apply_trak = false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
// retry:
|
||||
auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face,
|
||||
&hb_ot_font_cmap_cache_user_data_key);
|
||||
if (!cmap_cache)
|
||||
{
|
||||
cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t));
|
||||
if (unlikely (!cmap_cache)) goto out;
|
||||
new (cmap_cache) hb_ot_font_cmap_cache_t ();
|
||||
if (unlikely (!hb_face_set_user_data (font->face,
|
||||
&hb_ot_font_cmap_cache_user_data_key,
|
||||
cmap_cache,
|
||||
hb_free,
|
||||
false)))
|
||||
{
|
||||
hb_free (cmap_cache);
|
||||
cmap_cache = nullptr;
|
||||
/* Normally we would retry here, but that would
|
||||
* infinite-loop if the face is the empty-face.
|
||||
* Just let it go and this font will be uncached if it
|
||||
* happened to collide with another thread creating the
|
||||
* cache at the same time. */
|
||||
// goto retry;
|
||||
}
|
||||
}
|
||||
out:
|
||||
ot_font->cmap_cache = cmap_cache;
|
||||
#endif
|
||||
|
||||
return ot_font;
|
||||
}
|
||||
|
||||
@ -144,8 +185,7 @@ _hb_ot_font_destroy (void *font_data)
|
||||
{
|
||||
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
|
||||
|
||||
auto *cache = ot_font->advance_cache.get_relaxed ();
|
||||
hb_free (cache);
|
||||
ot_font->~hb_ot_font_t ();
|
||||
|
||||
hb_free (ot_font);
|
||||
}
|
||||
@ -159,11 +199,7 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
|
||||
{
|
||||
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;
|
||||
hb_ot_font_cmap_cache_t *cmap_cache = nullptr;
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
cmap_cache = ot_font->cmap_cache;
|
||||
#endif
|
||||
return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache);
|
||||
return ot_face->cmap->get_nominal_glyph (unicode, glyph);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
@ -178,14 +214,9 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
|
||||
{
|
||||
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;
|
||||
hb_ot_font_cmap_cache_t *cmap_cache = nullptr;
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
cmap_cache = ot_font->cmap_cache;
|
||||
#endif
|
||||
return ot_face->cmap->get_nominal_glyphs (count,
|
||||
first_unicode, unicode_stride,
|
||||
first_glyph, glyph_stride,
|
||||
cmap_cache);
|
||||
first_glyph, glyph_stride);
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
@ -198,13 +229,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
|
||||
{
|
||||
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;
|
||||
hb_ot_font_cmap_cache_t *cmap_cache = nullptr;
|
||||
#ifndef HB_NO_OT_FONT_CMAP_CACHE
|
||||
cmap_cache = ot_font->cmap_cache;
|
||||
#endif
|
||||
return ot_face->cmap->get_variation_glyph (unicode,
|
||||
variation_selector, glyph,
|
||||
cmap_cache);
|
||||
variation_selector, glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -216,47 +242,25 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
|
||||
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;
|
||||
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
|
||||
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
|
||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
||||
ot_font->check_serial (font);
|
||||
const OT::HVAR &HVAR = *hmtx.var_table;
|
||||
const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
|
||||
|
||||
hb_ot_font_advance_cache_t *advance_cache = nullptr;
|
||||
|
||||
bool use_cache = font->num_coords;
|
||||
#else
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
|
||||
bool use_cache = false;
|
||||
#endif
|
||||
|
||||
hb_ot_font_advance_cache_t *cache = nullptr;
|
||||
if (use_cache)
|
||||
{
|
||||
retry:
|
||||
cache = ot_font->advance_cache.get_acquire ();
|
||||
if (unlikely (!cache))
|
||||
{
|
||||
cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t));
|
||||
if (unlikely (!cache))
|
||||
{
|
||||
use_cache = false;
|
||||
goto out;
|
||||
}
|
||||
new (cache) hb_ot_font_advance_cache_t;
|
||||
|
||||
if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
|
||||
{
|
||||
hb_free (cache);
|
||||
goto retry;
|
||||
}
|
||||
ot_font->cached_coords_serial.set_release (font->serial_coords);
|
||||
}
|
||||
advance_cache = ot_font->h.acquire_advance_cache ();
|
||||
if (!advance_cache)
|
||||
use_cache = false;
|
||||
}
|
||||
out:
|
||||
|
||||
if (!use_cache)
|
||||
{
|
||||
@ -269,58 +273,26 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
||||
}
|
||||
else
|
||||
{ /* Use cache. */
|
||||
if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords)
|
||||
{
|
||||
ot_font->advance_cache->clear ();
|
||||
ot_font->cached_coords_serial.set_release (font->serial_coords);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
hb_position_t v;
|
||||
unsigned cv;
|
||||
if (ot_font->advance_cache->get (*first_glyph, &cv))
|
||||
if (advance_cache->get (*first_glyph, &cv))
|
||||
v = cv;
|
||||
else
|
||||
{
|
||||
v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
|
||||
ot_font->advance_cache->set (*first_glyph, v);
|
||||
advance_cache->set (*first_glyph, v);
|
||||
}
|
||||
*first_advance = font->em_scale_x (v);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
ot_font->h.release_advance_cache (advance_cache);
|
||||
}
|
||||
|
||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
||||
OT::ItemVariationStore::destroy_cache (varStore_cache);
|
||||
#endif
|
||||
|
||||
if (font->x_strength && !font->embolden_in_place)
|
||||
{
|
||||
/* Emboldening. */
|
||||
hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? x_strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
if (ot_font->apply_trak)
|
||||
{
|
||||
hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += tracking;
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ot_font->h.release_varStore_cache (varStore_cache);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
@ -337,17 +309,13 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
|
||||
if (vmtx.has_data ())
|
||||
{
|
||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
||||
ot_font->check_serial (font);
|
||||
const OT::VVAR &VVAR = *vmtx.var_table;
|
||||
const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
|
||||
#else
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
|
||||
#endif
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
|
||||
// TODO Use advance_cache.
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
@ -356,9 +324,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
|
||||
OT::ItemVariationStore::destroy_cache (varStore_cache);
|
||||
#endif
|
||||
ot_font->v.release_varStore_cache (varStore_cache);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -373,32 +339,6 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
if (font->y_strength && !font->embolden_in_place)
|
||||
{
|
||||
/* Emboldening. */
|
||||
hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? y_strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
if (ot_font->apply_trak)
|
||||
{
|
||||
hb_position_t tracking = font->face->table.trak->get_v_tracking (font);
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += tracking;
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -435,7 +375,8 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
|
||||
}
|
||||
|
||||
hb_glyph_extents_t extents = {0};
|
||||
if (ot_face->glyf->get_extents (font, glyph, &extents))
|
||||
|
||||
if (hb_font_get_glyph_extents (font, glyph, &extents))
|
||||
{
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
int tsb = 0;
|
||||
@ -448,7 +389,7 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
|
||||
hb_font_extents_t font_extents;
|
||||
font->get_h_extents_with_fallback (&font_extents);
|
||||
hb_position_t advance = font_extents.ascender - font_extents.descender;
|
||||
int diff = advance - -extents.height;
|
||||
hb_position_t diff = advance - -extents.height;
|
||||
*y = extents.y_bearing + (diff >> 1);
|
||||
return true;
|
||||
}
|
||||
@ -477,6 +418,9 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
||||
#endif
|
||||
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
|
||||
if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
@ -528,16 +472,9 @@ hb_ot_get_font_h_extents (hb_font_t *font,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
|
||||
|
||||
/* Embolden */
|
||||
int y_shift = font->y_strength;
|
||||
if (font->y_scale < 0) y_shift = -y_shift;
|
||||
metrics->ascender += y_shift;
|
||||
|
||||
return ret;
|
||||
return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
@ -554,68 +491,46 @@ hb_ot_get_font_v_extents (hb_font_t *font,
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
static void
|
||||
hb_ot_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)
|
||||
static hb_bool_t
|
||||
hb_ot_draw_glyph_or_fail (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)
|
||||
{
|
||||
bool embolden = font->x_strength || font->y_strength;
|
||||
hb_outline_t outline;
|
||||
|
||||
{ // Need draw_session to be destructed before emboldening.
|
||||
hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs,
|
||||
embolden ? &outline : draw_data, font->slant_xy);
|
||||
hb_draw_session_t draw_session {draw_funcs, draw_data};
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
if (!font->face->table.VARC->get_path (font, glyph, draw_session))
|
||||
if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true;
|
||||
#endif
|
||||
// Keep the following in synch with VARC::get_path_at()
|
||||
if (!font->face->table.glyf->get_path (font, glyph, draw_session))
|
||||
// Keep the following in synch with VARC::get_path_at()
|
||||
if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true;
|
||||
#ifndef HB_NO_CFF
|
||||
if (!font->face->table.cff2->get_path (font, glyph, draw_session))
|
||||
if (!font->face->table.cff1->get_path (font, glyph, draw_session))
|
||||
if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true;
|
||||
if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true;
|
||||
#endif
|
||||
{}
|
||||
}
|
||||
|
||||
if (embolden)
|
||||
{
|
||||
float x_shift = font->embolden_in_place ? 0 : (float) font->x_strength / 2;
|
||||
float y_shift = (float) font->y_strength / 2;
|
||||
if (font->x_scale < 0) x_shift = -x_shift;
|
||||
if (font->y_scale < 0) y_shift = -y_shift;
|
||||
outline.embolden (font->x_strength, font->y_strength,
|
||||
x_shift, y_shift);
|
||||
|
||||
outline.replay (draw_funcs, draw_data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
static void
|
||||
hb_ot_paint_glyph (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground,
|
||||
void *user_data)
|
||||
static hb_bool_t
|
||||
hb_ot_paint_glyph_or_fail (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
unsigned int palette,
|
||||
hb_color_t foreground,
|
||||
void *user_data)
|
||||
{
|
||||
#ifndef HB_NO_COLOR
|
||||
if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return;
|
||||
if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
|
||||
if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true;
|
||||
if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
|
||||
#ifndef HB_NO_OT_FONT_BITMAP
|
||||
if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
|
||||
if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
|
||||
if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
|
||||
if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Outline glyph
|
||||
paint_funcs->push_clip_glyph (paint_data, glyph, font);
|
||||
paint_funcs->color (paint_data, true, foreground);
|
||||
paint_funcs->pop_clip (paint_data);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -642,11 +557,11 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
hb_font_funcs_set_draw_glyph_func (funcs, hb_ot_draw_glyph, nullptr, nullptr);
|
||||
hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
hb_font_funcs_set_paint_glyph_func (funcs, hb_ot_paint_glyph, nullptr, nullptr);
|
||||
hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
|
||||
|
||||
@ -359,7 +359,13 @@ struct hmtxvmtx
|
||||
return true;
|
||||
}
|
||||
|
||||
return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb);
|
||||
// If there's no vmtx data, the phantom points from glyf table are not accurate,
|
||||
// so we cannot take the next path.
|
||||
bool is_vertical = T::tableTag == HB_OT_TAG_vmtx;
|
||||
if (is_vertical && !has_data ())
|
||||
return false;
|
||||
|
||||
return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -182,7 +182,7 @@ struct BaseCoord
|
||||
void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set);
|
||||
case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1850,7 +1850,7 @@ struct ClassDefFormat2_4
|
||||
hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
|
||||
hb_set_t orig_klasses;
|
||||
|
||||
if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2
|
||||
if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len)
|
||||
< get_population ())
|
||||
{
|
||||
for (hb_codepoint_t g : glyph_set)
|
||||
@ -1931,7 +1931,7 @@ struct ClassDefFormat2_4
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_class (g))
|
||||
@ -2000,7 +2000,7 @@ struct ClassDefFormat2_4
|
||||
}
|
||||
|
||||
unsigned count = rangeRecord.len;
|
||||
if (count > glyphs->get_population () * hb_bit_storage (count) * 8)
|
||||
if (count > glyphs->get_population () * hb_bit_storage (count))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
{
|
||||
@ -2548,11 +2548,13 @@ struct SparseVarRegionAxis
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
#define REGION_CACHE_ITEM_CACHE_INVALID 2.f
|
||||
#define REGION_CACHE_ITEM_CACHE_INVALID INT_MIN
|
||||
#define REGION_CACHE_ITEM_MULTIPLIER (float (1 << ((sizeof (int) * 8) - 2)))
|
||||
#define REGION_CACHE_ITEM_DIVISOR (1.f / float (1 << ((sizeof (int) * 8) - 2)))
|
||||
|
||||
struct VarRegionList
|
||||
{
|
||||
using cache_t = float;
|
||||
using cache_t = hb_atomic_t<int>;
|
||||
|
||||
float evaluate (unsigned int region_index,
|
||||
const int *coords, unsigned int coord_len,
|
||||
@ -2561,12 +2563,12 @@ struct VarRegionList
|
||||
if (unlikely (region_index >= regionCount))
|
||||
return 0.;
|
||||
|
||||
float *cached_value = nullptr;
|
||||
cache_t *cached_value = nullptr;
|
||||
if (cache)
|
||||
{
|
||||
cached_value = &(cache[region_index]);
|
||||
if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
|
||||
return *cached_value;
|
||||
if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
|
||||
return *cached_value * REGION_CACHE_ITEM_DIVISOR;
|
||||
}
|
||||
|
||||
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
|
||||
@ -2587,7 +2589,7 @@ struct VarRegionList
|
||||
}
|
||||
|
||||
if (cache)
|
||||
*cached_value = v;
|
||||
*cached_value = v * REGION_CACHE_ITEM_MULTIPLIER;
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -2730,7 +2732,7 @@ struct SparseVariationRegion : Array16Of<SparseVarRegionAxis>
|
||||
|
||||
struct SparseVarRegionList
|
||||
{
|
||||
using cache_t = float;
|
||||
using cache_t = hb_atomic_t<int>;
|
||||
|
||||
float evaluate (unsigned int region_index,
|
||||
const int *coords, unsigned int coord_len,
|
||||
@ -2739,12 +2741,12 @@ struct SparseVarRegionList
|
||||
if (unlikely (region_index >= regions.len))
|
||||
return 0.;
|
||||
|
||||
float *cached_value = nullptr;
|
||||
cache_t *cached_value = nullptr;
|
||||
if (cache)
|
||||
{
|
||||
cached_value = &(cache[region_index]);
|
||||
if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
|
||||
return *cached_value;
|
||||
if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
|
||||
return *cached_value * REGION_CACHE_ITEM_DIVISOR;
|
||||
}
|
||||
|
||||
const SparseVariationRegion ®ion = this+regions[region_index];
|
||||
@ -2752,7 +2754,7 @@ struct SparseVarRegionList
|
||||
float v = region.evaluate (coords, coord_len);
|
||||
|
||||
if (cache)
|
||||
*cached_value = v;
|
||||
*cached_value = v * REGION_CACHE_ITEM_MULTIPLIER;
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -2861,8 +2863,13 @@ struct VarData
|
||||
const hb_vector_t<const hb_vector_t<int>*>& rows)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
unsigned row_count = rows.length;
|
||||
if (!row_count) {
|
||||
// Nothing to serialize, will be empty.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
itemCount = row_count;
|
||||
|
||||
int min_threshold = has_long ? -65536 : -128;
|
||||
@ -3187,10 +3194,10 @@ struct ItemVariationStore
|
||||
#ifdef HB_NO_VAR
|
||||
return nullptr;
|
||||
#endif
|
||||
auto &r = this+regions;
|
||||
unsigned count = r.regionCount;
|
||||
unsigned count = (this+regions).regionCount;
|
||||
if (!count) return nullptr;
|
||||
|
||||
float *cache = (float *) hb_malloc (sizeof (float) * count);
|
||||
cache_t *cache = (cache_t *) hb_malloc (sizeof (float) * count);
|
||||
if (unlikely (!cache)) return nullptr;
|
||||
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
@ -3440,7 +3447,7 @@ struct MultiItemVariationStore
|
||||
{
|
||||
using cache_t = SparseVarRegionList::cache_t;
|
||||
|
||||
cache_t *create_cache (hb_array_t<float> static_cache = hb_array_t<float> ()) const
|
||||
cache_t *create_cache (hb_array_t<cache_t> static_cache = hb_array_t<cache_t> ()) const
|
||||
{
|
||||
#ifdef HB_NO_VAR
|
||||
return nullptr;
|
||||
@ -3448,12 +3455,12 @@ struct MultiItemVariationStore
|
||||
auto &r = this+regions;
|
||||
unsigned count = r.regions.len;
|
||||
|
||||
float *cache;
|
||||
cache_t *cache;
|
||||
if (count <= static_cache.length)
|
||||
cache = static_cache.arrayZ;
|
||||
else
|
||||
{
|
||||
cache = (float *) hb_malloc (sizeof (float) * count);
|
||||
cache = (cache_t *) hb_malloc (sizeof (float) * count);
|
||||
if (unlikely (!cache)) return nullptr;
|
||||
}
|
||||
|
||||
@ -3464,7 +3471,7 @@ struct MultiItemVariationStore
|
||||
}
|
||||
|
||||
static void destroy_cache (cache_t *cache,
|
||||
hb_array_t<float> static_cache = hb_array_t<float> ())
|
||||
hb_array_t<cache_t> static_cache = hb_array_t<cache_t> ())
|
||||
{
|
||||
if (cache != static_cache.arrayZ)
|
||||
hb_free (cache);
|
||||
@ -4777,12 +4784,12 @@ struct VariationDevice
|
||||
hb_position_t get_x_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
{ return font->em_scalef_x (get_delta (font, store, store_cache)); }
|
||||
{ return !font->num_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); }
|
||||
|
||||
hb_position_t get_y_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
{ return font->em_scalef_y (get_delta (font, store, store_cache)); }
|
||||
{ return !font->num_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); }
|
||||
|
||||
VariationDevice* copy (hb_serialize_context_t *c,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||
|
||||
@ -737,7 +737,8 @@ struct hb_ot_apply_context_t :
|
||||
hb_ot_apply_context_t (unsigned int table_index_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *table_blob_) :
|
||||
hb_blob_t *table_blob_,
|
||||
ItemVariationStore::cache_t *var_store_cache_ = nullptr) :
|
||||
table_index (table_index_),
|
||||
font (font_), face (font->face), buffer (buffer_),
|
||||
sanitizer (table_blob_),
|
||||
@ -756,13 +757,7 @@ struct hb_ot_apply_context_t :
|
||||
#endif
|
||||
),
|
||||
var_store (gdef.get_var_store ()),
|
||||
var_store_cache (
|
||||
#ifndef HB_NO_VAR
|
||||
table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr
|
||||
#else
|
||||
nullptr
|
||||
#endif
|
||||
),
|
||||
var_store_cache (var_store_cache_),
|
||||
direction (buffer_->props.direction),
|
||||
has_glyph_classes (gdef.has_glyph_classes ())
|
||||
{
|
||||
@ -770,13 +765,6 @@ struct hb_ot_apply_context_t :
|
||||
buffer->collect_codepoints (digest);
|
||||
}
|
||||
|
||||
~hb_ot_apply_context_t ()
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
ItemVariationStore::destroy_cache (var_store_cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_iters ()
|
||||
{
|
||||
iter_input.init (this, false);
|
||||
@ -4900,7 +4888,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 +4936,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:
|
||||
|
||||
@ -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
|
||||
@ -2013,7 +2015,11 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
||||
{
|
||||
const unsigned int table_index = proxy.table_index;
|
||||
unsigned int i = 0;
|
||||
OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ());
|
||||
|
||||
auto *font_data = font->data.ot.get ();
|
||||
auto *var_store_cache = font_data == HB_SHAPER_DATA_SUCCEEDED ? nullptr : (OT::ItemVariationStore::cache_t *) font_data;
|
||||
|
||||
OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob (), var_store_cache);
|
||||
c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
|
||||
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
|
||||
@ -2626,7 +2632,8 @@ struct hb_get_glyph_alternates_dispatch_t :
|
||||
* @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer.
|
||||
* Alternate glyphs associated with the glyph id.
|
||||
*
|
||||
* Fetches alternates of a glyph from a given GSUB lookup index.
|
||||
* Fetches alternates of a glyph from a given GSUB lookup index. Note that for one-to-one GSUB
|
||||
* glyph substitutions, this function fetches the substituted glyph.
|
||||
*
|
||||
* Return value: Total number of alternates found in the specific lookup index for the given glyph id.
|
||||
*
|
||||
|
||||
@ -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,18 @@ _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;
|
||||
info->unicode_props() |= UPROPS_MASK_HIDDEN;
|
||||
}
|
||||
|
||||
/* lig_props: aka lig_id / lig_comp
|
||||
*
|
||||
|
||||
@ -1104,6 +1104,24 @@ struct MATH
|
||||
mathVariants.sanitize (c, this));
|
||||
}
|
||||
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/4653
|
||||
HB_INTERNAL bool is_bad_cambria (hb_font_t *font) const
|
||||
{
|
||||
#ifndef HB_NO_MATH
|
||||
switch HB_CODEPOINT_ENCODE3 (font->face->table.MATH.get_blob ()->length,
|
||||
get_constant (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT, font),
|
||||
get_constant (HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT, font))
|
||||
{
|
||||
/* sha1sum:ab4a4fe054d23061f3c039493d6f665cfda2ecf5 cambria.ttc
|
||||
* sha1sum:086855301bff644f9d8827b88491fcf73a6d4cb9 cambria.ttc
|
||||
* sha1sum:b1e5a3feaca2ea3dfcf79ccb377de749ecf60343 cambria.ttc */
|
||||
case HB_CODEPOINT_ENCODE3 (25722, 2500, 3000):
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_position_t get_constant (hb_ot_math_constant_t constant,
|
||||
hb_font_t *font) const
|
||||
{ return (this+mathConstants).get_value (constant, font); }
|
||||
|
||||
@ -87,6 +87,20 @@ hb_position_t
|
||||
hb_ot_math_get_constant (hb_font_t *font,
|
||||
hb_ot_math_constant_t constant)
|
||||
{
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/4653
|
||||
* Cambria Math has incorrect value for displayOperatorMinHeight, and
|
||||
* apparently Microsoft implementation swaps displayOperatorMinHeight and
|
||||
* delimitedSubFormulaMinHeight, so we do the same if we detect Cambria Math
|
||||
* with the swapped values. */
|
||||
if ((constant == HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT ||
|
||||
constant == HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT) &&
|
||||
font->face->table.MATH->is_bad_cambria (font))
|
||||
{
|
||||
if (constant == HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)
|
||||
constant = HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT;
|
||||
else
|
||||
constant = HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT;
|
||||
}
|
||||
return font->face->table.MATH->get_constant(constant, font);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
mutable hb_atomic_t<uint16_t *> gids_sorted_by_name;
|
||||
};
|
||||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
@ -427,8 +427,13 @@ position_cluster (const hb_ot_shape_plan_t *plan,
|
||||
/* Find mark glyphs */
|
||||
unsigned int j;
|
||||
for (j = i + 1; j < end; j++)
|
||||
{
|
||||
if (_hb_glyph_info_is_hidden (&info[j]) ||
|
||||
_hb_glyph_info_is_default_ignorable (&info[j]))
|
||||
continue;
|
||||
if (!_hb_glyph_info_is_unicode_mark (&info[j]))
|
||||
break;
|
||||
}
|
||||
|
||||
position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
|
||||
|
||||
@ -455,7 +460,9 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]))) {
|
||||
if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]) &&
|
||||
!_hb_glyph_info_is_hidden (&info[i]) &&
|
||||
!_hb_glyph_info_is_default_ignorable (&info[i]))) {
|
||||
position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
|
||||
start = i;
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
#include "hb-set.hh"
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
|
||||
|
||||
@ -84,6 +85,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 +108,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'));
|
||||
@ -205,6 +211,14 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
||||
https://github.com/harfbuzz/harfbuzz/issues/2967. */
|
||||
if (plan.apply_morx)
|
||||
plan.adjust_mark_positioning_when_zeroing = false;
|
||||
|
||||
/* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
|
||||
#ifndef HB_NO_STYLE
|
||||
plan.apply_trak = hb_aat_layout_has_tracking (face) && face->table.STAT->has_data ();
|
||||
#else
|
||||
plan.apply_trak = false;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -269,6 +283,11 @@ hb_ot_shape_plan_t::position (hb_font_t *font,
|
||||
#endif
|
||||
else if (this->apply_fallback_kern)
|
||||
_hb_ot_shape_fallback_kern (this, font, buffer);
|
||||
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (this->apply_trak)
|
||||
hb_aat_layout_track (this, font, buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -405,17 +424,26 @@ _hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
|
||||
* shaper font data
|
||||
*/
|
||||
|
||||
struct hb_ot_font_data_t {};
|
||||
struct hb_ot_font_data_t {
|
||||
OT::ItemVariationStore::cache_t unused; // Just for alignment
|
||||
};
|
||||
|
||||
hb_ot_font_data_t *
|
||||
_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
|
||||
_hb_ot_shaper_font_data_create (hb_font_t *font)
|
||||
{
|
||||
return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
if (!font->num_coords)
|
||||
return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
|
||||
const OT::ItemVariationStore &var_store = font->face->table.GDEF->table->get_var_store ();
|
||||
auto *cache = (hb_ot_font_data_t *) var_store.create_cache ();
|
||||
return cache ? cache : (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED)
|
||||
_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data)
|
||||
{
|
||||
if (data == HB_SHAPER_DATA_SUCCEEDED) return;
|
||||
OT::ItemVariationStore::destroy_cache ((OT::ItemVariationStore::cache_t *) data);
|
||||
}
|
||||
|
||||
|
||||
@ -551,7 +579,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 +637,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 +1137,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. */
|
||||
|
||||
@ -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;
|
||||
@ -108,9 +109,11 @@ struct hb_ot_shape_plan_t
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
bool apply_kerx : 1;
|
||||
bool apply_morx : 1;
|
||||
bool apply_trak : 1;
|
||||
#else
|
||||
static constexpr bool apply_kerx = false;
|
||||
static constexpr bool apply_morx = false;
|
||||
static constexpr bool apply_trak = false;
|
||||
#endif
|
||||
|
||||
void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
|
||||
@ -141,6 +144,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;
|
||||
mutable 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
@ -594,9 +590,9 @@ struct gvar_GVAR
|
||||
/* If sanitize failed, set glyphCount to 0. */
|
||||
glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
|
||||
|
||||
/* For shared tuples that only have one axis active, shared the index of
|
||||
* that axis as a cache. This will speed up caclulate_scalar() a lot
|
||||
* for fonts with lots of axes and many "monovar" tuples. */
|
||||
/* For shared tuples that only have one or two axes active, shared the index
|
||||
* of that axis as a cache. This will speed up caclulate_scalar() a lot
|
||||
* for fonts with lots of axes and many "monovar" or "duovar" tuples. */
|
||||
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
|
||||
unsigned count = table->sharedTupleCount;
|
||||
if (unlikely (!shared_tuple_active_idx.resize (count, false))) return;
|
||||
|
||||
@ -117,7 +117,7 @@ hb_ot_var_get_axes (hb_face_t *face,
|
||||
* in the specified face.
|
||||
*
|
||||
* Since: 1.4.2
|
||||
* Deprecated: 2.2.0 - use hb_ot_var_find_axis_info() instead
|
||||
* Deprecated: 2.2.0: use hb_ot_var_find_axis_info() instead
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_var_find_axis (hb_face_t *face,
|
||||
|
||||
@ -84,6 +84,12 @@ void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
|
||||
}
|
||||
}
|
||||
|
||||
void hb_outline_t::slant (float slant_xy)
|
||||
{
|
||||
for (auto &p : points)
|
||||
p.x += slant_xy * p.y;
|
||||
}
|
||||
|
||||
float hb_outline_t::control_area () const
|
||||
{
|
||||
float a = 0;
|
||||
|
||||
@ -69,6 +69,7 @@ struct hb_outline_t
|
||||
|
||||
HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const;
|
||||
HB_INTERNAL float control_area () const;
|
||||
HB_INTERNAL void slant (float slant_xy);
|
||||
HB_INTERNAL void embolden (float x_strength, float y_strength,
|
||||
float x_shift, float y_shift);
|
||||
|
||||
|
||||
207
src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc
Normal file
207
src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright © 2022 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
|
||||
#include "hb-paint-bounded.hh"
|
||||
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
|
||||
/*
|
||||
* This file implements boundedness computation of COLRv1 fonts as described in:
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness
|
||||
*/
|
||||
|
||||
static void
|
||||
hb_paint_bounded_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->push_clip ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
float xmin, float ymin, float xmax, float ymax,
|
||||
void *user_data)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->push_clip ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->pop_clip ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_push_group (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->push_group ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_pop_group (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_paint_composite_mode_t mode,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->pop_group (mode);
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_paint_bounded_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_blob_t *blob HB_UNUSED,
|
||||
unsigned int width HB_UNUSED,
|
||||
unsigned int height HB_UNUSED,
|
||||
hb_tag_t format HB_UNUSED,
|
||||
float slant HB_UNUSED,
|
||||
hb_glyph_extents_t *glyph_extents,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->push_clip ();
|
||||
c->paint ();
|
||||
c->pop_clip ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_paint_color (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_bool_t use_foreground HB_UNUSED,
|
||||
hb_color_t color HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->paint ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_color_line_t *color_line HB_UNUSED,
|
||||
float x0 HB_UNUSED, float y0 HB_UNUSED,
|
||||
float x1 HB_UNUSED, float y1 HB_UNUSED,
|
||||
float x2 HB_UNUSED, float y2 HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->paint ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_color_line_t *color_line HB_UNUSED,
|
||||
float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED,
|
||||
float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->paint ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_bounded_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
hb_color_line_t *color_line HB_UNUSED,
|
||||
float cx HB_UNUSED, float cy HB_UNUSED,
|
||||
float start_angle HB_UNUSED,
|
||||
float end_angle HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data;
|
||||
|
||||
c->paint ();
|
||||
}
|
||||
|
||||
static inline void free_static_paint_bounded_funcs ();
|
||||
|
||||
static struct hb_paint_bounded_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<hb_paint_bounded_funcs_lazy_loader_t>
|
||||
{
|
||||
static hb_paint_funcs_t *create ()
|
||||
{
|
||||
hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
|
||||
|
||||
hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_bounded_push_clip_glyph, nullptr, nullptr);
|
||||
hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_bounded_push_clip_rectangle, nullptr, nullptr);
|
||||
hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_bounded_pop_clip, nullptr, nullptr);
|
||||
hb_paint_funcs_set_push_group_func (funcs, hb_paint_bounded_push_group, nullptr, nullptr);
|
||||
hb_paint_funcs_set_pop_group_func (funcs, hb_paint_bounded_pop_group, nullptr, nullptr);
|
||||
hb_paint_funcs_set_color_func (funcs, hb_paint_bounded_paint_color, nullptr, nullptr);
|
||||
hb_paint_funcs_set_image_func (funcs, hb_paint_bounded_paint_image, nullptr, nullptr);
|
||||
hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_bounded_paint_linear_gradient, nullptr, nullptr);
|
||||
hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_bounded_paint_radial_gradient, nullptr, nullptr);
|
||||
hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_bounded_paint_sweep_gradient, nullptr, nullptr);
|
||||
|
||||
hb_paint_funcs_make_immutable (funcs);
|
||||
|
||||
hb_atexit (free_static_paint_bounded_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_paint_bounded_funcs;
|
||||
|
||||
static inline
|
||||
void free_static_paint_bounded_funcs ()
|
||||
{
|
||||
static_paint_bounded_funcs.free_instance ();
|
||||
}
|
||||
|
||||
hb_paint_funcs_t *
|
||||
hb_paint_bounded_get_funcs ()
|
||||
{
|
||||
return static_paint_bounded_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
117
src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh
Normal file
117
src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright © 2022 Behdad Esfahbod
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HB_PAINT_BOUNDED_HH
|
||||
#define HB_PAINT_BOUNDED_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-paint.h"
|
||||
|
||||
#include "hb-geometry.hh"
|
||||
|
||||
|
||||
typedef struct hb_paint_bounded_context_t hb_paint_bounded_context_t;
|
||||
|
||||
struct hb_paint_bounded_context_t
|
||||
{
|
||||
void clear ()
|
||||
{
|
||||
clips = 0;
|
||||
bounded = true;
|
||||
groups.clear ();
|
||||
}
|
||||
|
||||
hb_paint_bounded_context_t ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
bool is_bounded ()
|
||||
{
|
||||
return bounded;
|
||||
}
|
||||
|
||||
void push_clip ()
|
||||
{
|
||||
clips++;
|
||||
}
|
||||
|
||||
void pop_clip ()
|
||||
{
|
||||
if (clips == 0) return;
|
||||
clips--;
|
||||
}
|
||||
|
||||
void push_group ()
|
||||
{
|
||||
groups.push (bounded);
|
||||
bounded = true;
|
||||
}
|
||||
|
||||
void pop_group (hb_paint_composite_mode_t mode)
|
||||
{
|
||||
const bool src_bounded = bounded;
|
||||
bounded = groups.pop ();
|
||||
bool &backdrop_bounded = bounded;
|
||||
|
||||
// https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite
|
||||
switch ((int) mode)
|
||||
{
|
||||
case HB_PAINT_COMPOSITE_MODE_CLEAR:
|
||||
backdrop_bounded = true;
|
||||
break;
|
||||
case HB_PAINT_COMPOSITE_MODE_SRC:
|
||||
case HB_PAINT_COMPOSITE_MODE_SRC_OUT:
|
||||
backdrop_bounded = src_bounded;
|
||||
break;
|
||||
case HB_PAINT_COMPOSITE_MODE_DEST:
|
||||
case HB_PAINT_COMPOSITE_MODE_DEST_OUT:
|
||||
break;
|
||||
case HB_PAINT_COMPOSITE_MODE_SRC_IN:
|
||||
case HB_PAINT_COMPOSITE_MODE_DEST_IN:
|
||||
backdrop_bounded = backdrop_bounded && src_bounded;
|
||||
break;
|
||||
default:
|
||||
backdrop_bounded = backdrop_bounded || src_bounded;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void paint ()
|
||||
{
|
||||
if (!clips)
|
||||
bounded = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool bounded; // true if current drawing bounded
|
||||
unsigned clips; // number of active clips
|
||||
hb_vector_t<bool> groups; // true if group bounded
|
||||
};
|
||||
|
||||
HB_INTERNAL hb_paint_funcs_t *
|
||||
hb_paint_bounded_get_funcs ();
|
||||
|
||||
|
||||
#endif /* HB_PAINT_BOUNDED_HH */
|
||||
@ -28,14 +28,13 @@
|
||||
|
||||
#include "hb-paint-extents.hh"
|
||||
|
||||
#include "hb-draw.h"
|
||||
#include "hb-draw.hh"
|
||||
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
|
||||
/*
|
||||
* This file implements bounds-extraction as well as boundedness
|
||||
* computation of COLRv1 fonts as described in:
|
||||
* This file implements bounds-extraction computation of COLRv1 fonts as described in:
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness
|
||||
*/
|
||||
@ -63,93 +62,6 @@ hb_paint_extents_pop_transform (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
c->pop_transform ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float control_x, float control_y,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (control_x, control_y);
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float control1_x, float control1_y,
|
||||
float control2_x, float control2_y,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
|
||||
extents->add_point (control1_x, control1_y);
|
||||
extents->add_point (control2_x, control2_y);
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
||||
static inline void free_static_draw_extents_funcs ();
|
||||
|
||||
static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
|
||||
{
|
||||
static hb_draw_funcs_t *create ()
|
||||
{
|
||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||
|
||||
hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
|
||||
|
||||
hb_draw_funcs_make_immutable (funcs);
|
||||
|
||||
hb_atexit (free_static_draw_extents_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_draw_extents_funcs;
|
||||
|
||||
static inline
|
||||
void free_static_draw_extents_funcs ()
|
||||
{
|
||||
static_draw_extents_funcs.free_instance ();
|
||||
}
|
||||
|
||||
static hb_draw_funcs_t *
|
||||
hb_draw_extents_get_funcs ()
|
||||
{
|
||||
return static_draw_extents_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
void *paint_data,
|
||||
@ -221,6 +133,9 @@ hb_paint_extents_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
|
||||
{
|
||||
hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
|
||||
|
||||
if (!glyph_extents)
|
||||
return false; // Happens with SVG images.
|
||||
|
||||
hb_extents_t extents = {(float) glyph_extents->x_bearing,
|
||||
(float) glyph_extents->y_bearing + glyph_extents->height,
|
||||
(float) glyph_extents->x_bearing + glyph_extents->width,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -87,7 +87,7 @@ hb_paint_image_nil (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
hb_tag_t format,
|
||||
float slant_xy,
|
||||
float slant_xy_deprecated,
|
||||
hb_glyph_extents_t *extents,
|
||||
void *user_data) { return false; }
|
||||
|
||||
@ -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
|
||||
@ -579,7 +615,7 @@ hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
* @width: width of the raster image in pixels, or 0
|
||||
* @height: height of the raster image in pixels, or 0
|
||||
* @format: the image format as a tag
|
||||
* @slant: the synthetic slant ratio to be applied to the image during rendering
|
||||
* @slant: Deprecated. set to 0.0
|
||||
* @extents: (nullable): the extents of the glyph
|
||||
*
|
||||
* Perform a "image" paint operation.
|
||||
@ -592,10 +628,10 @@ hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
hb_tag_t format,
|
||||
float slant,
|
||||
HB_UNUSED float slant,
|
||||
hb_glyph_extents_t *extents)
|
||||
{
|
||||
funcs->image (paint_data, image, width, height, format, slant, extents);
|
||||
funcs->image (paint_data, image, width, height, format, 0.f, extents);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -167,8 +167,10 @@ typedef hb_bool_t (*hb_paint_color_glyph_func_t) (hb_paint_funcs_t *funcs,
|
||||
* A virtual method for the #hb_paint_funcs_t to clip
|
||||
* subsequent paint calls to the outline of a glyph.
|
||||
*
|
||||
* The coordinates of the glyph outline are interpreted according
|
||||
* to the current transform.
|
||||
* The coordinates of the glyph outline are expected in the
|
||||
* current @font scale (ie. the results of calling
|
||||
* hb_font_draw_glyph() with @font). The outline is
|
||||
* transformed by the current transform.
|
||||
*
|
||||
* This clip is applied in addition to the current clip,
|
||||
* and remains in effect until a matching call to
|
||||
@ -281,7 +283,7 @@ typedef void (*hb_paint_color_func_t) (hb_paint_funcs_t *funcs,
|
||||
* @width: width of the raster image in pixels, or 0
|
||||
* @height: height of the raster image in pixels, or 0
|
||||
* @format: the image format as a tag
|
||||
* @slant: the synthetic slant ratio to be applied to the image during rendering
|
||||
* @slant: Deprecated. Always set to 0.0.
|
||||
* @extents: (nullable): glyph extents for desired rendering
|
||||
* @user_data: User data pointer passed to hb_paint_funcs_set_image_func()
|
||||
*
|
||||
@ -956,6 +958,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);
|
||||
|
||||
|
||||
@ -157,27 +157,29 @@ 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 ();
|
||||
int xscale = font->x_scale, yscale = font->y_scale;
|
||||
float slant = font->slant_xy;
|
||||
|
||||
push_transform (paint_data,
|
||||
xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0);
|
||||
xscale/upem, 0,
|
||||
0, 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;
|
||||
int yscale = font->y_scale ? font->y_scale : upem;
|
||||
float slant = font->slant_xy;
|
||||
|
||||
push_transform (paint_data,
|
||||
upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0);
|
||||
upem/xscale, 0,
|
||||
0, upem/yscale,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
HB_NODISCARD
|
||||
|
||||
484
src/java.desktop/share/native/libharfbuzz/hb-script-list.h
Normal file
484
src/java.desktop/share/native/libharfbuzz/hb-script-list.h
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR)
|
||||
#error "Include <hb.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_SCRIPT_LIST_H
|
||||
#define HB_SCRIPT_LIST_H
|
||||
|
||||
/* This file belongs to the middle of hb-common.h.
|
||||
* The reason it has been surgically extracted is because
|
||||
* FreeType imports types and enums from hb-common.h,
|
||||
* and since this enum is large and growing, we want to
|
||||
* make it easy to just copy the file over to FreeType.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/5271
|
||||
*/
|
||||
|
||||
/* Dummy lines to make our checks happy. */
|
||||
#if 0
|
||||
#include "hb-common.h"
|
||||
HB_BEGIN_DECLS
|
||||
HB_END_DECLS
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* hb_script_t:
|
||||
* @HB_SCRIPT_COMMON: `Zyyy`
|
||||
* @HB_SCRIPT_INHERITED: `Zinh`
|
||||
* @HB_SCRIPT_UNKNOWN: `Zzzz`
|
||||
* @HB_SCRIPT_ARABIC: `Arab`
|
||||
* @HB_SCRIPT_ARMENIAN: `Armn`
|
||||
* @HB_SCRIPT_BENGALI: `Beng`
|
||||
* @HB_SCRIPT_CYRILLIC: `Cyrl`
|
||||
* @HB_SCRIPT_DEVANAGARI: `Deva`
|
||||
* @HB_SCRIPT_GEORGIAN: `Geor`
|
||||
* @HB_SCRIPT_GREEK: `Grek`
|
||||
* @HB_SCRIPT_GUJARATI: `Gujr`
|
||||
* @HB_SCRIPT_GURMUKHI: `Guru`
|
||||
* @HB_SCRIPT_HANGUL: `Hang`
|
||||
* @HB_SCRIPT_HAN: `Hani`
|
||||
* @HB_SCRIPT_HEBREW: `Hebr`
|
||||
* @HB_SCRIPT_HIRAGANA: `Hira`
|
||||
* @HB_SCRIPT_KANNADA: `Knda`
|
||||
* @HB_SCRIPT_KATAKANA: `Kana`
|
||||
* @HB_SCRIPT_LAO: `Laoo`
|
||||
* @HB_SCRIPT_LATIN: `Latn`
|
||||
* @HB_SCRIPT_MALAYALAM: `Mlym`
|
||||
* @HB_SCRIPT_ORIYA: `Orya`
|
||||
* @HB_SCRIPT_TAMIL: `Taml`
|
||||
* @HB_SCRIPT_TELUGU: `Telu`
|
||||
* @HB_SCRIPT_THAI: `Thai`
|
||||
* @HB_SCRIPT_TIBETAN: `Tibt`
|
||||
* @HB_SCRIPT_BOPOMOFO: `Bopo`
|
||||
* @HB_SCRIPT_BRAILLE: `Brai`
|
||||
* @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans`
|
||||
* @HB_SCRIPT_CHEROKEE: `Cher`
|
||||
* @HB_SCRIPT_ETHIOPIC: `Ethi`
|
||||
* @HB_SCRIPT_KHMER: `Khmr`
|
||||
* @HB_SCRIPT_MONGOLIAN: `Mong`
|
||||
* @HB_SCRIPT_MYANMAR: `Mymr`
|
||||
* @HB_SCRIPT_OGHAM: `Ogam`
|
||||
* @HB_SCRIPT_RUNIC: `Runr`
|
||||
* @HB_SCRIPT_SINHALA: `Sinh`
|
||||
* @HB_SCRIPT_SYRIAC: `Syrc`
|
||||
* @HB_SCRIPT_THAANA: `Thaa`
|
||||
* @HB_SCRIPT_YI: `Yiii`
|
||||
* @HB_SCRIPT_DESERET: `Dsrt`
|
||||
* @HB_SCRIPT_GOTHIC: `Goth`
|
||||
* @HB_SCRIPT_OLD_ITALIC: `Ital`
|
||||
* @HB_SCRIPT_BUHID: `Buhd`
|
||||
* @HB_SCRIPT_HANUNOO: `Hano`
|
||||
* @HB_SCRIPT_TAGALOG: `Tglg`
|
||||
* @HB_SCRIPT_TAGBANWA: `Tagb`
|
||||
* @HB_SCRIPT_CYPRIOT: `Cprt`
|
||||
* @HB_SCRIPT_LIMBU: `Limb`
|
||||
* @HB_SCRIPT_LINEAR_B: `Linb`
|
||||
* @HB_SCRIPT_OSMANYA: `Osma`
|
||||
* @HB_SCRIPT_SHAVIAN: `Shaw`
|
||||
* @HB_SCRIPT_TAI_LE: `Tale`
|
||||
* @HB_SCRIPT_UGARITIC: `Ugar`
|
||||
* @HB_SCRIPT_BUGINESE: `Bugi`
|
||||
* @HB_SCRIPT_COPTIC: `Copt`
|
||||
* @HB_SCRIPT_GLAGOLITIC: `Glag`
|
||||
* @HB_SCRIPT_KHAROSHTHI: `Khar`
|
||||
* @HB_SCRIPT_NEW_TAI_LUE: `Talu`
|
||||
* @HB_SCRIPT_OLD_PERSIAN: `Xpeo`
|
||||
* @HB_SCRIPT_SYLOTI_NAGRI: `Sylo`
|
||||
* @HB_SCRIPT_TIFINAGH: `Tfng`
|
||||
* @HB_SCRIPT_BALINESE: `Bali`
|
||||
* @HB_SCRIPT_CUNEIFORM: `Xsux`
|
||||
* @HB_SCRIPT_NKO: `Nkoo`
|
||||
* @HB_SCRIPT_PHAGS_PA: `Phag`
|
||||
* @HB_SCRIPT_PHOENICIAN: `Phnx`
|
||||
* @HB_SCRIPT_CARIAN: `Cari`
|
||||
* @HB_SCRIPT_CHAM: `Cham`
|
||||
* @HB_SCRIPT_KAYAH_LI: `Kali`
|
||||
* @HB_SCRIPT_LEPCHA: `Lepc`
|
||||
* @HB_SCRIPT_LYCIAN: `Lyci`
|
||||
* @HB_SCRIPT_LYDIAN: `Lydi`
|
||||
* @HB_SCRIPT_OL_CHIKI: `Olck`
|
||||
* @HB_SCRIPT_REJANG: `Rjng`
|
||||
* @HB_SCRIPT_SAURASHTRA: `Saur`
|
||||
* @HB_SCRIPT_SUNDANESE: `Sund`
|
||||
* @HB_SCRIPT_VAI: `Vaii`
|
||||
* @HB_SCRIPT_AVESTAN: `Avst`
|
||||
* @HB_SCRIPT_BAMUM: `Bamu`
|
||||
* @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp`
|
||||
* @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi`
|
||||
* @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli`
|
||||
* @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti`
|
||||
* @HB_SCRIPT_JAVANESE: `Java`
|
||||
* @HB_SCRIPT_KAITHI: `Kthi`
|
||||
* @HB_SCRIPT_LISU: `Lisu`
|
||||
* @HB_SCRIPT_MEETEI_MAYEK: `Mtei`
|
||||
* @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb`
|
||||
* @HB_SCRIPT_OLD_TURKIC: `Orkh`
|
||||
* @HB_SCRIPT_SAMARITAN: `Samr`
|
||||
* @HB_SCRIPT_TAI_THAM: `Lana`
|
||||
* @HB_SCRIPT_TAI_VIET: `Tavt`
|
||||
* @HB_SCRIPT_BATAK: `Batk`
|
||||
* @HB_SCRIPT_BRAHMI: `Brah`
|
||||
* @HB_SCRIPT_MANDAIC: `Mand`
|
||||
* @HB_SCRIPT_CHAKMA: `Cakm`
|
||||
* @HB_SCRIPT_MEROITIC_CURSIVE: `Merc`
|
||||
* @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero`
|
||||
* @HB_SCRIPT_MIAO: `Plrd`
|
||||
* @HB_SCRIPT_SHARADA: `Shrd`
|
||||
* @HB_SCRIPT_SORA_SOMPENG: `Sora`
|
||||
* @HB_SCRIPT_TAKRI: `Takr`
|
||||
* @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30
|
||||
* @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30
|
||||
* @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30
|
||||
* @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30
|
||||
* @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30
|
||||
* @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30
|
||||
* @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30
|
||||
* @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30
|
||||
* @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30
|
||||
* @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30
|
||||
* @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30
|
||||
* @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30
|
||||
* @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30
|
||||
* @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30
|
||||
* @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30
|
||||
* @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30
|
||||
* @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30
|
||||
* @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30
|
||||
* @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30
|
||||
* @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30
|
||||
* @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30
|
||||
* @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0
|
||||
* @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0
|
||||
* @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0
|
||||
* @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0
|
||||
* @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0
|
||||
* @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0
|
||||
* @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0
|
||||
* @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0
|
||||
* @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0
|
||||
* @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0
|
||||
* @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0
|
||||
* @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0
|
||||
* @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0
|
||||
* @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0
|
||||
* @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0
|
||||
* @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0
|
||||
* @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0
|
||||
* @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0
|
||||
* @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0
|
||||
* @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0
|
||||
* @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0
|
||||
* @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7
|
||||
* @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
|
||||
* @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
|
||||
* @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
|
||||
* @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0
|
||||
* @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
|
||||
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
|
||||
* @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
|
||||
* @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0
|
||||
* @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0
|
||||
* @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0
|
||||
* @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0
|
||||
* @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0
|
||||
* @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0
|
||||
* @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0
|
||||
* @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0
|
||||
* @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0
|
||||
* @HB_SCRIPT_INVALID: No script set
|
||||
*
|
||||
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
|
||||
* to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/).
|
||||
*
|
||||
* See also the Script (sc) property of the Unicode Character Database.
|
||||
*
|
||||
**/
|
||||
|
||||
/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
|
||||
typedef enum
|
||||
{
|
||||
HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/
|
||||
HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/
|
||||
HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/
|
||||
|
||||
HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/
|
||||
HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/
|
||||
HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/
|
||||
HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/
|
||||
HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/
|
||||
HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/
|
||||
HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/
|
||||
HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/
|
||||
HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/
|
||||
HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/
|
||||
HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/
|
||||
HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/
|
||||
HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/
|
||||
HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/
|
||||
HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/
|
||||
HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/
|
||||
HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/
|
||||
HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/
|
||||
HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/
|
||||
HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/
|
||||
HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/
|
||||
HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/
|
||||
|
||||
HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/
|
||||
|
||||
HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/
|
||||
HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/
|
||||
HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/
|
||||
HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/
|
||||
HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/
|
||||
HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/
|
||||
HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/
|
||||
HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/
|
||||
HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/
|
||||
HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/
|
||||
HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/
|
||||
HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/
|
||||
HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/
|
||||
HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/
|
||||
|
||||
HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/
|
||||
HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/
|
||||
HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/
|
||||
|
||||
HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/
|
||||
HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/
|
||||
HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/
|
||||
HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/
|
||||
|
||||
HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/
|
||||
HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/
|
||||
HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/
|
||||
HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/
|
||||
HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/
|
||||
HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/
|
||||
HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/
|
||||
|
||||
HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/
|
||||
HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/
|
||||
HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/
|
||||
HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/
|
||||
HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/
|
||||
HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/
|
||||
HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/
|
||||
HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/
|
||||
|
||||
HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/
|
||||
HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/
|
||||
HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/
|
||||
HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/
|
||||
HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/
|
||||
|
||||
HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/
|
||||
HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/
|
||||
HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/
|
||||
HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/
|
||||
HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/
|
||||
HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/
|
||||
HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/
|
||||
HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/
|
||||
HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/
|
||||
HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/
|
||||
HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/
|
||||
|
||||
HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/
|
||||
HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/
|
||||
HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/
|
||||
HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/
|
||||
HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/
|
||||
HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/
|
||||
HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/
|
||||
HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/
|
||||
HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/
|
||||
HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/
|
||||
HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/
|
||||
HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/
|
||||
HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/
|
||||
HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/
|
||||
HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/
|
||||
|
||||
HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/
|
||||
HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/
|
||||
HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/
|
||||
|
||||
HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/
|
||||
HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/
|
||||
HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/
|
||||
HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/
|
||||
HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/
|
||||
HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/
|
||||
HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/
|
||||
|
||||
/*
|
||||
* Since: 0.9.30
|
||||
*/
|
||||
HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/
|
||||
HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/
|
||||
HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/
|
||||
HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/
|
||||
HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/
|
||||
HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/
|
||||
HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/
|
||||
HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/
|
||||
HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/
|
||||
HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/
|
||||
HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/
|
||||
HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/
|
||||
HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/
|
||||
HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/
|
||||
HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/
|
||||
HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/
|
||||
HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/
|
||||
HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/
|
||||
HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/
|
||||
HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/
|
||||
HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/
|
||||
HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/
|
||||
HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/
|
||||
|
||||
HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/
|
||||
HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/
|
||||
HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/
|
||||
HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/
|
||||
HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/
|
||||
HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/
|
||||
|
||||
/*
|
||||
* Since 1.3.0
|
||||
*/
|
||||
HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/
|
||||
HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/
|
||||
HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/
|
||||
HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/
|
||||
HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/
|
||||
HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/
|
||||
|
||||
/*
|
||||
* Since 1.6.0
|
||||
*/
|
||||
HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/
|
||||
HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/
|
||||
HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/
|
||||
HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/
|
||||
|
||||
/*
|
||||
* Since 1.8.0
|
||||
*/
|
||||
HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/
|
||||
HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/
|
||||
HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/
|
||||
HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/
|
||||
HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/
|
||||
HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/
|
||||
HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/
|
||||
|
||||
/*
|
||||
* Since 2.4.0
|
||||
*/
|
||||
HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/
|
||||
HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/
|
||||
HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/
|
||||
HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/
|
||||
|
||||
/*
|
||||
* Since 2.6.7
|
||||
*/
|
||||
HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/
|
||||
HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/
|
||||
HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
|
||||
HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
|
||||
|
||||
/*
|
||||
* Since 3.0.0
|
||||
*/
|
||||
HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/
|
||||
HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/
|
||||
HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/
|
||||
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
|
||||
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
|
||||
|
||||
/*
|
||||
* Since 3.4.0
|
||||
*/
|
||||
HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
|
||||
|
||||
/*
|
||||
* Since 5.2.0
|
||||
*/
|
||||
HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/
|
||||
HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/
|
||||
|
||||
/*
|
||||
* Since 10.0.0
|
||||
*/
|
||||
HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/
|
||||
HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/
|
||||
HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/
|
||||
HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/
|
||||
HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/
|
||||
HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/
|
||||
HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/
|
||||
|
||||
/* No script set. */
|
||||
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
/*< private >*/
|
||||
|
||||
/* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
||||
* without risking undefined behavior. We have two, for historical reasons.
|
||||
* HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed
|
||||
* to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well.
|
||||
*
|
||||
* See this thread for technicalities:
|
||||
*
|
||||
* https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
|
||||
*/
|
||||
_HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/
|
||||
_HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
|
||||
} hb_script_t;
|
||||
|
||||
|
||||
#endif /* HB_SCRIPT_LIST_H */
|
||||
@ -31,11 +31,10 @@
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
/*
|
||||
* The set-digests here implement various "filters" that support
|
||||
* "approximate member query". Conceptually these are like Bloom
|
||||
* Filter and Quotient Filter, however, much smaller, faster, and
|
||||
* designed to fit the requirements of our uses for glyph coverage
|
||||
* queries.
|
||||
* The set-digests implement "filters" that support "approximate
|
||||
* member query". Conceptually these are like Bloom Filter and
|
||||
* Quotient Filter, however, much smaller, faster, and designed
|
||||
* to fit the requirements of our uses for glyph coverage queries.
|
||||
*
|
||||
* Our filters are highly accurate if the lookup covers fairly local
|
||||
* set of glyphs, but fully flooded and ineffective if coverage is
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
**/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -868,7 +868,7 @@ hb_subset_input_override_name_table (hb_subset_input_t *input,
|
||||
src = hb_utf8_t::next (src, src_end, &unicode, replacement);
|
||||
if (unicode >= 0x0080u)
|
||||
{
|
||||
printf ("Non-ascii character detected, ignored...This API supports ascii characters only for mac platform\n");
|
||||
// Non-ascii character detected, ignored...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,27 +29,21 @@
|
||||
#include "hb-map.hh"
|
||||
#include "hb-multimap.hh"
|
||||
#include "hb-set.hh"
|
||||
#include "hb-subset.h"
|
||||
#include "hb-unicode.h"
|
||||
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
#include "hb-ot-layout-base-table.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "OT/Color/COLR/COLR.hh"
|
||||
#include "OT/Color/COLR/colrv1-closure.hh"
|
||||
#include "OT/Color/CPAL/CPAL.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
#include "hb-ot-math-table.hh"
|
||||
|
||||
using OT::Layout::GSUB;
|
||||
using OT::Layout::GPOS;
|
||||
|
||||
|
||||
hb_subset_accelerator_t::~hb_subset_accelerator_t ()
|
||||
{
|
||||
if (cmap_cache && destroy_cmap_cache)
|
||||
@ -63,7 +57,6 @@ hb_subset_accelerator_t::~hb_subset_accelerator_t ()
|
||||
}
|
||||
|
||||
|
||||
typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
|
||||
#ifndef HB_NO_SUBSET_CFF
|
||||
static inline bool
|
||||
_add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff,
|
||||
@ -98,414 +91,14 @@ _remap_palette_indexes (const hb_set_t *palette_indexes,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_remap_indexes (const hb_set_t *indexes,
|
||||
hb_map_t *mapping /* OUT */)
|
||||
void
|
||||
remap_indexes (const hb_set_t *indexes,
|
||||
hb_map_t *mapping /* OUT */)
|
||||
{
|
||||
for (auto _ : + hb_enumerate (indexes->iter ()))
|
||||
mapping->set (_.second, _.first);
|
||||
|
||||
}
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
|
||||
/*
|
||||
* Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates.
|
||||
* Returns true if anything was removed (not including duplicates).
|
||||
*/
|
||||
static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */
|
||||
const hb_set_t* filter)
|
||||
{
|
||||
hb_vector_t<hb_tag_t> out;
|
||||
out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator.
|
||||
|
||||
bool removed = false;
|
||||
hb_set_t visited;
|
||||
|
||||
for (hb_tag_t tag : *tags)
|
||||
{
|
||||
if (!tag) continue;
|
||||
if (visited.has (tag)) continue;
|
||||
|
||||
if (!filter->has (tag))
|
||||
{
|
||||
removed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
visited.add (tag);
|
||||
out.push (tag);
|
||||
}
|
||||
|
||||
// The collect function needs a null element to signal end of the array.
|
||||
out.push (HB_TAG_NONE);
|
||||
|
||||
hb_swap (out, *tags);
|
||||
return removed;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void _collect_layout_indices (hb_subset_plan_t *plan,
|
||||
const T& table,
|
||||
hb_set_t *lookup_indices, /* OUT */
|
||||
hb_set_t *feature_indices, /* OUT */
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */
|
||||
hb_set_t& catch_all_record_feature_idxes, /* OUT */
|
||||
hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map /* OUT */)
|
||||
{
|
||||
unsigned num_features = table.get_feature_count ();
|
||||
hb_vector_t<hb_tag_t> features;
|
||||
if (!plan->check_success (features.resize (num_features))) return;
|
||||
table.get_feature_tags (0, &num_features, features.arrayZ);
|
||||
bool retain_all_features = !_filter_tag_list (&features, &plan->layout_features);
|
||||
|
||||
unsigned num_scripts = table.get_script_count ();
|
||||
hb_vector_t<hb_tag_t> scripts;
|
||||
if (!plan->check_success (scripts.resize (num_scripts))) return;
|
||||
table.get_script_tags (0, &num_scripts, scripts.arrayZ);
|
||||
bool retain_all_scripts = !_filter_tag_list (&scripts, &plan->layout_scripts);
|
||||
|
||||
if (!plan->check_success (!features.in_error ()) || !features
|
||||
|| !plan->check_success (!scripts.in_error ()) || !scripts)
|
||||
return;
|
||||
|
||||
hb_ot_layout_collect_features (plan->source,
|
||||
T::tableTag,
|
||||
retain_all_scripts ? nullptr : scripts.arrayZ,
|
||||
nullptr,
|
||||
retain_all_features ? nullptr : features.arrayZ,
|
||||
feature_indices);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
// collect feature substitutes with variations
|
||||
if (!plan->user_axes_location.is_empty ())
|
||||
{
|
||||
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
|
||||
OT::hb_collect_feature_substitutes_with_var_context_t c =
|
||||
{
|
||||
&plan->axes_old_index_tag_map,
|
||||
&plan->axes_location,
|
||||
feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
catch_all_record_feature_idxes,
|
||||
feature_indices,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
&conditionset_map
|
||||
};
|
||||
table.collect_feature_substitutes_with_variations (&c);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (unsigned feature_index : *feature_indices)
|
||||
{
|
||||
const OT::Feature* f = &(table.get_feature (feature_index));
|
||||
const OT::Feature **p = nullptr;
|
||||
if (feature_substitutes_map->has (feature_index, &p))
|
||||
f = *p;
|
||||
|
||||
f->add_lookup_indexes_to (lookup_indices);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (catch_all_record_feature_idxes)
|
||||
{
|
||||
for (unsigned feature_index : catch_all_record_feature_idxes)
|
||||
{
|
||||
const OT::Feature& f = table.get_feature (feature_index);
|
||||
f.add_lookup_indexes_to (lookup_indices);
|
||||
const void *tag = reinterpret_cast<const void*> (&(table.get_feature_list ().get_tag (feature_index)));
|
||||
catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag));
|
||||
}
|
||||
}
|
||||
|
||||
// If all axes are pinned then all feature variations will be dropped so there's no need
|
||||
// to collect lookups from them.
|
||||
if (!plan->all_axes_pinned)
|
||||
table.feature_variation_collect_lookups (feature_indices,
|
||||
plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map,
|
||||
lookup_indices);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
|
||||
const hb_map_t *lookup_indices,
|
||||
const hb_set_t *feature_indices,
|
||||
const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
|
||||
hb_map_t *duplicate_feature_map /* OUT */)
|
||||
{
|
||||
if (feature_indices->is_empty ()) return;
|
||||
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
|
||||
//find out duplicate features after subset
|
||||
for (unsigned i : feature_indices->iter ())
|
||||
{
|
||||
hb_tag_t t = g.get_feature_tag (i);
|
||||
if (t == HB_MAP_VALUE_INVALID) continue;
|
||||
if (!unique_features.has (t))
|
||||
{
|
||||
if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
|
||||
return;
|
||||
if (unique_features.has (t))
|
||||
unique_features.get (t)->add (i);
|
||||
duplicate_feature_map->set (i, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
hb_set_t* same_tag_features = unique_features.get (t);
|
||||
for (unsigned other_f_index : same_tag_features->iter ())
|
||||
{
|
||||
const OT::Feature* f = &(g.get_feature (i));
|
||||
const OT::Feature **p = nullptr;
|
||||
if (feature_substitutes_map->has (i, &p))
|
||||
f = *p;
|
||||
|
||||
const OT::Feature* other_f = &(g.get_feature (other_f_index));
|
||||
if (feature_substitutes_map->has (other_f_index, &p))
|
||||
other_f = *p;
|
||||
|
||||
auto f_iter =
|
||||
+ hb_iter (f->lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
auto other_f_iter =
|
||||
+ hb_iter (other_f->lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
bool is_equal = true;
|
||||
for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
|
||||
{
|
||||
unsigned a = *f_iter;
|
||||
unsigned b = *other_f_iter;
|
||||
if (a != b) { is_equal = false; break; }
|
||||
}
|
||||
|
||||
if (is_equal == false || f_iter || other_f_iter) continue;
|
||||
|
||||
found = true;
|
||||
duplicate_feature_map->set (i, other_f_index);
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == false)
|
||||
{
|
||||
same_tag_features->add (i);
|
||||
duplicate_feature_map->set (i, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void
|
||||
_closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
||||
hb_set_t *gids_to_retain,
|
||||
hb_map_t *lookups,
|
||||
hb_map_t *features,
|
||||
script_langsys_map *langsys_map,
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
|
||||
hb_set_t &catch_all_record_feature_idxes,
|
||||
hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map)
|
||||
{
|
||||
hb_blob_ptr_t<T> table = plan->source_table<T> ();
|
||||
hb_tag_t table_tag = table->tableTag;
|
||||
hb_set_t lookup_indices, feature_indices;
|
||||
_collect_layout_indices<T> (plan,
|
||||
*table,
|
||||
&lookup_indices,
|
||||
&feature_indices,
|
||||
feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
catch_all_record_feature_idxes,
|
||||
catch_all_record_idx_feature_map);
|
||||
|
||||
if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
|
||||
hb_ot_layout_lookups_substitute_closure (plan->source,
|
||||
&lookup_indices,
|
||||
gids_to_retain);
|
||||
table->closure_lookups (plan->source,
|
||||
gids_to_retain,
|
||||
&lookup_indices);
|
||||
_remap_indexes (&lookup_indices, lookups);
|
||||
|
||||
// prune features
|
||||
table->prune_features (lookups,
|
||||
plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
&feature_indices);
|
||||
hb_map_t duplicate_feature_map;
|
||||
_GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map);
|
||||
|
||||
feature_indices.clear ();
|
||||
table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices);
|
||||
_remap_indexes (&feature_indices, features);
|
||||
|
||||
table.destroy ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
static inline void
|
||||
_generate_varstore_inner_maps (const hb_set_t& varidx_set,
|
||||
unsigned subtable_count,
|
||||
hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */)
|
||||
{
|
||||
if (varidx_set.is_empty () || subtable_count == 0) return;
|
||||
|
||||
if (unlikely (!inner_maps.resize (subtable_count))) return;
|
||||
for (unsigned idx : varidx_set)
|
||||
{
|
||||
uint16_t major = idx >> 16;
|
||||
uint16_t minor = idx & 0xFFFF;
|
||||
|
||||
if (major >= subtable_count)
|
||||
continue;
|
||||
inner_maps[major].add (minor);
|
||||
}
|
||||
}
|
||||
|
||||
static inline hb_font_t*
|
||||
_get_hb_font_with_variations (const hb_subset_plan_t *plan)
|
||||
{
|
||||
hb_font_t *font = hb_font_create (plan->source);
|
||||
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
if (!vars.alloc (plan->user_axes_location.get_population ())) {
|
||||
hb_font_destroy (font);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto _ : plan->user_axes_location)
|
||||
{
|
||||
hb_variation_t var;
|
||||
var.tag = _.first;
|
||||
var.value = _.second.middle;
|
||||
vars.push (var);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
|
||||
#endif
|
||||
return font;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_remap_variation_indices (const OT::ItemVariationStore &var_store,
|
||||
const hb_set_t &variation_indices,
|
||||
const hb_vector_t<int>& normalized_coords,
|
||||
bool calculate_delta, /* not pinned at default */
|
||||
bool no_variations, /* all axes pinned */
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */)
|
||||
{
|
||||
if (&var_store == &Null (OT::ItemVariationStore)) return;
|
||||
unsigned subtable_count = var_store.get_sub_table_count ();
|
||||
float *store_cache = var_store.create_cache ();
|
||||
|
||||
unsigned new_major = 0, new_minor = 0;
|
||||
unsigned last_major = (variation_indices.get_min ()) >> 16;
|
||||
for (unsigned idx : variation_indices)
|
||||
{
|
||||
int delta = 0;
|
||||
if (calculate_delta)
|
||||
delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
|
||||
normalized_coords.length, store_cache));
|
||||
|
||||
if (no_variations)
|
||||
{
|
||||
variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t major = idx >> 16;
|
||||
if (major >= subtable_count) break;
|
||||
if (major != last_major)
|
||||
{
|
||||
new_minor = 0;
|
||||
++new_major;
|
||||
}
|
||||
|
||||
unsigned new_idx = (new_major << 16) + new_minor;
|
||||
variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
|
||||
++new_minor;
|
||||
last_major = major;
|
||||
}
|
||||
var_store.destroy_cache (store_cache);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_collect_layout_variation_indices (hb_subset_plan_t* plan)
|
||||
{
|
||||
hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
|
||||
hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
|
||||
|
||||
if (!gdef->has_data () || !gdef->has_var_store ())
|
||||
{
|
||||
gdef.destroy ();
|
||||
gpos.destroy ();
|
||||
return;
|
||||
}
|
||||
|
||||
hb_set_t varidx_set;
|
||||
OT::hb_collect_variation_indices_context_t c (&varidx_set,
|
||||
&plan->_glyphset_gsub,
|
||||
&plan->gpos_lookups);
|
||||
gdef->collect_variation_indices (&c);
|
||||
|
||||
if (hb_ot_layout_has_positioning (plan->source))
|
||||
gpos->collect_variation_indices (&c);
|
||||
|
||||
_remap_variation_indices (gdef->get_var_store (),
|
||||
varidx_set, plan->normalized_coords,
|
||||
!plan->pinned_at_default,
|
||||
plan->all_axes_pinned,
|
||||
plan->layout_variation_idx_delta_map);
|
||||
|
||||
unsigned subtable_count = gdef->get_var_store ().get_sub_table_count ();
|
||||
_generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
|
||||
|
||||
gdef.destroy ();
|
||||
gpos.destroy ();
|
||||
}
|
||||
|
||||
#ifndef HB_NO_BASE
|
||||
static inline void
|
||||
_collect_base_variation_indices (hb_subset_plan_t* plan)
|
||||
{
|
||||
hb_blob_ptr_t<OT::BASE> base = plan->source_table<OT::BASE> ();
|
||||
if (!base->has_var_store ())
|
||||
{
|
||||
base.destroy ();
|
||||
return;
|
||||
}
|
||||
|
||||
hb_set_t varidx_set;
|
||||
base->collect_variation_indices (plan, varidx_set);
|
||||
const OT::ItemVariationStore &var_store = base->get_var_store ();
|
||||
unsigned subtable_count = var_store.get_sub_table_count ();
|
||||
|
||||
|
||||
_remap_variation_indices (var_store, varidx_set,
|
||||
plan->normalized_coords,
|
||||
!plan->pinned_at_default,
|
||||
plan->all_axes_pinned,
|
||||
plan->base_variation_idx_map);
|
||||
_generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps);
|
||||
|
||||
base.destroy ();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
_cmap_closure (hb_face_t *face,
|
||||
const hb_set_t *unicodes,
|
||||
@ -515,41 +108,6 @@ _cmap_closure (hb_face_t *face,
|
||||
cmap.table->closure_glyphs (unicodes, glyphset);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
static void
|
||||
_remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map,
|
||||
const hb_set_t &delta_set_idxes,
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
|
||||
hb_map_t &new_deltaset_idx_varidx_map /* OUT */)
|
||||
{
|
||||
if (!index_map.get_map_count ())
|
||||
return;
|
||||
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> delta_set_idx_delta_map;
|
||||
unsigned new_delta_set_idx = 0;
|
||||
for (unsigned delta_set_idx : delta_set_idxes)
|
||||
{
|
||||
unsigned var_idx = index_map.map (delta_set_idx);
|
||||
unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||
int delta = 0;
|
||||
|
||||
if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
{
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue;
|
||||
|
||||
new_varidx = hb_first (*new_varidx_delta);
|
||||
delta = hb_second (*new_varidx_delta);
|
||||
}
|
||||
|
||||
new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx);
|
||||
delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t<unsigned, int> (new_delta_set_idx, delta));
|
||||
new_delta_set_idx++;
|
||||
}
|
||||
variation_idx_delta_map = std::move (delta_set_idx_delta_map);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _colr_closure (hb_subset_plan_t* plan,
|
||||
hb_set_t *glyphs_colred)
|
||||
{
|
||||
@ -569,7 +127,7 @@ static void _colr_closure (hb_subset_plan_t* plan,
|
||||
colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices);
|
||||
|
||||
colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
|
||||
_remap_indexes (&layer_indices, &plan->colrv1_layers);
|
||||
remap_indexes (&layer_indices, &plan->colrv1_layers);
|
||||
_remap_palette_indexes (&palette_indices, &plan->colr_palettes);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
@ -578,7 +136,7 @@ static void _colr_closure (hb_subset_plan_t* plan,
|
||||
const OT::ItemVariationStore &var_store = colr.get_var_store ();
|
||||
// generated inner_maps is used by ItemVariationStore serialize(), which is subset only
|
||||
unsigned subtable_count = var_store.get_sub_table_count ();
|
||||
_generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
|
||||
generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
|
||||
|
||||
/* colr variation indices mapping during planning phase:
|
||||
* generate colrv1_variation_idx_delta_map. When delta set index map is not
|
||||
@ -590,7 +148,7 @@ static void _colr_closure (hb_subset_plan_t* plan,
|
||||
* instancing. */
|
||||
if (!plan->all_axes_pinned)
|
||||
{
|
||||
_remap_variation_indices (var_store,
|
||||
remap_variation_indices (var_store,
|
||||
variation_indices,
|
||||
plan->normalized_coords,
|
||||
false, /* no need to calculate delta for COLR during planning */
|
||||
@ -598,7 +156,7 @@ static void _colr_closure (hb_subset_plan_t* plan,
|
||||
plan->colrv1_variation_idx_delta_map);
|
||||
|
||||
if (colr.has_delta_set_index_map ())
|
||||
_remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (),
|
||||
remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (),
|
||||
delta_set_indices,
|
||||
plan->colrv1_variation_idx_delta_map,
|
||||
plan->colrv1_new_deltaset_idx_varidx_map);
|
||||
@ -616,25 +174,6 @@ _math_closure (hb_subset_plan_t *plan,
|
||||
math.destroy ();
|
||||
}
|
||||
|
||||
static inline void
|
||||
_remap_used_mark_sets (hb_subset_plan_t *plan,
|
||||
hb_map_t& used_mark_sets_map)
|
||||
{
|
||||
hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
|
||||
|
||||
if (!gdef->has_data () || !gdef->has_mark_glyph_sets ())
|
||||
{
|
||||
gdef.destroy ();
|
||||
return;
|
||||
}
|
||||
|
||||
hb_set_t used_mark_sets;
|
||||
gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets);
|
||||
gdef.destroy ();
|
||||
|
||||
_remap_indexes (&used_mark_sets, &used_mark_sets_map);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_remove_invalid_gids (hb_set_t *glyphs,
|
||||
unsigned int num_glyphs)
|
||||
@ -672,15 +211,46 @@ _fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
|
||||
_fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds additional unicode codepoints which are reachable from the input unicode set.
|
||||
* Currently this adds in mirrored variants (needed for bidi) of any input unicodes.
|
||||
*/
|
||||
static hb_set_t
|
||||
_unicode_closure (const hb_set_t* unicodes, bool bidi_closure) {
|
||||
// TODO: we may want to also consider pulling in reachable unicode composition and decompositions.
|
||||
// see: https://github.com/harfbuzz/harfbuzz/issues/2283
|
||||
hb_set_t out = *unicodes;
|
||||
if (!bidi_closure) return out;
|
||||
|
||||
if (out.is_inverted()) {
|
||||
// don't closure inverted sets, they are asking to specifically exclude certain codepoints.
|
||||
// otherwise everything is already included.
|
||||
return out;
|
||||
}
|
||||
|
||||
auto unicode_funcs = hb_unicode_funcs_get_default ();
|
||||
for (hb_codepoint_t cp : *unicodes) {
|
||||
hb_codepoint_t mirror = hb_unicode_mirroring(unicode_funcs, cp);
|
||||
if (unlikely (mirror != cp)) {
|
||||
out.add(mirror);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
_populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
_populate_unicodes_to_retain (const hb_set_t *unicodes_in,
|
||||
const hb_set_t *glyphs,
|
||||
hb_subset_plan_t *plan)
|
||||
{
|
||||
hb_set_t unicodes = _unicode_closure(unicodes_in,
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NO_BIDI_CLOSURE));
|
||||
|
||||
OT::cmap::accelerator_t cmap (plan->source);
|
||||
unsigned size_threshold = plan->source->get_num_glyphs ();
|
||||
|
||||
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
|
||||
if (glyphs->is_empty () && unicodes.get_population () < size_threshold)
|
||||
{
|
||||
|
||||
const hb_map_t* unicode_to_gid = nullptr;
|
||||
@ -690,9 +260,9 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
// This is approach to collection is faster, but can only be used if glyphs
|
||||
// are not being explicitly added to the subset and the input unicodes set is
|
||||
// not excessively large (eg. an inverted set).
|
||||
plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
|
||||
plan->unicode_to_new_gid_list.alloc (unicodes.get_population ());
|
||||
if (!unicode_to_gid) {
|
||||
_fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
|
||||
_fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) {
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid)) {
|
||||
return HB_MAP_VALUE_INVALID;
|
||||
@ -704,7 +274,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
// the map. This code is mostly duplicated from above to avoid doing
|
||||
// conditionals on the presence of the unicode_to_gid map each
|
||||
// iteration.
|
||||
_fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
|
||||
_fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) {
|
||||
return unicode_to_gid->get (cp);
|
||||
});
|
||||
}
|
||||
@ -721,7 +291,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
|
||||
if (!plan->accelerator) {
|
||||
cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage);
|
||||
plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
|
||||
plan->unicode_to_new_gid_list.alloc (hb_min(unicodes.get_population ()
|
||||
+ glyphs->get_population (),
|
||||
cmap_unicodes->get_population ()));
|
||||
} else {
|
||||
@ -730,10 +300,10 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
}
|
||||
|
||||
if (plan->accelerator &&
|
||||
unicodes->get_population () < cmap_unicodes->get_population () &&
|
||||
unicodes.get_population () < cmap_unicodes->get_population () &&
|
||||
glyphs->get_population () < cmap_unicodes->get_population ())
|
||||
{
|
||||
plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ());
|
||||
plan->codepoint_to_glyph->alloc (unicodes.get_population () + glyphs->get_population ());
|
||||
|
||||
auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
|
||||
|
||||
@ -748,7 +318,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
});
|
||||
}
|
||||
|
||||
_fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
|
||||
_fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) {
|
||||
/* Don't double-add entry. */
|
||||
if (plan->codepoint_to_glyph->has (cp))
|
||||
return HB_MAP_VALUE_INVALID;
|
||||
@ -769,7 +339,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||
{
|
||||
_fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) {
|
||||
hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
|
||||
if (!unicodes->has (cp) && !glyphs->has (gid))
|
||||
if (!unicodes.has (cp) && !glyphs->has (gid))
|
||||
return HB_MAP_VALUE_INVALID;
|
||||
return gid;
|
||||
},
|
||||
@ -860,18 +430,7 @@ _nameid_closure (hb_subset_plan_t* plan,
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (!drop_tables->has (HB_OT_TAG_GPOS))
|
||||
{
|
||||
hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
|
||||
gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids);
|
||||
gpos.destroy ();
|
||||
}
|
||||
if (!drop_tables->has (HB_OT_TAG_GSUB))
|
||||
{
|
||||
hb_blob_ptr_t<GSUB> gsub = plan->source_table<GSUB> ();
|
||||
gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids);
|
||||
gsub.destroy ();
|
||||
}
|
||||
layout_nameid_closure(plan, drop_tables);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -893,31 +452,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
_cmap_closure (plan->source, &plan->unicodes, &plan->_glyphset_gsub);
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (!drop_tables->has (HB_OT_TAG_GSUB))
|
||||
// closure all glyphs/lookups/features needed for GSUB substitutions.
|
||||
_closure_glyphs_lookups_features<GSUB> (
|
||||
plan,
|
||||
&plan->_glyphset_gsub,
|
||||
&plan->gsub_lookups,
|
||||
&plan->gsub_features,
|
||||
&plan->gsub_langsys,
|
||||
&plan->gsub_feature_record_cond_idx_map,
|
||||
&plan->gsub_feature_substitutes_map,
|
||||
plan->gsub_old_features,
|
||||
plan->gsub_old_feature_idx_tag_map);
|
||||
|
||||
if (!drop_tables->has (HB_OT_TAG_GPOS))
|
||||
_closure_glyphs_lookups_features<GPOS> (
|
||||
plan,
|
||||
&plan->_glyphset_gsub,
|
||||
&plan->gpos_lookups,
|
||||
&plan->gpos_features,
|
||||
&plan->gpos_langsys,
|
||||
&plan->gpos_feature_record_cond_idx_map,
|
||||
&plan->gpos_feature_substitutes_map,
|
||||
plan->gpos_old_features,
|
||||
plan->gpos_old_feature_idx_tag_map);
|
||||
layout_populate_gids_to_retain(plan, drop_tables);
|
||||
#endif
|
||||
|
||||
_remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
||||
|
||||
plan->_glyphset_mathed = plan->_glyphset_gsub;
|
||||
@ -962,8 +499,10 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
_remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ());
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (!drop_tables->has (HB_OT_TAG_GDEF))
|
||||
_collect_layout_variation_indices (plan);
|
||||
collect_layout_variation_indices (plan);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1077,193 +616,6 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
static void
|
||||
_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
||||
{
|
||||
if (plan->user_axes_location.is_empty ())
|
||||
return;
|
||||
|
||||
hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
|
||||
plan->normalized_coords.resize (axes.length);
|
||||
|
||||
bool has_avar = face->table.avar->has_data ();
|
||||
const OT::SegmentMaps *seg_maps = nullptr;
|
||||
unsigned avar_axis_count = 0;
|
||||
if (has_avar)
|
||||
{
|
||||
seg_maps = face->table.avar->get_segment_maps ();
|
||||
avar_axis_count = face->table.avar->get_axis_count();
|
||||
}
|
||||
|
||||
bool axis_not_pinned = false;
|
||||
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
||||
for (const auto& axis : axes)
|
||||
{
|
||||
hb_tag_t axis_tag = axis.get_axis_tag ();
|
||||
plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag);
|
||||
|
||||
if (!plan->user_axes_location.has (axis_tag) ||
|
||||
!plan->user_axes_location.get (axis_tag).is_point ())
|
||||
{
|
||||
axis_not_pinned = true;
|
||||
plan->axes_index_map.set (old_axis_idx, new_axis_idx);
|
||||
plan->axis_tags.push (axis_tag);
|
||||
new_axis_idx++;
|
||||
}
|
||||
|
||||
Triple *axis_range;
|
||||
if (plan->user_axes_location.has (axis_tag, &axis_range))
|
||||
{
|
||||
plan->axes_triple_distances.set (axis_tag, axis.get_triple_distances ());
|
||||
|
||||
int normalized_min = axis.normalize_axis_value (axis_range->minimum);
|
||||
int normalized_default = axis.normalize_axis_value (axis_range->middle);
|
||||
int normalized_max = axis.normalize_axis_value (axis_range->maximum);
|
||||
|
||||
if (has_avar && old_axis_idx < avar_axis_count)
|
||||
{
|
||||
normalized_min = seg_maps->map (normalized_min);
|
||||
normalized_default = seg_maps->map (normalized_default);
|
||||
normalized_max = seg_maps->map (normalized_max);
|
||||
}
|
||||
plan->axes_location.set (axis_tag, Triple (static_cast<double> (normalized_min / 16384.0),
|
||||
static_cast<double> (normalized_default / 16384.0),
|
||||
static_cast<double> (normalized_max / 16384.0)));
|
||||
|
||||
if (normalized_default != 0)
|
||||
plan->pinned_at_default = false;
|
||||
|
||||
plan->normalized_coords[old_axis_idx] = normalized_default;
|
||||
}
|
||||
|
||||
old_axis_idx++;
|
||||
|
||||
if (has_avar && old_axis_idx < avar_axis_count)
|
||||
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
||||
}
|
||||
plan->all_axes_pinned = !axis_not_pinned;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
|
||||
{
|
||||
if (!plan->normalized_coords) return;
|
||||
OT::cff2::accelerator_t cff2 (plan->source);
|
||||
if (!cff2.is_valid ()) return;
|
||||
|
||||
hb_font_t *font = _get_hb_font_with_variations (plan);
|
||||
if (unlikely (!plan->check_success (font != nullptr)))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return;
|
||||
}
|
||||
|
||||
hb_glyph_extents_t extents = {0x7FFF, -0x7FFF};
|
||||
OT::hmtx_accelerator_t _hmtx (plan->source);
|
||||
float *hvar_store_cache = nullptr;
|
||||
if (_hmtx.has_data () && _hmtx.var_table.get_length ())
|
||||
hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache ();
|
||||
|
||||
OT::vmtx_accelerator_t _vmtx (plan->source);
|
||||
float *vvar_store_cache = nullptr;
|
||||
if (_vmtx.has_data () && _vmtx.var_table.get_length ())
|
||||
vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache ();
|
||||
|
||||
for (auto p : *plan->glyph_map)
|
||||
{
|
||||
hb_codepoint_t old_gid = p.first;
|
||||
hb_codepoint_t new_gid = p.second;
|
||||
if (!cff2.get_extents (font, old_gid, &extents)) continue;
|
||||
bool has_bounds_info = true;
|
||||
if (extents.x_bearing == 0 && extents.width == 0 &&
|
||||
extents.height == 0 && extents.y_bearing == 0)
|
||||
has_bounds_info = false;
|
||||
|
||||
if (has_bounds_info)
|
||||
{
|
||||
plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, extents.x_bearing);
|
||||
plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, extents.x_bearing + extents.width);
|
||||
plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, extents.y_bearing);
|
||||
plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, extents.y_bearing + extents.height);
|
||||
}
|
||||
|
||||
if (_hmtx.has_data ())
|
||||
{
|
||||
int hori_aw = _hmtx.get_advance_without_var_unscaled (old_gid);
|
||||
if (_hmtx.var_table.get_length ())
|
||||
hori_aw += (int) roundf (_hmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
|
||||
hvar_store_cache));
|
||||
int lsb = extents.x_bearing;
|
||||
if (!has_bounds_info)
|
||||
{
|
||||
if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
|
||||
continue;
|
||||
}
|
||||
plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
|
||||
plan->bounds_width_vec[new_gid] = extents.width;
|
||||
}
|
||||
|
||||
if (_vmtx.has_data ())
|
||||
{
|
||||
int vert_aw = _vmtx.get_advance_without_var_unscaled (old_gid);
|
||||
if (_vmtx.var_table.get_length ())
|
||||
vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
|
||||
vvar_store_cache));
|
||||
|
||||
int tsb = extents.y_bearing;
|
||||
if (!has_bounds_info)
|
||||
{
|
||||
if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb))
|
||||
continue;
|
||||
}
|
||||
plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
|
||||
plan->bounds_height_vec[new_gid] = extents.height;
|
||||
}
|
||||
}
|
||||
hb_font_destroy (font);
|
||||
if (hvar_store_cache)
|
||||
_hmtx.var_table->get_var_store ().destroy_cache (hvar_store_cache);
|
||||
if (vvar_store_cache)
|
||||
_vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache);
|
||||
}
|
||||
|
||||
static bool
|
||||
_get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
|
||||
{
|
||||
/* contour_points vector only needed for updating gvar table (infer delta and
|
||||
* iup delta optimization) during partial instancing */
|
||||
if (plan->user_axes_location.is_empty () || plan->all_axes_pinned)
|
||||
return true;
|
||||
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
|
||||
for (auto &_ : plan->new_to_old_gid_list)
|
||||
{
|
||||
hb_codepoint_t new_gid = _.first;
|
||||
contour_point_vector_t all_points;
|
||||
if (new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
{
|
||||
if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
hb_codepoint_t old_gid = _.second;
|
||||
auto glyph = glyf.glyph_for_gid (old_gid);
|
||||
if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points)))
|
||||
return false;
|
||||
if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
|
||||
return false;
|
||||
|
||||
/* composite new gids are only needed by iup delta optimization */
|
||||
if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ())
|
||||
plan->composite_new_gids.add (new_gid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||
const hb_subset_input_t *input)
|
||||
{
|
||||
@ -1324,7 +676,7 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||
return;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
_normalize_axes_location (face, this);
|
||||
normalize_axes_location (face, this);
|
||||
#endif
|
||||
|
||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
|
||||
@ -1365,13 +717,15 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||
for (auto &v : bounds_height_vec)
|
||||
v = 0xFFFFFFFF;
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (!drop_tables.has (HB_OT_TAG_GDEF))
|
||||
_remap_used_mark_sets (this, used_mark_sets_map);
|
||||
remap_used_mark_sets (this, used_mark_sets_map);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
#ifndef HB_NO_BASE
|
||||
if (!drop_tables.has (HB_OT_TAG_BASE))
|
||||
_collect_base_variation_indices (this);
|
||||
collect_base_variation_indices (this);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1379,8 +733,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||
return;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
_update_instance_metrics_map_from_cff2 (this);
|
||||
if (!check_success (_get_instance_glyphs_contour_points (this)))
|
||||
update_instance_metrics_map_from_cff2 (this);
|
||||
if (!check_success (get_instance_glyphs_contour_points (this)))
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
@ -296,5 +296,75 @@ struct hb_subset_plan_t
|
||||
}
|
||||
};
|
||||
|
||||
// hb-subset-plan implementation is split into multiple files to keep
|
||||
// compile times more reasonable:
|
||||
// - hb-subset-plan.cc
|
||||
// - hb-subset-plan-layout.cc
|
||||
//
|
||||
// The functions below are those needed to connect the split files
|
||||
// above together.
|
||||
HB_INTERNAL void
|
||||
remap_indexes (const hb_set_t *indexes,
|
||||
hb_map_t *mapping /* OUT */);
|
||||
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
template<typename ItemVarStore>
|
||||
HB_INTERNAL void
|
||||
remap_variation_indices (const ItemVarStore &var_store,
|
||||
const hb_set_t &variation_indices,
|
||||
const hb_vector_t<int>& normalized_coords,
|
||||
bool calculate_delta, /* not pinned at default */
|
||||
bool no_variations, /* all axes pinned */
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */);
|
||||
|
||||
|
||||
template<typename DeltaSetIndexMap>
|
||||
HB_INTERNAL void
|
||||
remap_colrv1_delta_set_index_indices (const DeltaSetIndexMap &index_map,
|
||||
const hb_set_t &delta_set_idxes,
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
|
||||
hb_map_t &new_deltaset_idx_varidx_map /* OUT */);
|
||||
|
||||
|
||||
HB_INTERNAL void
|
||||
generate_varstore_inner_maps (const hb_set_t& varidx_set,
|
||||
unsigned subtable_count,
|
||||
hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */);
|
||||
|
||||
HB_INTERNAL void
|
||||
normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan);
|
||||
|
||||
HB_INTERNAL void
|
||||
update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan);
|
||||
|
||||
HB_INTERNAL bool
|
||||
get_instance_glyphs_contour_points (hb_subset_plan_t *plan);
|
||||
|
||||
#ifndef HB_NO_BASE
|
||||
HB_INTERNAL void
|
||||
collect_base_variation_indices (hb_subset_plan_t* plan);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
|
||||
|
||||
HB_INTERNAL void
|
||||
remap_used_mark_sets (hb_subset_plan_t *plan,
|
||||
hb_map_t& used_mark_sets_map);
|
||||
|
||||
HB_INTERNAL void
|
||||
layout_nameid_closure (hb_subset_plan_t* plan,
|
||||
hb_set_t* drop_tables);
|
||||
|
||||
HB_INTERNAL void
|
||||
layout_populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
hb_set_t* drop_tables);
|
||||
|
||||
HB_INTERNAL void
|
||||
collect_layout_variation_indices (hb_subset_plan_t* plan);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HB_SUBSET_PLAN_HH */
|
||||
|
||||
@ -708,3 +708,107 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
|
||||
end:
|
||||
return success ? hb_face_reference (plan->dest) : nullptr;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
||||
#include "hb-ot-cff1-table.hh"
|
||||
|
||||
template<typename accel_t>
|
||||
static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) {
|
||||
if (!accel.is_valid()) {
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
hb_ubytes_t bytes = (*accel.charStrings)[glyph_index];
|
||||
if (!bytes) {
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
hb_blob_t* cff_blob = accel.get_blob();
|
||||
uint32_t length;
|
||||
const char* cff_data = hb_blob_get_data(cff_blob, &length) ;
|
||||
|
||||
long int offset = (const char*) bytes.arrayZ - cff_data;
|
||||
if (offset < 0 || offset > INT32_MAX) {
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length);
|
||||
}
|
||||
|
||||
template<typename accel_t>
|
||||
static hb_blob_t* get_charstrings_index(accel_t& accel) {
|
||||
if (!accel.is_valid()) {
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
const char* charstrings_start = (const char*) accel.charStrings;
|
||||
unsigned charstrings_length = accel.charStrings->get_size();
|
||||
|
||||
hb_blob_t* cff_blob = accel.get_blob();
|
||||
uint32_t length;
|
||||
const char* cff_data = hb_blob_get_data(cff_blob, &length) ;
|
||||
|
||||
long int offset = charstrings_start - cff_data;
|
||||
if (offset < 0 || offset > INT32_MAX) {
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_cff_get_charstring_data:
|
||||
* @face: A face object
|
||||
* @glyph_index: Glyph index to get data for.
|
||||
*
|
||||
* Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index.
|
||||
*
|
||||
* XSince: EXPERIMENTAL
|
||||
**/
|
||||
HB_EXTERN hb_blob_t*
|
||||
hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) {
|
||||
return get_charstrings_data(*face->table.cff1, glyph_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_cff_get_charstrings_index:
|
||||
* @face: A face object
|
||||
*
|
||||
* Returns the raw CFF CharStrings INDEX from the CFF table.
|
||||
*
|
||||
* XSince: EXPERIMENTAL
|
||||
**/
|
||||
HB_EXTERN hb_blob_t*
|
||||
hb_subset_cff_get_charstrings_index (hb_face_t* face) {
|
||||
return get_charstrings_index (*face->table.cff1);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_cff2_get_charstring_data:
|
||||
* @face: A face object
|
||||
* @glyph_index: Glyph index to get data for.
|
||||
*
|
||||
* Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index.
|
||||
*
|
||||
* XSince: EXPERIMENTAL
|
||||
**/
|
||||
HB_EXTERN hb_blob_t*
|
||||
hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) {
|
||||
return get_charstrings_data(*face->table.cff2, glyph_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_cff2_get_charstrings_index:
|
||||
* @face: A face object
|
||||
*
|
||||
* Returns the raw CFF2 CharStrings INDEX from the CFF2 table.
|
||||
*
|
||||
* XSince: EXPERIMENTAL
|
||||
**/
|
||||
HB_EXTERN hb_blob_t*
|
||||
hb_subset_cff2_get_charstrings_index (hb_face_t* face) {
|
||||
return get_charstrings_index (*face->table.cff2);
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user