Merge "Add drop shadow for drawPosText in hwui renderer."
This commit is contained in:
@@ -288,13 +288,13 @@ void Font::render(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) {
|
||||
int numGlyphs, Rect *bounds, const float* positions) {
|
||||
if (bounds == NULL) {
|
||||
ALOGE("No return rectangle provided to measure text");
|
||||
return;
|
||||
}
|
||||
bounds->set(1e6, -1e6, -1e6, 1e6);
|
||||
render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL);
|
||||
render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
|
||||
}
|
||||
|
||||
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
|
||||
@@ -1007,7 +1007,7 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
|
||||
}
|
||||
|
||||
FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
|
||||
uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) {
|
||||
uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
|
||||
checkInit();
|
||||
|
||||
if (!mCurrentFont) {
|
||||
@@ -1025,7 +1025,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
|
||||
mBounds = NULL;
|
||||
|
||||
Rect bounds;
|
||||
mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
|
||||
mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);
|
||||
|
||||
uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
|
||||
uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
|
||||
@@ -1039,7 +1039,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
|
||||
int penY = radius - bounds.bottom;
|
||||
|
||||
mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
|
||||
dataBuffer, paddedWidth, paddedHeight);
|
||||
Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions);
|
||||
blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
|
||||
|
||||
DropShadow image;
|
||||
|
||||
@@ -184,7 +184,7 @@ protected:
|
||||
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);
|
||||
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);
|
||||
@@ -273,7 +273,7 @@ public:
|
||||
// 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);
|
||||
uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
|
||||
|
||||
GLuint getTexture(bool linearFiltering = false) {
|
||||
checkInit();
|
||||
|
||||
@@ -2303,6 +2303,44 @@ status_t OpenGLRenderer::drawRect(float left, float top, float right, float bott
|
||||
return DrawGlInfo::kStatusDrew;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
|
||||
const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
|
||||
float x, float y) {
|
||||
mCaches.activeTexture(0);
|
||||
|
||||
// NOTE: The drop shadow will not perform gamma correction
|
||||
// if shader-based correction is enabled
|
||||
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
|
||||
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
|
||||
paint, text, bytesCount, count, mShadowRadius, positions);
|
||||
const AutoTexture autoCleanup(shadow);
|
||||
|
||||
const float sx = x - shadow->left + mShadowDx;
|
||||
const float sy = y - shadow->top + mShadowDy;
|
||||
|
||||
const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
|
||||
int shadowColor = mShadowColor;
|
||||
if (mShader) {
|
||||
shadowColor = 0xffffffff;
|
||||
}
|
||||
|
||||
setupDraw();
|
||||
setupDrawWithTexture(true);
|
||||
setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
|
||||
setupDrawColorFilter();
|
||||
setupDrawShader();
|
||||
setupDrawBlending(true, mode);
|
||||
setupDrawProgram();
|
||||
setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
|
||||
setupDrawTexture(shadow->id);
|
||||
setupDrawPureColorUniforms();
|
||||
setupDrawColorFilterUniforms();
|
||||
setupDrawShaderUniforms();
|
||||
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
|
||||
}
|
||||
|
||||
status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
|
||||
const float* positions, SkPaint* paint) {
|
||||
if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
|
||||
@@ -2331,6 +2369,11 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
if (CC_UNLIKELY(mHasShadow)) {
|
||||
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
|
||||
0.0f, 0.0f);
|
||||
}
|
||||
|
||||
// Pick the appropriate texture filtering
|
||||
bool linearFilter = mSnapshot->transform->changesBounds();
|
||||
if (pureTranslate && !linearFilter) {
|
||||
@@ -2424,39 +2467,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
if (CC_UNLIKELY(mHasShadow)) {
|
||||
mCaches.activeTexture(0);
|
||||
|
||||
// NOTE: The drop shadow will not perform gamma correction
|
||||
// if shader-based correction is enabled
|
||||
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
|
||||
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
|
||||
paint, text, bytesCount, count, mShadowRadius);
|
||||
const AutoTexture autoCleanup(shadow);
|
||||
|
||||
const float sx = oldX - shadow->left + mShadowDx;
|
||||
const float sy = oldY - shadow->top + mShadowDy;
|
||||
|
||||
const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
|
||||
int shadowColor = mShadowColor;
|
||||
if (mShader) {
|
||||
shadowColor = 0xffffffff;
|
||||
}
|
||||
|
||||
setupDraw();
|
||||
setupDrawWithTexture(true);
|
||||
setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
|
||||
setupDrawColorFilter();
|
||||
setupDrawShader();
|
||||
setupDrawBlending(true, mode);
|
||||
setupDrawProgram();
|
||||
setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
|
||||
setupDrawTexture(shadow->id);
|
||||
setupDrawPureColorUniforms();
|
||||
setupDrawColorFilterUniforms();
|
||||
setupDrawShaderUniforms();
|
||||
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
|
||||
drawTextShadow(paint, text, bytesCount, count, NULL, fontRenderer, alpha, mode, oldX, oldY);
|
||||
}
|
||||
|
||||
// Pick the appropriate texture filtering
|
||||
|
||||
@@ -498,6 +498,24 @@ private:
|
||||
void drawTextDecorations(const char* text, int bytesCount, float length,
|
||||
float x, float y, SkPaint* paint);
|
||||
|
||||
/**
|
||||
* Draws shadow layer on text (with optional positions).
|
||||
*
|
||||
* @param paint The paint to draw the shadow with
|
||||
* @param text The text to draw
|
||||
* @param bytesCount The number of bytes in the text
|
||||
* @param count The number of glyphs in the text
|
||||
* @param positions The x, y positions of individual glyphs (or NULL)
|
||||
* @param fontRenderer The font renderer object
|
||||
* @param alpha The alpha value for drawing the shadow
|
||||
* @param mode The xfermode for drawing the shadow
|
||||
* @param x The x coordinate where the shadow will be drawn
|
||||
* @param y The y coordinate where the shadow will be drawn
|
||||
*/
|
||||
void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
|
||||
const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
|
||||
float x, float y);
|
||||
|
||||
/**
|
||||
* Draws a path texture. Path textures are alpha8 bitmaps that need special
|
||||
* compositing to apply colors/filters/etc.
|
||||
@@ -507,7 +525,7 @@ private:
|
||||
* @param y The y coordinate where the texture will be drawn
|
||||
* @param paint The paint to draw the texture with
|
||||
*/
|
||||
void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
|
||||
void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
|
||||
|
||||
/**
|
||||
* Resets the texture coordinates stored in mMeshVertices. Setting the values
|
||||
|
||||
@@ -102,13 +102,13 @@ void TextDropShadowCache::clear() {
|
||||
}
|
||||
|
||||
ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
|
||||
int numGlyphs, uint32_t radius) {
|
||||
ShadowText entry(paint, radius, len, text);
|
||||
int numGlyphs, uint32_t radius, const float* positions) {
|
||||
ShadowText entry(paint, radius, len, text, positions);
|
||||
ShadowTexture* texture = mCache.get(entry);
|
||||
|
||||
if (!texture) {
|
||||
FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
|
||||
len, numGlyphs, radius);
|
||||
len, numGlyphs, radius, positions);
|
||||
|
||||
texture = new ShadowTexture;
|
||||
texture->left = shadow.penX;
|
||||
|
||||
@@ -35,8 +35,9 @@ struct ShadowText {
|
||||
ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
|
||||
}
|
||||
|
||||
ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
|
||||
radius(radius), len(len) {
|
||||
ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText,
|
||||
const float* positions):
|
||||
radius(radius), len(len), positions(positions) {
|
||||
// TODO: Propagate this through the API, we should not cast here
|
||||
text = (const char16_t*) srcText;
|
||||
|
||||
@@ -66,11 +67,18 @@ struct ShadowText {
|
||||
uint32_t italicStyle;
|
||||
uint32_t scaleX;
|
||||
const char16_t* text;
|
||||
const float* positions;
|
||||
String16 str;
|
||||
Vector<float> positionsCopy;
|
||||
|
||||
void copyTextLocally() {
|
||||
str.setTo((const char16_t*) text, len >> 1);
|
||||
text = str.string();
|
||||
if (positions != NULL) {
|
||||
positionsCopy.clear();
|
||||
positionsCopy.appendArray(positions, len);
|
||||
positions = positionsCopy.array();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const ShadowText& rhs) const {
|
||||
@@ -81,7 +89,12 @@ struct ShadowText {
|
||||
LTE_INT(flags) {
|
||||
LTE_INT(italicStyle) {
|
||||
LTE_INT(scaleX) {
|
||||
return memcmp(text, rhs.text, len) < 0;
|
||||
int cmp = memcmp(text, rhs.text, len);
|
||||
if (cmp < 0) return true;
|
||||
if (cmp == 0 && rhs.positions != NULL) {
|
||||
if (positions == NULL) return true;
|
||||
return memcmp(positions, rhs.positions, len << 2) < 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +130,7 @@ public:
|
||||
void operator()(ShadowText& text, ShadowTexture*& texture);
|
||||
|
||||
ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
|
||||
int numGlyphs, uint32_t radius);
|
||||
int numGlyphs, uint32_t radius, const float* positions);
|
||||
|
||||
/**
|
||||
* Clears the cache. This causes all textures to be deleted.
|
||||
|
||||
Reference in New Issue
Block a user