diff options
Diffstat (limited to 'libs/minikin/Layout.cpp')
-rw-r--r-- | libs/minikin/Layout.cpp | 85 |
1 files changed, 53 insertions, 32 deletions
diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp index e7d41c8..6369109 100644 --- a/libs/minikin/Layout.cpp +++ b/libs/minikin/Layout.cpp @@ -18,12 +18,6 @@ #include "minikin/Layout.h" -#include <cmath> -#include <iostream> -#include <mutex> -#include <string> -#include <vector> - #include <hb-icu.h> #include <hb-ot.h> #include <log/log.h> @@ -31,18 +25,22 @@ #include <unicode/utf16.h> #include <utils/LruCache.h> -#include "minikin/Emoji.h" -#include "minikin/HbUtils.h" -#include "minikin/LayoutCache.h" -#include "minikin/LayoutPieces.h" -#include "minikin/Macros.h" +#include <cmath> +#include <iostream> +#include <mutex> +#include <string> +#include <vector> #include "BidiUtils.h" #include "LayoutSplitter.h" #include "LayoutUtils.h" #include "LocaleListCache.h" #include "MinikinInternal.h" - +#include "minikin/Emoji.h" +#include "minikin/HbUtils.h" +#include "minikin/LayoutCache.h" +#include "minikin/LayoutPieces.h" +#include "minikin/Macros.h" namespace minikin { void Layout::doLayout(const U16StringPiece& textBuf, const Range& range, Bidi bidiFlags, @@ -53,19 +51,27 @@ void Layout::doLayout(const U16StringPiece& textBuf, const Range& range, Bidi bi mGlyphs.reserve(count); for (const BidiText::RunInfo& runInfo : BidiText(textBuf, range, bidiFlags)) { doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, range.getStart(), - startHyphen, endHyphen, this, nullptr); + startHyphen, endHyphen, this, nullptr, nullptr); } } float Layout::measureText(const U16StringPiece& textBuf, const Range& range, Bidi bidiFlags, const MinikinPaint& paint, StartHyphenEdit startHyphen, - EndHyphenEdit endHyphen, float* advances) { + EndHyphenEdit endHyphen, float* advances, MinikinRect* bounds) { float advance = 0; + + MinikinRect tmpBounds; for (const BidiText::RunInfo& runInfo : BidiText(textBuf, range, bidiFlags)) { const size_t offset = range.toRangeOffset(runInfo.range.getStart()); float* advancesForRun = advances ? advances + offset : nullptr; - advance += doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, 0, startHyphen, - endHyphen, nullptr, advancesForRun); + tmpBounds.setEmpty(); + float run_advance = doLayoutRunCached(textBuf, runInfo.range, runInfo.isRtl, paint, 0, + startHyphen, endHyphen, nullptr, advancesForRun, + bounds ? &tmpBounds : nullptr); + if (bounds) { + bounds->join(tmpBounds, advance, 0); + } + advance += run_advance; } return advance; } @@ -73,11 +79,12 @@ float Layout::measureText(const U16StringPiece& textBuf, const Range& range, Bid float Layout::doLayoutRunCached(const U16StringPiece& textBuf, const Range& range, bool isRtl, const MinikinPaint& paint, size_t dstStart, StartHyphenEdit startHyphen, EndHyphenEdit endHyphen, - Layout* layout, float* advances) { + Layout* layout, float* advances, MinikinRect* bounds) { if (!range.isValid()) { return 0.0f; // ICU failed to retrieve the bidi run? } float advance = 0; + MinikinRect tmpBounds; for (const auto[context, piece] : LayoutSplitter(textBuf, range, isRtl)) { // Hyphenation only applies to the start/end of run. const StartHyphenEdit pieceStartHyphen = @@ -86,25 +93,32 @@ float Layout::doLayoutRunCached(const U16StringPiece& textBuf, const Range& rang (piece.getEnd() == range.getEnd()) ? endHyphen : EndHyphenEdit::NO_EDIT; float* advancesForRun = advances ? advances + (piece.getStart() - range.getStart()) : nullptr; - advance += doLayoutWord(textBuf.data() + context.getStart(), - piece.getStart() - context.getStart(), piece.getLength(), - context.getLength(), isRtl, paint, piece.getStart() - dstStart, - pieceStartHyphen, pieceEndHyphen, layout, advancesForRun); + tmpBounds.setEmpty(); + float word_advance = doLayoutWord( + textBuf.data() + context.getStart(), piece.getStart() - context.getStart(), + piece.getLength(), context.getLength(), isRtl, paint, piece.getStart() - dstStart, + pieceStartHyphen, pieceEndHyphen, layout, advancesForRun, + bounds ? &tmpBounds : nullptr); + if (bounds) { + bounds->join(tmpBounds, advance, 0); + } + advance += word_advance; } return advance; } class LayoutAppendFunctor { public: - LayoutAppendFunctor(Layout* layout, float* advances, float* totalAdvance, uint32_t outOffset, - float wordSpacing) + LayoutAppendFunctor(Layout* layout, float* advances, uint32_t outOffset, float wordSpacing, + MinikinRect* bounds) : mLayout(layout), mAdvances(advances), - mTotalAdvance(totalAdvance), mOutOffset(outOffset), - mWordSpacing(wordSpacing) {} + mWordSpacing(wordSpacing), + mBounds(bounds) {} - void operator()(const LayoutPiece& layoutPiece, const MinikinPaint& /* paint */) { + void operator()(const LayoutPiece& layoutPiece, const MinikinPaint& /* paint */, + const MinikinRect& bounds) { if (mLayout) { mLayout->appendLayout(layoutPiece, mOutOffset, mWordSpacing); } @@ -112,30 +126,37 @@ public: const std::vector<float>& advances = layoutPiece.advances(); std::copy(advances.begin(), advances.end(), mAdvances); } - if (mTotalAdvance) { - *mTotalAdvance = layoutPiece.advance(); + if (mBounds) { + mBounds->join(bounds, mTotalAdvance, 0); } + mTotalAdvance += layoutPiece.advance(); } + float getTotalAdvance() { return mTotalAdvance; } + private: Layout* mLayout; float* mAdvances; - float* mTotalAdvance; + float mTotalAdvance{0}; const uint32_t mOutOffset; const float mWordSpacing; + MinikinRect* mBounds; }; float Layout::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) { + float* advances, MinikinRect* bounds) { float wordSpacing = count == 1 && isWordSpace(buf[start]) ? paint.wordSpacing : 0; float totalAdvance = 0; + const bool boundsCalculation = bounds != nullptr; const U16StringPiece textBuf(buf, bufSize); const Range range(start, start + count); - LayoutAppendFunctor f(layout, advances, &totalAdvance, bufStart, wordSpacing); - LayoutCache::getInstance().getOrCreate(textBuf, range, paint, isRtl, startHyphen, endHyphen, f); + LayoutAppendFunctor f(layout, advances, bufStart, wordSpacing, bounds); + LayoutCache::getInstance().getOrCreate(textBuf, range, paint, isRtl, startHyphen, endHyphen, + boundsCalculation, f); + totalAdvance = f.getTotalAdvance(); if (wordSpacing != 0) { totalAdvance += wordSpacing; |