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