From 91e721ea8693205f4f738bca97a5055ee75cf463 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 25 Jul 2012 19:20:34 -0400 Subject: [PATCH] [hb-old] Fix clusters Unlike its "documentation", hb-old's log_clusters are, well, indeed logical, not visual. Fixup. Adapted / copied from hb-uniscribe. --- src/hb-old.cc | 51 ++++++++++++++++++++++++++++-------- src/hb-old/harfbuzz-shaper.h | 1 + src/hb-uniscribe.cc | 5 ++-- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/hb-old.cc b/src/hb-old.cc index a3b56797..e828ca83 100644 --- a/src/hb-old.cc +++ b/src/hb-old.cc @@ -251,6 +251,8 @@ _hb_old_shape (hb_font_t *font, buffer->guess_properties (); + bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); + #define FAIL(...) \ HB_STMT_START { \ DEBUG_MSG (OLD, NULL, __VA_ARGS__); \ @@ -285,23 +287,23 @@ retry: pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1)); } } -#undef utf16_index #define ALLOCATE_ARRAY(Type, name, len) \ name = (Type *) scratch; \ - scratch += len * sizeof (name[0]); \ - scratch_size -= len * sizeof (name[0]); + scratch += (len) * sizeof ((name)[0]); \ + scratch_size -= (len) * sizeof ((name)[0]); HB_ShaperItem item = {0}; ALLOCATE_ARRAY (const HB_UChar16, item.string, chars_len); + ALLOCATE_ARRAY (unsigned short, item.log_clusters, chars_len + 2); item.stringLength = chars_len; item.item.pos = 0; item.item.length = item.stringLength; item.item.script = hb_old_script_from_script (buffer->props.script); - item.item.bidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; + item.item.bidiLevel = backward ? 1 : 0; item.font = old_font; item.face = old_face; @@ -314,14 +316,17 @@ retry: sizeof (HB_GlyphAttributes) + sizeof (HB_Fixed) + sizeof (HB_FixedPoint) + - sizeof (unsigned short)); + sizeof (uint32_t)); item.num_glyphs = num_glyphs; ALLOCATE_ARRAY (HB_Glyph, item.glyphs, num_glyphs); ALLOCATE_ARRAY (HB_GlyphAttributes, item.attributes, num_glyphs); ALLOCATE_ARRAY (HB_Fixed, item.advances, num_glyphs); ALLOCATE_ARRAY (HB_FixedPoint, item.offsets, num_glyphs); - ALLOCATE_ARRAY (unsigned short, item.log_clusters, num_glyphs); + uint32_t *vis_clusters; + ALLOCATE_ARRAY (uint32_t, vis_clusters, num_glyphs); + +#undef ALLOCATE_ARRAY if (!HB_ShapeItem (&item)) return false; @@ -335,24 +340,48 @@ retry: } num_glyphs = item.num_glyphs; -#undef ALLOCATE_ARRAY + /* Ok, we've got everything we need, now compose output buffer, + * very, *very*, carefully! */ + + /* Calculate visual-clusters. That's what we ship. */ + for (unsigned int i = 0; i < num_glyphs; i++) + vis_clusters[i] = -1; + for (unsigned int i = 0; i < buffer->len; i++) { + uint32_t *p = &vis_clusters[item.log_clusters[buffer->info[i].utf16_index()]]; + *p = MIN (*p, buffer->info[i].cluster); + } + if (!backward) { + for (unsigned int i = 1; i < num_glyphs; i++) + if (vis_clusters[i] == -1) + vis_clusters[i] = vis_clusters[i - 1]; + } else { + for (int i = num_glyphs - 2; i >= 0; i--) + if (vis_clusters[i] == -1) + vis_clusters[i] = vis_clusters[i + 1]; + } + +#undef utf16_index + buffer->ensure (num_glyphs); + if (buffer->in_error) + FAIL ("Buffer in error"); + + + buffer->len = num_glyphs; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < num_glyphs; i++) { info[i].codepoint = item.glyphs[i]; - info[i].cluster = item.log_clusters[i]; + info[i].cluster = vis_clusters[i]; info[i].mask = item.advances[i]; info[i].var1.u32 = item.offsets[i].x; info[i].var2.u32 = item.offsets[i].y; } - buffer->len = num_glyphs; buffer->clear_positions (); - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; ++i) { + for (unsigned int i = 0; i < num_glyphs; ++i) { hb_glyph_info_t *info = &buffer->info[i]; hb_glyph_position_t *pos = &buffer->pos[i]; diff --git a/src/hb-old/harfbuzz-shaper.h b/src/hb-old/harfbuzz-shaper.h index 3f32d47c..ab650042 100644 --- a/src/hb-old/harfbuzz-shaper.h +++ b/src/hb-old/harfbuzz-shaper.h @@ -251,6 +251,7 @@ struct HB_ShaperItem_ { HB_Fixed *advances; /* output: advances */ HB_FixedPoint *offsets; /* output: offsets */ unsigned short *log_clusters; /* output: for each output glyph, the index in the input of the start of its logical cluster */ + /* XXX the discription for log_clusters is wrong. It maps each input position to output glyph position! */ /* internal */ HB_Bool kerning_applied; /* output: true if kerning was applied by the shaper */ diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index d41542ba..6b9a2617 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -257,8 +257,8 @@ retry: #define ALLOCATE_ARRAY(Type, name, len) \ Type *name = (Type *) scratch; \ - scratch += len * sizeof (name[0]); \ - scratch_size -= len * sizeof (name[0]); + scratch += (len) * sizeof ((name)[0]); \ + scratch_size -= (len) * sizeof ((name)[0]); #define utf16_index() var1.u32 @@ -294,6 +294,7 @@ retry: ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size); ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size); +#undef ALLOCATE_ARRAY #define MAX_ITEMS 256 -- GitLab