HyphenEdit in support of hyphenation
Adds a "HyphenEdit" field to the Minikin Paint object, which represents an edit to the text to add a hyphen (and, in the future, other edits to support nonstandard hyphenation). Change-Id: Ib4ee690b0fe2137e1d1e2c9251e5526b274ec3a7
This commit is contained in:
parent
4c4af7f4dc
commit
aa1337a41a
@ -27,6 +27,18 @@
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
// The hyphen edit represents an edit to the string when a word is
|
||||||
|
// hyphenated. The most common hyphen edit is adding a "-" at the end
|
||||||
|
// of a syllable, but nonstandard hyphenation allows for more choices.
|
||||||
|
class HyphenEdit {
|
||||||
|
public:
|
||||||
|
HyphenEdit() : hyphen(0) { }
|
||||||
|
HyphenEdit(uint32_t hyphenInt) : hyphen(hyphenInt) { }
|
||||||
|
bool hasHyphen() const { return hyphen != 0; }
|
||||||
|
private:
|
||||||
|
uint32_t hyphen;
|
||||||
|
};
|
||||||
|
|
||||||
class MinikinFont;
|
class MinikinFont;
|
||||||
|
|
||||||
// Possibly move into own .h file?
|
// Possibly move into own .h file?
|
||||||
@ -36,7 +48,8 @@ struct MinikinPaint {
|
|||||||
fakery(), fontFeatureSettings() { }
|
fakery(), fontFeatureSettings() { }
|
||||||
|
|
||||||
bool skipCache() const {
|
bool skipCache() const {
|
||||||
return !fontFeatureSettings.empty();
|
// TODO: add hyphen to cache
|
||||||
|
return !fontFeatureSettings.empty() || hyphenEdit.hasHyphen();
|
||||||
}
|
}
|
||||||
|
|
||||||
MinikinFont *font;
|
MinikinFont *font;
|
||||||
@ -46,6 +59,7 @@ struct MinikinPaint {
|
|||||||
float letterSpacing;
|
float letterSpacing;
|
||||||
uint32_t paintFlags;
|
uint32_t paintFlags;
|
||||||
FontFakery fakery;
|
FontFakery fakery;
|
||||||
|
HyphenEdit hyphenEdit;
|
||||||
std::string fontFeatureSettings;
|
std::string fontFeatureSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -594,12 +594,15 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu
|
|||||||
|
|
||||||
void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
|
void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
|
||||||
bool isRtl, LayoutContext* ctx, size_t dstStart) {
|
bool isRtl, LayoutContext* ctx, size_t dstStart) {
|
||||||
|
HyphenEdit hyphen = ctx->paint.hyphenEdit;
|
||||||
if (!isRtl) {
|
if (!isRtl) {
|
||||||
// left to right
|
// left to right
|
||||||
size_t wordstart = start == bufSize ? start : getPrevWordBreak(buf, start + 1);
|
size_t wordstart = start == bufSize ? start : getPrevWordBreak(buf, start + 1);
|
||||||
size_t wordend;
|
size_t wordend;
|
||||||
for (size_t iter = start; iter < start + count; iter = wordend) {
|
for (size_t iter = start; iter < start + count; iter = wordend) {
|
||||||
wordend = getNextWordBreak(buf, iter, bufSize);
|
wordend = getNextWordBreak(buf, iter, bufSize);
|
||||||
|
// Only apply hyphen to the last word in the string.
|
||||||
|
ctx->paint.hyphenEdit = wordend >= start + count ? hyphen : HyphenEdit();
|
||||||
size_t wordcount = std::min(start + count, wordend) - iter;
|
size_t wordcount = std::min(start + count, wordend) - iter;
|
||||||
doLayoutWord(buf + wordstart, iter - wordstart, wordcount, wordend - wordstart,
|
doLayoutWord(buf + wordstart, iter - wordstart, wordcount, wordend - wordstart,
|
||||||
isRtl, ctx, iter - dstStart);
|
isRtl, ctx, iter - dstStart);
|
||||||
@ -612,6 +615,8 @@ void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count,
|
|||||||
size_t wordend = end == 0 ? 0 : getNextWordBreak(buf, end - 1, bufSize);
|
size_t wordend = end == 0 ? 0 : getNextWordBreak(buf, end - 1, bufSize);
|
||||||
for (size_t iter = end; iter > start; iter = wordstart) {
|
for (size_t iter = end; iter > start; iter = wordstart) {
|
||||||
wordstart = getPrevWordBreak(buf, iter);
|
wordstart = getPrevWordBreak(buf, iter);
|
||||||
|
// Only apply hyphen to the last (leftmost) word in the string.
|
||||||
|
ctx->paint.hyphenEdit = iter == end ? hyphen : HyphenEdit();
|
||||||
size_t bufStart = std::max(start, wordstart);
|
size_t bufStart = std::max(start, wordstart);
|
||||||
doLayoutWord(buf + wordstart, bufStart - wordstart, iter - bufStart,
|
doLayoutWord(buf + wordstart, bufStart - wordstart, iter - bufStart,
|
||||||
wordend - wordstart, isRtl, ctx, bufStart - dstStart);
|
wordend - wordstart, isRtl, ctx, bufStart - dstStart);
|
||||||
@ -729,6 +734,12 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
|
|||||||
hb_buffer_set_language(buffer, hb_language_from_string(lang.c_str(), -1));
|
hb_buffer_set_language(buffer, hb_language_from_string(lang.c_str(), -1));
|
||||||
}
|
}
|
||||||
hb_buffer_add_utf16(buffer, buf, bufSize, srunstart + start, srunend - srunstart);
|
hb_buffer_add_utf16(buffer, buf, bufSize, srunstart + start, srunend - srunstart);
|
||||||
|
if (ctx->paint.hyphenEdit.hasHyphen() && srunend > srunstart) {
|
||||||
|
// TODO: check whether this is really the desired semantics. It could have the
|
||||||
|
// effect of assigning the hyphen width to a nonspacing mark
|
||||||
|
unsigned int lastCluster = srunend - 1;
|
||||||
|
hb_buffer_add(buffer, 0x2010, lastCluster);
|
||||||
|
}
|
||||||
hb_shape(hbFont, buffer, features.empty() ? NULL : &features[0], features.size());
|
hb_shape(hbFont, buffer, features.empty() ? NULL : &features[0], features.size());
|
||||||
unsigned int numGlyphs;
|
unsigned int numGlyphs;
|
||||||
hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, &numGlyphs);
|
hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, &numGlyphs);
|
||||||
@ -763,7 +774,12 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
|
|||||||
ctx->paint.font->GetBounds(&glyphBounds, glyph_ix, ctx->paint);
|
ctx->paint.font->GetBounds(&glyphBounds, glyph_ix, ctx->paint);
|
||||||
glyphBounds.offset(x + xoff, y + yoff);
|
glyphBounds.offset(x + xoff, y + yoff);
|
||||||
mBounds.join(glyphBounds);
|
mBounds.join(glyphBounds);
|
||||||
|
if (info[i].cluster - start < count) {
|
||||||
mAdvances[info[i].cluster - start] += xAdvance;
|
mAdvances[info[i].cluster - start] += xAdvance;
|
||||||
|
} else {
|
||||||
|
ALOGE("cluster %d (start %d) out of bounds of count %d",
|
||||||
|
info[i].cluster - start, start, count);
|
||||||
|
}
|
||||||
x += xAdvance;
|
x += xAdvance;
|
||||||
}
|
}
|
||||||
if (numGlyphs)
|
if (numGlyphs)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user