From 448b0fd720d7ba902b9be224a287d08abe3ebea8 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Fri, 30 May 2014 23:38:56 -0700 Subject: Support for scaleX and skewX Adds pseudo-css properties for scaleX and skewX, as well as paint flags, and plumb them through to the MinikinPaint abstraction and to Harfbuzz, to support nontrivial scale and stretch of text. This is the Minikin part of the fix for bug 15186705 "Usability of the suggestion strip in recent OTA's is severely reduced" Change-Id: Ifa60355e086e4691ff92c5d50d84eb7cea0fea95 --- include/minikin/CssParse.h | 8 +++++++- include/minikin/MinikinFont.h | 4 +++- libs/minikin/CssParse.cpp | 3 +++ libs/minikin/Layout.cpp | 43 ++++++++++++++++++++++++++++++------------- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/include/minikin/CssParse.h b/include/minikin/CssParse.h index 519056d..ae2aac6 100644 --- a/include/minikin/CssParse.h +++ b/include/minikin/CssParse.h @@ -24,24 +24,30 @@ namespace android { enum CssTag { unknown, + fontScaleX, fontSize, + fontSkewX, fontStyle, fontWeight, cssLang, minikinBidi, minikinHinting, minikinVariant, + paintFlags, }; const std::string cssTagNames[] = { "unknown", + "font-scale-x", "font-size", + "font-skew-x", "font-style", "font-weight", "lang", "-minikin-bidi", "-minikin-hinting", "-minikin-variant", + "-paint-flags", }; class CssValue { @@ -62,7 +68,7 @@ public: mType(FLOAT), floatValue(v), mUnits(SCALAR) { } Type getType() const { return mType; } double getFloatValue() const { return floatValue; } - int getIntValue() const { return floatValue; } + int32_t getIntValue() const { return floatValue; } std::string getStringValue() const { return stringValue; } std::string toString(CssTag tag) const; void setFloatValue(double v) { diff --git a/include/minikin/MinikinFont.h b/include/minikin/MinikinFont.h index dbb89f8..1f6894c 100644 --- a/include/minikin/MinikinFont.h +++ b/include/minikin/MinikinFont.h @@ -31,7 +31,9 @@ class MinikinFont; struct MinikinPaint { MinikinFont *font; float size; - // todo: skew, stretch, hinting + float scaleX; + float skewX; + int32_t paintFlags; }; struct MinikinRect { diff --git a/libs/minikin/CssParse.cpp b/libs/minikin/CssParse.cpp index 5e96007..147f330 100644 --- a/libs/minikin/CssParse.cpp +++ b/libs/minikin/CssParse.cpp @@ -37,7 +37,9 @@ static CssTag parseTag(const string str, size_t off, size_t len) { if (len == 0) return unknown; char c = str[off]; if (c == 'f') { + if (strEqC(str, off, len, "font-scale-x")) return fontScaleX; if (strEqC(str, off, len, "font-size")) return fontSize; + if (strEqC(str, off, len, "font-skew-x")) return fontSkewX; if (strEqC(str, off, len, "font-weight")) return fontWeight; if (strEqC(str, off, len, "font-style")) return fontStyle; } else if (c == 'l') { @@ -46,6 +48,7 @@ static CssTag parseTag(const string str, size_t off, size_t len) { if (strEqC(str, off, len, "-minikin-bidi")) return minikinBidi; if (strEqC(str, off, len, "-minikin-hinting")) return minikinHinting; if (strEqC(str, off, len, "-minikin-variant")) return minikinVariant; + if (strEqC(str, off, len, "-paint-flags")) return paintFlags; } return unknown; } diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp index 4028d9e..c13aed8 100644 --- a/libs/minikin/Layout.cpp +++ b/libs/minikin/Layout.cpp @@ -63,7 +63,8 @@ public: LayoutCacheKey(const FontCollection* collection, const MinikinPaint& paint, FontStyle style, const uint16_t* chars, size_t start, size_t count, size_t nchars, bool dir) : mStart(start), mCount(count), mId(collection->getId()), mStyle(style), - mSize(paint.size), mIsRtl(dir) { + mSize(paint.size), mScaleX(paint.scaleX), mSkewX(paint.skewX), + mPaintFlags(paint.paintFlags), mIsRtl(dir) { mText.setTo(chars, nchars); } bool operator==(const LayoutCacheKey &other) const; @@ -78,6 +79,9 @@ private: uint32_t mId; // for the font collection FontStyle mStyle; float mSize; + float mScaleX; + float mSkewX; + int mPaintFlags; bool mIsRtl; // Note: any fields added to MinikinPaint must also be reflected here. // TODO: language matching (possibly integrate into style) @@ -133,13 +137,16 @@ public: ANDROID_SINGLETON_STATIC_INSTANCE(LayoutEngine); bool LayoutCacheKey::operator==(const LayoutCacheKey& other) const { - return mId == other.mId && - mStart == other.mStart && - mCount == other.mCount && - mStyle == other.mStyle && - mSize == other.mSize && - mIsRtl == other.mIsRtl && - mText == other.mText; + return mId == other.mId + && mStart == other.mStart + && mCount == other.mCount + && mStyle == other.mStyle + && mSize == other.mSize + && mScaleX == other.mScaleX + && mSkewX == other.mSkewX + && mPaintFlags == other.mPaintFlags + && mIsRtl == other.mIsRtl + && mText == other.mText; } hash_t LayoutCacheKey::hash() const { @@ -148,6 +155,9 @@ hash_t LayoutCacheKey::hash() const { hash = JenkinsHashMix(hash, mCount); hash = JenkinsHashMix(hash, hash_type(mStyle)); hash = JenkinsHashMix(hash, hash_type(mSize)); + hash = JenkinsHashMix(hash, hash_type(mScaleX)); + hash = JenkinsHashMix(hash, hash_type(mSkewX)); + hash = JenkinsHashMix(hash, hash_type(mPaintFlags)); hash = JenkinsHashMix(hash, hash_type(mIsRtl)); hash = JenkinsHashMixShorts(hash, mText.string(), mText.size()); return JenkinsHashWhiten(hash); @@ -502,8 +512,13 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu ctx.props.parse(css); ctx.style = styleFromCss(ctx.props); - double size = ctx.props.value(fontSize).getFloatValue(); - ctx.paint.size = size; + ctx.paint.size = ctx.props.value(fontSize).getFloatValue(); + ctx.paint.scaleX = ctx.props.hasTag(fontScaleX) + ? ctx.props.value(fontScaleX).getFloatValue() : 1; + ctx.paint.skewX = ctx.props.hasTag(fontSkewX) + ? ctx.props.value(fontSkewX).getFloatValue() : 0; + ctx.paint.paintFlags = ctx.props.hasTag(paintFlags) + ?ctx.props.value(paintFlags).getIntValue() : 0; int bidiFlags = ctx.props.hasTag(minikinBidi) ? ctx.props.value(minikinBidi).getIntValue() : 0; bool isRtl = (bidiFlags & kDirection_Mask) != 0; bool doSingleRun = true; @@ -635,8 +650,9 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t " [" << run.start << ":" << run.end << "]" << std::endl; #endif double size = ctx->paint.size; - hb_font_set_ppem(hbFont, size, size); - hb_font_set_scale(hbFont, HBFloatToFixed(size), HBFloatToFixed(size)); + double scaleX = ctx->paint.scaleX; + hb_font_set_ppem(hbFont, size * scaleX, size); + hb_font_set_scale(hbFont, HBFloatToFixed(size * scaleX), HBFloatToFixed(size)); // TODO: if there are multiple scripts within a font in an RTL run, // we need to reorder those runs. This is unlikely with our current @@ -665,7 +681,8 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t #endif hb_codepoint_t glyph_ix = info[i].codepoint; float xoff = HBFixedToFloat(positions[i].x_offset); - float yoff = HBFixedToFloat(positions[i].y_offset); + float yoff = -HBFixedToFloat(positions[i].y_offset); + xoff += yoff * ctx->paint.skewX; LayoutGlyph glyph = {font_ix, glyph_ix, x + xoff, y + yoff}; mGlyphs.push_back(glyph); float xAdvance = HBFixedToFloat(positions[i].x_advance); -- cgit v1.2.3