diff --git a/configure.ac b/configure.ac index de3c55c3d..47a7b2b1c 100644 --- a/configure.ac +++ b/configure.ac @@ -160,7 +160,7 @@ AM_CONDITIONAL(HAVE_ICU, $have_icu) dnl ========================================================================== -PKG_CHECK_MODULES(ICU_LE, icu-le, have_icu_le=true, have_icu_le=false) +PKG_CHECK_MODULES(ICU_LE, icu-le icu-uc, have_icu_le=true, have_icu_le=false) if $have_icu_le; then AC_DEFINE(HAVE_ICU_LE, 1, [Have ICU Layout Engine library]) fi diff --git a/src/hb-icu-le.cc b/src/hb-icu-le.cc index 07f766dab..68c9c428a 100644 --- a/src/hb-icu-le.cc +++ b/src/hb-icu-le.cc @@ -30,14 +30,10 @@ #include "hb-icu-le/PortableFontInstance.h" -#include "layout/loengine.h" +#include "layout/LayoutEngine.h" +#include "unicode/unistr.h" -#include - - -#ifndef HB_DEBUG_ICU_LE -#define HB_DEBUG_ICU_LE (HB_DEBUG+0) -#endif +#include "hb-icu.h" /* @@ -93,8 +89,8 @@ struct hb_icu_le_shaper_shape_plan_data_t {}; hb_icu_le_shaper_shape_plan_data_t * _hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features) + const hb_feature_t *user_features, + unsigned int num_user_features) { return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -116,5 +112,102 @@ _hb_icu_le_shape (hb_shape_plan_t *shape_plan, const hb_feature_t *features, unsigned int num_features) { - return false; + LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font); + le_int32 script_code = hb_icu_script_from_script (shape_plan->props.script); + le_int32 language_code = -1 /* TODO */; + le_int32 typography_flags = 3; // essential for ligatures and kerning + LEErrorCode status = LE_NO_ERROR; + LayoutEngine *le = LayoutEngine::layoutEngineFactory (font_instance, + script_code, + language_code, + typography_flags, + status); + if (status != LE_NO_ERROR) + { delete (le); return false; } + +retry: + + unsigned int scratch_size; + char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); + +#define ALLOCATE_ARRAY(Type, name, len) \ + Type *name = (Type *) scratch; \ + scratch += (len) * sizeof ((name)[0]); \ + scratch_size -= (len) * sizeof ((name)[0]); + + ALLOCATE_ARRAY (LEUnicode, chars, buffer->len); + ALLOCATE_ARRAY (unsigned int, clusters, buffer->len); + + for (unsigned int i = 0; i < buffer->len; i++) { + chars[i] = buffer->info[i].codepoint; + clusters[i] = buffer->info[i].cluster; + } + + unsigned int glyph_count = le->layoutChars(chars, + 0, + buffer->len, + buffer->len, + HB_DIRECTION_IS_BACKWARD (buffer->props.direction), + 0., 0., + status); + if (status != LE_NO_ERROR) + { delete (le); return false; } + + unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) + + sizeof (le_int32) + + sizeof (float) * 2); + + if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) { + buffer->ensure (buffer->allocated * 2); + if (buffer->in_error) + { delete (le); return false; } + goto retry; + } + + ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count); + ALLOCATE_ARRAY (le_int32, indices, glyph_count); + ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2); + + le->getGlyphs(glyphs, status); + le->getCharIndices(indices, status); + le->getGlyphPositions(positions, status); + +#undef ALLOCATE_ARRAY + + /* Ok, we've got everything we need, now compose output buffer, + * very, *very*, carefully! */ + + unsigned int j = 0; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < glyph_count; i++) + { + if (glyphs[i] >= 0xFFFE) + continue; + + info[j].codepoint = glyphs[i]; + info[j].cluster = clusters[indices[i]]; + + /* icu-le doesn't seem to have separapte advance values. */ + info[j].mask = positions[2 * i + 2] - positions[2 * i]; + info[j].var1.u32 = 0; + info[j].var2.u32 = -positions[2 * i + 1]; + + j++; + } + buffer->len = j; + + buffer->clear_positions (); + + for (unsigned int i = 0; i < buffer->len; i++) { + hb_glyph_info_t *info = &buffer->info[i]; + hb_glyph_position_t *pos = &buffer->pos[i]; + + /* TODO vertical */ + pos->x_advance = info->mask; + pos->x_offset = info->var1.u32; + pos->y_offset = info->var2.u32; + } + + delete (le); + return true; } diff --git a/src/hb-icu-le/cmaps.h b/src/hb-icu-le/cmaps.h index df0bb116b..fcad788bb 100644 --- a/src/hb-icu-le/cmaps.h +++ b/src/hb-icu-le/cmaps.h @@ -78,7 +78,6 @@ inline CMAPMapper::CMAPMapper(const CMAPTable *cmap) inline CMAPMapper::~CMAPMapper() { - DELETE_ARRAY(fcmap); } #endif diff --git a/src/hb-shaper-list.hh b/src/hb-shaper-list.hh index 8e67dbdec..6c02de46d 100644 --- a/src/hb-shaper-list.hh +++ b/src/hb-shaper-list.hh @@ -47,4 +47,8 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */ HB_SHAPER_IMPLEMENT (old) #endif +#ifdef HAVE_ICU_LE +HB_SHAPER_IMPLEMENT (icu_le) +#endif + HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */