Exemple #1
0
/**
 * hb_shape_full:
 * @font: an #hb_font_t to use for shaping
 * @buffer: an #hb_buffer_t to shape
 * @features: (array length=num_features) (allow-none): an array of user
 *    specified #hb_feature_t or %NULL
 * @num_features: the length of @features array
 * @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated
 *    array of shapers to use or %NULL
 *
 * See hb_shape() for details. If @shaper_list is not %NULL, the specified
 * shapers will be used in the given order, otherwise the default shapers list
 * will be used.
 *
 * Return value: %FALSE if all shapers failed, %TRUE otherwise
 *
 * Since: 0.9.2
 **/
hb_bool_t
hb_shape_full (hb_font_t          *font,
               hb_buffer_t        *buffer,
               const hb_feature_t *features,
               unsigned int        num_features,
               const char * const *shaper_list)
{
  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
  hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
  hb_shape_plan_destroy (shape_plan);

  if (res)
    buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
  return res;
}
Exemple #2
0
int shape (lua_State *L) {    
    const char * text = luaL_checkstring(L, 1);
    FT_Face face = lua_touserdata(L, 2);
    const char * script = luaL_checkstring(L, 3);
    const char * direction_s = luaL_checkstring(L, 4);
    const char * lang = luaL_checkstring(L, 5);
    double point_size = luaL_checknumber(L, 6);
    const char * featurestring = luaL_checkstring(L, 7);

    hb_segment_properties_t segment_props;
    hb_shape_plan_t *shape_plan;

    hb_direction_t direction;
    hb_feature_t* features;
    int nFeatures = 0;
    unsigned int glyph_count = 0;
    hb_font_t *hb_ft_font;
    hb_face_t *hb_ft_face;
    hb_buffer_t *buf;
    hb_glyph_info_t *glyph_info;
    hb_glyph_position_t *glyph_pos;
    unsigned int j;

    features = scan_feature_string(featurestring, &nFeatures);

    if (!strcasecmp(direction_s,"RTL"))
      direction = HB_DIRECTION_RTL;
    else if (!strcasecmp(direction_s,"TTB"))
      direction = HB_DIRECTION_TTB;
    else
      direction = HB_DIRECTION_LTR;

    hb_ft_font = hb_ft_font_create(face, NULL);
    hb_face_t* hbFace = hb_font_get_face(hb_ft_font);

    buf = hb_buffer_create();
    hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));

    hb_buffer_set_script(buf, hb_tag_from_string(script, strlen(script)));
    hb_buffer_set_direction(buf, direction);
    hb_buffer_set_language(buf, hb_language_from_string(lang,strlen(lang)));

    hb_buffer_guess_segment_properties(buf);
    hb_buffer_get_segment_properties(buf, &segment_props);
    shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, features, nFeatures, NULL);
    int res = hb_shape_plan_execute(shape_plan, hb_ft_font, buf, features, nFeatures);

    glyph_info   = hb_buffer_get_glyph_infos(buf, &glyph_count);
    glyph_pos    = hb_buffer_get_glyph_positions(buf, &glyph_count);
    lua_checkstack(L, glyph_count);
    for (j = 0; j < glyph_count; ++j) {
      char namebuf[255];
      box glyph_extents  = { 0.0, 0.0, 0.0 };
      calculate_extents(&glyph_extents, glyph_info[j], glyph_pos[j], face, point_size, direction);

      lua_newtable(L);
      lua_pushstring(L, "name");
      FT_Get_Glyph_Name( face, glyph_info[j].codepoint, namebuf, 255 );      
      lua_pushstring(L, namebuf);
      lua_settable(L, -3);

      if (direction != HB_DIRECTION_TTB) { /* XXX */
        if (glyph_pos[j].x_offset) {
          lua_pushstring(L, "x_offset");
          lua_pushnumber(L, glyph_pos[j].x_offset / 64.0);
          lua_settable(L, -3);
        }

        if (glyph_pos[j].y_offset) {
          lua_pushstring(L, "y_offset");
          lua_pushnumber(L, glyph_pos[j].y_offset / 64.0);
          lua_settable(L, -3);
        }
      }

      lua_pushstring(L, "codepoint");
      lua_pushinteger(L, glyph_info[j].codepoint);
      lua_settable(L, -3);
      lua_pushstring(L, "width");
      lua_pushnumber(L, glyph_extents.width);
      lua_settable(L, -3);
      lua_pushstring(L, "height");
      lua_pushnumber(L, glyph_extents.height);
      lua_settable(L, -3);
      lua_pushstring(L, "depth");
      lua_pushnumber(L, glyph_extents.depth);
      lua_settable(L, -3);
    }
    /* Cleanup */
    hb_buffer_destroy(buf);
    hb_font_destroy(hb_ft_font);
    hb_shape_plan_destroy(shape_plan);

    free(features);
    return glyph_count;
}
Exemple #3
0
int shape (lua_State *L) {    
    size_t font_l;
    const char * text = luaL_checkstring(L, 1);
    const char * font_s = luaL_checklstring(L, 2, &font_l);
    unsigned int font_index = luaL_checknumber(L, 3);
    const char * script = luaL_checkstring(L, 4);
    const char * direction_s = luaL_checkstring(L, 5);
    const char * lang = luaL_checkstring(L, 6);
    double point_size = luaL_checknumber(L, 7);
    const char * featurestring = luaL_checkstring(L, 8);

    hb_segment_properties_t segment_props;
    hb_shape_plan_t *shape_plan;

    hb_direction_t direction;
    hb_feature_t* features;
    int nFeatures = 0;
    unsigned int glyph_count = 0;
    hb_font_t *hbFont;
    hb_buffer_t *buf;
    hb_glyph_info_t *glyph_info;
    hb_glyph_position_t *glyph_pos;
    unsigned int j;

    features = scan_feature_string(featurestring, &nFeatures);

    if (!strcasecmp(direction_s,"RTL"))
      direction = HB_DIRECTION_RTL;
    else if (!strcasecmp(direction_s,"TTB"))
      direction = HB_DIRECTION_TTB;
    else
      direction = HB_DIRECTION_LTR;

    hb_blob_t* blob = hb_blob_create (font_s, font_l, HB_MEMORY_MODE_WRITABLE, (void*)font_s, NULL);
    hb_face_t* hbFace = hb_face_create (blob, font_index);
    hbFont = hb_font_create (hbFace);
    unsigned int upem = hb_face_get_upem(hbFace);
    hb_font_set_scale(hbFont, upem, upem);

    /* Harfbuzz's support for OT fonts is great, but
       there's currently no support for CFF fonts, so
       downgrade to Freetype for those. */
    if (strncmp(font_s, "OTTO", 4) == 0) {
      hb_ft_font_set_funcs(hbFont);
    } else {
      hb_ot_font_set_funcs(hbFont);
    }

    buf = hb_buffer_create();
    hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));

    hb_buffer_set_script(buf, hb_tag_from_string(script, strlen(script)));
    hb_buffer_set_direction(buf, direction);
    hb_buffer_set_language(buf, hb_language_from_string(lang,strlen(lang)));

    hb_buffer_guess_segment_properties(buf);
    hb_buffer_get_segment_properties(buf, &segment_props);
    shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, features, nFeatures, NULL);
    int res = hb_shape_plan_execute(shape_plan, hbFont, buf, features, nFeatures);

    if (direction == HB_DIRECTION_RTL) {
      hb_buffer_reverse(buf); /* URGH */
    }
    glyph_info   = hb_buffer_get_glyph_infos(buf, &glyph_count);
    glyph_pos    = hb_buffer_get_glyph_positions(buf, &glyph_count);
    lua_checkstack(L, glyph_count);
    for (j = 0; j < glyph_count; ++j) {
      char namebuf[255];
      hb_glyph_extents_t extents = {0,0,0,0};
      hb_font_get_glyph_extents(hbFont, glyph_info[j].codepoint, &extents);

      lua_newtable(L);
      lua_pushstring(L, "name");
      hb_font_get_glyph_name( hbFont, glyph_info[j].codepoint, namebuf, 255 );
      lua_pushstring(L, namebuf);
      lua_settable(L, -3);

      /* We don't apply x-offset and y-offsets for TTB, which
      is arguably a bug. We should. The reason we don't is that
      Harfbuzz assumes that you want to shift the character from a
      top-center baseline to a bottom-left baseline, and gives you
      offsets which do that. We don't want to do that so we ignore the
      offsets. I'm told there is a way of configuring HB's idea of the
      baseline, and we should use that and take out this condition. */
      if (direction != HB_DIRECTION_TTB) {
        if (glyph_pos[j].x_offset) {
          lua_pushstring(L, "x_offset");
          lua_pushnumber(L, glyph_pos[j].x_offset * point_size / upem);
          lua_settable(L, -3);
        }

        if (glyph_pos[j].y_offset) {
          lua_pushstring(L, "y_offset");
          lua_pushnumber(L, glyph_pos[j].y_offset * point_size / upem);
          lua_settable(L, -3);
        }
      }

      lua_pushstring(L, "codepoint");
      lua_pushinteger(L, glyph_info[j].codepoint);
      lua_settable(L, -3);
      lua_pushstring(L, "index");
      lua_pushinteger(L, glyph_info[j].cluster);
      lua_settable(L, -3);

      double height = extents.y_bearing * point_size / upem;
      double tHeight = extents.height * point_size / upem;
      double width = glyph_pos[j].x_advance * point_size / upem;

      /* The PDF model expects us to make positioning adjustments
      after a glyph is painted. For this we need to know the natural
      glyph advance. libtexpdf will use this to compute the adjustment. */
      double glyphAdvance = hb_font_get_glyph_h_advance(hbFont, glyph_info[j].codepoint) * point_size / upem;

      if (direction == HB_DIRECTION_TTB) {
        height = -glyph_pos[j].y_advance * point_size / upem;
        tHeight = -height; /* Set depth to 0 - depth has no meaning for TTB */
        width = glyphAdvance;
        glyphAdvance = height;
      }
      lua_pushstring(L, "glyphAdvance");
      lua_pushnumber(L, glyphAdvance);
      lua_settable(L, -3);

      lua_pushstring(L, "width");
      lua_pushnumber(L, width);
      lua_settable(L, -3);

      lua_pushstring(L, "height");
      lua_pushnumber(L, height);
      lua_settable(L, -3);
      lua_pushstring(L, "depth");
      lua_pushnumber(L, -tHeight - height);
      lua_settable(L, -3);
    }
    /* Cleanup */
    hb_buffer_destroy(buf);
    hb_font_destroy(hbFont);
    hb_shape_plan_destroy(shape_plan);

    free(features);
    return glyph_count;
}
Exemple #4
0
int
layoutChars(XeTeXLayoutEngine engine, uint16_t chars[], int32_t offset, int32_t count, int32_t max,
                        bool rightToLeft)
{
    bool res;
    hb_script_t script = HB_SCRIPT_INVALID;
    hb_direction_t direction = HB_DIRECTION_LTR;
    hb_segment_properties_t segment_props;
    hb_shape_plan_t *shape_plan;
    hb_font_t* hbFont = engine->font->getHbFont();
    hb_face_t* hbFace = hb_font_get_face(hbFont);

    if (engine->font->getLayoutDirVertical())
        direction = HB_DIRECTION_TTB;
    else if (rightToLeft)
        direction = HB_DIRECTION_RTL;

    script = hb_ot_tag_to_script (engine->script);

    if (hbUnicodeFuncs == NULL)
        hbUnicodeFuncs = _get_unicode_funcs();

    hb_buffer_reset(engine->hbBuffer);
    hb_buffer_set_unicode_funcs(engine->hbBuffer, hbUnicodeFuncs);
    hb_buffer_add_utf16(engine->hbBuffer, chars, max, offset, count);
    hb_buffer_set_direction(engine->hbBuffer, direction);
    hb_buffer_set_script(engine->hbBuffer, script);
    hb_buffer_set_language(engine->hbBuffer, engine->language);

    hb_buffer_guess_segment_properties(engine->hbBuffer);
    hb_buffer_get_segment_properties(engine->hbBuffer, &segment_props);

    if (engine->ShaperList == NULL) {
        // HarfBuzz gives graphite2 shaper a priority, so that for hybrid
        // Graphite/OpenType fonts, Graphite will be used. However, pre-0.9999
        // XeTeX preferred OpenType over Graphite, so we are doing the same
        // here for sake of backward compatibility.
        engine->ShaperList = (char**) xcalloc(4, sizeof(char*));
        engine->ShaperList[0] = (char*) "ot";
        engine->ShaperList[1] = (char*) "graphite2";
        engine->ShaperList[2] = (char*) "fallback";
        engine->ShaperList[3] = NULL;
    }

    shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, engine->features, engine->nFeatures, engine->ShaperList);
    res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures);

    if (res) {
        engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan));
        hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
    } else {
        // all selected shapers failed, retrying with default
        // we don't use _cached here as the cached plain will always fail.
        hb_shape_plan_destroy(shape_plan);
        shape_plan = hb_shape_plan_create(hbFace, &segment_props, engine->features, engine->nFeatures, NULL);
        res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures);

        if (res) {
            engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan));
            hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
        } else {
            fprintf(stderr, "\nERROR: all shapers failed\n");
            exit(3);
        }
    }

    hb_shape_plan_destroy(shape_plan);

    int glyphCount = hb_buffer_get_length(engine->hbBuffer);

#ifdef DEBUG
    char buf[1024];
    unsigned int consumed;

    printf ("shaper: %s\n", engine->shaper);

    hb_buffer_serialize_flags_t flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT;
    hb_buffer_serialize_format_t format = HB_BUFFER_SERIALIZE_FORMAT_JSON;

    hb_buffer_serialize_glyphs (engine->hbBuffer, 0, glyphCount, buf, sizeof(buf), &consumed, hbFont, format, flags);
    if (consumed)
        printf ("buffer glyphs: %s\n", buf);
#endif

    return glyphCount;
}