summaryrefslogtreecommitdiff
path: root/include/minikin/Layout.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/minikin/Layout.h')
-rw-r--r--include/minikin/Layout.h101
1 files changed, 69 insertions, 32 deletions
diff --git a/include/minikin/Layout.h b/include/minikin/Layout.h
index 0d72317..0676c8c 100644
--- a/include/minikin/Layout.h
+++ b/include/minikin/Layout.h
@@ -22,6 +22,7 @@
#include <vector>
#include <gtest/gtest_prod.h>
+#include <utils/JenkinsHash.h>
#include "minikin/FontCollection.h"
#include "minikin/Range.h"
@@ -87,12 +88,15 @@ public:
void doLayout(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
const MinikinPaint& paint, StartHyphenEdit startHyphen, EndHyphenEdit endHyphen);
- static void addToLayoutPieces(const U16StringPiece& textBuf, const Range& range, Bidi bidiFlag,
- const MinikinPaint& paint, LayoutPieces* out);
+ void doLayoutWithPrecomputedPieces(const U16StringPiece& str, const Range& range,
+ Bidi bidiFlags, const MinikinPaint& paint,
+ StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
+ const LayoutPieces& pieces);
static float measureText(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
const MinikinPaint& paint, StartHyphenEdit startHyphen,
- EndHyphenEdit endHyphen, float* advances, MinikinExtent* extents);
+ EndHyphenEdit endHyphen, float* advances, MinikinExtent* extents,
+ LayoutPieces* pieces);
inline const std::vector<float>& advances() const { return mAdvances; }
@@ -139,11 +143,7 @@ private:
friend class LayoutCacheKey;
friend class LayoutCache;
- // TODO: Remove friend class with decoupling building logic from Layout.
- friend class LayoutCompositer;
-
- // TODO: Remove friend test by doing text layout in unit test.
- FRIEND_TEST(MeasuredTextTest, buildLayoutTest);
+ FRIEND_TEST(LayoutTest, doLayoutWithPrecomputedPiecesTest);
// Find a face in the mFaces vector. If not found, push back the entry to mFaces.
uint8_t findOrPushBackFace(const FakedFont& face);
@@ -157,14 +157,15 @@ private:
static float doLayoutRunCached(const U16StringPiece& textBuf, const Range& range, bool isRtl,
const MinikinPaint& paint, size_t dstStart,
StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
- Layout* layout, float* advances, MinikinExtent* extents,
- LayoutPieces* lpOut);
+ const LayoutPieces* lpIn, Layout* layout, float* advances,
+ MinikinExtent* extents, 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, Layout* layout,
- float* advances, MinikinExtent* extents, LayoutPieces* lpOut);
+ StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
+ const LayoutPieces* lpIn, Layout* layout, float* advances,
+ MinikinExtent* extents, 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,34 +185,70 @@ private:
};
struct LayoutPieces {
- // TODO: Sorted vector of pairs may be faster?
- std::unordered_map<uint32_t, Layout> offsetMap; // start offset to layout index map.
+ 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;
+ }
- uint32_t getMemoryUsage() const {
- uint32_t result = 0;
- for (const auto& i : offsetMap) {
- result += i.second.getMemoryUsage();
+ 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);
}
- return result;
- }
-};
-class LayoutCompositer {
-public:
- LayoutCompositer(uint32_t size) {
- mLayout.reset();
- mLayout.mAdvances.resize(size, 0);
- mLayout.mExtents.resize(size);
+ 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;
+ }
}
- void append(const Layout& layout, uint32_t start, float extraAdvance) {
- mLayout.appendLayout(layout, start, extraAdvance);
+ 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));
}
- Layout build() { return std::move(mLayout); }
+ 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;
+ }
-private:
- Layout mLayout;
+ 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