< prev index next >
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc
Print this page
*** 22,33 ****
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
! #include "hb-ot-shape-fallback-private.hh"
! #include "hb-ot-layout-gsubgpos-private.hh"
static unsigned int
recategorize_combining_class (hb_codepoint_t u,
unsigned int klass)
{
--- 22,33 ----
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
! #include "hb-ot-shape-fallback.hh"
! #include "hb-kern.hh"
static unsigned int
recategorize_combining_class (hb_codepoint_t u,
unsigned int klass)
{
*** 160,170 ****
return klass;
}
void
! _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
--- 160,170 ----
return klass;
}
void
! _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
*** 178,200 ****
static void
zero_mark_advances (hb_buffer_t *buffer,
unsigned int start,
! unsigned int end)
{
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = start; i < end; i++)
if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
{
buffer->pos[i].x_advance = 0;
buffer->pos[i].y_advance = 0;
}
}
static inline void
! position_mark (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer,
hb_glyph_extents_t &base_extents,
unsigned int i,
unsigned int combining_class)
--- 178,206 ----
static void
zero_mark_advances (hb_buffer_t *buffer,
unsigned int start,
! unsigned int end,
! bool adjust_offsets_when_zeroing)
{
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = start; i < end; i++)
if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
{
+ if (adjust_offsets_when_zeroing)
+ {
+ buffer->pos[i].x_offset -= buffer->pos[i].x_advance;
+ buffer->pos[i].y_offset -= buffer->pos[i].y_advance;
+ }
buffer->pos[i].x_advance = 0;
buffer->pos[i].y_advance = 0;
}
}
static inline void
! position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer,
hb_glyph_extents_t &base_extents,
unsigned int i,
unsigned int combining_class)
*** 301,326 ****
static inline void
position_around_base (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer,
unsigned int base,
! unsigned int end)
{
hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
buffer->unsafe_to_break (base, end);
hb_glyph_extents_t base_extents;
if (!font->get_glyph_extents (buffer->info[base].codepoint,
&base_extents))
{
/* If extents don't work, zero marks and go home. */
! zero_mark_advances (buffer, base + 1, end);
return;
}
- base_extents.x_bearing += buffer->pos[base].x_offset;
base_extents.y_bearing += buffer->pos[base].y_offset;
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
/* Use integer for num_lig_components such that it doesn't convert to unsigned
* when we divide or multiply by it. */
int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
--- 307,337 ----
static inline void
position_around_base (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer,
unsigned int base,
! unsigned int end,
! bool adjust_offsets_when_zeroing)
{
hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
buffer->unsafe_to_break (base, end);
hb_glyph_extents_t base_extents;
if (!font->get_glyph_extents (buffer->info[base].codepoint,
&base_extents))
{
/* If extents don't work, zero marks and go home. */
! zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing);
return;
}
base_extents.y_bearing += buffer->pos[base].y_offset;
+ /* Use horizontal advance for horizontal positioning.
+ * Generally a better idea. Also works for zero-ink glyphs. See:
+ * https://github.com/harfbuzz/harfbuzz/issues/1532 */
+ base_extents.x_bearing = 0;
+ base_extents.width = font->get_glyph_h_advance (buffer->info[base].codepoint);
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
/* Use integer for num_lig_components such that it doesn't convert to unsigned
* when we divide or multiply by it. */
int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
*** 392,402 ****
static inline void
position_cluster (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer,
unsigned int start,
! unsigned int end)
{
if (end - start < 2)
return;
/* Find the base glyph */
--- 403,414 ----
static inline void
position_cluster (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer,
unsigned int start,
! unsigned int end,
! bool adjust_offsets_when_zeroing)
{
if (end - start < 2)
return;
/* Find the base glyph */
*** 408,510 ****
unsigned int j;
for (j = i + 1; j < end; j++)
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
break;
! position_around_base (plan, font, buffer, i, j);
i = j - 1;
}
}
void
! _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
! hb_buffer_t *buffer)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
unsigned int start = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
! position_cluster (plan, font, buffer, start, i);
start = i;
}
! position_cluster (plan, font, buffer, start, count);
}
! /* Performs old-style TrueType kerning. */
void
_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
! if (!plan->has_kern) return;
!
! OT::hb_ot_apply_context_t c (1, font, buffer);
! c.set_lookup_mask (plan->kern_mask);
! c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
! OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
! skippy_iter.init (&c);
!
! unsigned int count = buffer->len;
! hb_glyph_info_t *info = buffer->info;
! hb_glyph_position_t *pos = buffer->pos;
! for (unsigned int idx = 0; idx < count;)
! {
! skippy_iter.reset (idx, 1);
! if (!skippy_iter.next ())
! {
! idx++;
! continue;
! }
! hb_position_t x_kern, y_kern;
! font->get_glyph_kerning_for_direction (info[idx].codepoint,
! info[skippy_iter.idx].codepoint,
! buffer->props.direction,
! &x_kern, &y_kern);
! if (x_kern)
! {
! hb_position_t kern1 = x_kern >> 1;
! hb_position_t kern2 = x_kern - kern1;
! pos[idx].x_advance += kern1;
! pos[skippy_iter.idx].x_advance += kern2;
! pos[skippy_iter.idx].x_offset += kern2;
! buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
! }
! if (y_kern)
! {
! hb_position_t kern1 = y_kern >> 1;
! hb_position_t kern2 = y_kern - kern1;
! pos[idx].y_advance += kern1;
! pos[skippy_iter.idx].y_advance += kern2;
! pos[skippy_iter.idx].y_offset += kern2;
! buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
! }
! idx = skippy_iter.idx;
! }
}
/* Adjusts width of various spaces. */
void
! _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
- if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
- return;
-
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
{
hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
--- 420,508 ----
unsigned int j;
for (j = i + 1; j < end; j++)
if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
break;
! position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
i = j - 1;
}
}
void
! _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
! hb_buffer_t *buffer,
! bool adjust_offsets_when_zeroing)
{
_hb_buffer_assert_gsubgpos_vars (buffer);
unsigned int start = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 1; i < count; i++)
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
! position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
start = i;
}
! position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
}
! struct hb_ot_shape_fallback_kern_driver_t
! {
! hb_ot_shape_fallback_kern_driver_t (hb_font_t *font_,
! hb_buffer_t *buffer) :
! font (font_), direction (buffer->props.direction) {}
!
! hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
! {
! hb_position_t kern = 0;
! font->get_glyph_kerning_for_direction (first, second,
! direction,
! &kern, &kern);
! return kern;
! }
!
! hb_font_t *font;
! hb_direction_t direction;
! };
!
! /* Performs font-assisted kerning. */
void
_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
! if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
! !font->has_glyph_h_kerning_func () :
! !font->has_glyph_v_kerning_func ())
! return;
! bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
! if (reverse)
! buffer->reverse ();
! hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
! OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
! machine.kern (font, buffer, plan->kern_mask, false);
! if (reverse)
! buffer->reverse ();
}
/* Adjusts width of various spaces. */
void
! _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
+ bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
{
hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
*** 521,559 ****
case t::SPACE_EM_3:
case t::SPACE_EM_4:
case t::SPACE_EM_5:
case t::SPACE_EM_6:
case t::SPACE_EM_16:
! pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
break;
case t::SPACE_4_EM_18:
! pos[i].x_advance = (int64_t) font->x_scale * 4 / 18;
break;
case t::SPACE_FIGURE:
for (char u = '0'; u <= '9'; u++)
if (font->get_nominal_glyph (u, &glyph))
{
pos[i].x_advance = font->get_glyph_h_advance (glyph);
break;
}
break;
case t::SPACE_PUNCTUATION:
! if (font->get_nominal_glyph ('.', &glyph))
! pos[i].x_advance = font->get_glyph_h_advance (glyph);
! else if (font->get_nominal_glyph (',', &glyph))
pos[i].x_advance = font->get_glyph_h_advance (glyph);
break;
case t::SPACE_NARROW:
/* Half-space?
* Unicode doc https://unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
* However, in my testing, many fonts have their regular space being about that
* size. To me, a percentage of the space width makes more sense. Half is as
* good as any. */
pos[i].x_advance /= 2;
break;
}
}
}
--- 519,573 ----
case t::SPACE_EM_3:
case t::SPACE_EM_4:
case t::SPACE_EM_5:
case t::SPACE_EM_6:
case t::SPACE_EM_16:
! if (horizontal)
! pos[i].x_advance = +(font->x_scale + ((int) space_type)/2) / (int) space_type;
! else
! pos[i].y_advance = -(font->y_scale + ((int) space_type)/2) / (int) space_type;
break;
case t::SPACE_4_EM_18:
! if (horizontal)
! pos[i].x_advance = (int64_t) +font->x_scale * 4 / 18;
! else
! pos[i].y_advance = (int64_t) -font->y_scale * 4 / 18;
break;
case t::SPACE_FIGURE:
for (char u = '0'; u <= '9'; u++)
if (font->get_nominal_glyph (u, &glyph))
{
+ if (horizontal)
pos[i].x_advance = font->get_glyph_h_advance (glyph);
+ else
+ pos[i].y_advance = font->get_glyph_v_advance (glyph);
break;
}
break;
case t::SPACE_PUNCTUATION:
! if (font->get_nominal_glyph ('.', &glyph) ||
! font->get_nominal_glyph (',', &glyph))
! {
! if (horizontal)
pos[i].x_advance = font->get_glyph_h_advance (glyph);
+ else
+ pos[i].y_advance = font->get_glyph_v_advance (glyph);
+ }
break;
case t::SPACE_NARROW:
/* Half-space?
* Unicode doc https://unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
* However, in my testing, many fonts have their regular space being about that
* size. To me, a percentage of the space width makes more sense. Half is as
* good as any. */
+ if (horizontal)
pos[i].x_advance /= 2;
+ else
+ pos[i].y_advance /= 2;
break;
}
}
}
< prev index next >