< prev index next >
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc
Print this page
@@ -22,12 +22,12 @@
* 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"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-kern.hh"
static unsigned int
recategorize_combining_class (hb_codepoint_t u,
unsigned int klass)
{
@@ -160,11 +160,11 @@
return klass;
}
void
-_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
+_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,23 +178,29 @@
static void
zero_mark_advances (hb_buffer_t *buffer,
unsigned int start,
- unsigned int end)
+ 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,
+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,26 +307,31 @@
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)
+ 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);
+ zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing);
return;
}
- base_extents.x_bearing += buffer->pos[base].x_offset;
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,11 +403,12 @@
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)
+ unsigned int end,
+ bool adjust_offsets_when_zeroing)
{
if (end - start < 2)
return;
/* Find the base glyph */
@@ -408,103 +420,89 @@
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);
+ position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
i = j - 1;
}
}
void
-_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
+_hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
- hb_buffer_t *buffer)
+ 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);
+ position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
start = i;
}
- position_cluster (plan, font, buffer, start, count);
+ position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
}
-/* Performs old-style TrueType kerning. */
+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 (!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;
- }
+ if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
+ !font->has_glyph_h_kerning_func () :
+ !font->has_glyph_v_kerning_func ())
+ return;
- 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);
+ bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
- 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 (reverse)
+ buffer->reverse ();
- 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);
- }
+ 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);
- idx = skippy_iter.idx;
- }
+ if (reverse)
+ buffer->reverse ();
}
/* Adjusts width of various spaces. */
void
-_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
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;
+ 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,39 +519,55 @@
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;
+ 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:
- pos[i].x_advance = (int64_t) font->x_scale * 4 / 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))
- pos[i].x_advance = font->get_glyph_h_advance (glyph);
- else if (font->get_nominal_glyph (',', &glyph))
+ 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 >