Merge "Properly scale text" into jb-mr2-dev
This commit is contained in:
@@ -39,6 +39,11 @@ static const float EPSILON = 0.0000001f;
|
||||
// Matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const Matrix4& Matrix4::identity() {
|
||||
static Matrix4 sIdentity;
|
||||
return sIdentity;
|
||||
}
|
||||
|
||||
void Matrix4::loadIdentity() {
|
||||
data[kScaleX] = 1.0f;
|
||||
data[kSkewY] = 0.0f;
|
||||
|
||||
@@ -152,6 +152,8 @@ public:
|
||||
|
||||
void dump() const;
|
||||
|
||||
static const Matrix4& identity();
|
||||
|
||||
private:
|
||||
mutable uint32_t mType;
|
||||
|
||||
|
||||
@@ -1657,13 +1657,13 @@ void OpenGLRenderer::setupDrawModelViewTranslate(float left, float top, float ri
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
|
||||
if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
|
||||
} else {
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mIdentity);
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mat4::identity());
|
||||
if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawModelViewIdentity(bool offset) {
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform, offset);
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mat4::identity(), *mSnapshot->transform, offset);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom,
|
||||
@@ -1681,7 +1681,7 @@ void OpenGLRenderer::setupDrawModelView(float left, float top, float right, floa
|
||||
dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
|
||||
}
|
||||
} else {
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mIdentity);
|
||||
mCaches.currentProgram->set(mOrthoMatrix, mModelView, mat4::identity());
|
||||
if (mTrackDirtyRegions && dirty) dirtyLayer(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
@@ -1716,7 +1716,7 @@ void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
|
||||
void OpenGLRenderer::setupDrawShaderIdentityUniforms() {
|
||||
if (mDrawModifiers.mShader) {
|
||||
mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
|
||||
mIdentity, *mSnapshot, &mTextureUnit);
|
||||
mat4::identity(), *mSnapshot, &mTextureUnit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2587,7 +2587,7 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
|
||||
}
|
||||
|
||||
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
|
||||
fontRenderer.setFont(paint, *mSnapshot->transform);
|
||||
fontRenderer.setFont(paint, mat4::identity());
|
||||
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
@@ -2663,17 +2663,10 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
#if DEBUG_GLYPHS
|
||||
ALOGD("OpenGLRenderer drawText() with FontID=%d",
|
||||
SkTypeface::UniqueID(paint->getTypeface()));
|
||||
#endif
|
||||
|
||||
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
|
||||
fontRenderer.setFont(paint, *mSnapshot->transform);
|
||||
|
||||
const float oldX = x;
|
||||
const float oldY = y;
|
||||
const bool pureTranslate = mSnapshot->transform->isPureTranslate();
|
||||
|
||||
if (CC_LIKELY(pureTranslate)) {
|
||||
x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
|
||||
y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
|
||||
@@ -2683,16 +2676,19 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
|
||||
|
||||
if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
|
||||
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
|
||||
oldX, oldY);
|
||||
fontRenderer.setFont(paint, mat4::identity());
|
||||
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
|
||||
alpha, mode, oldX, oldY);
|
||||
}
|
||||
|
||||
fontRenderer.setFont(paint, pureTranslate ? mat4::identity() : *mSnapshot->transform);
|
||||
|
||||
// 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;
|
||||
}
|
||||
bool linearFilter = !mSnapshot->transform->isPureTranslate() ||
|
||||
fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
|
||||
|
||||
// The font renderer will always use texture unit 0
|
||||
mCaches.activeTexture(0);
|
||||
@@ -2705,17 +2701,16 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
setupDrawShader();
|
||||
setupDrawBlending(true, mode);
|
||||
setupDrawProgram();
|
||||
setupDrawModelView(x, y, x, y, pureTranslate, true);
|
||||
setupDrawModelView(x, y, x, y, true, true);
|
||||
// See comment above; the font renderer must use texture unit 0
|
||||
// assert(mTextureUnit == 0)
|
||||
setupDrawTexture(fontRenderer.getTexture(linearFilter));
|
||||
setupDrawPureColorUniforms();
|
||||
setupDrawColorFilterUniforms();
|
||||
setupDrawShaderUniforms(pureTranslate);
|
||||
setupDrawShaderUniforms(true);
|
||||
setupDrawTextGammaUniforms();
|
||||
|
||||
const Rect* clip = pureTranslate ? mSnapshot->clipRect :
|
||||
(mSnapshot->hasPerspectiveTransform() ? NULL : &mSnapshot->getLocalClip());
|
||||
const Rect* clip = mSnapshot->hasPerspectiveTransform() ? NULL : mSnapshot->clipRect;
|
||||
Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
|
||||
|
||||
const bool hasActiveLayer = hasLayer();
|
||||
@@ -2732,9 +2727,6 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
}
|
||||
|
||||
if (status && hasActiveLayer) {
|
||||
if (!pureTranslate) {
|
||||
mSnapshot->transform->mapRect(bounds);
|
||||
}
|
||||
dirtyLayerUnchecked(bounds, getRegion());
|
||||
}
|
||||
|
||||
@@ -2750,7 +2742,7 @@ status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int co
|
||||
}
|
||||
|
||||
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
|
||||
fontRenderer.setFont(paint, *mSnapshot->transform);
|
||||
fontRenderer.setFont(paint, mat4::identity());
|
||||
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
|
||||
@@ -936,9 +936,6 @@ private:
|
||||
// List of layers to update at the beginning of a frame
|
||||
Vector<Layer*> mLayerUpdates;
|
||||
|
||||
// Indentity matrix
|
||||
const mat4 mIdentity;
|
||||
|
||||
// Indicates whether the clip must be restored
|
||||
bool mDirtyClip;
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix)
|
||||
mStyle = paint->getStyle();
|
||||
mStrokeWidth = paint->getStrokeWidth();
|
||||
mAntiAliasing = paint->isAntiAlias();
|
||||
mLookupTransform[SkMatrix::kMScaleX] = matrix.data[mat4::kScaleX];
|
||||
mLookupTransform[SkMatrix::kMScaleY] = matrix.data[mat4::kScaleY];
|
||||
mLookupTransform[SkMatrix::kMSkewX] = matrix.data[mat4::kSkewX];
|
||||
mLookupTransform[SkMatrix::kMSkewY] = matrix.data[mat4::kSkewY];
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
@@ -71,6 +75,10 @@ hash_t Font::FontDescription::hash() const {
|
||||
hash = JenkinsHashMix(hash, android::hash_type(mStyle));
|
||||
hash = JenkinsHashMix(hash, android::hash_type(mStrokeWidth));
|
||||
hash = JenkinsHashMix(hash, int(mAntiAliasing));
|
||||
hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMScaleX]));
|
||||
hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMScaleY]));
|
||||
hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMSkewX]));
|
||||
hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMSkewY]));
|
||||
return JenkinsHashWhiten(hash);
|
||||
}
|
||||
|
||||
@@ -100,6 +108,26 @@ int Font::FontDescription::compare(const Font::FontDescription& lhs,
|
||||
deltaInt = int(lhs.mAntiAliasing) - int(rhs.mAntiAliasing);
|
||||
if (deltaInt != 0) return deltaInt;
|
||||
|
||||
if (lhs.mLookupTransform[SkMatrix::kMScaleX] <
|
||||
rhs.mLookupTransform[SkMatrix::kMScaleX]) return -1;
|
||||
if (lhs.mLookupTransform[SkMatrix::kMScaleX] >
|
||||
rhs.mLookupTransform[SkMatrix::kMScaleX]) return +1;
|
||||
|
||||
if (lhs.mLookupTransform[SkMatrix::kMScaleY] <
|
||||
rhs.mLookupTransform[SkMatrix::kMScaleY]) return -1;
|
||||
if (lhs.mLookupTransform[SkMatrix::kMScaleY] >
|
||||
rhs.mLookupTransform[SkMatrix::kMScaleY]) return +1;
|
||||
|
||||
if (lhs.mLookupTransform[SkMatrix::kMSkewX] <
|
||||
rhs.mLookupTransform[SkMatrix::kMSkewX]) return -1;
|
||||
if (lhs.mLookupTransform[SkMatrix::kMSkewX] >
|
||||
rhs.mLookupTransform[SkMatrix::kMSkewX]) return +1;
|
||||
|
||||
if (lhs.mLookupTransform[SkMatrix::kMSkewY] <
|
||||
rhs.mLookupTransform[SkMatrix::kMSkewY]) return -1;
|
||||
if (lhs.mLookupTransform[SkMatrix::kMSkewY] >
|
||||
rhs.mLookupTransform[SkMatrix::kMSkewY]) return +1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,12 +197,6 @@ void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
|
||||
int32_t bX = 0, bY = 0;
|
||||
for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
|
||||
for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
|
||||
#if DEBUG_FONT_RENDERER
|
||||
if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
|
||||
ALOGE("Skipping invalid index");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
|
||||
bitmap[bY * bitmapW + bX] = tempCol;
|
||||
}
|
||||
@@ -226,16 +248,16 @@ CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool pre
|
||||
ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
|
||||
if (index >= 0) {
|
||||
cachedGlyph = mCachedGlyphs.valueAt(index);
|
||||
|
||||
// Is the glyph still in texture cache?
|
||||
if (!cachedGlyph->mIsValid) {
|
||||
const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit, &mDescription.mLookupTransform);
|
||||
updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
|
||||
}
|
||||
} else {
|
||||
cachedGlyph = cacheGlyph(paint, textUnit, precaching);
|
||||
}
|
||||
|
||||
// Is the glyph still in texture cache?
|
||||
if (!cachedGlyph->mIsValid) {
|
||||
const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit, NULL);
|
||||
updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
|
||||
}
|
||||
|
||||
return cachedGlyph;
|
||||
}
|
||||
|
||||
@@ -357,22 +379,14 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len
|
||||
|
||||
// If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
|
||||
if (cachedGlyph->mIsValid) {
|
||||
int penX = x + positions[(glyphsCount << 1)];
|
||||
int penY = y + positions[(glyphsCount << 1) + 1];
|
||||
float penX = x + positions[(glyphsCount << 1)];
|
||||
float penY = y + positions[(glyphsCount << 1) + 1];
|
||||
|
||||
switch (align) {
|
||||
case SkPaint::kRight_Align:
|
||||
penX -= SkFixedToFloat(cachedGlyph->mAdvanceX);
|
||||
penY -= SkFixedToFloat(cachedGlyph->mAdvanceY);
|
||||
break;
|
||||
case SkPaint::kCenter_Align:
|
||||
penX -= SkFixedToFloat(cachedGlyph->mAdvanceX >> 1);
|
||||
penY -= SkFixedToFloat(cachedGlyph->mAdvanceY >> 1);
|
||||
default:
|
||||
break;
|
||||
if (!mTransform.isIdentity()) {
|
||||
mTransform.mapPoint(penX, penY);
|
||||
}
|
||||
|
||||
(*this.*render)(cachedGlyph, penX, penY,
|
||||
(*this.*render)(cachedGlyph, roundf(penX), roundf(penY),
|
||||
bitmap, bitmapW, bitmapH, bounds, positions);
|
||||
}
|
||||
|
||||
@@ -394,7 +408,7 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
|
||||
|
||||
// Get the bitmap for the glyph
|
||||
if (!skiaGlyph.fImage) {
|
||||
paint->findImage(skiaGlyph, NULL);
|
||||
paint->findImage(skiaGlyph, &mDescription.mLookupTransform);
|
||||
}
|
||||
mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching);
|
||||
|
||||
@@ -425,7 +439,7 @@ CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching
|
||||
CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
|
||||
mCachedGlyphs.add(glyph, newGlyph);
|
||||
|
||||
const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph, NULL);
|
||||
const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph, &mDescription.mLookupTransform);
|
||||
newGlyph->mGlyphIndex = skiaGlyph.fID;
|
||||
newGlyph->mIsValid = false;
|
||||
|
||||
@@ -439,6 +453,7 @@ Font* Font::create(FontRenderer* state, const SkPaint* paint, const mat4& matrix
|
||||
Font* font = state->mActiveFonts.get(description);
|
||||
|
||||
if (font) {
|
||||
font->mTransform.load(matrix);
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
uint8_t mStyle;
|
||||
float mStrokeWidth;
|
||||
bool mAntiAliasing;
|
||||
SkMatrix mLookupTransform;
|
||||
};
|
||||
|
||||
~Font();
|
||||
@@ -136,6 +137,8 @@ private:
|
||||
|
||||
// Cache of glyphs
|
||||
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
|
||||
|
||||
mat4 mTransform;
|
||||
};
|
||||
|
||||
inline int strictly_order_type(const Font::FontDescription& lhs,
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
|
||||
<activity
|
||||
android:name="ScaledTextActivity"
|
||||
android:label="_ScaledText">
|
||||
android:label="_ScaledText"
|
||||
android:theme="@android:style/Theme.Holo.Light">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -54,6 +54,7 @@ public class ScaledTextActivity extends Activity {
|
||||
|
||||
public ScaledTextView(Context c) {
|
||||
super(c);
|
||||
setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
mPath = makePath();
|
||||
|
||||
@@ -92,11 +93,28 @@ public class ScaledTextActivity extends Activity {
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.drawARGB(255, 255, 255, 255);
|
||||
|
||||
canvas.drawText(TEXT, 30.0f, 30.0f, mPaint);
|
||||
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||
canvas.drawText(TEXT, 30.0f, 50.0f, mPaint);
|
||||
mPaint.setTextAlign(Paint.Align.RIGHT);
|
||||
canvas.drawText(TEXT, 30.0f, 70.0f, mPaint);
|
||||
|
||||
canvas.translate(0.0f, 50.0f);
|
||||
canvas.save();
|
||||
canvas.translate(400.0f, 0.0f);
|
||||
canvas.scale(3.0f, 3.0f);
|
||||
mPaint.setTextAlign(Paint.Align.LEFT);
|
||||
mPaint.setStrikeThruText(true);
|
||||
canvas.drawText(TEXT, 30.0f, 30.0f, mPaint);
|
||||
mPaint.setStrikeThruText(false);
|
||||
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||
canvas.drawText(TEXT, 30.0f, 50.0f, mPaint);
|
||||
mPaint.setTextAlign(Paint.Align.RIGHT);
|
||||
canvas.drawText(TEXT, 30.0f, 70.0f, mPaint);
|
||||
canvas.restore();
|
||||
|
||||
mPaint.setTextAlign(Paint.Align.LEFT);
|
||||
canvas.translate(0.0f, 100.0f);
|
||||
|
||||
canvas.save();
|
||||
canvas.scale(mScale, mScale);
|
||||
|
||||
Reference in New Issue
Block a user