Loading core/jni/android_view_GLES20Canvas.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -585,10 +585,10 @@ static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count const jchar* glyphs = value->getGlyphs(); size_t glyphsCount = value->getGlyphsCount(); if (count < int(glyphsCount)) glyphsCount = count; int bytesCount = glyphsCount * sizeof(jchar); renderer->drawPosText((const char*) glyphs, bytesCount, count < int(glyphsCount) ? count : glyphsCount, positions, paint); renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint); } static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz, Loading docs/html/guide/topics/graphics/hardware-accel.jd +0 −5 Original line number Diff line number Diff line Loading @@ -283,8 +283,6 @@ changed.</li> <li>{@link android.graphics.Canvas#drawPicture drawPicture()}</li> <li>{@link android.graphics.Canvas#drawPosText drawPosText()}</li> <li>{@link android.graphics.Canvas#drawTextOnPath drawTextOnPath()}</li> <li>{@link android.graphics.Canvas#drawVertices drawVertices()}</li> Loading Loading @@ -318,9 +316,6 @@ changed.</li> <li>{@link android.graphics.Canvas#drawBitmapMesh drawBitmapMesh()}: colors array is ignored</li> <li>{@link android.graphics.Canvas#drawLines drawLines()}: anti-aliasing is not supported</li> <li>{@link android.graphics.Canvas#setDrawFilter setDrawFilter()}: can be set, but is ignored</li> </ul> Loading libs/hwui/FontRenderer.cpp +112 −50 Original line number Diff line number Diff line Loading @@ -94,7 +94,8 @@ void Font::invalidateTextureCache(CacheTextureLine *cacheLine) { } } void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds) { void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop; Loading @@ -115,7 +116,8 @@ void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds } } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) { void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight; Loading @@ -133,8 +135,8 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) { nPenX, nPenY - height, u1, v1, glyph->mCachedTextureLine->mCacheTexture); } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop; Loading Loading @@ -181,13 +183,19 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) { render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap, bitmapW, bitmapH, NULL); bitmapW, bitmapH, NULL, NULL); } else { render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL); 0, 0, NULL, NULL); } } void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, const float* positions) { render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL, positions); } void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds) { if (bounds == NULL) { Loading @@ -195,31 +203,38 @@ void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t le return; } bounds->set(1e6, -1e6, -1e6, 1e6); render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds); render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL); } #define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16) 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) { uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } int glyphsCount = 0; text += start; static RenderGlyph gRenderGlyph[] = { &android::uirenderer::Font::drawCachedGlyph, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::measureCachedGlyph }; RenderGlyph render = gRenderGlyph[mode]; if (positions == NULL) { SkFixed prevRsbDelta = 0; float penX = x; int penY = y; int glyphsLeft = 1; if (numGlyphs > 0) { glyphsLeft = numGlyphs; } SkFixed prevRsbDelta = 0; penX += 0.5f; text += start; while (glyphsLeft > 0) { while (glyphsCount < numGlyphs) { glyph_t glyph = GET_GLYPH(text); // Reached the end of the string Loading @@ -233,24 +248,50 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if (cachedGlyph->mIsValid) { switch(mode) { case FRAMEBUFFER: drawCachedGlyph(cachedGlyph, (int) floorf(penX), penY); (*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; case BITMAP: drawCachedGlyph(cachedGlyph, (int) floorf(penX), penY, bitmap, bitmapW, bitmapH); } 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 MEASURE: measureCachedGlyph(cachedGlyph, (int) floorf(penX), penY, bounds); case SkPaint::kCenter_Align: penX -= SkFixedToFloat(cachedGlyph->mAdvanceX >> 1); penY -= SkFixedToFloat(cachedGlyph->mAdvanceY >> 1); default: break; } } penX += SkFixedToFloat(cachedGlyph->mAdvanceX); (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions); } // If we were given a specific number of glyphs, decrement if (numGlyphs > 0) { glyphsLeft--; glyphsCount++; } } } Loading Loading @@ -866,21 +907,15 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch return image; } bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) { void FontRenderer::initRender(const Rect* clip, Rect* bounds) { checkInit(); if (!mCurrentFont) { ALOGE("No font set"); return false; } mDrawn = false; mBounds = bounds; mClip = clip; } mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y); void FontRenderer::finishRender() { mBounds = NULL; mClip = NULL; Loading @@ -888,6 +923,33 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text issueDrawCommand(); mCurrentQuadIndex = 0; } } bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) { if (!mCurrentFont) { ALOGE("No font set"); return false; } initRender(clip, bounds); mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y); finishRender(); return mDrawn; } bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds) { if (!mCurrentFont) { ALOGE("No font set"); return false; } initRender(clip, bounds); mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions); finishRender(); return mDrawn; } Loading libs/hwui/FontRenderer.h +24 −6 Original line number Diff line number Diff line Loading @@ -151,6 +151,10 @@ public: void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, const float* positions); /** * Creates a new font associated with the specified font state. */ Loading @@ -160,6 +164,8 @@ public: protected: friend class FontRenderer; typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, uint32_t, uint32_t, Rect*, const float*); enum RenderMode { FRAMEBUFFER, Loading @@ -169,7 +175,7 @@ protected: void 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); uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds); Loading @@ -184,10 +190,16 @@ protected: CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph); void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph); void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds); void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y); void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); Loading Loading @@ -226,8 +238,12 @@ public: } void setFont(SkPaint* paint, uint32_t fontId, float fontSize); // bounds is an out parameter bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds); // bounds is an out parameter bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); struct DropShadow { DropShadow() { }; Loading Loading @@ -297,6 +313,8 @@ protected: void initVertexArrayBuffers(); void checkInit(); void initRender(const Rect* clip, Rect* bounds); void finishRender(); String16 mLatinPrecache; void precacheLatin(SkPaint* paint); Loading libs/hwui/OpenGLRenderer.cpp +66 −12 Original line number Diff line number Diff line Loading @@ -2084,23 +2084,81 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint) { if (text == NULL || count == 0) { if (text == NULL || count == 0 || mSnapshot->isIgnored() || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { return; } if (mSnapshot->isIgnored()) return; // TODO: implement properly drawText(text, bytesCount, count, 0, 0, paint); // NOTE: Skia does not support perspective transform on drawPosText yet if (!mSnapshot->transform->isSimple()) { return; } float x = 0.0f; float y = 0.0f; const bool pureTranslate = mSnapshot->transform->isPureTranslate(); if (pureTranslate) { x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f); y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); } FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint); fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize()); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); // Pick the appropriate texture filtering bool linearFilter = mSnapshot->transform->changesBounds(); if (pureTranslate && !linearFilter) { linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f; } mCaches.activeTexture(0); setupDraw(); setupDrawDirtyRegionsDisabled(); setupDrawWithTexture(true); setupDrawAlpha8Color(paint->getColor(), alpha); setupDrawColorFilter(); setupDrawShader(); setupDrawBlending(true, mode); setupDrawProgram(); setupDrawModelView(x, y, x, y, pureTranslate, true); setupDrawTexture(fontRenderer.getTexture(linearFilter)); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderUniforms(pureTranslate); const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip(); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); #if RENDER_LAYERS_AS_REGIONS bool hasActiveLayer = hasLayer(); #else bool hasActiveLayer = false; #endif if (fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, positions, hasActiveLayer ? &bounds : NULL)) { #if RENDER_LAYERS_AS_REGIONS if (hasActiveLayer) { if (!pureTranslate) { mSnapshot->transform->mapRect(bounds); } dirtyLayerUnchecked(bounds, getRegion()); } #endif } } void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint, float length) { if (text == NULL || count == 0) { if (text == NULL || count == 0 || mSnapshot->isIgnored() || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { return; } if (mSnapshot->isIgnored()) return; // NOTE: AA and glyph id encoding are set in DisplayListRenderer.cpp switch (paint->getTextAlign()) { case SkPaint::kCenter_Align: Loading Loading @@ -2177,10 +2235,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); } if (paint->getAlpha() == 0 && paint->getXfermode() == NULL) { return; } // Pick the appropriate texture filtering bool linearFilter = mSnapshot->transform->changesBounds(); if (pureTranslate && !linearFilter) { Loading Loading
core/jni/android_view_GLES20Canvas.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -585,10 +585,10 @@ static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count const jchar* glyphs = value->getGlyphs(); size_t glyphsCount = value->getGlyphsCount(); if (count < int(glyphsCount)) glyphsCount = count; int bytesCount = glyphsCount * sizeof(jchar); renderer->drawPosText((const char*) glyphs, bytesCount, count < int(glyphsCount) ? count : glyphsCount, positions, paint); renderer->drawPosText((const char*) glyphs, bytesCount, glyphsCount, positions, paint); } static void android_view_GLES20Canvas_drawPosTextArray(JNIEnv* env, jobject clazz, Loading
docs/html/guide/topics/graphics/hardware-accel.jd +0 −5 Original line number Diff line number Diff line Loading @@ -283,8 +283,6 @@ changed.</li> <li>{@link android.graphics.Canvas#drawPicture drawPicture()}</li> <li>{@link android.graphics.Canvas#drawPosText drawPosText()}</li> <li>{@link android.graphics.Canvas#drawTextOnPath drawTextOnPath()}</li> <li>{@link android.graphics.Canvas#drawVertices drawVertices()}</li> Loading Loading @@ -318,9 +316,6 @@ changed.</li> <li>{@link android.graphics.Canvas#drawBitmapMesh drawBitmapMesh()}: colors array is ignored</li> <li>{@link android.graphics.Canvas#drawLines drawLines()}: anti-aliasing is not supported</li> <li>{@link android.graphics.Canvas#setDrawFilter setDrawFilter()}: can be set, but is ignored</li> </ul> Loading
libs/hwui/FontRenderer.cpp +112 −50 Original line number Diff line number Diff line Loading @@ -94,7 +94,8 @@ void Font::invalidateTextureCache(CacheTextureLine *cacheLine) { } } void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds) { void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop; Loading @@ -115,7 +116,8 @@ void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds } } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) { void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight; Loading @@ -133,8 +135,8 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) { nPenX, nPenY - height, u1, v1, glyph->mCachedTextureLine->mCacheTexture); } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop; Loading Loading @@ -181,13 +183,19 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) { render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap, bitmapW, bitmapH, NULL); bitmapW, bitmapH, NULL, NULL); } else { render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL); 0, 0, NULL, NULL); } } void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, const float* positions) { render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL, positions); } void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds) { if (bounds == NULL) { Loading @@ -195,31 +203,38 @@ void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t le return; } bounds->set(1e6, -1e6, -1e6, 1e6); render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds); render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL); } #define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16) 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) { uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } int glyphsCount = 0; text += start; static RenderGlyph gRenderGlyph[] = { &android::uirenderer::Font::drawCachedGlyph, &android::uirenderer::Font::drawCachedGlyphBitmap, &android::uirenderer::Font::measureCachedGlyph }; RenderGlyph render = gRenderGlyph[mode]; if (positions == NULL) { SkFixed prevRsbDelta = 0; float penX = x; int penY = y; int glyphsLeft = 1; if (numGlyphs > 0) { glyphsLeft = numGlyphs; } SkFixed prevRsbDelta = 0; penX += 0.5f; text += start; while (glyphsLeft > 0) { while (glyphsCount < numGlyphs) { glyph_t glyph = GET_GLYPH(text); // Reached the end of the string Loading @@ -233,24 +248,50 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if (cachedGlyph->mIsValid) { switch(mode) { case FRAMEBUFFER: drawCachedGlyph(cachedGlyph, (int) floorf(penX), penY); (*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; case BITMAP: drawCachedGlyph(cachedGlyph, (int) floorf(penX), penY, bitmap, bitmapW, bitmapH); } 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 MEASURE: measureCachedGlyph(cachedGlyph, (int) floorf(penX), penY, bounds); case SkPaint::kCenter_Align: penX -= SkFixedToFloat(cachedGlyph->mAdvanceX >> 1); penY -= SkFixedToFloat(cachedGlyph->mAdvanceY >> 1); default: break; } } penX += SkFixedToFloat(cachedGlyph->mAdvanceX); (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions); } // If we were given a specific number of glyphs, decrement if (numGlyphs > 0) { glyphsLeft--; glyphsCount++; } } } Loading Loading @@ -866,21 +907,15 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch return image; } bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) { void FontRenderer::initRender(const Rect* clip, Rect* bounds) { checkInit(); if (!mCurrentFont) { ALOGE("No font set"); return false; } mDrawn = false; mBounds = bounds; mClip = clip; } mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y); void FontRenderer::finishRender() { mBounds = NULL; mClip = NULL; Loading @@ -888,6 +923,33 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text issueDrawCommand(); mCurrentQuadIndex = 0; } } bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) { if (!mCurrentFont) { ALOGE("No font set"); return false; } initRender(clip, bounds); mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y); finishRender(); return mDrawn; } bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds) { if (!mCurrentFont) { ALOGE("No font set"); return false; } initRender(clip, bounds); mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions); finishRender(); return mDrawn; } Loading
libs/hwui/FontRenderer.h +24 −6 Original line number Diff line number Diff line Loading @@ -151,6 +151,10 @@ public: void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, const float* positions); /** * Creates a new font associated with the specified font state. */ Loading @@ -160,6 +164,8 @@ public: protected: friend class FontRenderer; typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, uint32_t, uint32_t, Rect*, const float*); enum RenderMode { FRAMEBUFFER, Loading @@ -169,7 +175,7 @@ protected: void 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); uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds); Loading @@ -184,10 +190,16 @@ protected: CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph); void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph); void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds); void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y); void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); Loading Loading @@ -226,8 +238,12 @@ public: } void setFont(SkPaint* paint, uint32_t fontId, float fontSize); // bounds is an out parameter bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds); // bounds is an out parameter bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); struct DropShadow { DropShadow() { }; Loading Loading @@ -297,6 +313,8 @@ protected: void initVertexArrayBuffers(); void checkInit(); void initRender(const Rect* clip, Rect* bounds); void finishRender(); String16 mLatinPrecache; void precacheLatin(SkPaint* paint); Loading
libs/hwui/OpenGLRenderer.cpp +66 −12 Original line number Diff line number Diff line Loading @@ -2084,23 +2084,81 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint) { if (text == NULL || count == 0) { if (text == NULL || count == 0 || mSnapshot->isIgnored() || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { return; } if (mSnapshot->isIgnored()) return; // TODO: implement properly drawText(text, bytesCount, count, 0, 0, paint); // NOTE: Skia does not support perspective transform on drawPosText yet if (!mSnapshot->transform->isSimple()) { return; } float x = 0.0f; float y = 0.0f; const bool pureTranslate = mSnapshot->transform->isPureTranslate(); if (pureTranslate) { x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f); y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); } FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(paint); fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize()); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); // Pick the appropriate texture filtering bool linearFilter = mSnapshot->transform->changesBounds(); if (pureTranslate && !linearFilter) { linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f; } mCaches.activeTexture(0); setupDraw(); setupDrawDirtyRegionsDisabled(); setupDrawWithTexture(true); setupDrawAlpha8Color(paint->getColor(), alpha); setupDrawColorFilter(); setupDrawShader(); setupDrawBlending(true, mode); setupDrawProgram(); setupDrawModelView(x, y, x, y, pureTranslate, true); setupDrawTexture(fontRenderer.getTexture(linearFilter)); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderUniforms(pureTranslate); const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip(); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); #if RENDER_LAYERS_AS_REGIONS bool hasActiveLayer = hasLayer(); #else bool hasActiveLayer = false; #endif if (fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, positions, hasActiveLayer ? &bounds : NULL)) { #if RENDER_LAYERS_AS_REGIONS if (hasActiveLayer) { if (!pureTranslate) { mSnapshot->transform->mapRect(bounds); } dirtyLayerUnchecked(bounds, getRegion()); } #endif } } void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint, float length) { if (text == NULL || count == 0) { if (text == NULL || count == 0 || mSnapshot->isIgnored() || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { return; } if (mSnapshot->isIgnored()) return; // NOTE: AA and glyph id encoding are set in DisplayListRenderer.cpp switch (paint->getTextAlign()) { case SkPaint::kCenter_Align: Loading Loading @@ -2177,10 +2235,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); } if (paint->getAlpha() == 0 && paint->getXfermode() == NULL) { return; } // Pick the appropriate texture filtering bool linearFilter = mSnapshot->transform->changesBounds(); if (pureTranslate && !linearFilter) { Loading