Skip to content

Commit 416a847

Browse files
committed
Add drop shadow for drawPosText in hwui renderer.
This patch adds support for drop shadows (setShadowLayer) for drawPosText in the hwui renderer. In and of itself, it's not very important, but it's on the critical path for correct mark positioning, tracked as bug 5443796. The change itself is fairly straightforward - it basically just adds an extra "positions" argument to all draw and measure methods on the code path for drawing drop shadowed text, as well as to the cache key for cached shadow textures. Change-Id: Ic1cb63299ba61ccbef31779459ecb82aa4a5e672
1 parent 592b29f commit 416a847

File tree

6 files changed

+90
-48
lines changed

6 files changed

+90
-48
lines changed

libs/hwui/FontRenderer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len
288288
}
289289

290290
void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
291-
int numGlyphs, Rect *bounds) {
291+
int numGlyphs, Rect *bounds, const float* positions) {
292292
if (bounds == NULL) {
293293
ALOGE("No return rectangle provided to measure text");
294294
return;
295295
}
296296
bounds->set(1e6, -1e6, -1e6, 1e6);
297-
render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL);
297+
render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
298298
}
299299

300300
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
@@ -1008,7 +1008,7 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
10081008
}
10091009

10101010
FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
1011-
uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) {
1011+
uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
10121012
checkInit();
10131013

10141014
if (!mCurrentFont) {
@@ -1026,7 +1026,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
10261026
mBounds = NULL;
10271027

10281028
Rect bounds;
1029-
mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
1029+
mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);
10301030

10311031
uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
10321032
uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
@@ -1040,7 +1040,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
10401040
int penY = radius - bounds.bottom;
10411041

10421042
mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
1043-
dataBuffer, paddedWidth, paddedHeight);
1043+
Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions);
10441044
blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
10451045

10461046
DropShadow image;

libs/hwui/FontRenderer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class Font {
185185
uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
186186

187187
void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
188-
int numGlyphs, Rect *bounds);
188+
int numGlyphs, Rect *bounds, const float* positions);
189189

190190
Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
191191
uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
@@ -274,7 +274,7 @@ class FontRenderer {
274274
// After renderDropShadow returns, the called owns the memory in DropShadow.image
275275
// and is responsible for releasing it when it's done with it
276276
DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
277-
uint32_t len, int numGlyphs, uint32_t radius);
277+
uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
278278

279279
GLuint getTexture(bool linearFiltering = false) {
280280
checkInit();

libs/hwui/OpenGLRenderer.cpp

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,6 +2294,44 @@ status_t OpenGLRenderer::drawRect(float left, float top, float right, float bott
22942294
return DrawGlInfo::kStatusDrew;
22952295
}
22962296

2297+
void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
2298+
const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
2299+
float x, float y) {
2300+
mCaches.activeTexture(0);
2301+
2302+
// NOTE: The drop shadow will not perform gamma correction
2303+
// if shader-based correction is enabled
2304+
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
2305+
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
2306+
paint, text, bytesCount, count, mShadowRadius, positions);
2307+
const AutoTexture autoCleanup(shadow);
2308+
2309+
const float sx = x - shadow->left + mShadowDx;
2310+
const float sy = y - shadow->top + mShadowDy;
2311+
2312+
const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
2313+
int shadowColor = mShadowColor;
2314+
if (mShader) {
2315+
shadowColor = 0xffffffff;
2316+
}
2317+
2318+
setupDraw();
2319+
setupDrawWithTexture(true);
2320+
setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
2321+
setupDrawColorFilter();
2322+
setupDrawShader();
2323+
setupDrawBlending(true, mode);
2324+
setupDrawProgram();
2325+
setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
2326+
setupDrawTexture(shadow->id);
2327+
setupDrawPureColorUniforms();
2328+
setupDrawColorFilterUniforms();
2329+
setupDrawShaderUniforms();
2330+
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
2331+
2332+
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
2333+
}
2334+
22972335
status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
22982336
const float* positions, SkPaint* paint) {
22992337
if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
@@ -2322,6 +2360,11 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
23222360
SkXfermode::Mode mode;
23232361
getAlphaAndMode(paint, &alpha, &mode);
23242362

2363+
if (CC_UNLIKELY(mHasShadow)) {
2364+
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
2365+
0.0f, 0.0f);
2366+
}
2367+
23252368
// Pick the appropriate texture filtering
23262369
bool linearFilter = mSnapshot->transform->changesBounds();
23272370
if (pureTranslate && !linearFilter) {
@@ -2415,39 +2458,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
24152458
getAlphaAndMode(paint, &alpha, &mode);
24162459

24172460
if (CC_UNLIKELY(mHasShadow)) {
2418-
mCaches.activeTexture(0);
2419-
2420-
// NOTE: The drop shadow will not perform gamma correction
2421-
// if shader-based correction is enabled
2422-
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
2423-
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
2424-
paint, text, bytesCount, count, mShadowRadius);
2425-
const AutoTexture autoCleanup(shadow);
2426-
2427-
const float sx = oldX - shadow->left + mShadowDx;
2428-
const float sy = oldY - shadow->top + mShadowDy;
2429-
2430-
const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
2431-
int shadowColor = mShadowColor;
2432-
if (mShader) {
2433-
shadowColor = 0xffffffff;
2434-
}
2435-
2436-
setupDraw();
2437-
setupDrawWithTexture(true);
2438-
setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
2439-
setupDrawColorFilter();
2440-
setupDrawShader();
2441-
setupDrawBlending(true, mode);
2442-
setupDrawProgram();
2443-
setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
2444-
setupDrawTexture(shadow->id);
2445-
setupDrawPureColorUniforms();
2446-
setupDrawColorFilterUniforms();
2447-
setupDrawShaderUniforms();
2448-
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
2449-
2450-
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
2461+
drawTextShadow(paint, text, bytesCount, count, NULL, fontRenderer, alpha, mode, oldX, oldY);
24512462
}
24522463

24532464
// Pick the appropriate texture filtering

libs/hwui/OpenGLRenderer.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,24 @@ class OpenGLRenderer {
498498
void drawTextDecorations(const char* text, int bytesCount, float length,
499499
float x, float y, SkPaint* paint);
500500

501+
/**
502+
* Draws shadow layer on text (with optional positions).
503+
*
504+
* @param paint The paint to draw the shadow with
505+
* @param text The text to draw
506+
* @param bytesCount The number of bytes in the text
507+
* @param count The number of glyphs in the text
508+
* @param positions The x, y positions of individual glyphs (or NULL)
509+
* @param fontRenderer The font renderer object
510+
* @param alpha The alpha value for drawing the shadow
511+
* @param mode The xfermode for drawing the shadow
512+
* @param x The x coordinate where the shadow will be drawn
513+
* @param y The y coordinate where the shadow will be drawn
514+
*/
515+
void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
516+
const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
517+
float x, float y);
518+
501519
/**
502520
* Draws a path texture. Path textures are alpha8 bitmaps that need special
503521
* compositing to apply colors/filters/etc.
@@ -507,7 +525,7 @@ class OpenGLRenderer {
507525
* @param y The y coordinate where the texture will be drawn
508526
* @param paint The paint to draw the texture with
509527
*/
510-
void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
528+
void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
511529

512530
/**
513531
* Resets the texture coordinates stored in mMeshVertices. Setting the values

libs/hwui/TextDropShadowCache.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ void TextDropShadowCache::clear() {
102102
}
103103

104104
ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
105-
int numGlyphs, uint32_t radius) {
106-
ShadowText entry(paint, radius, len, text);
105+
int numGlyphs, uint32_t radius, const float* positions) {
106+
ShadowText entry(paint, radius, len, text, positions);
107107
ShadowTexture* texture = mCache.get(entry);
108108

109109
if (!texture) {
110110
FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
111-
len, numGlyphs, radius);
111+
len, numGlyphs, radius, positions);
112112

113113
texture = new ShadowTexture;
114114
texture->left = shadow.penX;

libs/hwui/TextDropShadowCache.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ struct ShadowText {
3535
ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
3636
}
3737

38-
ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
39-
radius(radius), len(len) {
38+
ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText,
39+
const float* positions):
40+
radius(radius), len(len), positions(positions) {
4041
// TODO: Propagate this through the API, we should not cast here
4142
text = (const char16_t*) srcText;
4243

@@ -66,11 +67,18 @@ struct ShadowText {
6667
uint32_t italicStyle;
6768
uint32_t scaleX;
6869
const char16_t* text;
70+
const float* positions;
6971
String16 str;
72+
Vector<float> positionsCopy;
7073

7174
void copyTextLocally() {
7275
str.setTo((const char16_t*) text, len >> 1);
7376
text = str.string();
77+
if (positions != NULL) {
78+
positionsCopy.clear();
79+
positionsCopy.appendArray(positions, len);
80+
positions = positionsCopy.array();
81+
}
7482
}
7583

7684
bool operator<(const ShadowText& rhs) const {
@@ -81,7 +89,12 @@ struct ShadowText {
8189
LTE_INT(flags) {
8290
LTE_INT(italicStyle) {
8391
LTE_INT(scaleX) {
84-
return memcmp(text, rhs.text, len) < 0;
92+
int cmp = memcmp(text, rhs.text, len);
93+
if (cmp < 0) return true;
94+
if (cmp == 0 && rhs.positions != NULL) {
95+
if (positions == NULL) return true;
96+
return memcmp(positions, rhs.positions, len << 2) < 0;
97+
}
8598
}
8699
}
87100
}
@@ -117,7 +130,7 @@ class TextDropShadowCache: public OnEntryRemoved<ShadowText, ShadowTexture*> {
117130
void operator()(ShadowText& text, ShadowTexture*& texture);
118131

119132
ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
120-
int numGlyphs, uint32_t radius);
133+
int numGlyphs, uint32_t radius, const float* positions);
121134

122135
/**
123136
* Clears the cache. This causes all textures to be deleted.

0 commit comments

Comments
 (0)