Merge "Add support for non-antialiased text"

This commit is contained in:
Romain Guy
2013-02-05 23:02:44 +00:00
committed by Android (Google) Code Review
6 changed files with 119 additions and 24 deletions

View File

@@ -814,7 +814,6 @@ status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, i
SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
if (!text || count <= 0) return DrawGlInfo::kStatusDone;
paint->setAntiAlias(true);
text = refText(text, bytesCount);
path = refPath(path);
paint = refPaint(paint);
@@ -833,7 +832,6 @@ status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int
const float* positions, SkPaint* paint) {
if (!text || count <= 0) return DrawGlInfo::kStatusDone;
paint->setAntiAlias(true);
text = refText(text, bytesCount);
positions = refBuffer<float>(positions, count * 2);
paint = refPaint(paint);
@@ -851,14 +849,6 @@ status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int cou
float x, float y, const float* positions, SkPaint* paint, float length) {
if (!text || count <= 0) return DrawGlInfo::kStatusDone;
// TODO: We should probably make a copy of the paint instead of modifying
// it; modifying the paint will change its generationID the first
// time, which might impact caches. More investigation needed to
// see if it matters.
// If we make a copy, then drawTextDecorations() should *not* make
// its own copy as it does right now.
// Beware: this needs Glyph encoding (already done on the Paint constructor)
paint->setAntiAlias(true);
if (length < 0.0f) length = paint->measureText(text, bytesCount);
text = refText(text, bytesCount);

View File

@@ -218,12 +218,14 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
cacheTexture->allocateTexture();
}
uint8_t* cacheBuffer = cacheTexture->getTexture();
uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
unsigned int stride = glyph.rowBytes();
// Tells us whether the glyphs is B&W (1 bit per pixel)
// or anti-aliased (8 bits per pixel)
SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
uint8_t* cacheBuffer = cacheTexture->getTexture();
uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
// Zero out the borders
for (cacheX = startX - TEXTURE_BORDER_SIZE; cacheX < endX + TEXTURE_BORDER_SIZE; cacheX++) {
cacheBuffer[(startY - TEXTURE_BORDER_SIZE) * cacheWidth + cacheX] = 0;
cacheBuffer[(endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + cacheX] = 0;
@@ -235,20 +237,49 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
cacheBuffer[cacheY * cacheWidth + endX + TEXTURE_BORDER_SIZE - 1] = 0;
}
if (mGammaTable) {
for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
uint8_t tempCol = bitmapBuffer[bY * stride + bX];
cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
// Copy the glyph image, taking the mask format into account
uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
int stride = glyph.rowBytes();
switch (format) {
case SkMask::kA8_Format: {
if (mGammaTable) {
for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += stride) {
for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
uint8_t tempCol = bitmapBuffer[bY + bX];
cacheBuffer[cacheY * cacheWidth + cacheX] = mGammaTable[tempCol];
}
}
} else {
for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += stride) {
memcpy(&cacheBuffer[cacheY * cacheWidth + startX], &bitmapBuffer[bY],
glyph.fWidth);
}
}
break;
}
} else {
for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
uint8_t tempCol = bitmapBuffer[bY * stride + bX];
cacheBuffer[cacheY * cacheWidth + cacheX] = tempCol;
case SkMask::kBW_Format: {
static const uint8_t COLORS[2] = { 0, 255 };
for (cacheY = startY; cacheY < endY; cacheY++) {
cacheX = startX;
int rowBytes = stride;
uint8_t* buffer = bitmapBuffer;
while (--rowBytes >= 0) {
uint8_t b = *buffer++;
for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) {
cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1];
}
}
bitmapBuffer += stride;
}
break;
}
default:
ALOGW("Unkown glyph format: 0x%x", format);
break;
}
cachedGlyph->mIsValid = true;

View File

@@ -50,6 +50,7 @@ Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix)
mScaleX = paint->getTextScaleX();
mStyle = paint->getStyle();
mStrokeWidth = paint->getStrokeWidth();
mAntiAliasing = paint->isAntiAlias();
}
Font::~Font() {
@@ -68,6 +69,7 @@ hash_t Font::FontDescription::hash() const {
hash = JenkinsHashMix(hash, android::hash_type(mScaleX));
hash = JenkinsHashMix(hash, android::hash_type(mStyle));
hash = JenkinsHashMix(hash, android::hash_type(mStrokeWidth));
hash = JenkinsHashMix(hash, int(mAntiAliasing));
return JenkinsHashWhiten(hash);
}
@@ -94,6 +96,9 @@ int Font::FontDescription::compare(const Font::FontDescription& lhs,
if (lhs.mStrokeWidth < rhs.mStrokeWidth) return -1;
if (lhs.mStrokeWidth > rhs.mStrokeWidth) return +1;
deltaInt = int(lhs.mAntiAliasing) - int(rhs.mAntiAliasing);
if (deltaInt != 0) return deltaInt;
return 0;
}
@@ -384,7 +389,9 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
uint32_t startY = 0;
// Get the bitmap for the glyph
paint->findImage(skiaGlyph, NULL);
if (!skiaGlyph.fImage) {
paint->findImage(skiaGlyph, NULL);
}
mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching);
if (!glyph->mIsValid) {

View File

@@ -68,6 +68,7 @@ public:
float mScaleX;
uint8_t mStyle;
float mStrokeWidth;
bool mAntiAliasing;
};
~Font();

View File

@@ -41,6 +41,15 @@
</intent-filter>
</activity>
<activity
android:name="NoAATextActivity"
android:label="_NoAAText">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ScaledPathsActivity"
android:label="_ScaledPaths">

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
@SuppressWarnings({"UnusedDeclaration"})
public class NoAATextActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ScaledNoAA view = new ScaledNoAA(this);
setContentView(view);
}
public static class ScaledNoAA extends View {
private static final String TEXT = "Hello libhwui!";
private final Paint mPaint;
public ScaledNoAA(Context c) {
super(c);
mPaint = new Paint();
mPaint.setTextSize(60.0f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawARGB(255, 255, 255, 255);
canvas.drawText(TEXT, 30.0f, 150.0f, mPaint);
}
}
}