Upgrade Harfbuzz to 11.2.1

[ChangeLog][Third-Party Code] Upgraded Harfbuzz to version
11.2.1.

Task-number: QTBUG-136745
Change-Id: Ie3f67e84447f30579933d92677908f3606e557a4
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit f17a8ac6fb9a194b984521fa9f0120540de8b8d2)
Reviewed-by: Akseli Salovaara <akseli.salovaara@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2025-05-13 11:43:10 +02:00 committed by Jani Heikkinen
parent 31f1c78b0b
commit 60cf2f867b
54 changed files with 1853 additions and 871 deletions

View File

@ -44,6 +44,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
src/hb-open-type.hh
src/hb-outline.cc src/hb-outline.hh
src/hb-paint.cc src/hb-paint.h src/hb-paint.hh
src/hb-paint-bounded.cc src/hb-paint-bounded.hh
src/hb-paint-extents.cc src/hb-paint-extents.hh
src/hb-priority-queue.hh
src/hb-repacker.hh

View File

@ -7,8 +7,8 @@
"Description": "HarfBuzz is an OpenType text shaping engine.",
"Homepage": "http://harfbuzz.org",
"Version": "11.1.0",
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.1.0",
"Version": "11.2.1",
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.2.1",
"PURL": "pkg:github/harfbuzz/harfbuzz@$<VERSION>",
"CPE": "cpe:2.3:a:harfbuzz_project:harfbuzz:$<VERSION>:*:*:*:*:*:*:*",
"License": "MIT License",

View File

@ -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;
}

View File

@ -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"
@ -49,6 +50,7 @@ struct hb_paint_context_t;
struct hb_colr_scratch_t
{
hb_paint_bounded_context_t paint_bounded;
hb_paint_extents_context_t paint_extents;
};
@ -101,7 +103,21 @@ public:
),
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)
{
@ -1620,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;
}
}
@ -2230,7 +2246,7 @@ struct COLR
public:
hb_blob_ptr_t<COLR> colr;
private:
hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
mutable hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
};
void closure_glyphs (hb_codepoint_t glyph,
@ -2632,7 +2648,6 @@ struct COLR
}
else
{
// Ugh. We need to undo the synthetic slant here. Leave it for now. :-(.
extents->x_bearing = e.xmin;
extents->y_bearing = e.ymax;
extents->width = e.xmax - e.xmin;
@ -2700,7 +2715,6 @@ struct COLR
if (get_clip (glyph, &extents, instancer))
{
font->scale_glyph_extents (&extents);
font->synthetic_glyph_extents (&extents);
c.funcs->push_clip_rectangle (c.data,
extents.x_bearing,
extents.y_bearing + extents.height,
@ -2709,23 +2723,22 @@ struct COLR
}
else
{
auto *extents_funcs = hb_paint_extents_get_funcs ();
scratch.paint_extents.clear ();
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, &scratch.paint_extents,
bounded_funcs, &scratch.paint_bounded,
palette_index, foreground,
false,
scratch);
auto extents = scratch.paint_extents.get_extents ();
is_bounded = scratch.paint_extents.is_bounded ();
c.funcs->push_clip_rectangle (c.data,
extents.xmin,
extents.ymin,
extents.xmax,
extents.ymax);
is_bounded = scratch.paint_bounded.is_bounded ();
}
}

View File

@ -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;
}

View File

@ -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:

View File

@ -130,7 +130,7 @@ struct CursivePosFormat1
unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
hb_barrier ();
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_from;
if (unlikely (!skippy_iter.prev (&unsafe_from)))

View File

@ -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);

View File

@ -119,7 +119,7 @@ struct MarkBasePosFormat1_2
/* Now we search backwards for a non-mark glyph.
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (c->last_base_until > buffer->idx)

View File

@ -101,7 +101,7 @@ struct MarkLigPosFormat1_2
/* Now we search backwards for a non-mark glyph */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
if (c->last_base_until > buffer->idx)

View File

@ -100,7 +100,7 @@ struct MarkMarkPosFormat1_2
if (likely (mark1_index == NOT_COVERED)) return_trace (false);
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx);
skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
unsigned unsafe_from;

View File

@ -148,7 +148,7 @@ struct PairPosFormat1_3
#endif
if (index == NOT_COVERED) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_to;
if (unlikely (!skippy_iter.next (&unsafe_to)))

View File

@ -179,7 +179,7 @@ struct PairPosFormat2_4 : ValueBase
#endif
if (index == NOT_COVERED) return_trace (false);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset_fast (buffer->idx);
unsigned unsafe_to;
if (unlikely (!skippy_iter.next (&unsafe_to)))

View File

@ -96,7 +96,7 @@ struct LigatureSet
*
* This is replicated in ChainRuleSet and RuleSet. */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);

View File

@ -355,12 +355,12 @@ VARC::get_path_at (const hb_varc_context_t &c,
hb_draw_session_t transformer_session {transformer_funcs, &context};
hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session;
if (!c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch))
if (c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch)) return true;
#ifndef HB_NO_CFF
if (!c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords))
if (!c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) // Doesn't have variations
if (c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords)) return true;
if (c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) return true; // Doesn't have variations
#endif
return false;
return false;
}
else if (c.extents)
{

View File

@ -235,7 +235,7 @@ struct VARC
private:
hb_blob_ptr_t<VARC> table;
hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
mutable hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
};
bool has_data () const { return version.major != 0; }

View File

@ -543,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_t<hb_glyf_scratch_t *> cached_scratch;
mutable hb_atomic_t<hb_glyf_scratch_t *> cached_scratch;
};

View File

@ -43,6 +43,7 @@
#include "hb-ot-tag.cc"
#include "hb-ot-var.cc"
#include "hb-outline.cc"
#include "hb-paint-bounded.cc"
#include "hb-paint-extents.cc"
#include "hb-paint.cc"
#include "hb-set.cc"

View File

@ -52,6 +52,7 @@
#include "hb-ot-tag.cc"
#include "hb-ot-var.cc"
#include "hb-outline.cc"
#include "hb-paint-bounded.cc"
#include "hb-paint-extents.cc"
#include "hb-paint.cc"
#include "hb-set.cc"

View File

@ -194,7 +194,7 @@ struct hb_atomic_t<T*>
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 (); }

View File

@ -410,6 +410,9 @@ struct hb_buffer_t
bool interior = false,
bool from_out_buffer = false)
{
if (unlikely (end != (unsigned) -1 && end - start > 255))
return;
end = hb_min (end, len);
if (interior && !from_out_buffer && end - start < 2)

View File

@ -31,8 +31,6 @@
#include "hb-cairo-utils.hh"
#include <cairo.h>
/* Some routines in this file were ported from BlackRenderer by Black Foundry.
* Used by permission to relicense to HarfBuzz license.
*
@ -101,7 +99,7 @@ _hb_cairo_paint_glyph_image (hb_cairo_context_t *c,
unsigned width,
unsigned height,
hb_tag_t format,
float slant,
HB_UNUSED float slant_deprecated,
hb_glyph_extents_t *extents)
{
cairo_t *cr = c->cr;
@ -186,12 +184,6 @@ _hb_cairo_paint_glyph_image (hb_cairo_context_t *c,
cairo_matrix_t matrix = {(double) width, 0, 0, (double) height, 0, 0};
cairo_pattern_set_matrix (pattern, &matrix);
/* Undo slant in the extents and apply it in the context. */
extents->width -= extents->height * slant;
extents->x_bearing -= extents->y_bearing * slant;
cairo_matrix_t cairo_matrix = {1., 0., (double) slant, 1., 0., 0.};
cairo_transform (cr, &cairo_matrix);
cairo_translate (cr, extents->x_bearing, extents->y_bearing);
cairo_scale (cr, extents->width, extents->height);
cairo_set_source (cr, pattern);

View File

@ -204,7 +204,9 @@ hb_cairo_push_clip_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED,
cairo_save (cr);
cairo_new_path (cr);
hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr);
cairo_close_path (cr);
cairo_clip (cr);
}
@ -572,9 +574,12 @@ hb_cairo_text_to_glyphs (cairo_scaled_font_t *scaled_font,
hb_buffer_guess_segment_properties (buffer);
hb_shape (font, buffer, nullptr, 0);
int x_scale, y_scale;
hb_font_get_scale (font, &x_scale, &y_scale);
hb_cairo_glyphs_from_buffer (buffer,
true,
font->x_scale, font->y_scale,
x_scale, y_scale,
0., 0.,
utf8, utf8_len,
glyphs, (unsigned *) num_glyphs,
@ -601,10 +606,11 @@ hb_cairo_render_glyph (cairo_scaled_font_t *scaled_font,
+1. / (x_scale ? x_scale : 1),
-1. / (y_scale ? y_scale : 1));
hb_font_draw_glyph (font, glyph, hb_cairo_draw_get_funcs (), cr);
cairo_fill (cr);
if (hb_font_draw_glyph_or_fail (font, glyph, hb_cairo_draw_get_funcs (), cr))
cairo_fill (cr);
// If draw fails, we still return SUCCESS, as we want empty drawing, not
// setting the cairo object into error.
return CAIRO_STATUS_SUCCESS;
}
@ -639,8 +645,8 @@ hb_cairo_render_color_glyph (cairo_scaled_font_t *scaled_font,
c.cr = cr;
c.color_cache = (hb_map_t *) cairo_scaled_font_get_user_data (scaled_font, &color_cache_key);
hb_font_paint_glyph (font, glyph, hb_cairo_paint_get_funcs (), &c, palette, color);
if (!hb_font_paint_glyph_or_fail (font, glyph, hb_cairo_paint_get_funcs (), &c, palette, color))
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
return CAIRO_STATUS_SUCCESS;
}
@ -657,8 +663,7 @@ user_font_face_create (hb_face_t *face)
cairo_user_font_face_set_text_to_glyphs_func (cairo_face, hb_cairo_text_to_glyphs);
cairo_user_font_face_set_render_glyph_func (cairo_face, hb_cairo_render_glyph);
#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
if (hb_ot_color_has_png (face) || hb_ot_color_has_layers (face) || hb_ot_color_has_paint (face))
cairo_user_font_face_set_render_color_glyph_func (cairo_face, hb_cairo_render_color_glyph);
cairo_user_font_face_set_render_color_glyph_func (cairo_face, hb_cairo_render_color_glyph);
#endif
if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face,
@ -689,7 +694,8 @@ hb_cairo_font_face_create_for_font (hb_font_t *font)
{
hb_font_make_immutable (font);
auto *cairo_face = user_font_face_create (font->face);
auto *hb_face = hb_font_get_face (font);
auto *cairo_face = user_font_face_create (hb_face);
if (unlikely (CAIRO_STATUS_SUCCESS != cairo_font_face_set_user_data (cairo_face,
&hb_cairo_font_user_data_key,

View File

@ -365,12 +365,12 @@ ct_apply_func (void *info, const CGPathElement *element)
}
}
static void
hb_coretext_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_coretext_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)
{
CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
@ -383,13 +383,15 @@ hb_coretext_draw_glyph (hb_font_t *font,
CGPathRef path = CTFontCreatePathForGlyph (ct_font, glyph, &transform);
if (!path)
return;
return false;
hb_draw_session_t drawing = {draw_funcs, draw_data, font->slant};
hb_draw_session_t drawing {draw_funcs, draw_data};
CGPathApply (path, &drawing, ct_apply_func);
CFRelease (path);
return true;
}
#endif
@ -469,7 +471,7 @@ static struct hb_coretext_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t
#endif
#ifndef HB_NO_DRAW
hb_font_funcs_set_draw_glyph_func (funcs, hb_coretext_draw_glyph, nullptr, nullptr);
hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_coretext_draw_glyph_or_fail, nullptr, nullptr);
#endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_coretext_get_glyph_extents, nullptr, nullptr);

View File

@ -205,10 +205,18 @@ create_cg_font (hb_blob_t *blob, unsigned int index)
if (unlikely (named_instance_index != 0))
{
// https://github.com/harfbuzz/harfbuzz/issues/5300
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || \
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || \
(defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED >= 110000) || \
(defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED >= 40000) || \
(defined(__MACCATALYST_VERSION_MIN_REQUIRED) && __MACCATALYST_VERSION_MIN_REQUIRED >= 130100) || \
(defined(__VISION_OS_VERSION_MIN_REQUIRED) && __VISION_OS_VERSION_MIN_REQUIRED >= 10000)
auto ct_font_desc_array = CTFontManagerCreateFontDescriptorsFromData (CFDataCreate (kCFAllocatorDefault, (const UInt8 *) blob_data, blob_length));
if (unlikely (!ct_font_desc_array))
return nullptr;
return create_cg_font (ct_font_desc_array, named_instance_index);
if (likely (ct_font_desc_array))
return create_cg_font (ct_font_desc_array, named_instance_index);
#endif
return nullptr;
}
hb_blob_reference (blob);

View File

@ -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,

View File

@ -114,6 +114,8 @@ hb_directwrite_get_glyph_h_advances (hb_font_t* font,
dw_face->QueryInterface (__uuidof(IDWriteFontFace1), (void**)&dw_face1);
assert (dw_face1);
unsigned int num_glyphs = font->face->get_num_glyphs ();
for (unsigned i = 0; i < count;)
{
UINT16 gids[MAX_GLYPHS];
@ -130,7 +132,9 @@ hb_directwrite_get_glyph_h_advances (hb_font_t* font,
dw_face1->GetDesignGlyphAdvances (n, gids, advances, false);
for (unsigned j = 0; j < n; j++)
{
*first_advance = font->em_scale_x (advances[j]);
// https://github.com/harfbuzz/harfbuzz/issues/5319
auto advance = gids[j] < num_glyphs ? advances[j] : 0;
*first_advance = font->em_scale_x (advance);
first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride);
}
@ -238,7 +242,7 @@ public:
GeometrySink(hb_font_t *font,
hb_draw_funcs_t *draw_funcs,
void *draw_data)
: font (font), drawing ({draw_funcs, draw_data, font->slant}) {}
: font (font), drawing ({draw_funcs, draw_data}) {}
virtual ~GeometrySink() {}
@ -275,12 +279,12 @@ public:
}
};
static void
hb_directwrite_draw_glyph (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data)
static hb_bool_t
hb_directwrite_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)
{
IDWriteFontFace *dw_face = (IDWriteFontFace *) (const void *) font->data.directwrite;
@ -288,11 +292,11 @@ hb_directwrite_draw_glyph (hb_font_t *font,
UINT16 gid = static_cast<UINT16>(glyph);
unsigned upem = font->face->get_upem();
(void) dw_face->GetGlyphRunOutline (upem,
&gid, nullptr, nullptr,
1,
false, false,
&sink);
return S_OK == dw_face->GetGlyphRunOutline (upem,
&gid, nullptr, nullptr,
1,
false, false,
&sink);
}
#endif
@ -317,7 +321,7 @@ static struct hb_directwrite_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loade
#endif
#ifndef HB_NO_DRAW
hb_font_funcs_set_draw_glyph_func (funcs, hb_directwrite_draw_glyph, nullptr, nullptr);
hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_directwrite_draw_glyph_or_fail, nullptr, nullptr);
#endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_directwrite_get_glyph_extents, nullptr, nullptr);

View File

@ -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

View File

@ -41,16 +41,9 @@ HB_BEGIN_DECLS
* @path_start_y: Y component of the start of current path
* @current_x: X component of current point
* @current_y: Y component of current point
* @slant_xy: Slanting factor for synthetic oblique, Since: 11.0.0
*
* Current drawing state.
*
* The @slant_xy is a slanting factor for synthetic oblique. If the font's
* oblique angle is not 0, this factor is used to slant the drawing. For
* fonts with uniform x and y scales, this factor is calculated as
* tan(oblique_angle). For fonts with non-uniform scales, this factor is
* calculated as tan(oblique_angle) * x_scale / y_scale, or 0 if y_scale is 0.
*
* Since: 4.0.0
**/
typedef struct hb_draw_state_t {
@ -62,8 +55,6 @@ typedef struct hb_draw_state_t {
float current_x;
float current_y;
float slant_xy;
/*< private >*/
hb_var_num_t reserved1;
hb_var_num_t reserved2;
@ -71,6 +62,7 @@ typedef struct hb_draw_state_t {
hb_var_num_t reserved4;
hb_var_num_t reserved5;
hb_var_num_t reserved6;
hb_var_num_t reserved7;
} hb_draw_state_t;
/**
@ -78,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.f, {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}}
/**

View File

@ -100,9 +100,6 @@ struct hb_draw_funcs_t
{
if (unlikely (st.path_open)) close_path (draw_data, st);
if (st.slant_xy)
to_x += to_y * st.slant_xy;
st.current_x = to_x;
st.current_y = to_y;
}
@ -114,9 +111,6 @@ struct hb_draw_funcs_t
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
if (st.slant_xy)
to_x += to_y * st.slant_xy;
emit_line_to (draw_data, st, to_x, to_y);
st.current_x = to_x;
@ -131,12 +125,6 @@ struct hb_draw_funcs_t
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
if (st.slant_xy)
{
control_x += control_y * st.slant_xy;
to_x += to_y * st.slant_xy;
}
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
st.current_x = to_x;
@ -152,13 +140,6 @@ struct hb_draw_funcs_t
{
if (unlikely (!st.path_open)) start_path (draw_data, st);
if (st.slant_xy)
{
control1_x += control1_y * st.slant_xy;
control2_x += control2_y * st.slant_xy;
to_x += to_y * st.slant_xy;
}
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
st.current_x = to_x;
@ -194,9 +175,9 @@ 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_xy = 0.f)
hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_)
: funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
{ st.slant_xy = slant_xy; }
{}
~hb_draw_session_t () { close_path (); }
@ -244,4 +225,9 @@ struct hb_draw_session_t
hb_draw_state_t st;
};
HB_INTERNAL hb_draw_funcs_t *
hb_draw_extents_get_funcs ();
#endif /* HB_DRAW_HH */

View File

@ -103,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);
@ -128,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);
@ -234,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
@ -259,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
@ -281,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);
}
@ -290,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);
@ -313,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);
}
@ -322,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);
@ -442,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);
@ -472,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;
@ -524,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 {
@ -551,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
@ -564,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
@ -579,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
@ -598,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
@ -619,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
@ -650,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) =
@ -1429,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
@ -1438,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.
*
@ -1445,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);
}
/**
@ -1460,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
@ -1482,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
@ -2608,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
@ -2625,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
@ -2689,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
@ -3195,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

View File

@ -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
@ -1092,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,

View File

@ -33,6 +33,8 @@
#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"
@ -59,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
@ -206,7 +208,7 @@ struct hb_font_t
void synthetic_glyph_extents (hb_glyph_extents_t *extents)
{
/* Apply slant. */
/* Slant. */
if (slant_xy)
{
hb_position_t x1 = extents->x_bearing;
@ -221,6 +223,7 @@ struct hb_font_t
extents->width = x2 - extents->x_bearing;
}
/* Embolden. */
if (x_strength || y_strength)
{
/* Y */
@ -263,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)
@ -316,15 +345,16 @@ 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)
{
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 (x_strength && !embolden_in_place)
if (synthetic && x_strength && !embolden_in_place)
{
/* Emboldening. */
/* Embolden */
hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
advance += advance ? strength : 0;
}
@ -332,15 +362,16 @@ struct hb_font_t
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)
{
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 (y_strength && !embolden_in_place)
if (synthetic && y_strength && !embolden_in_place)
{
/* Emboldening. */
/* Embolden */
hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
advance += advance ? strength : 0;
}
@ -352,7 +383,8 @@ struct hb_font_t
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)
{
klass->get.f.glyph_h_advances (this, user_data,
count,
@ -360,9 +392,9 @@ struct hb_font_t
first_advance, advance_stride,
!klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
if (x_strength && !embolden_in_place)
if (synthetic && x_strength && !embolden_in_place)
{
/* Emboldening. */
/* Embolden */
hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength;
for (unsigned int i = 0; i < count; i++)
{
@ -376,7 +408,8 @@ struct hb_font_t
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)
{
klass->get.f.glyph_v_advances (this, user_data,
count,
@ -384,9 +417,9 @@ struct hb_font_t
first_advance, advance_stride,
!klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
if (y_strength && !embolden_in_place)
if (synthetic && y_strength && !embolden_in_place)
{
/* Emboldening. */
/* Embolden */
hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength;
for (unsigned int i = 0; i < count; i++)
{
@ -439,9 +472,51 @@ 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));
/* 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. */
#ifndef HB_NO_PAINT
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;
}
#endif
#ifndef HB_NO_DRAW
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;
}
#endif
bool ret = klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
@ -453,13 +528,30 @@ struct hb_font_t
}
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,
@ -483,56 +575,94 @@ 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)
{
#ifndef HB_NO_DRAW
#ifndef HB_NO_OUTLINE
bool embolden = x_strength || y_strength;
bool slanted = slant_xy;
synthetic = synthetic && (embolden || slanted);
#else
constexpr bool embolden = false;
synthetic = false;
#endif
if (!embolden)
if (!synthetic)
{
klass->get.f.draw_glyph (this, user_data,
glyph,
draw_funcs, draw_data,
!klass->user_data ? nullptr : klass->user_data->draw_glyph);
return;
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
/* Emboldening. */
hb_outline_t outline;
klass->get.f.draw_glyph (this, user_data,
glyph,
hb_outline_recording_pen_get_funcs (), &outline,
!klass->user_data ? nullptr : klass->user_data->draw_glyph);
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);
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
#endif
return false;
}
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);
#ifndef HB_NO_PAINT
/* 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;
#endif
return false;
}
/* 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))
@ -770,6 +900,11 @@ struct hb_font_t
return false;
}
bool is_synthetic () const
{
return x_embolden || y_embolden || slant;
}
void changed ()
{
float upem = face->get_upem ();

View File

@ -28,7 +28,7 @@
#include "hb.hh"
#include "hb-decycler.hh"
#include "hb-paint-extents.hh"
#include "hb-paint-bounded.hh"
#include FT_COLOR_H
@ -80,15 +80,30 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
struct hb_ft_paint_context_t
{
hb_ft_paint_context_t (const hb_ft_font_t *ft_font,
hb_font_t *font,
hb_ft_paint_context_t (const hb_ft_font_t *ft_font_,
hb_font_t *font_,
hb_paint_funcs_t *paint_funcs, void *paint_data,
hb_array_t<const FT_Color> palette,
unsigned palette_index,
hb_color_t foreground) :
ft_font (ft_font), font(font),
ft_font (ft_font_), font (font_),
funcs (paint_funcs), data (paint_data),
palette (palette), palette_index (palette_index), foreground (foreground) {}
palette (palette), palette_index (palette_index), foreground (foreground)
{
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_ft_paint_context_t ()
{
hb_font_destroy (font);
}
void recurse (FT_OpaquePaint paint)
{
@ -512,52 +527,41 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
hb_decycler_node_t node (c.glyphs_decycler);
node.visit (gid);
bool is_bounded = true;
bool clip = false;
bool is_bounded = false;
FT_ClipBox clip_box;
if (FT_Get_Color_Glyph_ClipBox (ft_face, gid, &clip_box))
{
c.funcs->push_clip_rectangle (c.data,
clip_box.bottom_left.x +
roundf (hb_min (font->slant_xy * clip_box.bottom_left.y,
font->slant_xy * clip_box.top_left.y)),
clip_box.bottom_left.x,
clip_box.bottom_left.y,
clip_box.top_right.x +
roundf (hb_max (font->slant_xy * clip_box.bottom_right.y,
font->slant_xy * clip_box.top_right.y)),
clip_box.top_right.x,
clip_box.top_right.y);
clip = true;
is_bounded = true;
}
else
if (!is_bounded)
{
auto *extents_funcs = hb_paint_extents_get_funcs ();
hb_paint_extents_context_t extents_data;
auto *bounded_funcs = hb_paint_bounded_get_funcs ();
hb_paint_bounded_context_t bounded_data;
hb_ft_paint_context_t ce (ft_font, font,
extents_funcs, &extents_data,
bounded_funcs, &bounded_data,
palette_array, palette_index, foreground);
hb_decycler_node_t node2 (ce.glyphs_decycler);
node2.visit (gid);
ce.funcs->push_font_transform (ce.data, font);
ce.recurse (paint);
ce.funcs->pop_transform (ce.data);
hb_extents_t extents = extents_data.get_extents ();
is_bounded = extents_data.is_bounded ();
c.funcs->push_clip_rectangle (c.data,
extents.xmin,
extents.ymin,
extents.xmax,
extents.ymax);
is_bounded = bounded_data.is_bounded ();
}
c.funcs->push_font_transform (c.data, font);
if (is_bounded)
{
c.recurse (paint);
}
c.funcs->pop_transform (c.data);
c.funcs->pop_clip (c.data);
if (clip)
c.funcs->pop_clip (c.data);
return true;
}

View File

@ -626,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,
@ -633,6 +668,10 @@ 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);
@ -797,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);
@ -848,12 +887,12 @@ _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);
@ -863,10 +902,10 @@ hb_ft_draw_glyph (hb_font_t *font,
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,
@ -877,11 +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);
hb_draw_session_t draw_session {draw_funcs, draw_data};
FT_Outline_Decompose (&ft_face->glyph->outline,
&outline_funcs,
&draw_session);
return true;
}
#endif
@ -890,14 +931,14 @@ 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);
@ -905,7 +946,7 @@ hb_ft_paint_glyph (hb_font_t *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
@ -914,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)
{
@ -922,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 ();
@ -951,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
@ -1006,12 +1041,12 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
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

View File

@ -0,0 +1,150 @@
/*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author(s): Behdad Esfahbod
*/
#include "hb.hh"
#ifdef HAVE_HARFRUZZ
#include "hb-shaper-impl.hh"
/*
* shaper face data
*/
extern "C" void *
_hb_harfruzz_shaper_face_data_create_rs (hb_face_t *face);
hb_harfruzz_face_data_t *
_hb_harfruzz_shaper_face_data_create (hb_face_t *face)
{
return (hb_harfruzz_face_data_t *) _hb_harfruzz_shaper_face_data_create_rs (face);
}
extern "C" void
_hb_harfruzz_shaper_face_data_destroy_rs (void *data);
void
_hb_harfruzz_shaper_face_data_destroy (hb_harfruzz_face_data_t *data)
{
_hb_harfruzz_shaper_face_data_destroy_rs (data);
}
/*
* shaper font data
*/
extern "C" void *
_hb_harfruzz_shaper_font_data_create_rs (hb_font_t *font, const void *face_data);
hb_harfruzz_font_data_t *
_hb_harfruzz_shaper_font_data_create (hb_font_t *font)
{
const hb_harfruzz_face_data_t *face_data = font->face->data.harfruzz;
return (hb_harfruzz_font_data_t *) _hb_harfruzz_shaper_font_data_create_rs (font, face_data);
}
extern "C" void
_hb_harfruzz_shaper_font_data_destroy_rs (void *data);
void
_hb_harfruzz_shaper_font_data_destroy (hb_harfruzz_font_data_t *data)
{
_hb_harfruzz_shaper_font_data_destroy_rs (data);
}
/*
* shape plan
*/
extern "C" void *
_hb_harfruzz_shape_plan_create_rs (const void *font_data,
hb_script_t script,
hb_language_t language,
hb_direction_t direction);
extern "C" void
_hb_harfruzz_shape_plan_destroy_rs (void *data);
/*
* shaper
*/
extern "C" hb_bool_t
_hb_harfruzz_shape_rs (const void *face_data,
const void *rs_shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features);
static hb_user_data_key_t hr_shape_plan_key = {0};
hb_bool_t
_hb_harfruzz_shape (hb_shape_plan_t *shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
const hb_harfruzz_font_data_t *font_data = font->data.harfruzz;
void *hr_shape_plan = nullptr;
if (!num_features)
{
retry:
hr_shape_plan = hb_shape_plan_get_user_data (shape_plan,
&hr_shape_plan_key);
if (unlikely (!hr_shape_plan))
{
hr_shape_plan = _hb_harfruzz_shape_plan_create_rs (font_data,
shape_plan->key.props.script,
shape_plan->key.props.language,
shape_plan->key.props.direction);
if (hr_shape_plan &&
!hb_shape_plan_set_user_data (shape_plan,
&hr_shape_plan_key,
hr_shape_plan,
_hb_harfruzz_shape_plan_destroy_rs,
false))
{
_hb_harfruzz_shape_plan_destroy_rs (hr_shape_plan);
goto retry;
}
}
}
return _hb_harfruzz_shape_rs (font_data,
hr_shape_plan,
font,
buffer,
features,
num_features);
}
#endif

View File

@ -273,7 +273,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
private:
/* Must only have one pointer. */
hb_atomic_t<Stored *> instance;
mutable hb_atomic_t<Stored *> instance;
};
/* Specializations. */

View File

@ -412,15 +412,15 @@ hb_ot_get_glyph_extents (hb_font_t *font,
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
const hb_ot_face_t *ot_face = ot_font->ot_face;
#ifndef HB_NO_VAR_COMPOSITES
if (ot_face->VARC->get_extents (font, glyph, extents)) return true;
#endif
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
#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
@ -472,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
@ -498,50 +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)
{
hb_draw_session_t draw_session (draw_funcs, 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))
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
{}
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
@ -568,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);

View File

@ -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;
}
}

View File

@ -397,292 +397,277 @@ struct hb_collect_coverage_context_t :
set_t *set;
};
struct hb_ot_apply_context_t :
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
struct matcher_t
{
struct matcher_t
typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
template <typename context_t>
void init (const context_t *c, bool context_match = false)
{
typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
set_match_func (nullptr, nullptr);
lookup_props = c->lookup_props;
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
ignore_zwnj = c->table_index == 1 || (context_match && c->auto_zwnj);
/* Ignore ZWJ if we are matching context, or asked to. */
ignore_zwj = context_match || c->auto_zwj;
/* Ignore hidden glyphs (like CGJ) during GPOS. */
ignore_hidden = c->table_index == 1;
mask = context_match ? -1 : c->lookup_mask;
/* Per syllable matching is only for GSUB. */
per_syllable = c->table_index == 0 && c->per_syllable;
syllable = 0;
}
void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
void set_ignore_hidden (bool ignore_hidden_) { ignore_hidden = ignore_hidden_; }
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
void set_mask (hb_mask_t mask_) { mask = mask_; }
void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
void set_syllable (uint8_t syllable_) { syllable = per_syllable ? syllable_ : 0; }
void set_match_func (match_func_t match_func_,
const void *match_data_)
{ match_func = match_func_; match_data = match_data_; }
void set_match_func (match_func_t match_func_,
const void *match_data_)
{ match_func = match_func_; match_data = match_data_; }
enum may_match_t {
MATCH_NO,
MATCH_YES,
MATCH_MAYBE
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_match_t may_match (hb_glyph_info_t &info,
hb_codepoint_t glyph_data) const
{
if (!(info.mask & mask) ||
(syllable && syllable != info.syllable ()))
return MATCH_NO;
if (match_func)
return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
enum may_skip_t {
SKIP_NO,
SKIP_YES,
SKIP_MAYBE
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_skip_t may_skip (const hb_ot_apply_context_t *c,
const hb_glyph_info_t &info) const
{
if (!c->check_glyph_property (&info, lookup_props))
return SKIP_YES;
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
(ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
(ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
return SKIP_MAYBE;
return SKIP_NO;
}
protected:
unsigned int lookup_props = 0;
hb_mask_t mask = -1;
bool ignore_zwnj = false;
bool ignore_zwj = false;
bool ignore_hidden = false;
bool per_syllable = false;
uint8_t syllable = 0;
match_func_t match_func = nullptr;
const void *match_data = nullptr;
enum may_match_t {
MATCH_NO,
MATCH_YES,
MATCH_MAYBE
};
struct skipping_iterator_t
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_match_t may_match (hb_glyph_info_t &info,
hb_codepoint_t glyph_data) const
{
void init (hb_ot_apply_context_t *c_, bool context_match = false)
{
c = c_;
end = c->buffer->len;
match_glyph_data16 = nullptr;
if (!(info.mask & mask) ||
(per_syllable && syllable && syllable != info.syllable ()))
return MATCH_NO;
if (match_func)
return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
enum may_skip_t {
SKIP_NO,
SKIP_YES,
SKIP_MAYBE
};
template <typename context_t>
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_skip_t may_skip (const context_t *c,
const hb_glyph_info_t &info) const
{
if (!c->check_glyph_property (&info, lookup_props))
return SKIP_YES;
if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
(ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
(ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
(ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
return SKIP_MAYBE;
return SKIP_NO;
}
public:
unsigned int lookup_props = 0;
hb_mask_t mask = -1;
bool ignore_zwnj = false;
bool ignore_zwj = false;
bool ignore_hidden = false;
bool per_syllable = false;
uint8_t syllable = 0;
match_func_t match_func = nullptr;
const void *match_data = nullptr;
};
template <typename context_t>
struct skipping_iterator_t
{
void init (context_t *c_, bool context_match = false)
{
c = c_;
end = c->buffer->len;
match_glyph_data16 = nullptr;
#ifndef HB_NO_BEYOND_64K
match_glyph_data24 = nullptr;
match_glyph_data24 = nullptr;
#endif
matcher.set_match_func (nullptr, nullptr);
matcher.set_lookup_props (c->lookup_props);
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
/* Ignore ZWJ if we are matching context, or asked to. */
matcher.set_ignore_zwj (context_match || c->auto_zwj);
/* Ignore hidden glyphs (like CGJ) during GPOS. */
matcher.set_ignore_hidden (c->table_index == 1);
matcher.set_mask (context_match ? -1 : c->lookup_mask);
/* Per syllable matching is only for GSUB. */
matcher.set_per_syllable (c->table_index == 0 && c->per_syllable);
matcher.set_syllable (0);
}
void set_lookup_props (unsigned int lookup_props)
{
matcher.set_lookup_props (lookup_props);
}
void set_match_func (matcher_t::match_func_t match_func_,
const void *match_data_)
{
matcher.set_match_func (match_func_, match_data_);
}
void set_glyph_data (const HBUINT16 glyph_data[])
{
match_glyph_data16 = glyph_data;
matcher.init (c, context_match);
}
void set_lookup_props (unsigned int lookup_props)
{
matcher.lookup_props = lookup_props;
}
void set_match_func (matcher_t::match_func_t match_func_,
const void *match_data_)
{
matcher.set_match_func (match_func_, match_data_);
}
void set_glyph_data (const HBUINT16 glyph_data[])
{
match_glyph_data16 = glyph_data;
#ifndef HB_NO_BEYOND_64K
match_glyph_data24 = nullptr;
match_glyph_data24 = nullptr;
#endif
}
}
#ifndef HB_NO_BEYOND_64K
void set_glyph_data (const HBUINT24 glyph_data[])
{
match_glyph_data16 = nullptr;
match_glyph_data24 = glyph_data;
}
void set_glyph_data (const HBUINT24 glyph_data[])
{
match_glyph_data16 = nullptr;
match_glyph_data24 = glyph_data;
}
#endif
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
HB_ALWAYS_INLINE
#endif
void reset (unsigned int start_index_)
{
idx = start_index_;
end = c->buffer->len;
matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
void reset_fast (unsigned int start_index_)
{
// Doesn't set end or syllable. Used by GPOS which doesn't care / change.
idx = start_index_;
}
void reject ()
{
backup_glyph_data ();
}
matcher_t::may_skip_t
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
enum match_t {
MATCH,
NOT_MATCH,
SKIP
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
match_t match (hb_glyph_info_t &info)
{
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
return SKIP;
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
return MATCH;
if (skip == matcher_t::SKIP_NO)
return NOT_MATCH;
return SKIP;
void reset (unsigned int start_index_)
{
idx = start_index_;
end = c->buffer->len;
matcher.syllable = start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
HB_ALWAYS_INLINE
#endif
bool next (unsigned *unsafe_to = nullptr)
{
const signed stop = (signed) end - 1;
while ((signed) idx < stop)
{
idx++;
switch (match (c->buffer->info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_to)
*unsafe_to = idx + 1;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_to)
*unsafe_to = end;
return false;
}
void reset_fast (unsigned int start_index_)
{
// Doesn't set end or syllable. Used by GPOS which doesn't care / change.
idx = start_index_;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
HB_ALWAYS_INLINE
#endif
bool prev (unsigned *unsafe_from = nullptr)
{
const unsigned stop = 0;
while (idx > stop)
{
idx--;
switch (match (c->buffer->out_info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_from)
*unsafe_from = hb_max (1u, idx) - 1u;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_from)
*unsafe_from = 0;
return false;
}
matcher_t::may_skip_t may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
HB_ALWAYS_INLINE
hb_codepoint_t
get_glyph_data ()
{
if (match_glyph_data16) return *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) return *match_glyph_data24;
#endif
return 0;
}
HB_ALWAYS_INLINE
void
advance_glyph_data ()
{
if (match_glyph_data16) match_glyph_data16++;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) match_glyph_data24++;
#endif
}
void
backup_glyph_data ()
{
if (match_glyph_data16) match_glyph_data16--;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) match_glyph_data24--;
#endif
}
unsigned int idx;
protected:
hb_ot_apply_context_t *c;
matcher_t matcher;
const HBUINT16 *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
const HBUINT24 *match_glyph_data24;
#endif
unsigned int end;
enum match_t {
MATCH,
NOT_MATCH,
SKIP
};
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
match_t match (hb_glyph_info_t &info)
{
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
return SKIP;
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
return MATCH;
if (skip == matcher_t::SKIP_NO)
return NOT_MATCH;
return SKIP;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
bool next (unsigned *unsafe_to = nullptr)
{
const signed stop = (signed) end - 1;
while ((signed) idx < stop)
{
idx++;
switch (match (c->buffer->info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_to)
*unsafe_to = idx + 1;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_to)
*unsafe_to = end;
return false;
}
#ifndef HB_OPTIMIZE_SIZE
HB_ALWAYS_INLINE
#endif
bool prev (unsigned *unsafe_from = nullptr)
{
const unsigned stop = 0;
while (idx > stop)
{
idx--;
switch (match (c->buffer->out_info[idx]))
{
case MATCH:
{
advance_glyph_data ();
return true;
}
case NOT_MATCH:
{
if (unsafe_from)
*unsafe_from = hb_max (1u, idx) - 1u;
return false;
}
case SKIP:
continue;
}
}
if (unsafe_from)
*unsafe_from = 0;
return false;
}
HB_ALWAYS_INLINE
hb_codepoint_t
get_glyph_data ()
{
if (match_glyph_data16) return *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) return *match_glyph_data24;
#endif
return 0;
}
HB_ALWAYS_INLINE
void
advance_glyph_data ()
{
if (match_glyph_data16) match_glyph_data16++;
#ifndef HB_NO_BEYOND_64K
else
if (match_glyph_data24) match_glyph_data24++;
#endif
}
unsigned int idx;
protected:
context_t *c;
matcher_t matcher;
const HBUINT16 *match_glyph_data16;
#ifndef HB_NO_BEYOND_64K
const HBUINT24 *match_glyph_data24;
#endif
unsigned int end;
};
struct hb_ot_apply_context_t :
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
{
const char *get_name () { return "APPLY"; }
typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
template <typename T>
@ -703,7 +688,7 @@ struct hb_ot_apply_context_t :
return ret;
}
skipping_iterator_t iter_input, iter_context;
skipping_iterator_t<hb_ot_apply_context_t> iter_input, iter_context;
unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font;
@ -1270,7 +1255,7 @@ static bool match_input (hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer;
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx);
skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (input);
@ -1349,7 +1334,7 @@ static bool match_input (hb_ot_apply_context_t *c,
j--;
}
if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
if (found && skippy_iter.may_skip (out[j]) == matcher_t::SKIP_YES)
ligbase = LIGBASE_MAY_SKIP;
else
ligbase = LIGBASE_MAY_NOT_SKIP;
@ -1512,7 +1497,7 @@ static bool match_backtrack (hb_ot_apply_context_t *c,
{
TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
auto &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len ());
skippy_iter.set_match_func (match_func, match_data);
skippy_iter.set_glyph_data (backtrack);
@ -1545,7 +1530,7 @@ static bool match_lookahead (hb_ot_apply_context_t *c,
{
TRACE_APPLY (nullptr);
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
auto &skippy_iter = c->iter_context;
assert (start_index >= 1);
skippy_iter.reset (start_index - 1);
skippy_iter.set_match_func (match_func, match_data);
@ -2209,7 +2194,7 @@ struct RuleSet
*
* Replicated from LigatureSet::apply(). */
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
@ -3420,7 +3405,7 @@ struct ChainRuleSet
if (!c->auto_zwnj || !c->auto_zwj)
goto slow;
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
auto &skippy_iter = c->iter_input;
skippy_iter.reset (c->buffer->idx);
skippy_iter.set_match_func (match_always, nullptr);
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);

View File

@ -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_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 (); }

View File

@ -260,7 +260,7 @@ struct arabic_shape_plan_t
* mask_array[NONE] == 0. */
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
hb_atomic_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;

View File

@ -222,60 +222,60 @@ hb_use_u8[3345] =
133, 134, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2,
2, 2, 2, 2, 2, 10, 22, 59, 99, 76, 135, 136, 137, 0, 0, 0,
0, 2, 138, 2, 2, 2, 2, 139, 0, 30, 2, 42, 5, 0, 79, 15,
2, 53, 22, 140, 52, 53, 2, 2, 105, 10, 9, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 141, 21, 25, 0, 0, 142, 143, 0, 0, 0,
0, 2, 65, 45, 23, 80, 47, 144, 0, 81, 81, 81, 81, 81, 81, 81,
2, 140, 20, 53, 128, 140, 2, 2, 141, 10, 9, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 142, 21, 25, 0, 0, 143, 144, 0, 0, 0,
0, 2, 65, 45, 23, 80, 47, 145, 0, 81, 81, 81, 81, 81, 81, 81,
81, 0, 0, 0, 0, 0, 0, 0, 6, 120, 120, 120, 120, 121, 0, 0,
0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 30, 2, 2, 2,
2, 2, 30, 2, 2, 2, 30, 9, 0, 128, 20, 27, 31, 0, 0, 145,
146, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0,
147, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0,
2, 2, 30, 2, 2, 2, 30, 9, 0, 128, 20, 27, 31, 0, 0, 146,
147, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0,
148, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 30, 2, 2, 9, 2, 2, 11, 41, 0, 0, 0,
0, 2, 2, 2, 0, 27, 22, 22, 30, 2, 2, 2, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 27, 38, 0, 2, 2, 2, 116, 116, 116, 116,
116, 148, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0,
116, 149, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0,
0, 9, 2, 2, 9, 2, 2, 2, 2, 30, 2, 9, 0, 30, 2, 0,
0, 149, 150, 151, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20,
20, 20, 22, 22, 134, 0, 0, 0, 0, 0, 152, 152, 152, 152, 152, 152,
152, 152, 152, 152, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0,
153, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0,
0, 150, 151, 152, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20,
20, 20, 22, 22, 134, 0, 0, 0, 0, 0, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0,
154, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0,
0, 0, 31, 0, 0, 0, 0, 0, 0, 11, 49, 2, 2, 2, 2, 2,
2, 2, 2, 2, 128, 20, 22, 154, 22, 21, 155, 156, 2, 2, 2, 2,
2, 0, 0, 65, 157, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0,
0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 158, 0, 0, 56, 159, 31,
160, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23,
19, 22, 22, 161, 44, 0, 0, 0, 49, 128, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 128, 20, 22, 155, 22, 21, 156, 157, 2, 2, 2, 2,
2, 0, 0, 65, 158, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0,
0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 159, 0, 0, 56, 160, 31,
161, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23,
19, 22, 22, 162, 44, 0, 0, 0, 49, 128, 0, 0, 0, 0, 0, 0,
0, 2, 2, 2, 9, 9, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2,
30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 162, 31, 0,
30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 163, 31, 0,
0, 11, 11, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 58, 17,
23, 16, 23, 47, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 0,
2, 2, 23, 0, 11, 11, 11, 46, 0, 11, 11, 46, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 30, 0, 9, 2, 2, 2, 30, 45, 59, 20,
20, 31, 33, 32, 32, 25, 163, 29, 164, 165, 37, 0, 0, 0, 0, 0,
20, 31, 33, 32, 32, 25, 164, 29, 165, 166, 37, 0, 0, 0, 0, 0,
0, 12, 26, 0, 0, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20,
22, 23, 126, 15, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
166, 167, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25,
160, 11, 168, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
65, 25, 20, 20, 0, 48, 48, 11, 169, 37, 0, 0, 0, 0, 0, 0,
167, 168, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25,
161, 11, 169, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
65, 25, 20, 20, 0, 48, 48, 11, 170, 37, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 2, 2, 20, 0, 23, 19, 20, 20, 21, 16, 82,
169, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 170,
25, 20, 22, 22, 168, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43,
170, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 171,
25, 20, 22, 22, 169, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43,
136, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 9, 0, 0, 0,
0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 169, 37, 0,
0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 170, 37, 0,
0, 2, 2, 2, 9, 30, 0, 2, 2, 2, 2, 30, 9, 2, 2, 2,
2, 23, 23, 18, 32, 33, 12, 171, 165, 172, 173, 0, 0, 0, 0, 0,
2, 23, 23, 18, 32, 33, 12, 172, 166, 173, 174, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 0, 2, 2, 2, 65, 25, 20, 20, 0, 22, 23,
29, 108, 0, 33, 0, 0, 0, 0, 0, 52, 20, 22, 22, 22, 140, 2,
2, 2, 174, 175, 11, 15, 176, 61, 177, 0, 0, 1, 147, 0, 0, 0,
0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 158, 158, 158, 178, 178,
2, 2, 175, 141, 11, 15, 176, 61, 177, 0, 0, 1, 148, 0, 0, 0,
0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 159, 159, 159, 178, 178,
178, 178, 178, 178, 15, 179, 0, 30, 0, 22, 20, 20, 31, 22, 22, 11,
169, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0,
170, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0,
0, 2, 2, 2, 9, 2, 30, 2, 2, 52, 22, 22, 31, 0, 38, 22,
27, 11, 159, 180, 181, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2,
27, 11, 160, 180, 181, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2,
2, 2, 2, 2, 2, 2, 23, 23, 47, 22, 35, 82, 68, 0, 0, 0,
0, 2, 182, 66, 47, 0, 0, 0, 0, 11, 183, 2, 2, 2, 2, 2,
2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 143, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 156, 0, 0, 184, 184, 184, 184, 184, 184, 184,
2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 144, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 157, 0, 0, 184, 184, 184, 184, 184, 184, 184,
184, 185, 185, 185, 186, 187, 185, 184, 184, 188, 184, 184, 189, 190, 190, 190,
190, 190, 190, 190, 0, 0, 0, 0, 0, 184, 184, 184, 184, 184, 191, 0,
0, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 192, 193,
@ -306,11 +306,11 @@ hb_use_u8[3345] =
CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, SB,
SE, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,
CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv,
FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O,
IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv,
IS,CMAbv, O, VPst, B, R, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst,
O,VMAbv,CMBlw, IS, R,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv,
VPst, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv,
FPst, VBlw, B, VBlw,VMAbv, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,
VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre,
VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,
CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst,
VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,FMBlw, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv,
IS, VBlw, IS, R, MBlw, GB, VAbv, R,VMPst, G, G, J, J, J, SB, SE,
J, HR, G, G, HM, HM, HM, G, O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O,
VBlw,
@ -528,60 +528,60 @@ hb_use_u8[3657] =
2, 2, 131, 23, 22, 20, 48, 132, 133, 134, 0, 0, 0, 0, 0, 0,
0, 2, 2, 52, 30, 2, 2, 2, 2, 2, 2, 2, 2, 10, 22, 59,
99, 76, 135, 136, 137, 0, 0, 0, 0, 2, 138, 2, 2, 2, 2, 139,
0, 30, 2, 42, 5, 0, 79, 15, 2, 53, 22, 140, 52, 53, 2, 2,
105, 10, 9, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 141, 21,
25, 0, 0, 142, 143, 0, 0, 0, 0, 2, 65, 45, 23, 80, 47, 144,
0, 30, 2, 42, 5, 0, 79, 15, 2, 140, 20, 53, 128, 140, 2, 2,
141, 10, 9, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 142, 21,
25, 0, 0, 143, 144, 0, 0, 0, 0, 2, 65, 45, 23, 80, 47, 145,
0, 81, 81, 81, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, 0,
6, 120, 120, 120, 120, 121, 0, 0, 0, 2, 2, 2, 2, 2, 9, 2,
2, 2, 9, 2, 30, 2, 2, 2, 2, 2, 30, 2, 2, 2, 30, 9,
0, 128, 20, 27, 31, 0, 0, 145, 146, 2, 2, 30, 2, 30, 2, 2,
2, 2, 2, 2, 0, 14, 37, 0, 147, 2, 2, 13, 37, 0, 30, 2,
0, 128, 20, 27, 31, 0, 0, 146, 147, 2, 2, 30, 2, 30, 2, 2,
2, 2, 2, 2, 0, 14, 37, 0, 148, 2, 2, 13, 37, 0, 30, 2,
2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 2, 2,
9, 2, 2, 11, 41, 0, 0, 0, 0, 2, 2, 2, 0, 27, 22, 22,
30, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 27, 38,
0, 2, 2, 2, 116, 116, 116, 116, 116, 148, 2, 9, 0, 0, 0, 0,
0, 2, 2, 2, 116, 116, 116, 116, 116, 149, 2, 9, 0, 0, 0, 0,
0, 2, 14, 14, 0, 0, 0, 0, 0, 9, 2, 2, 9, 2, 2, 2,
2, 30, 2, 9, 0, 30, 2, 0, 0, 149, 150, 151, 2, 2, 2, 2,
2, 30, 2, 9, 0, 30, 2, 0, 0, 150, 151, 152, 2, 2, 2, 2,
2, 2, 2, 2, 2, 22, 22, 20, 20, 20, 22, 22, 134, 0, 0, 0,
0, 0, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 2, 2, 2, 2,
2, 53, 52, 53, 0, 0, 0, 0, 153, 11, 74, 2, 2, 2, 2, 2,
0, 0, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 2, 2, 2, 2,
2, 53, 52, 53, 0, 0, 0, 0, 154, 11, 74, 2, 2, 2, 2, 2,
2, 18, 19, 21, 16, 24, 37, 0, 0, 0, 31, 0, 0, 0, 0, 0,
0, 11, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 20, 22, 154,
22, 21, 155, 156, 2, 2, 2, 2, 2, 0, 0, 65, 157, 0, 0, 0,
0, 11, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 20, 22, 155,
22, 21, 156, 157, 2, 2, 2, 2, 2, 0, 0, 65, 158, 0, 0, 0,
0, 2, 13, 0, 0, 0, 0, 0, 0, 2, 65, 25, 20, 20, 20, 22,
22, 108, 158, 0, 0, 56, 159, 31, 160, 30, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 23, 19, 22, 22, 161, 44, 0, 0, 0,
22, 108, 159, 0, 0, 56, 160, 31, 161, 30, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 23, 19, 22, 22, 162, 44, 0, 0, 0,
49, 128, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 9, 2, 2,
30, 2, 2, 2, 2, 2, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2,
10, 18, 19, 21, 22, 162, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9,
10, 18, 19, 21, 22, 163, 31, 0, 0, 11, 11, 30, 2, 2, 2, 9,
30, 9, 2, 30, 2, 2, 58, 17, 23, 16, 23, 47, 32, 33, 32, 34,
0, 0, 0, 0, 35, 0, 0, 0, 2, 2, 23, 0, 11, 11, 11, 46,
0, 11, 11, 46, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 30, 0,
9, 2, 2, 2, 30, 45, 59, 20, 20, 31, 33, 32, 32, 25, 163, 29,
164, 165, 37, 0, 0, 0, 0, 0, 0, 12, 26, 0, 0, 0, 0, 0,
9, 2, 2, 2, 30, 45, 59, 20, 20, 31, 33, 32, 32, 25, 164, 29,
165, 166, 37, 0, 0, 0, 0, 0, 0, 12, 26, 0, 0, 0, 0, 0,
0, 2, 2, 65, 25, 20, 20, 20, 22, 23, 126, 15, 17, 0, 0, 0,
0, 2, 2, 2, 2, 2, 0, 0, 166, 167, 0, 0, 0, 0, 0, 0,
0, 18, 19, 20, 20, 66, 99, 25, 160, 11, 168, 9, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 0, 0, 167, 168, 0, 0, 0, 0, 0, 0,
0, 18, 19, 20, 20, 66, 99, 25, 161, 11, 169, 9, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 2, 2, 65, 25, 20, 20, 0, 48, 48, 11,
169, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 20,
0, 23, 19, 20, 20, 21, 16, 82, 169, 38, 0, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 10, 170, 25, 20, 22, 22, 168, 9, 0, 0,
170, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 20,
0, 23, 19, 20, 20, 21, 16, 82, 170, 38, 0, 0, 0, 0, 0, 0,
0, 2, 2, 2, 2, 2, 10, 171, 25, 20, 22, 22, 169, 9, 0, 0,
0, 2, 2, 2, 2, 2, 9, 43, 136, 23, 22, 20, 76, 21, 22, 0,
0, 2, 2, 2, 9, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 18,
19, 20, 21, 22, 105, 169, 37, 0, 0, 2, 2, 2, 9, 30, 0, 2,
2, 2, 2, 30, 9, 2, 2, 2, 2, 23, 23, 18, 32, 33, 12, 171,
165, 172, 173, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2,
19, 20, 21, 22, 105, 170, 37, 0, 0, 2, 2, 2, 9, 30, 0, 2,
2, 2, 2, 30, 9, 2, 2, 2, 2, 23, 23, 18, 32, 33, 12, 172,
166, 173, 174, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2,
2, 65, 25, 20, 20, 0, 22, 23, 29, 108, 0, 33, 0, 0, 0, 0,
0, 52, 20, 22, 22, 22, 140, 2, 2, 2, 174, 175, 11, 15, 176, 61,
177, 0, 0, 1, 147, 0, 0, 0, 0, 52, 20, 22, 16, 19, 20, 2,
2, 2, 2, 158, 158, 158, 178, 178, 178, 178, 178, 178, 15, 179, 0, 30,
0, 22, 20, 20, 31, 22, 22, 11, 169, 0, 61, 61, 61, 61, 61, 61,
0, 52, 20, 22, 22, 22, 140, 2, 2, 2, 175, 141, 11, 15, 176, 61,
177, 0, 0, 1, 148, 0, 0, 0, 0, 52, 20, 22, 16, 19, 20, 2,
2, 2, 2, 159, 159, 159, 178, 178, 178, 178, 178, 178, 15, 179, 0, 30,
0, 22, 20, 20, 31, 22, 22, 11, 170, 0, 61, 61, 61, 61, 61, 61,
61, 66, 21, 82, 46, 0, 0, 0, 0, 2, 2, 2, 9, 2, 30, 2,
2, 52, 22, 22, 31, 0, 38, 22, 27, 11, 159, 180, 181, 0, 0, 0,
2, 52, 22, 22, 31, 0, 38, 22, 27, 11, 160, 180, 181, 0, 0, 0,
0, 2, 2, 2, 30, 9, 2, 2, 2, 2, 2, 2, 2, 2, 23, 23,
47, 22, 35, 82, 68, 0, 0, 0, 0, 2, 182, 66, 47, 0, 0, 0,
0, 11, 183, 2, 2, 2, 2, 2, 2, 2, 2, 23, 22, 20, 31, 0,
48, 16, 143, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 156, 0,
48, 16, 144, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 157, 0,
0, 184, 184, 184, 184, 184, 184, 184, 184, 185, 185, 185, 186, 187, 185, 184,
184, 188, 184, 184, 189, 190, 190, 190, 190, 190, 190, 190, 0, 0, 0, 0,
0, 184, 184, 184, 184, 184, 191, 0, 0, 2, 2, 2, 2, 2, 2, 2,
@ -612,12 +612,12 @@ hb_use_u8[3657] =
IS, RK, RK, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ,
CGJ, WJ, WJ, WJ, O,FMPst, O, SB, SE, O, H, MPst, VPst, H,VMAbv, VAbv,
VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw,
MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS,
O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS,
B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R,CMBlw,
VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv, B, CS,
CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,
VMAbv, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, R, MBlw, GB, VAbv, R,
MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, VBlw,VMAbv, B, VPre, O,
VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst,
CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R,
R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,VMPst, O,VMAbv,CMBlw, IS, R,FMAbv,
B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, MPst, R, MPst,CMBlw, B,
FMBlw, CS, SUB, SUB, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, R, MBlw, GB, VAbv, R,
VMPst, G, G, J, J, J, SB, SE, J, HR, G, G, HM, HM, HM, G,
O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O, VBlw,
};

View File

@ -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,

View File

@ -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;

View File

@ -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);

View 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

View 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 */

View File

@ -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,

View File

@ -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; }
@ -615,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.
@ -628,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);
}
/**

View File

@ -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()
*

View File

@ -162,10 +162,11 @@ struct hb_paint_funcs_t
{
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_font_transform (void *paint_data,
@ -174,10 +175,11 @@ struct hb_paint_funcs_t
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

View File

@ -57,6 +57,10 @@ HB_SHAPER_IMPLEMENT (directwrite)
HB_SHAPER_IMPLEMENT (coretext)
#endif
#ifdef HAVE_HARFRUZZ
HB_SHAPER_IMPLEMENT (harfruzz)
#endif
#ifndef HB_NO_FALLBACK_SHAPE
HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
#endif

View File

@ -47,20 +47,20 @@ HB_BEGIN_DECLS
*
* The minor component of the library version available at compile-time.
*/
#define HB_VERSION_MINOR 1
#define HB_VERSION_MINOR 2
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
#define HB_VERSION_MICRO 0
#define HB_VERSION_MICRO 1
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
#define HB_VERSION_STRING "11.1.0"
#define HB_VERSION_STRING "11.2.1"
/**
* HB_VERSION_ATLEAST: