summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeigo Nonaka <nona@google.com>2018-04-02 21:39:34 -0700
committerSeigo Nonaka <nona@google.com>2018-04-04 14:23:08 -0700
commit3da4269e6097e0dafdb438c760dafdde13feda95 (patch)
tree0fb4bdaab0a92603e032e416a16ede258946c27c
parent2adb04f8edb61857a2c53c16ced533df47be67c3 (diff)
downloadminikin-3da4269e6097e0dafdb438c760dafdde13feda95.tar.gz
Include MinikinPaint into cache key
MeasruedText::buildLayout can not be used for acquiring bounding box since the input range can across the style boundary. To make things correctly, include MinikinPaint as the key of the LayoutPiece. This is totally same as the LayoutCacheKey in LayoutCache, so reuses LayoutCacheKey instead of self defined key class in LayoutPiece. This increases the memory usage and ideally run index can be used for layout cache key instead of full MinikinPaint, but let me make thing correct first. Here is a raw performance result. android.text.PrecomputedTextMemoryUsageTest: MemoryUsage Hyphenation : 50,873 -> 59,721: (+17.4%) Hyphenation WidthOnly : 8,856 -> 8,856: (+0.0%) NoHyphenation : 26,386 -> 29,242: (+10.8%) NoHyphenation WidthOnly : 8,000 -> 8,000: (+0.0%) android.text.PrecomputedTextPerfTest: create NoStyle Hyphenation : 18,378,988 -> 18,332,327: (-0.3%) NoStyle Hyphenation WidthOnly : 18,332,392 -> 18,397,337: (+0.4%) NoStyle NoHyphenation : 7,385,258 -> 7,390,699: (+0.1%) NoStyle NoHyphenation WidthOnly : 7,403,445 -> 7,388,476: (-0.2%) Style Hyphenation : 12,637,464 -> 12,624,799: (-0.1%) Style Hyphenation WidthOnly : 12,667,559 -> 12,642,056: (-0.2%) Style NoHyphenation : 12,348,519 -> 12,241,291: (-0.9%) Style NoHyphenation WidthOnly : 12,325,515 -> 12,317,746: (-0.1%) android.text.StaticLayoutPerfTest: create PrecomputedText Balanced Hyphenation : 691,388 -> 680,137: (-1.6%) Balanced NoHyphenation : 502,038 -> 495,980: (-1.2%) Greedy Hyphenation : 451,619 -> 446,380: (-1.2%) Greedy NoHyphenation : 449,011 -> 444,621: (-1.0%) RandomText Balanced Hyphenation : 17,639,029 -> 17,609,190: (-0.2%) Balanced NoHyphenation : 7,295,497 -> 7,251,221: (-0.6%) Greedy Hyphenation : 7,268,452 -> 7,201,506: (-0.9%) Greedy NoHyphenation : 7,215,397 -> 7,225,217: (+0.1%) draw PrecomputedText NoStyle : 588,349 -> 620,041: (+5.4%) NoStyle WithoutCache : 613,312 -> 645,161: (+5.2%) Style : 911,309 -> 938,200: (+3.0%) Style WithoutCache : 920,240 -> 955,410: (+3.8%) RandomText NoStyle : 542,517 -> 555,951: (+2.5%) NoStyle WithoutCache : 6,747,436 -> 6,723,770: (-0.4%) Style : 1,022,591 -> 1,034,170: (+1.1%) Style WithoutCache : 2,862,071 -> 2,835,226: (-0.9%) android.widget.TextViewPrecomputedTextPerfTest: newLayout PrecomputedText : 791,018 -> 785,320: (-0.7%) PrecomputedText Selectable : 1,569,428 -> 1,190,267: (-24.2%) RandomText : 17,146,396 -> 17,064,908: (-0.5%) RandomText Selectable : 18,239,348 -> 18,225,575: (-0.1%) onDraw PrecomputedText : 1,263,842 -> 1,286,294: (+1.8%) PrecomputedText Selectable : 1,380,186 -> 1,303,995: (-5.5%) RandomText : 17,734,725 -> 17,823,735: (+0.5%) RandomText Selectable : 18,549,828 -> 18,610,101: (+0.3%) onMeasure PrecomputedText : 799,962 -> 809,164: (+1.2%) PrecomputedText Selectable : 1,747,993 -> 1,358,504: (-22.3%) RandomText : 17,155,624 -> 17,087,524: (-0.4%) RandomText Selectable : 18,435,408 -> 18,515,944: (+0.4%) setText PrecomputedText : 136,250 -> 133,602: (-1.9%) PrecomputedText Selectable : 213,980 -> 205,610: (-3.9%) RandomText : 16,512 -> 16,599: (+0.5%) RandomText Selectable : 56,143 -> 56,239: (+0.2%) Bug: 77495049 Test: atest CtsWidgetTestCases:EditTextTest CtsWidgetTestCases:TextViewFadingEdgeTest FrameworksCoreTests:TextViewFallbackLineSpacingTest FrameworksCoreTests:TextViewTest FrameworksCoreTests:TypefaceTest CtsGraphicsTestCases:TypefaceTest CtsWidgetTestCases:TextViewTest CtsTextTestCases FrameworksCoreTests:android.text CtsWidgetTestCases:TextViewPrecomputedTextTest Change-Id: I20d7cdd2f11960e334a1f2cd816679bb8f84e6cb
-rw-r--r--include/minikin/Layout.h78
-rw-r--r--include/minikin/LayoutCache.h (renamed from libs/minikin/LayoutCache.h)4
-rw-r--r--include/minikin/LayoutPieces.h76
-rw-r--r--include/minikin/MeasuredText.h18
-rw-r--r--include/minikin/Range.h3
-rw-r--r--libs/minikin/Layout.cpp73
-rw-r--r--libs/minikin/MeasuredText.cpp18
-rw-r--r--tests/unittest/LayoutCacheTest.cpp4
-rw-r--r--tests/unittest/LayoutTest.cpp17
-rw-r--r--tests/unittest/LineBreakerTestHelper.h6
10 files changed, 195 insertions, 102 deletions
diff --git a/include/minikin/Layout.h b/include/minikin/Layout.h
index 0676c8c..ba32d98 100644
--- a/include/minikin/Layout.h
+++ b/include/minikin/Layout.h
@@ -92,6 +92,11 @@ public:
Bidi bidiFlags, const MinikinPaint& paint,
StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
const LayoutPieces& pieces);
+ static std::pair<float, MinikinRect> getBoundsWithPrecomputedPieces(const U16StringPiece& str,
+ const Range& range,
+ Bidi bidiFlags,
+ const MinikinPaint& paint,
+ const LayoutPieces& pieces);
static float measureText(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
const MinikinPaint& paint, StartHyphenEdit startHyphen,
@@ -123,6 +128,7 @@ public:
float getCharAdvance(size_t i) const { return mAdvances[i]; }
void getBounds(MinikinRect* rect) const;
+ const MinikinRect& getBounds() const { return mBounds; }
// Purge all caches, useful in low memory conditions
static void purgeCaches();
@@ -158,14 +164,15 @@ private:
const MinikinPaint& paint, size_t dstStart,
StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
const LayoutPieces* lpIn, Layout* layout, float* advances,
- MinikinExtent* extents, LayoutPieces* lpOut);
+ MinikinExtent* extents, MinikinRect* bounds,
+ LayoutPieces* lpOut);
// Lay out a single word
static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
bool isRtl, const MinikinPaint& paint, size_t bufStart,
StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
const LayoutPieces* lpIn, Layout* layout, float* advances,
- MinikinExtent* extents, LayoutPieces* lpOut);
+ MinikinExtent* extents, MinikinRect* bounds, LayoutPieces* lpOut);
// Lay out a single bidi run
void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize, bool isRtl,
@@ -184,73 +191,6 @@ private:
MinikinRect mBounds;
};
-struct LayoutPieces {
- struct Key {
- Key(const U16StringPiece& textBuf, const Range& range, HyphenEdit edit)
- : text(textBuf.data()), length(textBuf.length()), range(range), hyphenEdit(edit) {}
-
- void makePersistent() {
- uint16_t* copied = new uint16_t[length];
- std::copy(text, text + length, copied);
- text = copied;
- }
-
- inline bool operator==(const Key& o) const {
- return length == o.length && hyphenEdit == o.hyphenEdit && range == o.range &&
- (text == o.text || memcmp(text, o.text, sizeof(uint16_t) * length) == 0);
- }
-
- const uint16_t* text;
- const uint32_t length;
- Range range;
- HyphenEdit hyphenEdit;
- };
-
- struct KeyHasher {
- std::size_t operator()(const Key& key) const {
- uint32_t hash = android::JenkinsHashMix(0, static_cast<uint8_t>(key.hyphenEdit));
- hash = android::JenkinsHashMix(hash, key.range.getStart());
- hash = android::JenkinsHashMix(hash, key.range.getEnd());
- hash = android::JenkinsHashMixShorts(hash, key.text, key.length);
- return android::JenkinsHashWhiten(hash);
- }
- };
-
- LayoutPieces() {}
-
- ~LayoutPieces() {
- for (const auto it : offsetMap) {
- delete[] it.first.text;
- }
- }
-
- std::unordered_map<Key, Layout, KeyHasher> offsetMap;
-
- void insert(const U16StringPiece& textBuf, const Range& range, HyphenEdit edit,
- const Layout& layout) {
- Key key(textBuf, range, edit);
- key.makePersistent();
- offsetMap.insert(std::make_pair(key, layout));
- }
-
- const Layout* get(const U16StringPiece& textBuf, const Range& range, HyphenEdit edit) const {
- auto it = offsetMap.find(Key(textBuf, range, edit));
- if (it == offsetMap.end()) {
- return nullptr;
- }
- return &it->second;
- }
-
- uint32_t getMemoryUsage() const {
- uint32_t result = 0;
- for (const auto& i : offsetMap) {
- result += sizeof(Key) + sizeof(uint16_t) * i.first.length;
- result += i.second.getMemoryUsage();
- }
- return result;
- }
-};
-
} // namespace minikin
#endif // MINIKIN_LAYOUT_H
diff --git a/libs/minikin/LayoutCache.h b/include/minikin/LayoutCache.h
index 5b87fcc..e99fbe4 100644
--- a/libs/minikin/LayoutCache.h
+++ b/include/minikin/LayoutCache.h
@@ -24,8 +24,6 @@
#include <utils/JenkinsHash.h>
#include <utils/LruCache.h>
-#include "LocaleListCache.h"
-
namespace minikin {
// Layout cache datatypes
@@ -81,6 +79,8 @@ public:
mEndHyphen);
}
+ uint32_t getMemoryUsage() const { return sizeof(LayoutCacheKey) + sizeof(uint16_t) * mNchars; }
+
private:
const uint16_t* mChars;
size_t mNchars;
diff --git a/include/minikin/LayoutPieces.h b/include/minikin/LayoutPieces.h
new file mode 100644
index 0000000..f581372
--- /dev/null
+++ b/include/minikin/LayoutPieces.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MINIKIN_LAYOUT_PIECES_H
+#define MINIKIN_LAYOUT_PIECES_H
+
+#include <unordered_map>
+
+#include "minikin/Layout.h"
+#include "minikin/LayoutCache.h"
+
+namespace minikin {
+
+struct LayoutPieces {
+ struct KeyHasher {
+ std::size_t operator()(const LayoutCacheKey& key) const { return key.hash(); }
+ };
+
+ LayoutPieces() {}
+
+ ~LayoutPieces() {
+ for (const auto it : offsetMap) {
+ const_cast<LayoutCacheKey*>(&it.first)->freeText();
+ }
+ }
+
+ std::unordered_map<LayoutCacheKey, Layout, KeyHasher> offsetMap;
+
+ void insert(const U16StringPiece& textBuf, const Range& range, const MinikinPaint& paint,
+ bool dir, StartHyphenEdit startEdit, EndHyphenEdit endEdit, const Layout& layout) {
+ auto result = offsetMap.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(textBuf, range, paint, dir, startEdit, endEdit),
+ std::forward_as_tuple(layout));
+ if (result.second) {
+ const_cast<LayoutCacheKey*>(&result.first->first)->copyText();
+ }
+ }
+
+ template <typename F>
+ void getOrCreate(const U16StringPiece& textBuf, const Range& range, const MinikinPaint& paint,
+ bool dir, StartHyphenEdit startEdit, EndHyphenEdit endEdit, F& f) const {
+ auto it = offsetMap.find(LayoutCacheKey(textBuf, range, paint, dir, startEdit, endEdit));
+ if (it == offsetMap.end()) {
+ LayoutCache::getInstance().getOrCreate(textBuf, range, paint, dir, startEdit, endEdit,
+ f);
+ } else {
+ f(it->second);
+ }
+ }
+
+ uint32_t getMemoryUsage() const {
+ uint32_t result = 0;
+ for (const auto& i : offsetMap) {
+ result += i.first.getMemoryUsage() + i.second.getMemoryUsage();
+ }
+ return result;
+ }
+};
+
+} // namespace minikin
+
+#endif // MINIKIN_LAYOUT_PIECES_H
diff --git a/include/minikin/MeasuredText.h b/include/minikin/MeasuredText.h
index 474cdf3..d33a1ca 100644
--- a/include/minikin/MeasuredText.h
+++ b/include/minikin/MeasuredText.h
@@ -22,6 +22,7 @@
#include "minikin/FontCollection.h"
#include "minikin/Layout.h"
+#include "minikin/LayoutPieces.h"
#include "minikin/Macros.h"
#include "minikin/MinikinFont.h"
#include "minikin/Range.h"
@@ -47,6 +48,9 @@ public:
virtual void getMetrics(const U16StringPiece& text, float* advances, MinikinExtent* extents,
LayoutPieces* piece) const = 0;
+ virtual std::pair<float, MinikinRect> getBounds(const U16StringPiece& text, const Range& range,
+ const LayoutPieces& pieces) const = 0;
+
// Following two methods are only called when the implementation returns true for
// canHyphenate method.
@@ -85,6 +89,12 @@ public:
EndHyphenEdit::NO_EDIT, advances, extents, pieces);
}
+ std::pair<float, MinikinRect> getBounds(const U16StringPiece& text, const Range& range,
+ const LayoutPieces& pieces) const override {
+ Bidi bidiFlag = mIsRtl ? Bidi::FORCE_RTL : Bidi::FORCE_LTR;
+ return Layout::getBoundsWithPrecomputedPieces(text, range, bidiFlag, mPaint, pieces);
+ }
+
const MinikinPaint* getPaint() const override { return &mPaint; }
float measureHyphenPiece(const U16StringPiece& text, const Range& range,
@@ -115,6 +125,13 @@ public:
// TODO: Get the extents information from the caller.
}
+ std::pair<float, MinikinRect> getBounds(const U16StringPiece& /* text */,
+ const Range& /* range */,
+ const LayoutPieces& /* pieces */) const override {
+ // Bounding Box is not used in replacement run.
+ return std::make_pair(mWidth, MinikinRect());
+ }
+
private:
const float mWidth;
const uint32_t mLocaleListId;
@@ -165,6 +182,7 @@ public:
void buildLayout(const U16StringPiece& textBuf, const Range& range, const MinikinPaint& paint,
Bidi bidiFlag, StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
Layout* layout);
+ MinikinRect getBounds(const U16StringPiece& textBuf, const Range& range);
MeasuredText(MeasuredText&&) = default;
MeasuredText& operator=(MeasuredText&&) = default;
diff --git a/include/minikin/Range.h b/include/minikin/Range.h
index 2efde7e..4c7fbfa 100644
--- a/include/minikin/Range.h
+++ b/include/minikin/Range.h
@@ -73,6 +73,9 @@ public:
return left.isValid() && right.isValid() && left.mStart < right.mEnd &&
right.mStart < left.mEnd;
}
+ inline static Range intersection(const Range& left, const Range& right) {
+ return Range(std::max(left.mStart, right.mStart), std::min(left.mEnd, right.mEnd));
+ }
// Returns merged range. This method assumes left and right are not invalid ranges and they have
// an intersection.
diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp
index 4383d60..1b05274 100644
--- a/libs/minikin/Layout.cpp
+++ b/libs/minikin/Layout.cpp
@@ -34,10 +34,11 @@
#include "minikin/Emoji.h"
#include "minikin/HbUtils.h"
+#include "minikin/LayoutCache.h"
+#include "minikin/LayoutPieces.h"
#include "minikin/Macros.h"
#include "BidiUtils.h"
-#include "LayoutCache.h"
#include "LayoutUtils.h"
#include "LocaleListCache.h"
#include "MinikinInternal.h"
@@ -234,7 +235,8 @@ void Layout::doLayout(const U16StringPiece& textBuf, const Range& range, Bidi bi
for (const BidiText::RunInfo& runInfo : BidiText(textBuf, range, bidiFlags)) {
doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, range.getStart(),
- startHyphen, endHyphen, nullptr, this, nullptr, nullptr, nullptr);
+ startHyphen, endHyphen, nullptr, this, nullptr, nullptr, nullptr,
+ nullptr);
}
}
@@ -249,10 +251,25 @@ void Layout::doLayoutWithPrecomputedPieces(const U16StringPiece& textBuf, const
for (const BidiText::RunInfo& runInfo : BidiText(textBuf, range, bidiFlags)) {
doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, range.getStart(),
- startHyphen, endHyphen, &lpIn, this, nullptr, nullptr, nullptr);
+ startHyphen, endHyphen, &lpIn, this, nullptr, nullptr, nullptr, nullptr);
}
}
+std::pair<float, MinikinRect> Layout::getBoundsWithPrecomputedPieces(const U16StringPiece& textBuf,
+ const Range& range,
+ Bidi bidiFlags,
+ const MinikinPaint& paint,
+ const LayoutPieces& pieces) {
+ MinikinRect rect;
+ float advance = 0;
+ for (const BidiText::RunInfo& runInfo : BidiText(textBuf, range, bidiFlags)) {
+ advance += doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, 0,
+ StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, &pieces,
+ nullptr, nullptr, nullptr, &rect, nullptr);
+ }
+ return std::make_pair(advance, rect);
+}
+
float Layout::measureText(const U16StringPiece& textBuf, const Range& range, Bidi bidiFlags,
const MinikinPaint& paint, StartHyphenEdit startHyphen,
EndHyphenEdit endHyphen, float* advances, MinikinExtent* extents,
@@ -264,7 +281,7 @@ float Layout::measureText(const U16StringPiece& textBuf, const Range& range, Bid
MinikinExtent* extentsForRun = extents ? extents + offset : nullptr;
advance += doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, 0, startHyphen,
endHyphen, nullptr, nullptr, advancesForRun, extentsForRun,
- pieces);
+ nullptr, pieces);
}
return advance;
}
@@ -273,7 +290,7 @@ float Layout::doLayoutRunCached(const U16StringPiece& textBuf, const Range& rang
const MinikinPaint& paint, size_t dstStart,
StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
const LayoutPieces* lpIn, Layout* layout, float* advances,
- MinikinExtent* extents, LayoutPieces* lpOut) {
+ MinikinExtent* extents, MinikinRect* bounds, LayoutPieces* lpOut) {
if (!range.isValid()) {
return 0.0f; // ICU failed to retrieve the bidi run?
}
@@ -297,7 +314,7 @@ float Layout::doLayoutRunCached(const U16StringPiece& textBuf, const Range& rang
iter == start ? startHyphen : StartHyphenEdit::NO_EDIT,
wordend >= end ? endHyphen : EndHyphenEdit::NO_EDIT, lpIn,
layout, advances ? advances + offset : nullptr,
- extents ? extents + offset : nullptr, lpOut);
+ extents ? extents + offset : nullptr, bounds, lpOut);
wordstart = wordend;
}
} else {
@@ -315,7 +332,7 @@ float Layout::doLayoutRunCached(const U16StringPiece& textBuf, const Range& rang
wordstart <= start ? startHyphen : StartHyphenEdit::NO_EDIT,
iter == end ? endHyphen : EndHyphenEdit::NO_EDIT, lpIn, layout,
advances ? advances + offset : nullptr,
- extents ? extents + offset : nullptr, lpOut);
+ extents ? extents + offset : nullptr, bounds, lpOut);
wordend = wordstart;
}
}
@@ -324,18 +341,23 @@ float Layout::doLayoutRunCached(const U16StringPiece& textBuf, const Range& rang
class LayoutAppendFunctor {
public:
- LayoutAppendFunctor(const U16StringPiece& textBuf, const Range& range, HyphenEdit hyphenEdit,
- Layout* layout, float* advances, MinikinExtent* extents,
- LayoutPieces* pieces, float* totalAdvance, uint32_t outOffset,
- float wordSpacing)
+ LayoutAppendFunctor(const U16StringPiece& textBuf, const Range& range,
+ const MinikinPaint& paint, bool dir, StartHyphenEdit startEdit,
+ EndHyphenEdit endEdit, Layout* layout, float* advances,
+ MinikinExtent* extents, LayoutPieces* pieces, float* totalAdvance,
+ MinikinRect* bounds, uint32_t outOffset, float wordSpacing)
: mTextBuf(textBuf),
mRange(range),
- mHyphenEdit(hyphenEdit),
+ mPaint(paint),
+ mDir(dir),
+ mStartEdit(startEdit),
+ mEndEdit(endEdit),
mLayout(layout),
mAdvances(advances),
mExtents(extents),
mPieces(pieces),
mTotalAdvance(totalAdvance),
+ mBounds(bounds),
mOutOffset(outOffset),
mWordSpacing(wordSpacing) {}
@@ -352,20 +374,27 @@ public:
if (mExtents) {
layout.getExtents(mExtents);
}
+ if (mBounds) {
+ mBounds->join(layout.getBounds());
+ }
if (mPieces) {
- mPieces->insert(mTextBuf, mRange, mHyphenEdit, layout);
+ mPieces->insert(mTextBuf, mRange, mPaint, mDir, mStartEdit, mEndEdit, layout);
}
}
private:
const U16StringPiece& mTextBuf;
const Range& mRange;
- HyphenEdit mHyphenEdit;
+ const MinikinPaint& mPaint;
+ bool mDir;
+ StartHyphenEdit mStartEdit;
+ EndHyphenEdit mEndEdit;
Layout* mLayout;
float* mAdvances;
MinikinExtent* mExtents;
LayoutPieces* mPieces;
float* mTotalAdvance;
+ MinikinRect* mBounds;
const uint32_t mOutOffset;
const float mWordSpacing;
};
@@ -374,22 +403,16 @@ float Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size
bool isRtl, const MinikinPaint& paint, size_t bufStart,
StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
const LayoutPieces* lpIn, Layout* layout, float* advances,
- MinikinExtent* extents, LayoutPieces* lpOut) {
+ MinikinExtent* extents, MinikinRect* bounds, LayoutPieces* lpOut) {
float wordSpacing = count == 1 && isWordSpace(buf[start]) ? paint.wordSpacing : 0;
float totalAdvance;
const U16StringPiece textBuf(buf, bufSize);
const Range range(start, start + count);
- HyphenEdit hyphenEdit = packHyphenEdit(startHyphen, endHyphen);
-
- LayoutAppendFunctor f(textBuf, range, hyphenEdit, layout, advances, extents, lpOut,
- &totalAdvance, bufStart, wordSpacing);
-
- const Layout* layoutInPieces =
- lpIn == nullptr ? nullptr : lpIn->get(textBuf, range, hyphenEdit);
-
- if (layoutInPieces != nullptr) {
- f(*layoutInPieces);
+ LayoutAppendFunctor f(textBuf, range, paint, isRtl, startHyphen, endHyphen, layout, advances,
+ extents, lpOut, &totalAdvance, bounds, bufStart, wordSpacing);
+ if (lpIn != nullptr) {
+ lpIn->getOrCreate(textBuf, range, paint, isRtl, startHyphen, endHyphen, f);
} else {
LayoutCache::getInstance().getOrCreate(textBuf, range, paint, isRtl, startHyphen, endHyphen,
f);
diff --git a/libs/minikin/MeasuredText.cpp b/libs/minikin/MeasuredText.cpp
index 7be949b..bbc6091 100644
--- a/libs/minikin/MeasuredText.cpp
+++ b/libs/minikin/MeasuredText.cpp
@@ -63,4 +63,22 @@ void MeasuredText::buildLayout(const U16StringPiece& textBuf, const Range& range
layoutPieces);
}
+MinikinRect MeasuredText::getBounds(const U16StringPiece& textBuf, const Range& range) {
+ MinikinRect rect;
+ float advance = 0.0f;
+ for (const auto& run : runs) {
+ const Range& runRange = run->getRange();
+ if (!Range::intersects(range, runRange)) {
+ continue;
+ }
+ std::pair<float, MinikinRect> next =
+ run->getBounds(textBuf, Range::intersection(runRange, range), layoutPieces);
+ MinikinRect nextRect = next.second;
+ nextRect.offset(advance, 0);
+ rect.join(nextRect);
+ advance += next.first;
+ }
+ return rect;
+}
+
} // namespace minikin
diff --git a/tests/unittest/LayoutCacheTest.cpp b/tests/unittest/LayoutCacheTest.cpp
index 8235556..b7ad0ba 100644
--- a/tests/unittest/LayoutCacheTest.cpp
+++ b/tests/unittest/LayoutCacheTest.cpp
@@ -18,8 +18,10 @@
#include <gtest/gtest.h>
+#include "minikin/LayoutCache.h"
+
#include "FontTestUtils.h"
-#include "LayoutCache.h"
+#include "LocaleListCache.h"
#include "UnicodeUtils.h"
namespace minikin {
diff --git a/tests/unittest/LayoutTest.cpp b/tests/unittest/LayoutTest.cpp
index 830dc92..21109cb 100644
--- a/tests/unittest/LayoutTest.cpp
+++ b/tests/unittest/LayoutTest.cpp
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include "minikin/FontCollection.h"
+#include "minikin/LayoutPieces.h"
#include "FontTestUtils.h"
#include "UnicodeUtils.h"
@@ -554,12 +555,14 @@ TEST_F(LayoutTest, doLayoutWithPrecomputedPiecesTest) {
float MARKER1 = 1e+16;
float MARKER2 = 1e+17;
auto fc = buildFontCollection("LayoutTestFont.ttf");
+ MinikinPaint paint(fc);
{
LayoutPieces pieces;
Layout inLayout = doLayout("I", MinikinPaint(fc));
inLayout.mAdvances[0] = MARKER1; // Modify the advance to make sure this layout is used.
- pieces.insert(utf8ToUtf16("I"), Range(0, 1), 0 /* hyphen edit */, inLayout);
+ pieces.insert(utf8ToUtf16("I"), Range(0, 1), paint, false /* dir */,
+ StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, inLayout);
Layout outLayout = doLayoutWithPrecomputedPieces("I", MinikinPaint(fc), pieces);
EXPECT_EQ(MARKER1, outLayout.mAdvances[0]);
@@ -569,7 +572,8 @@ TEST_F(LayoutTest, doLayoutWithPrecomputedPiecesTest) {
Layout inLayout = doLayout("I", MinikinPaint(fc));
inLayout.mAdvances[0] = MARKER1;
- pieces.insert(utf8ToUtf16("I"), Range(0, 1), 0 /* hyphen edit */, inLayout);
+ pieces.insert(utf8ToUtf16("I"), Range(0, 1), paint, false /* dir */,
+ StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, inLayout);
Layout outLayout = doLayoutWithPrecomputedPieces("II", MinikinPaint(fc), pieces);
// The layout pieces are used in word units. Should not be used "I" for "II".
@@ -581,7 +585,8 @@ TEST_F(LayoutTest, doLayoutWithPrecomputedPiecesTest) {
Layout inLayout = doLayout("I", MinikinPaint(fc));
inLayout.mAdvances[0] = MARKER1;
- pieces.insert(utf8ToUtf16("I"), Range(0, 1), 0 /* hyphen edit */, inLayout);
+ pieces.insert(utf8ToUtf16("I"), Range(0, 1), paint, false /* dir */,
+ StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, inLayout);
Layout outLayout = doLayoutWithPrecomputedPieces("I I", MinikinPaint(fc), pieces);
EXPECT_EQ(MARKER1, outLayout.mAdvances[0]);
@@ -592,11 +597,13 @@ TEST_F(LayoutTest, doLayoutWithPrecomputedPiecesTest) {
Layout inLayout = doLayout("I", MinikinPaint(fc));
inLayout.mAdvances[0] = MARKER1; // Modify the advance to make sure this layout is used.
- pieces.insert(utf8ToUtf16("I"), Range(0, 1), 0 /* hyphen edit */, inLayout);
+ pieces.insert(utf8ToUtf16("I"), Range(0, 1), paint, false /* dir */,
+ StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, inLayout);
inLayout = doLayout("V", MinikinPaint(fc));
inLayout.mAdvances[0] = MARKER2; // Modify the advance to make sure this layout is used.
- pieces.insert(utf8ToUtf16("V"), Range(0, 1), 0 /* hyphen edit */, inLayout);
+ pieces.insert(utf8ToUtf16("V"), Range(0, 1), paint, false /* dir */,
+ StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, inLayout);
Layout outLayout = doLayoutWithPrecomputedPieces("I V", MinikinPaint(fc), pieces);
EXPECT_EQ(MARKER1, outLayout.mAdvances[0]);
diff --git a/tests/unittest/LineBreakerTestHelper.h b/tests/unittest/LineBreakerTestHelper.h
index d6ab740..70d6521 100644
--- a/tests/unittest/LineBreakerTestHelper.h
+++ b/tests/unittest/LineBreakerTestHelper.h
@@ -57,6 +57,12 @@ public:
std::fill(advances, advances + mRange.getLength(), mWidth);
}
+ virtual std::pair<float, MinikinRect> getBounds(const U16StringPiece& /* text */,
+ const Range& /* range */,
+ const LayoutPieces& /* pieces */) const {
+ return std::make_pair(mWidth, MinikinRect());
+ }
+
virtual const MinikinPaint* getPaint() const { return &mPaint; }
virtual float measureHyphenPiece(const U16StringPiece&, const Range& range,