提交 8e7a3dae 编写于 作者: B Behdad Esfahbod

Add letter-spacing support

Bug: 15594400
Change-Id: Ied94d7674be4097b0f44c9b0770d3294dc6433c1
上级 4422f4dd
......@@ -30,6 +30,7 @@ enum CssTag {
fontStyle,
fontWeight,
cssLang,
letterSpacing,
minikinBidi,
minikinHinting,
minikinVariant,
......@@ -44,6 +45,7 @@ const std::string cssTagNames[] = {
"font-style",
"font-weight",
"lang",
"letter-spacing",
"-minikin-bidi",
"-minikin-hinting",
"-minikin-variant",
......
......@@ -34,6 +34,7 @@ struct MinikinPaint {
float size;
float scaleX;
float skewX;
float letterSpacing;
uint32_t paintFlags;
FontFakery fakery;
};
......
......@@ -44,6 +44,7 @@ static CssTag parseTag(const string str, size_t off, size_t len) {
if (strEqC(str, off, len, "font-style")) return fontStyle;
} else if (c == 'l') {
if (strEqC(str, off, len, "lang")) return cssLang;
if (strEqC(str, off, len, "letter-spacing")) return letterSpacing;
} else if (c == '-') {
if (strEqC(str, off, len, "-minikin-bidi")) return minikinBidi;
if (strEqC(str, off, len, "-minikin-hinting")) return minikinHinting;
......
......@@ -64,6 +64,7 @@ public:
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), mScaleX(paint.scaleX), mSkewX(paint.skewX),
mLetterSpacing(paint.letterSpacing),
mPaintFlags(paint.paintFlags), mIsRtl(dir) {
mText.setTo(chars, nchars);
}
......@@ -81,6 +82,7 @@ private:
float mSize;
float mScaleX;
float mSkewX;
float mLetterSpacing;
int32_t mPaintFlags;
bool mIsRtl;
// Note: any fields added to MinikinPaint must also be reflected here.
......@@ -144,6 +146,7 @@ bool LayoutCacheKey::operator==(const LayoutCacheKey& other) const {
&& mSize == other.mSize
&& mScaleX == other.mScaleX
&& mSkewX == other.mSkewX
&& mLetterSpacing == other.mLetterSpacing
&& mPaintFlags == other.mPaintFlags
&& mIsRtl == other.mIsRtl
&& mText == other.mText;
......@@ -157,6 +160,7 @@ hash_t LayoutCacheKey::hash() const {
hash = JenkinsHashMix(hash, hash_type(mSize));
hash = JenkinsHashMix(hash, hash_type(mScaleX));
hash = JenkinsHashMix(hash, hash_type(mSkewX));
hash = JenkinsHashMix(hash, hash_type(mLetterSpacing));
hash = JenkinsHashMix(hash, hash_type(mPaintFlags));
hash = JenkinsHashMix(hash, hash_type(mIsRtl));
hash = JenkinsHashMixShorts(hash, mText.string(), mText.size());
......@@ -511,6 +515,8 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu
? ctx.props.value(fontScaleX).getDoubleValue() : 1;
ctx.paint.skewX = ctx.props.hasTag(fontSkewX)
? ctx.props.value(fontSkewX).getDoubleValue() : 0;
ctx.paint.letterSpacing = ctx.props.hasTag(letterSpacing)
? ctx.props.value(letterSpacing).getDoubleValue() : 0;
ctx.paint.paintFlags = ctx.props.hasTag(paintFlags)
? ctx.props.value(paintFlags).getUintValue() : 0;
int bidiFlags = ctx.props.hasTag(minikinBidi) ? ctx.props.value(minikinBidi).getIntValue() : 0;
......@@ -646,8 +652,25 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
}
vector<hb_feature_t> features;
// Disable default-on non-required ligature features if letter-spacing
// See http://dev.w3.org/csswg/css-text-3/#letter-spacing-property
// "When the effective spacing between two characters is not zero (due to
// either justification or a non-zero value of letter-spacing), user agents
// should not apply optional ligatures."
if (fabs(ctx->paint.letterSpacing) > 0.03)
{
static const hb_feature_t no_liga = { HB_TAG('l', 'i', 'g', 'a'), 0, 0, ~0u };
static const hb_feature_t no_clig = { HB_TAG('c', 'l', 'i', 'g'), 0, 0, ~0u };
features.push_back(no_liga);
features.push_back(no_clig);
}
addFeatures(&features);
double size = ctx->paint.size;
double scaleX = ctx->paint.scaleX;
double letterSpace = ctx->paint.letterSpacing * size * scaleX;
double letterSpaceHalf = letterSpace * .5;
float x = mAdvance;
float y = 0;
for (size_t run_ix = 0; run_ix < items.size(); run_ix++) {
......@@ -664,8 +687,7 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
std::cout << "Run " << run_ix << ", font " << font_ix <<
" [" << run.start << ":" << run.end << "]" << std::endl;
#endif
double size = ctx->paint.size;
double scaleX = ctx->paint.scaleX;
hb_font_set_ppem(hbFont, size * scaleX, size);
hb_font_set_scale(hbFont, HBFloatToFixed(size * scaleX), HBFloatToFixed(size));
......@@ -689,11 +711,22 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
unsigned int numGlyphs;
hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, &numGlyphs);
hb_glyph_position_t* positions = hb_buffer_get_glyph_positions(buffer, NULL);
if (numGlyphs)
{
mAdvances[info[0].cluster - start] += letterSpaceHalf;
x += letterSpaceHalf;
}
for (unsigned int i = 0; i < numGlyphs; i++) {
#ifdef VERBOSE
std::cout << positions[i].x_advance << " " << positions[i].y_advance << " " << positions[i].x_offset << " " << positions[i].y_offset << std::endl; std::cout << "DoLayout " << info[i].codepoint <<
": " << HBFixedToFloat(positions[i].x_advance) << "; " << positions[i].x_offset << ", " << positions[i].y_offset << std::endl;
#endif
if (i > 0 && info[i - 1].cluster != info[i].cluster) {
mAdvances[info[i - 1].cluster - start] += letterSpaceHalf;
mAdvances[info[i].cluster - start] += letterSpaceHalf;
x += letterSpaceHalf;
}
hb_codepoint_t glyph_ix = info[i].codepoint;
float xoff = HBFixedToFloat(positions[i].x_offset);
float yoff = -HBFixedToFloat(positions[i].y_offset);
......@@ -705,10 +738,14 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
ctx->paint.font->GetBounds(&glyphBounds, glyph_ix, ctx->paint);
glyphBounds.offset(x + xoff, y + yoff);
mBounds.join(glyphBounds);
size_t cluster = info[i].cluster - start;
mAdvances[cluster] += xAdvance;
mAdvances[info[i].cluster - start] += xAdvance;
x += xAdvance;
}
if (numGlyphs)
{
mAdvances[info[numGlyphs - 1].cluster - start] += letterSpaceHalf;
x += letterSpaceHalf;
}
}
}
mAdvance = x;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册