예제 #1
0
파일: SkShaper.cpp 프로젝트: OwenTan/skia
SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
    fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
    int index;
    std::unique_ptr<SkStreamAsset> asset(fImpl->fTypeface->openStream(&index));
    size_t size = asset->getLength();
    SkAutoMalloc autoMalloc(size);  // TODO(halcanary): Avoid this malloc+copy.
    asset->read(autoMalloc.get(), size);
    asset = nullptr;
    void* ptr = autoMalloc.get();
    hb_blob_t* blob = hb_blob_create((char*)autoMalloc.release(), size,
                                     HB_MEMORY_MODE_READONLY, ptr, sk_free);
    SkASSERT(blob);
    hb_blob_make_immutable(blob);

    struct HBFaceDel {
        void operator()(hb_face_t* f) { hb_face_destroy(f); }
    };
    std::unique_ptr<hb_face_t, HBFaceDel> face(hb_face_create(blob, (unsigned)index));
    hb_blob_destroy(blob);
    SkASSERT(face);
    if (!face) {
        return;
    }
    hb_face_set_index(face.get(), (unsigned)index);
    hb_face_set_upem(face.get(), fImpl->fTypeface->getUnitsPerEm());

    fImpl->fHarfBuzzFont.reset(hb_font_create(face.get()));
    SkASSERT(fImpl->fHarfBuzzFont);
    hb_font_set_scale(fImpl->fHarfBuzzFont.get(), FONT_SIZE_SCALE, FONT_SIZE_SCALE);
    hb_ot_font_set_funcs(fImpl->fHarfBuzzFont.get());

    fImpl->fBuffer.reset(hb_buffer_create());
}
예제 #2
0
LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance,
                           le_int32 scriptCode,
                           le_int32 languageCode,
                           le_int32 typoFlags,
                           LEErrorCode &success)
  : fHbFont(NULL), fHbBuffer(NULL), fTypoFlags(typoFlags)
{
    if (LE_FAILURE(success)) {
        return;
    }

    fHbBuffer = hb_buffer_create ();
    if (fHbBuffer == hb_buffer_get_empty ()) {
	success = LE_MEMORY_ALLOCATION_ERROR;
	return;
    }
    hb_buffer_set_unicode_funcs (fHbBuffer, hb_icu_get_unicode_funcs ());
    hb_buffer_set_script (fHbBuffer, hb_icu_script_to_script ((UScriptCode) scriptCode));
    /* TODO set language */

    hb_face_t *face = hb_face_create_for_tables (icu_le_hb_reference_table, (void *) fontInstance, NULL);
    fHbFont = hb_font_create (face);
    hb_face_destroy (face);
    if (fHbFont == hb_font_get_empty ()) {
        success = LE_MEMORY_ALLOCATION_ERROR;
	return;
    }
    hb_font_set_funcs (fHbFont, icu_le_hb_get_font_funcs (), (void *) fontInstance, NULL);
    hb_font_set_scale (fHbFont,
		       +from_float (fontInstance->getXPixelsPerEm () * fontInstance->getScaleFactorX ()),
		       -from_float (fontInstance->getYPixelsPerEm () * fontInstance->getScaleFactorY ()));
    hb_font_set_ppem (fHbFont,
		      fontInstance->getXPixelsPerEm (),
		      fontInstance->getYPixelsPerEm ());
}
예제 #3
0
hb_font_t* HarfBuzzFace::createFont()
{
    hb_font_t* font = hb_font_create(m_face);
    hb_font_set_funcs(font, harfBuzzCoreTextGetFontFuncs(), m_platformData, 0);
    const float size = m_platformData->m_size;
    hb_font_set_ppem(font, size, size);
    const int scale = (1 << 16) * static_cast<int>(size);
    hb_font_set_scale(font, scale, scale);
    hb_font_make_immutable(font);
    return font;
}
예제 #4
0
hb_font_t* HarfBuzzFace::createFont()
{
    HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCacheEntry);
    m_platformData->setupPaint(&hbFontData->m_paint);
    hb_font_t* font = hb_font_create(m_face);
    hb_font_set_funcs(font, harfBuzzSkiaGetFontFuncs(), hbFontData, destroyHarfBuzzFontData);
    float size = m_platformData->size();
    int scale = SkiaScalarToHarfBuzzPosition(size);
    hb_font_set_scale(font, scale, scale);
    hb_font_make_immutable(font);
    return font;
}
hb_font_t* createFont(hb_face_t* face, SkPaint* paint, float sizeX, float sizeY) {
    hb_font_t* font = hb_font_create(face);
    
    // Note: this needs to be reworked when we do subpixels
    int x_ppem = floor(sizeX + 0.5);
    int y_ppem = floor(sizeY + 0.5);
    hb_font_set_ppem(font, x_ppem, y_ppem); 
    hb_font_set_scale(font, HBFloatToFixed(sizeX), HBFloatToFixed(sizeY));

    HarfBuzzFontData* data = new HarfBuzzFontData(paint);
    hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), data, destroyHarfBuzzFontData);

    return font;
}
예제 #6
0
hb_font_t* HarfBuzzFace::createFont()
{
    hb_font_t* font = hb_font_create(m_face);
    SkPaint* paint = new SkPaint;
    m_platformData->setupPaint(paint);
    hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), paint, destroyPaint);
    float size = m_platformData->size();
    if (floorf(size) == size)
        hb_font_set_ppem(font, size, size);
    int scale = SkiaScalarToHarfbuzzPosition(size);
    hb_font_set_scale(font, scale, scale);
    hb_font_make_immutable(font);
    return font;
}
예제 #7
0
  FT_Error
  af_get_char_index( AF_StyleMetrics  metrics,
                     FT_ULong         charcode,
                     FT_ULong        *codepoint,
                     FT_Long         *y_offset )
  {
    AF_StyleClass  style_class;

    const hb_feature_t*  feature;

    FT_ULong  in_idx, out_idx;


    if ( !metrics )
      return FT_THROW( Invalid_Argument );

    in_idx = FT_Get_Char_Index( metrics->globals->face, charcode );

    style_class = metrics->style_class;

    feature = features[style_class->coverage];

    if ( feature )
    {
      FT_Int  upem = (FT_Int)metrics->globals->face->units_per_EM;

      hb_font_t*    font = metrics->globals->hb_font;
      hb_buffer_t*  buf  = hb_buffer_create();

      uint32_t  c = (uint32_t)charcode;

      hb_glyph_info_t*      ginfo;
      hb_glyph_position_t*  gpos;
      unsigned int          gcount;


      /* we shape at a size of units per EM; this means font units */
      hb_font_set_scale( font, upem, upem );

      /* XXX: is this sufficient for a single character of any script? */
      hb_buffer_set_direction( buf, HB_DIRECTION_LTR );
      hb_buffer_set_script( buf, scripts[style_class->script] );

      /* we add one character to `buf' ... */
      hb_buffer_add_utf32( buf, &c, 1, 0, 1 );

      /* ... and apply one feature */
      hb_shape( font, buf, feature, 1 );

      ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
      gpos  = hb_buffer_get_glyph_positions( buf, &gcount );

      out_idx = ginfo[0].codepoint;

      /* getting the same index indicates no substitution,         */
      /* which means that the glyph isn't available in the feature */
      if ( in_idx == out_idx )
      {
        *codepoint = 0;
        *y_offset  = 0;
      }
      else
      {
        *codepoint = out_idx;
        *y_offset  = gpos[0].y_offset;
      }

      hb_buffer_destroy( buf );

#ifdef FT_DEBUG_LEVEL_TRACE
      if ( gcount > 1 )
        FT_TRACE1(( "af_get_char_index:"
                    " input character mapped to multiple glyphs\n" ));
#endif
    }
    else
    {
      *codepoint = in_idx;
      *y_offset  = 0;
    }

    return FT_Err_Ok;
  }
예제 #8
0
void
XeTeXFontInst::initialize(const char* pathname, int index, int &status)
{
    TT_Postscript *postTable;
    TT_OS2* os2Table;
    FT_Error error;
    hb_face_t *hbFace;

    if (!gFreeTypeLibrary) {
        error = FT_Init_FreeType(&gFreeTypeLibrary);
        if (error) {
            fprintf(stderr, "FreeType initialization failed! (%d)\n", error);
            exit(1);
        }
    }

    error = FT_New_Face(gFreeTypeLibrary, pathname, index, &m_ftFace);
    if (error) {
        status = 1;
        return;
    }

    if (!FT_IS_SCALABLE(m_ftFace)) {
        status = 1;
        return;
    }

    /* for non-sfnt-packaged fonts (presumably Type 1), see if there is an AFM file we can attach */
    if (index == 0 && !FT_IS_SFNT(m_ftFace)) {
        char* afm = xstrdup (xbasename (pathname));
        char* p = strrchr (afm, '.');
        if (p != NULL && strlen(p) == 4 && tolower(*(p+1)) == 'p' &&
            tolower(*(p+2)) == 'f')
            strcpy(p, ".afm");
        char *fullafm = kpse_find_file (afm, kpse_afm_format, 0);
        free (afm);
        if (fullafm) {
            FT_Attach_File(m_ftFace, fullafm);
            free (fullafm);
        }
    }

    m_filename = xstrdup(pathname);
    m_index = index;
    m_unitsPerEM = m_ftFace->units_per_EM;
    m_ascent = unitsToPoints(m_ftFace->ascender);
    m_descent = unitsToPoints(m_ftFace->descender);

    postTable = (TT_Postscript *) getFontTable(ft_sfnt_post);
    if (postTable != NULL) {
        m_italicAngle = Fix2D(postTable->italicAngle);
    }

    os2Table = (TT_OS2*) getFontTable(ft_sfnt_os2);
    if (os2Table) {
        m_capHeight = unitsToPoints(os2Table->sCapHeight);
        m_xHeight = unitsToPoints(os2Table->sxHeight);
    }

    // Set up HarfBuzz font
    hbFace = hb_face_create_for_tables(_get_table, m_ftFace, NULL);
    hb_face_set_index(hbFace, index);
    hb_face_set_upem(hbFace, m_unitsPerEM);
    m_hbFont = hb_font_create(hbFace);
    hb_face_destroy(hbFace);

    if (hbFontFuncs == NULL)
        hbFontFuncs = _get_font_funcs();

    hb_font_set_funcs(m_hbFont, hbFontFuncs, m_ftFace, NULL);
    hb_font_set_scale(m_hbFont, m_unitsPerEM, m_unitsPerEM);
    // We don’t want device tables adjustments
    hb_font_set_ppem(m_hbFont, 0, 0);

    return;
}
예제 #9
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;
}
예제 #10
0
파일: afshaper.c 프로젝트: 93i/godot
  const char*
  af_shaper_get_cluster( const char*      p,
                         AF_StyleMetrics  metrics,
                         void*            buf_,
                         unsigned int*    count )
  {
    AF_StyleClass        style_class;
    const hb_feature_t*  feature;
    FT_Int               upem;
    const char*          q;
    int                  len;

    hb_buffer_t*    buf = (hb_buffer_t*)buf_;
    hb_font_t*      font;
    hb_codepoint_t  dummy;


    upem        = (FT_Int)metrics->globals->face->units_per_EM;
    style_class = metrics->style_class;
    feature     = features[style_class->coverage];

    font = metrics->globals->hb_font;

    /* we shape at a size of units per EM; this means font units */
    hb_font_set_scale( font, upem, upem );

    while ( *p == ' ' )
      p++;

    /* count bytes up to next space (or end of buffer) */
    q = p;
    while ( !( *q == ' ' || *q == '\0' ) )
      GET_UTF8_CHAR( dummy, q );
    len = (int)( q - p );

    /* feed character(s) to the HarfBuzz buffer */
    hb_buffer_clear_contents( buf );
    hb_buffer_add_utf8( buf, p, len, 0, len );

    /* we let HarfBuzz guess the script and writing direction */
    hb_buffer_guess_segment_properties( buf );

    /* shape buffer, which means conversion from character codes to */
    /* glyph indices, possibly applying a feature                   */
    hb_shape( font, buf, feature, feature ? 1 : 0 );

    if ( feature )
    {
      hb_buffer_t*  hb_buf = metrics->globals->hb_buf;

      unsigned int      gcount;
      hb_glyph_info_t*  ginfo;

      unsigned int      hb_gcount;
      hb_glyph_info_t*  hb_ginfo;


      /* we have to check whether applying a feature does actually change */
      /* glyph indices; otherwise the affected glyph or glyphs aren't     */
      /* available at all in the feature                                  */

      hb_buffer_clear_contents( hb_buf );
      hb_buffer_add_utf8( hb_buf, p, len, 0, len );
      hb_buffer_guess_segment_properties( hb_buf );
      hb_shape( font, hb_buf, NULL, 0 );

      ginfo    = hb_buffer_get_glyph_infos( buf, &gcount );
      hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount );

      if ( gcount == hb_gcount )
      {
        unsigned int  i;


        for (i = 0; i < gcount; i++ )
          if ( ginfo[i].codepoint != hb_ginfo[i].codepoint )
            break;

        if ( i == gcount )
        {
          /* both buffers have identical glyph indices */
          hb_buffer_clear_contents( buf );
        }
      }
    }

    *count = hb_buffer_get_length( buf );

#ifdef FT_DEBUG_LEVEL_TRACE
    if ( feature && *count > 1 )
      FT_TRACE1(( "af_shaper_get_cluster:"
                  " input character mapped to multiple glyphs\n" ));
#endif

    return q;
  }