diff options
Diffstat (limited to 'libs/minikin/LineBreakerUtil.h')
-rw-r--r-- | libs/minikin/LineBreakerUtil.h | 93 |
1 files changed, 79 insertions, 14 deletions
diff --git a/libs/minikin/LineBreakerUtil.h b/libs/minikin/LineBreakerUtil.h index 5764c5e..030e677 100644 --- a/libs/minikin/LineBreakerUtil.h +++ b/libs/minikin/LineBreakerUtil.h @@ -19,19 +19,21 @@ #include <vector> -#include "minikin/Hyphenator.h" -#include "minikin/MeasuredText.h" -#include "minikin/U16StringPiece.h" - #include "HyphenatorMap.h" #include "LayoutUtils.h" #include "Locale.h" #include "LocaleListCache.h" #include "MinikinInternal.h" #include "WordBreaker.h" +#include "minikin/Hyphenator.h" +#include "minikin/LineBreakStyle.h" +#include "minikin/MeasuredText.h" +#include "minikin/U16StringPiece.h" namespace minikin { +constexpr uint32_t LBW_AUTO_HEURISTICS_LINE_COUNT = 5; + // ParaWidth is used to hold cumulative width from beginning of paragraph. Note that for very large // paragraphs, accuracy could degrade using only 32-bit float. Note however that float is used // extensively on the Java side for this. This is a typedef so that we can easily change it based @@ -55,6 +57,15 @@ inline bool isLineEndSpace(uint16_t c) { || c == 0x3000; } +inline Range trimTrailingLineEndSpaces(const U16StringPiece& textBuf, const Range& range) { + for (uint32_t i = 0; i < range.getLength(); i++) { + if (!isLineEndSpace(textBuf[range.getEnd() - i - 1])) { + return Range(range.getStart(), range.getEnd() - i); + } + } + return Range(range.getStart(), range.getStart()); +} + inline Locale getEffectiveLocale(uint32_t localeListId) { const LocaleList& localeList = LocaleListCache::getById(localeListId); return localeList.empty() ? Locale() : localeList[0]; @@ -125,6 +136,58 @@ inline void populateHyphenationPoints( } } +// Class for tracking the word breaker transition point. +class WordBreakerTransitionTracker { +public: + // Update the word breaker transition information. This function return true if the word + // breaker need to be updated. + bool update(const Run& run) { + const uint32_t newLocaleListId = run.getLocaleListId(); + const LineBreakStyle newLineBreakStyle = run.lineBreakStyle(); + const LineBreakWordStyle newLineBreakWordStyle = run.lineBreakWordStyle(); + const bool isUpdate = localeListId != newLocaleListId || + lineBreakStyle != newLineBreakStyle || + lineBreakWordStyle != newLineBreakWordStyle; + + localeListId = newLocaleListId; + lineBreakStyle = newLineBreakStyle; + lineBreakWordStyle = newLineBreakWordStyle; + + return isUpdate; + } + + const LocaleList& getCurrentLocaleList() const { + return LocaleListCache::getById(localeListId); + } + + LineBreakStyle getCurrentLineBreakStyle() const { return lineBreakStyle; } + + LineBreakWordStyle getCurrentLineBreakWordStyle() const { return lineBreakWordStyle; } + +private: + uint32_t localeListId = LocaleListCache::kInvalidListId; + LineBreakStyle lineBreakStyle = LineBreakStyle::None; + LineBreakWordStyle lineBreakWordStyle = LineBreakWordStyle::None; +}; + +inline std::pair<LineBreakWordStyle, bool> resolveWordStyleAuto(LineBreakWordStyle lbWordStyle, + const LocaleList& localeList, + bool forceWordStyleAutoToPhrase) { + if (lbWordStyle == LineBreakWordStyle::Auto) { + if (forceWordStyleAutoToPhrase) { + return std::make_pair(LineBreakWordStyle::Phrase, false); + } else if (localeList.hasKorean()) { + return std::make_pair(LineBreakWordStyle::Phrase, false); + } else if (localeList.hasJapanese()) { + return std::make_pair(LineBreakWordStyle::None, true); + } else { + return std::make_pair(LineBreakWordStyle::None, false); + } + } else { + return std::make_pair(lbWordStyle, false); + } +} + // Processes and retrieve informations from characters in the paragraph. struct CharProcessor { // The number of spaces. @@ -157,6 +220,8 @@ struct CharProcessor { // The current hyphenator. const Hyphenator* hyphenator = nullptr; + bool retryWithPhraseWordBreak = false; + // Retrieve the current word range. inline Range wordRange() const { return breaker.wordRange(); } @@ -175,15 +240,17 @@ struct CharProcessor { // The user of CharProcessor must call updateLocaleIfNecessary with valid locale at least one // time before feeding characters. - void updateLocaleIfNecessary(const Run& run) { - uint32_t newLocaleListId = run.getLocaleListId(); - if (localeListId != newLocaleListId) { - Locale locale = getEffectiveLocale(newLocaleListId); - nextWordBreak = breaker.followingWithLocale(locale, run.lineBreakStyle(), - run.lineBreakWordStyle(), + void updateLocaleIfNecessary(const Run& run, bool forceWordStyleAutoToPhrase) { + if (wbTracker.update(run)) { + const LocaleList& localeList = wbTracker.getCurrentLocaleList(); + const Locale locale = localeList.empty() ? Locale() : localeList[0]; + + LineBreakWordStyle lbWordStyle = wbTracker.getCurrentLineBreakWordStyle(); + std::tie(lbWordStyle, retryWithPhraseWordBreak) = + resolveWordStyleAuto(lbWordStyle, localeList, forceWordStyleAutoToPhrase); + nextWordBreak = breaker.followingWithLocale(locale, run.lineBreakStyle(), lbWordStyle, run.getRange().getStart()); hyphenator = HyphenatorMap::lookup(locale); - localeListId = newLocaleListId; } } @@ -212,9 +279,7 @@ struct CharProcessor { } private: - // The current locale list id. - uint32_t localeListId = LocaleListCache::kInvalidListId; - + WordBreakerTransitionTracker wbTracker; WordBreaker breaker; }; } // namespace minikin |