From ea408fc18e8e78d984ebdf63703da668a15720de Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Thu, 18 Feb 2016 11:35:42 -0800 Subject: Optimize: Use measureText instead of doLayout. With this CL, measureText is used for getRunAdvance, getOffsetForAdvance and line breaking. Bug: 24505153 Change-Id: Ib699f6b1391b46537736fc274cdb41686586b550 --- include/minikin/Measurement.h | 5 +++-- libs/minikin/LineBreaker.cpp | 24 ++++++++++++------------ libs/minikin/Measurement.cpp | 20 ++++++++++---------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/minikin/Measurement.h b/include/minikin/Measurement.h index fc47fa3..7bcab66 100644 --- a/include/minikin/Measurement.h +++ b/include/minikin/Measurement.h @@ -21,9 +21,10 @@ namespace android { -float getRunAdvance(Layout& layout, const uint16_t* buf, size_t start, size_t count, size_t offset); +float getRunAdvance(const float* advances, const uint16_t* buf, size_t start, size_t count, + size_t offset); -size_t getOffsetForAdvance(Layout& layout, const uint16_t* buf, size_t start, size_t count, +size_t getOffsetForAdvance(const float* advances, const uint16_t* buf, size_t start, size_t count, float advance); } diff --git a/libs/minikin/LineBreaker.cpp b/libs/minikin/LineBreaker.cpp index 22c3954..9c4ff6f 100644 --- a/libs/minikin/LineBreaker.cpp +++ b/libs/minikin/LineBreaker.cpp @@ -122,17 +122,13 @@ static bool isLineBreakingHyphen(uint16_t c) { // to addCandidate. float LineBreaker::addStyleRun(MinikinPaint* paint, const FontCollection* typeface, FontStyle style, size_t start, size_t end, bool isRtl) { - Layout layout; // performance TODO: move layout to self object to reduce allocation cost? float width = 0.0f; int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; float hyphenPenalty = 0.0; if (paint != nullptr) { - layout.setFontCollection(typeface); - layout.doLayout(mTextBuf.data(), start, end - start, mTextBuf.size(), bidiFlags, style, - *paint); - layout.getAdvances(mCharWidths.data() + start); - width = layout.getAdvance(); + width = Layout::measureText(mTextBuf.data(), start, end - start, mTextBuf.size(), bidiFlags, + style, *paint, typeface, mCharWidths.data() + start); // a heuristic that seems to perform well hyphenPenalty = 0.5 * paint->size * paint->scaleX * mLineWidths.getLineWidth(0); @@ -192,13 +188,17 @@ float LineBreaker::addStyleRun(MinikinPaint* paint, const FontCollection* typefa uint8_t hyph = mHyphBuf[j - wordStart]; if (hyph) { paint->hyphenEdit = hyph; - layout.doLayout(mTextBuf.data(), lastBreak, j - lastBreak, - mTextBuf.size(), bidiFlags, style, *paint); - ParaWidth hyphPostBreak = lastBreakWidth + layout.getAdvance(); + + const float firstPartWidth = Layout::measureText(mTextBuf.data(), + lastBreak, j - lastBreak, mTextBuf.size(), bidiFlags, style, + *paint, typeface, nullptr); + ParaWidth hyphPostBreak = lastBreakWidth + firstPartWidth; paint->hyphenEdit = 0; - layout.doLayout(mTextBuf.data(), j, afterWord - j, - mTextBuf.size(), bidiFlags, style, *paint); - ParaWidth hyphPreBreak = postBreak - layout.getAdvance(); + + const float secondPartWith = Layout::measureText(mTextBuf.data(), j, + afterWord - j, mTextBuf.size(), bidiFlags, style, *paint, + typeface, nullptr); + ParaWidth hyphPreBreak = postBreak - secondPartWith; addWordBreak(j, hyphPreBreak, hyphPostBreak, hyphenPenalty, hyph); } } diff --git a/libs/minikin/Measurement.cpp b/libs/minikin/Measurement.cpp index 0b68ac5..1ba6678 100644 --- a/libs/minikin/Measurement.cpp +++ b/libs/minikin/Measurement.cpp @@ -28,26 +28,26 @@ namespace android { // These could be considered helper methods of layout, but need only be loosely coupled, so // are separate. -static float getRunAdvance(Layout& layout, const uint16_t* buf, size_t layoutStart, size_t start, - size_t count, size_t offset) { +static float getRunAdvance(const float* advances, const uint16_t* buf, size_t layoutStart, + size_t start, size_t count, size_t offset) { float advance = 0.0f; size_t lastCluster = start; float clusterWidth = 0.0f; for (size_t i = start; i < offset; i++) { - float charAdvance = layout.getCharAdvance(i - layoutStart); + float charAdvance = advances[i - layoutStart]; if (charAdvance != 0.0f) { advance += charAdvance; lastCluster = i; clusterWidth = charAdvance; } } - if (offset < start + count && layout.getCharAdvance(offset - layoutStart) == 0.0f) { + if (offset < start + count && advances[offset - layoutStart] == 0.0f) { // In the middle of a cluster, distribute width of cluster so that each grapheme cluster // gets an equal share. // TODO: get caret information out of font when that's available size_t nextCluster; for (nextCluster = offset + 1; nextCluster < start + count; nextCluster++) { - if (layout.getCharAdvance(nextCluster - layoutStart) != 0.0f) break; + if (advances[nextCluster - layoutStart] != 0.0f) break; } int numGraphemeClusters = 0; int numGraphemeClustersAfter = 0; @@ -67,9 +67,9 @@ static float getRunAdvance(Layout& layout, const uint16_t* buf, size_t layoutSta return advance; } -float getRunAdvance(Layout& layout, const uint16_t* buf, size_t start, size_t count, +float getRunAdvance(const float* advances, const uint16_t* buf, size_t start, size_t count, size_t offset) { - return getRunAdvance(layout, buf, start, start, count, offset); + return getRunAdvance(advances, buf, start, start, count, offset); } /** @@ -80,7 +80,7 @@ float getRunAdvance(Layout& layout, const uint16_t* buf, size_t start, size_t co * The actual implementation fast-forwards through clusters to get "close", then does a finer-grain * search within the cluster and grapheme breaks. */ -size_t getOffsetForAdvance(Layout& layout, const uint16_t* buf, size_t start, size_t count, +size_t getOffsetForAdvance(const float* advances, const uint16_t* buf, size_t start, size_t count, float advance) { float x = 0.0f, xLastClusterStart = 0.0f, xSearchStart = 0.0f; size_t lastClusterStart = start, searchStart = start; @@ -89,7 +89,7 @@ size_t getOffsetForAdvance(Layout& layout, const uint16_t* buf, size_t start, si searchStart = lastClusterStart; xSearchStart = xLastClusterStart; } - float width = layout.getCharAdvance(i - start); + float width = advances[i - start]; if (width != 0.0f) { lastClusterStart = i; xLastClusterStart = x; @@ -104,7 +104,7 @@ size_t getOffsetForAdvance(Layout& layout, const uint16_t* buf, size_t start, si for (size_t i = searchStart; i <= start + count; i++) { if (GraphemeBreak::isGraphemeBreak(buf, start, count, i)) { // "getRunAdvance(layout, buf, start, count, i) - advance" but more efficient - float delta = getRunAdvance(layout, buf, start, searchStart, count - searchStart, i) + float delta = getRunAdvance(advances, buf, start, searchStart, count - searchStart, i) + xSearchStart - advance; if (std::abs(delta) < bestDist) { -- cgit v1.2.3