void Font::render(const SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, const SkPath* path, float hOffset, float vOffset) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } text += start; int glyphsCount = 0; SkFixed prevRsbDelta = 0; float penX = 0.0f; SkPoint position; SkVector tangent; SkPathMeasure measure(*path, false); float pathLength = SkScalarToFloat(measure.getLength()); if (paint->getTextAlign() != SkPaint::kLeft_Align) { float textWidth = SkScalarToFloat(paint->measureText(text, len)); float pathOffset = pathLength; if (paint->getTextAlign() == SkPaint::kCenter_Align) { textWidth *= 0.5f; pathOffset *= 0.5f; } penX += pathOffset - textWidth; } while (glyphsCount < numGlyphs && penX < pathLength) { glyph_t glyph = GET_GLYPH(text); if (IS_END_OF_STRING(glyph)) { break; } CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta)); prevRsbDelta = cachedGlyph->mRsbDelta; if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) { drawCachedGlyph(cachedGlyph, penX, hOffset, vOffset, measure, &position, &tangent); } penX += SkFixedToFloat(cachedGlyph->mAdvanceX); glyphsCount++; } }
void Font::render(const SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } static RenderGlyph gRenderGlyph[] = { &android::uirenderer::Font::drawCachedGlyph, &android::uirenderer::Font::drawCachedGlyphTransformed, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::measureCachedGlyph, &android::uirenderer::Font::measureCachedGlyph }; RenderGlyph render = gRenderGlyph[(mode << 1) + !mIdentityTransform]; text += start; int glyphsCount = 0; const SkPaint::Align align = paint->getTextAlign(); while (glyphsCount < numGlyphs) { glyph_t glyph = GET_GLYPH(text); // Reached the end of the string if (IS_END_OF_STRING(glyph)) { break; } CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); // If it's still not valid, we couldn't cache it, so we shouldn't // draw garbage; also skip empty glyphs (spaces) if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) { int penX = x + (int) roundf(positions[(glyphsCount << 1)]); int penY = y + (int) roundf(positions[(glyphsCount << 1) + 1]); (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions); } glyphsCount++; } }
void Font::precache(const SkPaint* paint, const char* text, int numGlyphs) { ATRACE_NAME("Precache Glyphs"); if (numGlyphs == 0 || text == NULL) { return; } int glyphsCount = 0; while (glyphsCount < numGlyphs) { glyph_t glyph = GET_GLYPH(text); // Reached the end of the string if (IS_END_OF_STRING(glyph)) { break; } CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph, true); glyphsCount++; } }
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } static RenderGlyph gRenderGlyph[] = { &android::uirenderer::Font::drawCachedGlyph, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::measureCachedGlyph }; RenderGlyph render = gRenderGlyph[mode]; text += start; int glyphsCount = 0; if (CC_LIKELY(positions == NULL)) { SkFixed prevRsbDelta = 0; float penX = x + 0.5f; int penY = y; while (glyphsCount < numGlyphs) { glyph_t glyph = GET_GLYPH(text); // Reached the end of the string if (IS_END_OF_STRING(glyph)) { break; } CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta)); prevRsbDelta = cachedGlyph->mRsbDelta; // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if (cachedGlyph->mIsValid) { (*this.*render)(cachedGlyph, (int) floorf(penX), penY, bitmap, bitmapW, bitmapH, bounds, positions); } penX += SkFixedToFloat(cachedGlyph->mAdvanceX); glyphsCount++; } } else { const SkPaint::Align align = paint->getTextAlign(); // This is for renderPosText() while (glyphsCount < numGlyphs) { glyph_t glyph = GET_GLYPH(text); // Reached the end of the string if (IS_END_OF_STRING(glyph)) { break; } CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if (cachedGlyph->mIsValid) { int penX = x + positions[(glyphsCount << 1)]; int penY = y + positions[(glyphsCount << 1) + 1]; switch (align) { case SkPaint::kRight_Align: penX -= SkFixedToFloat(cachedGlyph->mAdvanceX); penY -= SkFixedToFloat(cachedGlyph->mAdvanceY); break; case SkPaint::kCenter_Align: penX -= SkFixedToFloat(cachedGlyph->mAdvanceX >> 1); penY -= SkFixedToFloat(cachedGlyph->mAdvanceY >> 1); default: break; } (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions); } glyphsCount++; } }