Make font runs less sticky

Fixes b/15734816 In the text "Wi-Fi", "-Fi" appears bolder than "Wi"

The problem was caused by "stickiness" in choosing fonts, where layout
would prefer using a font used for preceding characters as long as it
mapped the following characters in a run, in favor of the "best match"
rules. This patch adds a whitelist for making the stickiness more
conservative, only applying it for characters necessary for correct
shaping (ZWJ and ZWNJ in particular) and basic punctuation, where it is
desirable to match the style of the preceding text.

Change-Id: I1cf116879f074a5a71c351846707bfdd07b0d320
This commit is contained in:
Raph Levien
2014-06-19 01:51:47 -07:00
parent 01d64756a7
commit ba5dbb6f24

View File

@@ -147,6 +147,20 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
return bestInstance;
}
const uint32_t NBSP = 0xa0;
const uint32_t ZWJ = 0x200c;
const uint32_t ZWNJ = 0x200d;
// Characters where we want to continue using existing font run instead of
// recomputing the best match in the fallback list.
static const uint32_t stickyWhitelist[] = { '!', ',', '.', ':', ';', '?', NBSP, ZWJ, ZWNJ };
static bool isStickyWhitelisted(uint32_t c) {
for (size_t i = 0; i < sizeof(stickyWhitelist) / sizeof(stickyWhitelist[0]); i++) {
if (stickyWhitelist[i] == c) return true;
}
return false;
}
void FontCollection::itemize(const uint16_t *string, size_t string_size, FontStyle style,
vector<Run>* result) const {
FontLanguage lang = style.getLanguage();
@@ -164,8 +178,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
nShorts = 2;
}
}
// Continue using existing font as long as it has coverage.
if (lastInstance == NULL || !lastInstance->mCoverage->get(ch)) {
// Continue using existing font as long as it has coverage and is whitelisted
if (lastInstance == NULL
|| !(isStickyWhitelisted(ch) && lastInstance->mCoverage->get(ch))) {
const FontInstance* instance = getInstanceForChar(ch, lang, variant);
if (i == 0 || instance != lastInstance) {
Run dummy;