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
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user