diff options
author | Romain Guy <romainguy@google.com> | 2013-01-08 17:38:15 -0800 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2013-01-08 17:38:15 -0800 |
commit | 19d4f1806a953b87435a2bb6fd8e738424e94003 (patch) | |
tree | ab561da75ff49699432723e2904a89d5cda534e2 /libs | |
parent | 1a9853fef502ef4dac48476b8b588650ae5db4ce (diff) | |
parent | c88c60bed1fdf5b84cc16905c8743453203c19a5 (diff) | |
download | frameworks_base-19d4f1806a953b87435a2bb6fd8e738424e94003.zip frameworks_base-19d4f1806a953b87435a2bb6fd8e738424e94003.tar.gz frameworks_base-19d4f1806a953b87435a2bb6fd8e738424e94003.tar.bz2 |
resolved conflicts for merge of c88c60be to master-chromium
Change-Id: I3b4b42443312068e942aa779dfdc928afa7569fd
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 78 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.h | 11 | ||||
-rw-r--r-- | libs/hwui/LayerCache.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/LayerCache.h | 28 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 33 | ||||
-rw-r--r-- | libs/hwui/PathCache.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/font/Font.cpp | 196 | ||||
-rw-r--r-- | libs/hwui/font/Font.h | 78 | ||||
-rw-r--r-- | libs/hwui/font/FontUtil.h | 4 |
10 files changed, 216 insertions, 229 deletions
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 747856c..06574cd 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -1775,7 +1775,7 @@ status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, i paint->setAntiAlias(true); SkPaint* addedPaint = addPaint(paint); FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint); - fontRenderer.precache(addedPaint, text, count); + fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform); return DrawGlInfo::kStatusDone; } @@ -1789,7 +1789,7 @@ status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int paint->setAntiAlias(true); SkPaint* addedPaint = addPaint(paint); FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint); - fontRenderer.precache(addedPaint, text, count); + fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform); return DrawGlInfo::kStatusDone; } @@ -1823,7 +1823,7 @@ status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int cou SkPaint* addedPaint = addPaint(paint); if (!reject) { FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint); - fontRenderer.precache(addedPaint, text, count); + fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform); } addFloat(length); addSkip(location); diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 2a09ced..61107c6 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -37,7 +37,9 @@ namespace uirenderer { static bool sLogFontRendererCreate = true; -FontRenderer::FontRenderer() { +FontRenderer::FontRenderer() : + mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) { + if (sLogFontRendererCreate) { INIT_LOGD("Creating FontRenderer"); } @@ -108,10 +110,11 @@ FontRenderer::~FontRenderer() { delete[] mTextMesh; } - Vector<Font*> fontsToDereference = mActiveFonts; - for (uint32_t i = 0; i < fontsToDereference.size(); i++) { - delete fontsToDereference[i]; + LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); + while (it.next()) { + delete it.value(); } + mActiveFonts.clear(); } void FontRenderer::flushAllAndInvalidate() { @@ -119,8 +122,9 @@ void FontRenderer::flushAllAndInvalidate() { issueDrawCommand(); } - for (uint32_t i = 0; i < mActiveFonts.size(); i++) { - mActiveFonts[i]->invalidateTextureCache(); + LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); + while (it.next()) { + it.value()->invalidateTextureCache(); } for (uint32_t i = 0; i < mCacheTextures.size(); i++) { @@ -147,8 +151,9 @@ void FontRenderer::flushLargeCaches() { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture->getTexture()) { cacheTexture->init(); - for (uint32_t j = 0; j < mActiveFonts.size(); j++) { - mActiveFonts[j]->invalidateTextureCache(cacheTexture); + LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); + while (it.next()) { + it.value()->invalidateTextureCache(cacheTexture); } cacheTexture->releaseTexture(); } @@ -481,22 +486,8 @@ void FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, } } -void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) { - int flags = 0; - if (paint->isFakeBoldText()) { - flags |= Font::kFakeBold; - } - - const float skewX = paint->getTextSkewX(); - uint32_t italicStyle = *(uint32_t*) &skewX; - const float scaleXFloat = paint->getTextScaleX(); - uint32_t scaleX = *(uint32_t*) &scaleXFloat; - SkPaint::Style style = paint->getStyle(); - const float strokeWidthFloat = paint->getStrokeWidth(); - uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat; - mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle, - scaleX, style, strokeWidth); - +void FontRenderer::setFont(SkPaint* paint, const mat4& matrix) { + mCurrentFont = Font::create(this, paint, matrix); } FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text, @@ -562,39 +553,11 @@ void FontRenderer::finishRender() { } } -void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs) { - int flags = 0; - if (paint->isFakeBoldText()) { - flags |= Font::kFakeBold; - } - const float skewX = paint->getTextSkewX(); - uint32_t italicStyle = *(uint32_t*) &skewX; - const float scaleXFloat = paint->getTextScaleX(); - uint32_t scaleX = *(uint32_t*) &scaleXFloat; - SkPaint::Style style = paint->getStyle(); - const float strokeWidthFloat = paint->getStrokeWidth(); - uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat; - float fontSize = paint->getTextSize(); - Font* font = Font::create(this, SkTypeface::UniqueID(paint->getTypeface()), - fontSize, flags, italicStyle, scaleX, style, strokeWidth); - +void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix) { + Font* font = Font::create(this, paint, matrix); font->precache(paint, text, numGlyphs); } -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) { @@ -626,12 +589,7 @@ bool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char } void FontRenderer::removeFont(const Font* font) { - for (uint32_t ct = 0; ct < mActiveFonts.size(); ct++) { - if (mActiveFonts[ct] == font) { - mActiveFonts.removeAt(ct); - break; - } - } + mActiveFonts.remove(font->getDescription()); if (mCurrentFont == font) { mCurrentFont = NULL; diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index 09a3c25..3964bca 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -17,6 +17,7 @@ #ifndef ANDROID_HWUI_FONT_RENDERER_H #define ANDROID_HWUI_FONT_RENDERER_H +#include <utils/LruCache.h> #include <utils/Vector.h> #include <SkPaint.h> @@ -27,6 +28,7 @@ #include "font/CacheTexture.h" #include "font/CachedGlyphInfo.h" #include "font/Font.h" +#include "Matrix.h" #include "Properties.h" namespace android { @@ -47,14 +49,11 @@ public: mGammaTable = gammaTable; } - void setFont(SkPaint* paint, uint32_t fontId, float fontSize); + void setFont(SkPaint* paint, const mat4& matrix); - void precache(SkPaint* paint, const char* text, int numGlyphs); + void precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix); // 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); // bounds is an out parameter @@ -153,7 +152,7 @@ private: Vector<CacheTexture*> mCacheTextures; Font* mCurrentFont; - Vector<Font*> mActiveFonts; + LruCache<Font::FontDescription, Font*> mActiveFonts; CacheTexture* mCurrentCacheTexture; diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index ce74cee..cfc5b04 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -67,6 +67,14 @@ void LayerCache::setMaxSize(uint32_t maxSize) { // Caching /////////////////////////////////////////////////////////////////////////////// +int LayerCache::LayerEntry::compare(const LayerCache::LayerEntry& lhs, + const LayerCache::LayerEntry& rhs) { + int deltaInt = int(lhs.mWidth) - int(rhs.mWidth); + if (deltaInt != 0) return deltaInt; + + return int(lhs.mHeight) - int(rhs.mHeight); +} + void LayerCache::deleteLayer(Layer* layer) { if (layer) { LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(), diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index fd698e2..fc2cd91 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -102,9 +102,6 @@ public: */ void dump(); -private: - void deleteLayer(Layer* layer); - struct LayerEntry { LayerEntry(): mLayer(NULL), mWidth(0), mHeight(0) { @@ -119,15 +116,14 @@ private: mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) { } - bool operator<(const LayerEntry& rhs) const { - if (mWidth == rhs.mWidth) { - return mHeight < rhs.mHeight; - } - return mWidth < rhs.mWidth; + static int compare(const LayerEntry& lhs, const LayerEntry& rhs); + + bool operator==(const LayerEntry& other) const { + return compare(*this, other) == 0; } - bool operator==(const LayerEntry& rhs) const { - return mWidth == rhs.mWidth && mHeight == rhs.mHeight; + bool operator!=(const LayerEntry& other) const { + return compare(*this, other) != 0; } Layer* mLayer; @@ -135,12 +131,24 @@ private: uint32_t mHeight; }; // struct LayerEntry +private: + void deleteLayer(Layer* layer); + SortedList<LayerEntry> mCache; uint32_t mSize; uint32_t mMaxSize; }; // class LayerCache +inline int strictly_order_type(const LayerCache::LayerEntry& lhs, + const LayerCache::LayerEntry& rhs) { + return LayerCache::LayerEntry::compare(lhs, rhs) < 0; +} + +inline int compare_type(const LayerCache::LayerEntry& lhs, const LayerCache::LayerEntry& rhs) { + return LayerCache::LayerEntry::compare(lhs, rhs); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8756805..8cda729 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1716,7 +1716,6 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes return DrawGlInfo::kStatusDone; } - // TODO: We should compute the bounding box when recording the display list float left = FLT_MAX; float top = FLT_MAX; float right = FLT_MIN; @@ -1754,7 +1753,6 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes TextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1); TextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2); - // TODO: This could be optimized to avoid unnecessary ops left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx]))); top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy]))); right = fmaxf(right, fmaxf(vertices[ax], fmaxf(vertices[bx], vertices[cx]))); @@ -2453,7 +2451,8 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto } // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180) - if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || p->getStrokeCap() != SkPaint::kButt_Cap || useCenter) { + if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || + p->getStrokeCap() != SkPaint::kButt_Cap || useCenter) { mCaches.activeTexture(0); const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top, startAngle, sweepAngle, useCenter, p); @@ -2577,16 +2576,15 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count } FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); - fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), - paint->getTextSize()); + fontRenderer.setFont(paint, *mSnapshot->transform); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); if (CC_UNLIKELY(mHasShadow)) { - drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode, - 0.0f, 0.0f); + drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, + alpha, mode, 0.0f, 0.0f); } // Pick the appropriate texture filtering @@ -2655,6 +2653,14 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, return DrawGlInfo::kStatusDone; } +#if DEBUG_GLYPHS + ALOGD("OpenGLRenderer drawText() with FontID=%d", + SkTypeface::UniqueID(paint->getTypeface())); +#endif + + FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); + fontRenderer.setFont(paint, *mSnapshot->transform); + const float oldX = x; const float oldY = y; const bool pureTranslate = mSnapshot->transform->isPureTranslate(); @@ -2663,15 +2669,6 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); } -#if DEBUG_GLYPHS - ALOGD("OpenGLRenderer drawText() with FontID=%d", - SkTypeface::UniqueID(paint->getTypeface())); -#endif - - FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); - fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), - paint->getTextSize()); - int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); @@ -2744,8 +2741,7 @@ status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int co } FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint); - fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()), - paint->getTextSize()); + fontRenderer.setFont(paint, *mSnapshot->transform); int alpha; SkXfermode::Mode mode; @@ -2789,7 +2785,6 @@ status_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { mCaches.activeTexture(0); - // TODO: Perform early clip test before we rasterize the path const PathTexture* texture = mCaches.pathCache.get(path, paint); if (!texture) return DrawGlInfo::kStatusDone; const AutoTexture autoCleanup(texture); diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 03ddf59..4f682ed 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -93,9 +93,6 @@ PathTexture* PathCache::get(SkPath* path, SkPaint* paint) { PathCacheEntry entry(path, paint); PathTexture* texture = mCache.get(entry); - float left, top, offset; - uint32_t width, height; - if (!texture) { texture = addTexture(entry, path, paint); } else if (path->getGenerationID() != texture->generation) { diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp index 9068b8a..34afe97 100644 --- a/libs/hwui/font/Font.cpp +++ b/libs/hwui/font/Font.cpp @@ -18,7 +18,8 @@ #include <cutils/compiler.h> -#include <SkGlyph.h> +#include <utils/JenkinsHash.h> + #include <SkUtils.h> #include "Debug.h" @@ -34,14 +35,22 @@ namespace uirenderer { // Font /////////////////////////////////////////////////////////////////////////////// -Font::Font(FontRenderer* state, uint32_t fontId, float fontSize, - int flags, uint32_t italicStyle, uint32_t scaleX, - SkPaint::Style style, uint32_t strokeWidth) : - mState(state), mFontId(fontId), mFontSize(fontSize), - mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX), - mStyle(style), mStrokeWidth(mStrokeWidth) { +Font::Font(FontRenderer* state, const Font::FontDescription& desc) : + mState(state), mDescription(desc) { } +Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix) { + mFontId = SkTypeface::UniqueID(paint->getTypeface()); + mFontSize = paint->getTextSize(); + mFlags = 0; + if (paint->isFakeBoldText()) { + mFlags |= Font::kFakeBold; + } + mItalicStyle = paint->getTextSkewX(); + mScaleX = paint->getTextScaleX(); + mStyle = paint->getStyle(); + mStrokeWidth = paint->getStrokeWidth(); +} Font::~Font() { mState->removeFont(this); @@ -51,6 +60,43 @@ Font::~Font() { } } +hash_t Font::FontDescription::hash() const { + uint32_t hash = JenkinsHashMix(0, mFontId); + hash = JenkinsHashMix(hash, android::hash_type(mFontSize)); + hash = JenkinsHashMix(hash, android::hash_type(mFlags)); + hash = JenkinsHashMix(hash, android::hash_type(mItalicStyle)); + hash = JenkinsHashMix(hash, android::hash_type(mScaleX)); + hash = JenkinsHashMix(hash, android::hash_type(mStyle)); + hash = JenkinsHashMix(hash, android::hash_type(mStrokeWidth)); + return JenkinsHashWhiten(hash); +} + +int Font::FontDescription::compare(const Font::FontDescription& lhs, + const Font::FontDescription& rhs) { + int deltaInt = int(lhs.mFontId) - int(rhs.mFontId); + if (deltaInt != 0) return deltaInt; + + if (lhs.mFontSize < rhs.mFontSize) return -1; + if (lhs.mFontSize > rhs.mFontSize) return +1; + + if (lhs.mItalicStyle < rhs.mItalicStyle) return -1; + if (lhs.mItalicStyle > rhs.mItalicStyle) return +1; + + deltaInt = int(lhs.mFlags) - int(rhs.mFlags); + if (deltaInt != 0) return deltaInt; + + if (lhs.mScaleX < rhs.mScaleX) return -1; + if (lhs.mScaleX > rhs.mScaleX) return +1; + + deltaInt = int(lhs.mStyle) - int(rhs.mStyle); + if (deltaInt != 0) return deltaInt; + + if (lhs.mStrokeWidth < rhs.mStrokeWidth) return -1; + if (lhs.mStrokeWidth > rhs.mStrokeWidth) return +1; + + return 0; +} + void Font::invalidateTextureCache(CacheTexture* cacheTexture) { for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) { CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i); @@ -84,17 +130,17 @@ void Font::measureCachedGlyph(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; + float nPenX = x + glyph->mBitmapLeft; + float nPenY = y + (glyph->mBitmapTop + glyph->mBitmapHeight); + + float width = (float) glyph->mBitmapWidth; + float height = (float) glyph->mBitmapHeight; float u1 = glyph->mBitmapMinU; float u2 = glyph->mBitmapMaxU; float v1 = glyph->mBitmapMinV; float v2 = glyph->mBitmapMaxV; - int width = (int) glyph->mBitmapWidth; - int height = (int) glyph->mBitmapHeight; - mState->appendMeshQuad(nPenX, nPenY, u1, v2, nPenX + width, nPenY, u2, v2, nPenX + width, nPenY - height, u2, v1, @@ -137,7 +183,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset += glyph->mBitmapTop + height; SkPoint destination[4]; - measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent); + measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent); // Move along the tangent and offset by the normal destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset, @@ -177,24 +223,13 @@ CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool pre // Is the glyph still in texture cache? if (!cachedGlyph->mIsValid) { - const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit); + const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit, NULL); updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching); } return cachedGlyph; } -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, NULL); - } else { - render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, 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, @@ -299,71 +334,40 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len 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; + const SkPaint::Align align = paint->getTextAlign(); - // 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); + while (glyphsCount < numGlyphs) { + glyph_t glyph = GET_GLYPH(text); - glyphsCount++; + // Reached the end of the string + if (IS_END_OF_STRING(glyph)) { + break; } - } 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); - 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); + // 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; } - glyphsCount++; + (*this.*render)(cachedGlyph, penX, penY, + bitmap, bitmapW, bitmapH, bounds, positions); } + + glyphsCount++; } } @@ -380,7 +384,7 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp uint32_t startY = 0; // Get the bitmap for the glyph - paint->findImage(skiaGlyph); + paint->findImage(skiaGlyph, NULL); mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching); if (!glyph->mIsValid) { @@ -410,7 +414,7 @@ CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching CachedGlyphInfo* newGlyph = new CachedGlyphInfo(); mCachedGlyphs.add(glyph, newGlyph); - const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph); + const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph, NULL); newGlyph->mGlyphIndex = skiaGlyph.fID; newGlyph->mIsValid = false; @@ -419,24 +423,16 @@ CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching return newGlyph; } -Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize, - int flags, uint32_t italicStyle, uint32_t scaleX, - SkPaint::Style style, uint32_t strokeWidth) { - Vector<Font*> &activeFonts = state->mActiveFonts; - - for (uint32_t i = 0; i < activeFonts.size(); i++) { - Font* font = activeFonts[i]; - if (font->mFontId == fontId && font->mFontSize == fontSize && - font->mFlags == flags && font->mItalicStyle == italicStyle && - font->mScaleX == scaleX && font->mStyle == style && - (style == SkPaint::kFill_Style || font->mStrokeWidth == strokeWidth)) { - return font; - } +Font* Font::create(FontRenderer* state, const SkPaint* paint, const mat4& matrix) { + FontDescription description(paint, matrix); + Font* font = state->mActiveFonts.get(description); + + if (font) { + return font; } - Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle, - scaleX, style, strokeWidth); - activeFonts.push(newFont); + Font* newFont = new Font(state, description); + state->mActiveFonts.put(description, newFont); return newFont; } diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h index 7cab31e..6ddf162 100644 --- a/libs/hwui/font/Font.h +++ b/libs/hwui/font/Font.h @@ -25,6 +25,7 @@ #include "CachedGlyphInfo.h" #include "../Rect.h" +#include "../Matrix.h" namespace android { namespace uirenderer { @@ -45,31 +46,52 @@ public: kFakeBold = 1 }; - ~Font(); + struct FontDescription { + FontDescription(const SkPaint* paint, const mat4& matrix); - /** - * Renders the specified string of text. - * If bitmap is specified, it will be used as the render target - */ - 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); + static int compare(const FontDescription& lhs, const FontDescription& rhs); - void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, + hash_t hash() const; + + bool operator==(const FontDescription& other) const { + return compare(*this, other) == 0; + } + + bool operator!=(const FontDescription& other) const { + return compare(*this, other) != 0; + } + + SkFontID mFontId; + float mFontSize; + int mFlags; + float mItalicStyle; + float mScaleX; + uint8_t mStyle; + float mStrokeWidth; + }; + + ~Font(); + + void render(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, const float* positions); - void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, + void render(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset); + const Font::FontDescription& getDescription() const { + return mDescription; + } + /** * Creates a new font associated with the specified font state. */ - static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, - int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, - uint32_t strokeWidth); + static Font* create(FontRenderer* state, const SkPaint* paint, const mat4& matrix); private: friend class FontRenderer; + + Font(FontRenderer* state, const Font::FontDescription& desc); + typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, uint32_t, uint32_t, Rect*, const float*); @@ -88,12 +110,6 @@ private: void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds, const float* positions); - Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, - uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); - - // Cache of glyphs - DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; - void invalidateTextureCache(CacheTexture* cacheTexture = NULL); CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching); @@ -115,15 +131,25 @@ private: CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false); FontRenderer* mState; - uint32_t mFontId; - float mFontSize; - int mFlags; - uint32_t mItalicStyle; - uint32_t mScaleX; - SkPaint::Style mStyle; - uint32_t mStrokeWidth; + FontDescription mDescription; + + // Cache of glyphs + DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; }; +inline int strictly_order_type(const Font::FontDescription& lhs, + const Font::FontDescription& rhs) { + return Font::FontDescription::compare(lhs, rhs) < 0; +} + +inline int compare_type(const Font::FontDescription& lhs, const Font::FontDescription& rhs) { + return Font::FontDescription::compare(lhs, rhs); +} + +inline hash_t hash_type(const Font::FontDescription& entry) { + return entry.hash(); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/font/FontUtil.h b/libs/hwui/font/FontUtil.h index 12247ba..4f9c46b 100644 --- a/libs/hwui/font/FontUtil.h +++ b/libs/hwui/font/FontUtil.h @@ -37,7 +37,7 @@ #if RENDER_TEXT_AS_GLYPHS typedef uint16_t glyph_t; #define TO_GLYPH(g) g - #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph) + #define GET_METRICS(paint, glyph, matrix) paint->getGlyphMetrics(glyph, matrix) #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text) #define IS_END_OF_STRING(glyph) false @@ -50,7 +50,7 @@ #else typedef SkUnichar glyph_t; #define TO_GLYPH(g) ((SkUnichar) g) - #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph) + #define GET_METRICS(paint, glyph, matrix) paint->getUnicharMetrics(glyph, matrix) #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text) #define IS_END_OF_STRING(glyph) glyph < 0 #endif |