Merge "Correctly render text when coordinates are not integers. Bug #3225632"

This commit is contained in:
Romain Guy
2010-12-06 18:08:46 -08:00
committed by Android (Google) Code Review
4 changed files with 98 additions and 27 deletions

View File

@@ -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;

View File

@@ -103,6 +103,8 @@ public:
multiply(u);
}
bool isPureTranslate();
bool changesBounds();
void copyTo(float* v) const;

View File

@@ -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,

View File

@@ -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.