Loading libs/hwui/FontRenderer.cpp +91 −18 Original line number Diff line number Diff line Loading @@ -62,6 +62,27 @@ void Font::invalidateTextureCache() { } } void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop; int width = (int) glyph->mBitmapWidth; int height = (int) glyph->mBitmapHeight; if(bounds->bottom > nPenY) { bounds->bottom = nPenY; } if(bounds->left > nPenX) { bounds->left = nPenX; } if(bounds->right < nPenX + width) { bounds->right = nPenX + width; } if(bounds->top < nPenY + height) { bounds->top = nPenY + height; } } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight; Loading @@ -88,22 +109,17 @@ void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y, uint32_t endX = glyph->mStartX + glyph->mBitmapWidth; uint32_t endY = glyph->mStartY + glyph->mBitmapHeight; if(nPenX < 0 || nPenY < 0) { LOGE("Cannot render into a bitmap, some of the glyph is below zero"); return; } if(nPenX + glyph->mBitmapWidth >= bitmapW || nPenY + glyph->mBitmapHeight >= bitmapH) { LOGE("Cannot render into a bitmap, dimentions too small"); return; } uint32_t cacheWidth = mState->getCacheWidth(); const uint8_t* cacheBuffer = mState->getTextTextureData(); uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; uint32_t cacheX = 0, cacheY = 0; int32_t bX = 0, bY = 0; for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) { for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) { if(bX < 0 || bY < 0 || bX >= (int32_t)bitmapW || bY >= (int32_t)bitmapH) { LOGE("Skipping invalid index"); continue; } uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; bitmap[bY * bitmapW + bX] = tempCol; } Loading @@ -127,7 +143,33 @@ Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) { } void Font::renderUTF(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) { int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { if(bitmap != NULL && bitmapW > 0 && bitmapH > 0) { renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap, bitmapW, bitmapH, NULL); } else { renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL); } } void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds) { if(bounds == NULL) { LOGE("No return rectangle provided to measure text"); return; } bounds->set(1e6, -1e6, -1e6, 1e6); renderUTF(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds); } void Font::renderUTF(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) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } Loading @@ -152,11 +194,16 @@ void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if (cachedGlyph->mIsValid) { if(bitmap != NULL) { drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); } else { switch(mode) { case FRAMEBUFFER: drawCachedGlyph(cachedGlyph, penX, penY); break; case BITMAP: drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); break; case MEASURE: measureCachedGlyph(cachedGlyph, penX, penY, bounds); break; } } Loading Loading @@ -569,6 +616,32 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) { precacheLatin(paint); } } FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) { Rect bounds; mCurrentFont->measureUTF(paint, text, startIndex, len, numGlyphs, &bounds); uint32_t paddedWidth = (uint32_t)(bounds.right - bounds.left) + 2*radius; uint32_t paddedHeight = (uint32_t)(bounds.top - bounds.bottom) + 2*radius; uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight]; for(uint32_t i = 0; i < paddedWidth * paddedHeight; i ++) { dataBuffer[i] = 0; } int penX = radius - bounds.left; int penY = radius - bounds.bottom; mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, penX, penY, dataBuffer, paddedWidth, paddedHeight); blurImage(dataBuffer, paddedWidth, paddedHeight, radius); DropShadow image; image.width = paddedWidth; image.height = paddedHeight; image.image = dataBuffer; image.penX = penX; image.penY = penY; return image; } void FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y) { Loading Loading @@ -598,11 +671,11 @@ void FontRenderer::computeGaussianWeights(float* weights, int32_t radius) { // and sigma varies with radius. // Based on some experimental radius values and sigma's // we approximately fit sigma = f(radius) as // sigma = radius * 0.4 + 0.6 // sigma = radius * 0.3 + 0.6 // The larger the radius gets, the more our gaussian blur // will resemble a box blur since with large sigma // the gaussian curve begins to lose its shape float sigma = 0.4f * (float)radius + 0.6f; float sigma = 0.3f * (float)radius + 0.6f; // Now compute the coefficints // We will store some redundant values to save some math during Loading libs/hwui/FontRenderer.h +29 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ public: /** * Renders the specified string of text. * If bitmap is specified, it will be used as the render target */ void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, Loading @@ -57,6 +58,20 @@ public: protected: friend class FontRenderer; enum RenderMode { FRAMEBUFFER, BITMAP, MEASURE, }; void renderUTF(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); void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds); struct CachedGlyphInfo { // Has the cache been invalidated? bool mIsValid; Loading Loading @@ -89,6 +104,7 @@ protected: CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_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 drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); Loading @@ -112,6 +128,19 @@ public: void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y); struct DropShadow { uint32_t width; uint32_t height; uint8_t* image; int32_t penX; int32_t penY; }; // After renderDropShadow returns, the called owns the memory in DropShadow.image // and is responsible for releasing it when it's done with it DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius); GLuint getTexture() { checkInit(); return mTextureId; Loading Loading
libs/hwui/FontRenderer.cpp +91 −18 Original line number Diff line number Diff line Loading @@ -62,6 +62,27 @@ void Font::invalidateTextureCache() { } } void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop; int width = (int) glyph->mBitmapWidth; int height = (int) glyph->mBitmapHeight; if(bounds->bottom > nPenY) { bounds->bottom = nPenY; } if(bounds->left > nPenX) { bounds->left = nPenX; } if(bounds->right < nPenX + width) { bounds->right = nPenX + width; } if(bounds->top < nPenY + height) { bounds->top = nPenY + height; } } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) { int nPenX = x + glyph->mBitmapLeft; int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight; Loading @@ -88,22 +109,17 @@ void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y, uint32_t endX = glyph->mStartX + glyph->mBitmapWidth; uint32_t endY = glyph->mStartY + glyph->mBitmapHeight; if(nPenX < 0 || nPenY < 0) { LOGE("Cannot render into a bitmap, some of the glyph is below zero"); return; } if(nPenX + glyph->mBitmapWidth >= bitmapW || nPenY + glyph->mBitmapHeight >= bitmapH) { LOGE("Cannot render into a bitmap, dimentions too small"); return; } uint32_t cacheWidth = mState->getCacheWidth(); const uint8_t* cacheBuffer = mState->getTextTextureData(); uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; uint32_t cacheX = 0, cacheY = 0; int32_t bX = 0, bY = 0; for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) { for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) { if(bX < 0 || bY < 0 || bX >= (int32_t)bitmapW || bY >= (int32_t)bitmapH) { LOGE("Skipping invalid index"); continue; } uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; bitmap[bY * bitmapW + bX] = tempCol; } Loading @@ -127,7 +143,33 @@ Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) { } void Font::renderUTF(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) { int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { if(bitmap != NULL && bitmapW > 0 && bitmapH > 0) { renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap, bitmapW, bitmapH, NULL); } else { renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL); } } void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds) { if(bounds == NULL) { LOGE("No return rectangle provided to measure text"); return; } bounds->set(1e6, -1e6, -1e6, 1e6); renderUTF(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds); } void Font::renderUTF(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) { if (numGlyphs == 0 || text == NULL || len == 0) { return; } Loading @@ -152,11 +194,16 @@ void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if (cachedGlyph->mIsValid) { if(bitmap != NULL) { drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); } else { switch(mode) { case FRAMEBUFFER: drawCachedGlyph(cachedGlyph, penX, penY); break; case BITMAP: drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); break; case MEASURE: measureCachedGlyph(cachedGlyph, penX, penY, bounds); break; } } Loading Loading @@ -569,6 +616,32 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) { precacheLatin(paint); } } FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) { Rect bounds; mCurrentFont->measureUTF(paint, text, startIndex, len, numGlyphs, &bounds); uint32_t paddedWidth = (uint32_t)(bounds.right - bounds.left) + 2*radius; uint32_t paddedHeight = (uint32_t)(bounds.top - bounds.bottom) + 2*radius; uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight]; for(uint32_t i = 0; i < paddedWidth * paddedHeight; i ++) { dataBuffer[i] = 0; } int penX = radius - bounds.left; int penY = radius - bounds.bottom; mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, penX, penY, dataBuffer, paddedWidth, paddedHeight); blurImage(dataBuffer, paddedWidth, paddedHeight, radius); DropShadow image; image.width = paddedWidth; image.height = paddedHeight; image.image = dataBuffer; image.penX = penX; image.penY = penY; return image; } void FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y) { Loading Loading @@ -598,11 +671,11 @@ void FontRenderer::computeGaussianWeights(float* weights, int32_t radius) { // and sigma varies with radius. // Based on some experimental radius values and sigma's // we approximately fit sigma = f(radius) as // sigma = radius * 0.4 + 0.6 // sigma = radius * 0.3 + 0.6 // The larger the radius gets, the more our gaussian blur // will resemble a box blur since with large sigma // the gaussian curve begins to lose its shape float sigma = 0.4f * (float)radius + 0.6f; float sigma = 0.3f * (float)radius + 0.6f; // Now compute the coefficints // We will store some redundant values to save some math during Loading
libs/hwui/FontRenderer.h +29 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ public: /** * Renders the specified string of text. * If bitmap is specified, it will be used as the render target */ void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len, int numGlyphs, int x, int y, Loading @@ -57,6 +58,20 @@ public: protected: friend class FontRenderer; enum RenderMode { FRAMEBUFFER, BITMAP, MEASURE, }; void renderUTF(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); void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, int numGlyphs, Rect *bounds); struct CachedGlyphInfo { // Has the cache been invalidated? bool mIsValid; Loading Loading @@ -89,6 +104,7 @@ protected: CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_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 drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); Loading @@ -112,6 +128,19 @@ public: void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y); struct DropShadow { uint32_t width; uint32_t height; uint8_t* image; int32_t penX; int32_t penY; }; // After renderDropShadow returns, the called owns the memory in DropShadow.image // and is responsible for releasing it when it's done with it DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius); GLuint getTexture() { checkInit(); return mTextureId; Loading