diff options
author | Romain Guy <romainguy@google.com> | 2010-12-06 18:08:46 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-12-06 18:08:46 -0800 |
commit | ffac19ede6723ae00ed24ecc658d69c5effbe4bc (patch) | |
tree | 65a2a4430f73b44e6f313b770ac84aa4074571a4 /libs | |
parent | 97fdd7dcfd617482e1dba7748a73f189b0af8330 (diff) | |
parent | 6620c6d413f972819fada92b574f0fa9e96d36c1 (diff) | |
download | frameworks_base-ffac19ede6723ae00ed24ecc658d69c5effbe4bc.zip frameworks_base-ffac19ede6723ae00ed24ecc658d69c5effbe4bc.tar.gz frameworks_base-ffac19ede6723ae00ed24ecc658d69c5effbe4bc.tar.bz2 |
Merge "Correctly render text when coordinates are not integers. Bug #3225632"
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Matrix.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/Matrix.h | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 113 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 5 |
4 files changed, 98 insertions, 27 deletions
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 7462d5b..fe7f883 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -62,6 +62,11 @@ bool Matrix4::changesBounds() { ALMOST_EQUAL(data[10], 1.0f)); } +bool Matrix4::isPureTranslate() { + return mSimpleMatrix && + ALMOST_EQUAL(data[kScaleX], 1.0f) && ALMOST_EQUAL(data[kScaleY], 1.0f); +} + void Matrix4::load(const float* v) { memcpy(data, v, sizeof(data)); mSimpleMatrix = false; diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index d678bd0..23fc6c3 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -103,6 +103,8 @@ public: multiply(u); } + bool isPureTranslate(); + bool changesBounds(); void copyTo(float* v) const; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index f3e5b16..b24c04f 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -909,9 +909,19 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f, - mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], - GL_TRIANGLE_STRIP, gMeshCount); + if (mSnapshot->transform->isPureTranslate()) { + const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f); + const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f); + + drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop), + texture->id, alpha / 255.0f, mode, texture->blend, + &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], + GL_TRIANGLE_STRIP, gMeshCount, false, true); + } else { + drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f, + mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], + GL_TRIANGLE_STRIP, gMeshCount); + } resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); } @@ -937,6 +947,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors); if (mesh && mesh->verticesCount > 0) { + const bool pureTranslate = mSnapshot->transform->isPureTranslate(); #if RENDER_LAYERS_AS_REGIONS // Mark the current layer dirty where we are going to draw the patch if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && @@ -944,16 +955,33 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int const size_t count = mesh->quads.size(); for (size_t i = 0; i < count; i++) { Rect bounds = mesh->quads.itemAt(i); - dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, - *mSnapshot->transform); + if (pureTranslate) { + const float x = (int) floorf(bounds.left + 0.5f); + const float y = (int) floorf(bounds.top + 0.5f); + dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getBottom(), + *mSnapshot->transform); + } else { + dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, + *mSnapshot->transform); + } } } #endif - drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, - mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, - GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer, - true, !mesh->hasEmptyQuads); + if (pureTranslate) { + const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); + const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); + + drawTextureMesh(x, y, x + right - left, y + bottom - top, texture->id, alpha / 255.0f, + mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, + GL_TRIANGLES, mesh->verticesCount, false, true, mesh->meshBuffer, + true, !mesh->hasEmptyQuads); + } else { + drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, + mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, + GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer, + true, !mesh->hasEmptyQuads); + } } } @@ -1087,6 +1115,13 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, break; } + // TODO: Handle paint->getTextScaleX() + const bool pureTranslate = mSnapshot->transform->isPureTranslate(); + if (pureTranslate) { + x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f); + y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); + } + int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); @@ -1110,7 +1145,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, count, mShadowRadius); const AutoTexture autoCleanup(shadow); - setupShadow(shadow, x, y, mode, a); + setupShadow(shadow, x, y, mode, a, pureTranslate); // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); @@ -1120,14 +1155,17 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, GLuint textureUnit = 0; glActiveTexture(gTextureUnits[textureUnit]); - // Assume that the modelView matrix does not force scales, rotates, etc. - const bool linearFilter = mSnapshot->transform->changesBounds(); + // Pick the appropriate texture filtering + bool linearFilter = mSnapshot->transform->changesBounds(); + if (pureTranslate && !linearFilter) { + linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f; + } // Dimensions are set to (0,0), the layer (if any) won't be dirtied setupTextureAlpha8(fontRenderer.getTexture(linearFilter), 0, 0, textureUnit, - x, y, r, g, b, a, mode, false, true, NULL, NULL); + x, y, r, g, b, a, mode, false, true, NULL, NULL, 0, pureTranslate); - const Rect& clip = mSnapshot->getLocalClip(); + const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip(); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); #if RENDER_LAYERS_AS_REGIONS @@ -1137,11 +1175,13 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, #endif mCaches.unbindMeshBuffer(); - if (fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y, + if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y, hasLayer ? &bounds : NULL)) { #if RENDER_LAYERS_AS_REGIONS if (hasLayer) { - mSnapshot->transform->mapRect(bounds); + if (!pureTranslate) { + mSnapshot->transform->mapRect(bounds); + } bounds.intersect(*mSnapshot->clipRect); bounds.snapToPixelBoundaries(); @@ -1241,7 +1281,7 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y, - SkXfermode::Mode mode, float alpha) { + SkXfermode::Mode mode, float alpha, bool ignoreTransforms) { const float sx = x - texture->left + mShadowDx; const float sy = y - texture->top + mShadowDy; @@ -1252,7 +1292,9 @@ void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y, const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; GLuint textureUnit = 0; - setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false); + setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit, + sx, sy, r, g, b, a, mode, true, false, + (GLvoid*) 0, (GLvoid*) gMeshTextureOffset, 0, ignoreTransforms); } void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, @@ -1273,7 +1315,7 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters, - GLvoid* vertices, GLvoid* texCoords, GLuint vbo) { + GLvoid* vertices, GLvoid* texCoords, GLuint vbo, bool ignoreTransform) { // Describe the required shaders ProgramDescription description; description.hasTexture = true; @@ -1321,9 +1363,14 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t mModelView.loadIdentity(); } - mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); + mat4 t; + if (!ignoreTransform) { + t.load(*mSnapshot->transform); + } + + mCaches.currentProgram->set(mOrthoMatrix, mModelView, t); if (width > 0 && height > 0) { - dirtyLayer(x, y, x + width, y + height, *mSnapshot->transform); + dirtyLayer(x, y, x + width, y + height, t); } if (setColor) { @@ -1334,6 +1381,9 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t if (applyFilters) { // Setup attributes and uniforms required by the shaders if (mShader) { + if (ignoreTransform) { + mModelView.loadInverse(*mSnapshot->transform); + } mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { @@ -1473,7 +1523,11 @@ void OpenGLRenderer::setupColorRect(float left, float top, float right, float bo // Setup attributes and uniforms required by the shaders if (mShader) { - if (ignoreMatrix) mModelView.loadIdentity(); + if (ignoreMatrix) { + mModelView.loadIdentity(); + } else if (ignoreTransform) { + mModelView.loadInverse(*mSnapshot->transform); + } mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { @@ -1489,9 +1543,18 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); - drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, - texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, - GL_TRIANGLE_STRIP, gMeshCount); + if (mSnapshot->transform->isPureTranslate()) { + const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); + const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); + + drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id, + alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL, + (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true); + } else { + drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, + texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, + GL_TRIANGLE_STRIP, gMeshCount); + } } void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index a942dde..e866d1b 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -294,9 +294,10 @@ private: * @param y The y coordinate of the shadow * @param mode The blending mode * @param alpha The alpha value + * @param ignoreTransforms True if the coordinates are already in screen space */ void setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode, - float alpha); + float alpha, bool ignoreTransforms = false); /** * Prepares the renderer to draw the specified Alpha8 texture as a rectangle. @@ -349,7 +350,7 @@ private: void setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters, - GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0); + GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0, bool ignoreTransform = false); /** * Draws text underline and strike-through if needed. |