static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints) { if (flags & HB_ShaperFlag_UseDesignMetrics) // This is requesting pre-hinted positions. We can't support this. return HB_Err_Invalid_Argument; SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t glyph16 = glyph; SkPath path; paint->getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); uint32_t numPoints = path.getPoints(0, 0); if (point >= numPoints) return HB_Err_Invalid_SubTable; SkPoint* points = static_cast<SkPoint*>(malloc(sizeof(SkPoint) * (point + 1))); if (!points) return HB_Err_Invalid_SubTable; // Skia does let us get a single point from the path. path.getPoints(points, point + 1); *xPos = SkScalarToHBFixed(points[point].fX); *yPos = SkScalarToHBFixed(points[point].fY); *resultingNumPoints = numPoints; delete points; return HB_Err_Ok; }
static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, HB_Fixed* advances, int flags) { SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t* glyphs16 = new uint16_t[numGlyphs]; if (!glyphs16) return; for (unsigned i = 0; i < numGlyphs; ++i) glyphs16[i] = glyphs[i]; SkScalar* scalarAdvances = reinterpret_cast<SkScalar*>(advances); paint->getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), scalarAdvances); // The |advances| values which Skia outputs are SkScalars, which are floats // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format. // These two formats are both 32-bits long. for (unsigned i = 0; i < numGlyphs; ++i) { advances[i] = SkScalarToHBFixed(scalarAdvances[i]); #if DEBUG_ADVANCES ALOGD("glyphsToAdvances -- advances[%d]=%d", i, advances[i]); #endif } delete[] glyphs16; }
static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics) { SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t glyph16 = glyph; SkScalar width; SkRect bounds; paint->getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); metrics->x = SkScalarToHBFixed(bounds.fLeft); metrics->y = SkScalarToHBFixed(bounds.fTop); metrics->width = SkScalarToHBFixed(bounds.width()); metrics->height = SkScalarToHBFixed(bounds.height()); metrics->xOffset = SkScalarToHBFixed(width); // We can't actually get the |y| correct because Skia doesn't export // the vertical advance. However, nor we do ever render vertical text at // the moment so it's unimportant. metrics->yOffset = 0; }
static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) { ALOG_ASSERT(codepoint <= 0xFFFF); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkScalar skWidth; SkRect skBounds; uint16_t glyph = codepoint; paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, &skBounds); if (kDebugGlyphs) { ALOGD("returned glyph for %i: width = %f", codepoint, skWidth); } if (width) *width = SkScalarToHBFixed(skWidth); if (extents) { // Invert y-axis because Skia is y-grows-down but we set up harfbuzz to be y-grows-up. extents->x_bearing = SkScalarToHBFixed(skBounds.fLeft); extents->y_bearing = SkScalarToHBFixed(-skBounds.fTop); extents->width = SkScalarToHBFixed(skBounds.width()); extents->height = SkScalarToHBFixed(-skBounds.height()); } }
static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) { SkPaint* paint = static_cast<SkPaint*>(hbFont->userData); SkPaint::FontMetrics skiaMetrics; paint->getFontMetrics(&skiaMetrics); switch (metric) { case HB_FontAscent: return SkScalarToHBFixed(-skiaMetrics.fAscent); // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them. default: return 0; } return 0; }