diff options
author | Romain Guy <romainguy@google.com> | 2011-06-01 14:52:00 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2011-06-01 14:55:42 -0700 |
commit | 726aeba80ffc6778a9bc3e0ee957b8d644183505 (patch) | |
tree | 2a270831f12cfa6dd69a07e9068c76c3b737754e /libs/hwui | |
parent | f09ef51889f75289b041f9e9f949b7b82ed5b686 (diff) | |
download | frameworks_base-726aeba80ffc6778a9bc3e0ee957b8d644183505.zip frameworks_base-726aeba80ffc6778a9bc3e0ee957b8d644183505.tar.gz frameworks_base-726aeba80ffc6778a9bc3e0ee957b8d644183505.tar.bz2 |
Add support to OpenGLRendere to draw BiDi text.
Bug #4350336
Change-Id: I1cf31693f7ca9653fa3a41b5b91c27ef288d680f
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 43 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.h | 61 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 2 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 3 | ||||
-rw-r--r-- | libs/hwui/TextDropShadowCache.h | 1 |
7 files changed, 84 insertions, 49 deletions
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index f8582d8..afab26a 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -1151,6 +1151,7 @@ void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) { void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint) { + if (count <= 0) return; addOp(DisplayList::DrawText); addText(text, bytesCount); addInt(count); diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 1ca0a19..9bf3de8 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -35,6 +35,7 @@ namespace uirenderer { #define DEFAULT_TEXT_CACHE_WIDTH 1024 #define DEFAULT_TEXT_CACHE_HEIGHT 256 +// We should query these values from the GL context #define MAX_TEXT_CACHE_WIDTH 2048 #define MAX_TEXT_CACHE_HEIGHT 2048 @@ -58,8 +59,7 @@ Font::~Font() { } for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) { - CachedGlyphInfo* glyph = mCachedGlyphs.valueAt(i); - delete glyph; + delete mCachedGlyphs.valueAt(i); } } @@ -134,48 +134,49 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, } -Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) { +Font::CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) { CachedGlyphInfo* cachedGlyph = NULL; - ssize_t index = mCachedGlyphs.indexOfKey(utfChar); + ssize_t index = mCachedGlyphs.indexOfKey(textUnit); if (index >= 0) { cachedGlyph = mCachedGlyphs.valueAt(index); } else { - cachedGlyph = cacheGlyph(paint, utfChar); + cachedGlyph = cacheGlyph(paint, textUnit); } // Is the glyph still in texture cache? if (!cachedGlyph->mIsValid) { - const SkGlyph& skiaGlyph = paint->getUnicharMetrics(utfChar); + const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit); updateGlyphCache(paint, skiaGlyph, cachedGlyph); } return cachedGlyph; } -void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, +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) { - renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap, + render(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); + render(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, +void Font::measure(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); + render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds); } #define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16) -void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, +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) { if (numGlyphs == 0 || text == NULL || len == 0) { @@ -195,14 +196,14 @@ void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t text += start; while (glyphsLeft > 0) { - int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text); + glyph_t glyph = GET_GLYPH(text); // Reached the end of the string - if (utfChar < 0) { + if (IS_END_OF_STRING(glyph)) { break; } - CachedGlyphInfo* cachedGlyph = getCachedUTFChar(paint, utfChar); + CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); penX += SkAutoKern_AdjustF(prevRsbDelta, cachedGlyph->mLsbDelta); prevRsbDelta = cachedGlyph->mRsbDelta; @@ -268,11 +269,11 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp mState->mUploadTexture = true; } -Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, int32_t glyph) { +Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) { CachedGlyphInfo* newGlyph = new CachedGlyphInfo(); mCachedGlyphs.add(glyph, newGlyph); - const SkGlyph& skiaGlyph = paint->getUnicharMetrics(glyph); + const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph); newGlyph->mGlyphIndex = skiaGlyph.fID; newGlyph->mIsValid = false; @@ -672,7 +673,7 @@ void FontRenderer::precacheLatin(SkPaint* paint) { uint32_t remainingCapacity = getRemainingCacheCapacity(); uint32_t precacheIdx = 0; while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { - mCurrentFont->getCachedUTFChar(paint, (int32_t) mLatinPrecache[precacheIdx]); + mCurrentFont->getCachedGlyph(paint, (int32_t) mLatinPrecache[precacheIdx]); remainingCapacity = getRemainingCacheCapacity(); precacheIdx ++; } @@ -714,7 +715,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch } Rect bounds; - mCurrentFont->measureUTF(paint, text, startIndex, len, numGlyphs, &bounds); + mCurrentFont->measure(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]; @@ -725,7 +726,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch int penX = radius - bounds.left; int penY = radius - bounds.bottom; - mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, penX, penY, + mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, dataBuffer, paddedWidth, paddedHeight); blurImage(dataBuffer, paddedWidth, paddedHeight, radius); @@ -755,7 +756,7 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text mDrawn = false; mBounds = bounds; mClip = clip; - mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, x, y); + mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y); mBounds = NULL; if (mCurrentQuadIndex != 0) { diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index 95f714f..24ed6fa 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -33,8 +33,32 @@ namespace android { namespace uirenderer { +/////////////////////////////////////////////////////////////////////////////// +// Defines +/////////////////////////////////////////////////////////////////////////////// + +#if RENDER_TEXT_AS_GLYPHS + typedef uint16_t glyph_t; + #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph) + #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text) + #define IS_END_OF_STRING(glyph) false +#else + typedef SkUnichar glyph_t; + #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph) + #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text) + #define IS_END_OF_STRING(glyph) glyph < 0 +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Declarations +/////////////////////////////////////////////////////////////////////////////// + class FontRenderer; +/////////////////////////////////////////////////////////////////////////////// +// Font +/////////////////////////////////////////////////////////////////////////////// + /** * Represents a font, defined by a Skia font id and a font size. A font is used * to generate glyphs and cache them in the FontState. @@ -51,9 +75,9 @@ 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, - 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, uint8_t *bitmap = NULL, + uint32_t bitmapW = 0, uint32_t bitmapH = 0); /** * Creates a new font associated with the specified font state. */ @@ -69,13 +93,12 @@ protected: 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 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); - void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len, - int numGlyphs, Rect *bounds); + void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, + int numGlyphs, Rect *bounds); struct CachedGlyphInfo { // Has the cache been invalidated? @@ -107,18 +130,26 @@ protected: Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, uint32_t scaleX); - DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs; + // Cache of glyphs + DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; void invalidateTextureCache(); - CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph); + 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 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); - CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar); + CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); + + static glyph_t nextGlyph(const uint16_t** srcPtr) { + const uint16_t* src = *srcPtr; + glyph_t g = *src++; + *srcPtr = src; + return g; + } FontRenderer* mState; uint32_t mFontId; @@ -128,6 +159,10 @@ protected: uint32_t mScaleX; }; +/////////////////////////////////////////////////////////////////////////////// +// Renderer +/////////////////////////////////////////////////////////////////////////////// + class FontRenderer { public: FontRenderer(); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 6243b01..45f4a42 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2073,11 +2073,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, drawTextDecorations(text, bytesCount, length, oldX, oldY, paint); } -void OpenGLRenderer::drawGlyphs(const char* glyphs, int index, int count, float x, float y, - SkPaint* paint) { - // TODO -} - void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { if (mSnapshot->isIgnored()) return; @@ -2230,14 +2225,19 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { + SkPaint paintCopy(*paint); +#if RENDER_TEXT_AS_GLYPHS + paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding); +#endif + float underlineWidth = length; // If length is > 0.0f, we already measured the text for the text alignment if (length <= 0.0f) { - underlineWidth = paint->measureText(text, bytesCount); + underlineWidth = paintCopy.measureText(text, bytesCount); } float offsetX = 0; - switch (paint->getTextAlign()) { + switch (paintCopy.getTextAlign()) { case SkPaint::kCenter_Align: offsetX = underlineWidth * 0.5f; break; @@ -2249,8 +2249,7 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float } if (underlineWidth > 0.0f) { - const float textSize = paint->getTextSize(); - // TODO: Support stroke width < 1.0f when we have AA lines + const float textSize = paintCopy.getTextSize(); const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f); const float left = x - offsetX; @@ -2280,10 +2279,9 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float points[currentPoint++] = top; } - SkPaint linesPaint(*paint); - linesPaint.setStrokeWidth(strokeWidth); + paintCopy.setStrokeWidth(strokeWidth); - drawLines(&points[0], pointsCount, &linesPaint); + drawLines(&points[0], pointsCount, &paintCopy); } } } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index e2dbba0..549d6e9 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -123,8 +123,6 @@ public: virtual void drawPoints(float* points, int count, SkPaint* paint); virtual void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint); - virtual void drawGlyphs(const char* glyphs, int index, int count, float x, float y, - SkPaint* paint); virtual void resetShader(); virtual void setupShader(SkiaShader* shader); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 2d8b6f3..7c10518 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -28,6 +28,9 @@ // If turned on, layers drawn inside FBOs are optimized with regions #define RENDER_LAYERS_AS_REGIONS 1 +// If turned on, text is interpreted as glyphs instead of UTF-16 +#define RENDER_TEXT_AS_GLYPHS 1 + /** * Debug level for app developers. */ diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h index d46686d..28dba13 100644 --- a/libs/hwui/TextDropShadowCache.h +++ b/libs/hwui/TextDropShadowCache.h @@ -73,7 +73,6 @@ struct ShadowText { text = str.string(); } - // TODO: Should take into account fake bold and text skew bool operator<(const ShadowText& rhs) const { LTE_INT(len) { LTE_INT(radius) { |