From 84b080abc57a299fc2ea0d0b0b09d895476ca2a9 Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Tue, 13 Oct 2015 19:20:09 +0900 Subject: [PATCH] Add light weight methods for text measurement. The intruduced method measureText can be used instead of doLayout for text measurement purpose. Bug: 24505153 Change-Id: Ic29bbb347daf18d1f6c13f86970dcdd11dd6a2bd --- engine/src/flutter/include/minikin/Layout.h | 16 +++-- engine/src/flutter/libs/minikin/Layout.cpp | 68 ++++++++++++++++----- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/engine/src/flutter/include/minikin/Layout.h b/engine/src/flutter/include/minikin/Layout.h index cb68db9c3d..d9bb01f1a7 100644 --- a/engine/src/flutter/include/minikin/Layout.h +++ b/engine/src/flutter/include/minikin/Layout.h @@ -93,6 +93,10 @@ public: void doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize, int bidiFlags, const FontStyle &style, const MinikinPaint &paint); + static float measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, + int bidiFlags, const FontStyle &style, const MinikinPaint &paint, + const FontCollection* collection, float* advances); + void draw(minikin::Bitmap*, int x0, int y0, float size) const; // Deprecated. Nont needed. Remove when callers are removed. @@ -129,12 +133,16 @@ private: int findFace(FakedFont face, LayoutContext* ctx); // Lay out a single bidi run - void doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength, size_t bufSize, - bool isRtl, LayoutContext* ctx, size_t dstStart); + // When layout is not null, layout info will be stored in the object. + // When advances is not null, measurement results will be stored in the array. + static float doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength, + size_t bufSize, bool isRtl, LayoutContext* ctx, size_t dstStart, + const FontCollection* collection, Layout* layout, float* advances); // Lay out a single word - void doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize, - bool isRtl, LayoutContext* ctx, size_t bufStart); + static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize, + bool isRtl, LayoutContext* ctx, size_t bufStart, const FontCollection* collection, + Layout* layout, float* advances); // Lay out a single bidi run void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize, diff --git a/engine/src/flutter/libs/minikin/Layout.cpp b/engine/src/flutter/libs/minikin/Layout.cpp index 2e206a20fc..2839e5b71d 100644 --- a/engine/src/flutter/libs/minikin/Layout.cpp +++ b/engine/src/flutter/libs/minikin/Layout.cpp @@ -596,15 +596,37 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu for (const BidiText::Iter::RunInfo& runInfo : BidiText(buf, start, count, bufSize, bidiFlags)) { doLayoutRunCached(buf, runInfo.mRunStart, runInfo.mRunLength, bufSize, runInfo.mIsRtl, &ctx, - start); + start, mCollection, this, NULL); } ctx.clearHbFonts(); mCollection->purgeFontFamilyHbFontCache(); } -void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize, - bool isRtl, LayoutContext* ctx, size_t dstStart) { +float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, + int bidiFlags, const FontStyle &style, const MinikinPaint &paint, + const FontCollection* collection, float* advances) { + AutoMutex _l(gMinikinLock); + + LayoutContext ctx; + ctx.style = style; + ctx.paint = paint; + + float advance = 0; + for (const BidiText::Iter::RunInfo& runInfo : BidiText(buf, start, count, bufSize, bidiFlags)) { + float* advancesForRun = advances ? advances + (runInfo.mRunStart - start) : advances; + advance += doLayoutRunCached(buf, runInfo.mRunStart, runInfo.mRunLength, bufSize, + runInfo.mIsRtl, &ctx, 0, collection, NULL, advancesForRun); + } + + ctx.clearHbFonts(); + return advance; +} + +float Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize, + bool isRtl, LayoutContext* ctx, size_t dstStart, const FontCollection* collection, + Layout* layout, float* advances) { HyphenEdit hyphen = ctx->paint.hyphenEdit; + float advance = 0; if (!isRtl) { // left to right size_t wordstart = @@ -615,8 +637,9 @@ void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, // 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; - doLayoutWord(buf + wordstart, iter - wordstart, wordcount, wordend - wordstart, - isRtl, ctx, iter - dstStart); + advance += doLayoutWord(buf + wordstart, iter - wordstart, wordcount, + wordend - wordstart, isRtl, ctx, iter - dstStart, collection, layout, + advances ? advances + (iter - start) : advances); wordstart = wordend; } } else { @@ -629,25 +652,40 @@ void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, // 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); - doLayoutWord(buf + wordstart, bufStart - wordstart, iter - bufStart, - wordend - wordstart, isRtl, ctx, bufStart - dstStart); + advance += doLayoutWord(buf + wordstart, bufStart - wordstart, iter - bufStart, + wordend - wordstart, isRtl, ctx, bufStart - dstStart, collection, layout, + advances ? advances + (bufStart - start) : advances); wordend = wordstart; } } + return advance; } -void Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize, - bool isRtl, LayoutContext* ctx, size_t bufStart) { +float Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize, + bool isRtl, LayoutContext* ctx, size_t bufStart, const FontCollection* collection, + Layout* layout, float* advances) { LayoutCache& cache = LayoutEngine::getInstance().layoutCache; - LayoutCacheKey key(mCollection, ctx->paint, ctx->style, buf, start, count, bufSize, isRtl); + LayoutCacheKey key(collection, ctx->paint, ctx->style, buf, start, count, bufSize, isRtl); bool skipCache = ctx->paint.skipCache(); if (skipCache) { - Layout layout; - key.doLayout(&layout, ctx, mCollection); - appendLayout(&layout, bufStart); + Layout layoutForWord; + key.doLayout(&layoutForWord, ctx, collection); + if (layout) { + layout->appendLayout(&layoutForWord, bufStart); + } + if (advances) { + layoutForWord.getAdvances(advances); + } + return layoutForWord.getAdvance(); } else { - Layout* layout = cache.get(key, ctx, mCollection); - appendLayout(layout, bufStart); + Layout* layoutForWord = cache.get(key, ctx, collection); + if (layout) { + layout->appendLayout(layoutForWord, bufStart); + } + if (advances) { + layoutForWord->getAdvances(advances); + } + return layoutForWord->getAdvance(); } }