101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien/* 201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * Copyright (C) 2015 The Android Open Source Project 301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * 401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * Licensed under the Apache License, Version 2.0 (the "License"); 501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * you may not use this file except in compliance with the License. 601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * You may obtain a copy of the License at 701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * 801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * http://www.apache.org/licenses/LICENSE-2.0 901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * 1001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * Unless required by applicable law or agreed to in writing, software 1101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * distributed under the License is distributed on an "AS IS" BASIS, 1201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * See the License for the specific language governing permissions and 1401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * limitations under the License. 1501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien */ 1601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 1701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien/** 1801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * A module for breaking paragraphs into lines, supporting high quality 1901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien * hyphenation and justification. 2001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien */ 2101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 2201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#ifndef MINIKIN_LINE_BREAKER_H 2301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#define MINIKIN_LINE_BREAKER_H 2401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 25728f42cbd5acd0fa8d8dbe07d0302d41475eb95cRoozbeh Pournader#include <gtest/gtest_prod.h> 2601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include "unicode/brkiter.h" 2701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include "unicode/locid.h" 2801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include <cmath> 2901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include <vector> 30728f42cbd5acd0fa8d8dbe07d0302d41475eb95cRoozbeh Pournader#include "minikin/FontCollection.h" 315cdad92c300a65cab89b172e952186f0c5870657Raph Levien#include "minikin/Hyphenator.h" 32728f42cbd5acd0fa8d8dbe07d0302d41475eb95cRoozbeh Pournader#include "minikin/MinikinFont.h" 3357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include "minikin/WordBreaker.h" 3401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 3514e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin { 3601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 3701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienenum BreakStrategy { 3801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien kBreakStrategy_Greedy = 0, 3901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien kBreakStrategy_HighQuality = 1, 4001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien kBreakStrategy_Balanced = 2 4101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}; 4201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 430dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournaderenum HyphenationFrequency { 440dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader kHyphenationFrequency_None = 0, 450dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader kHyphenationFrequency_Normal = 1, 460dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader kHyphenationFrequency_Full = 2 470dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader}; 480dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader 4901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien// TODO: want to generalize to be able to handle array of line widths 5001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineWidths { 5101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien public: 5201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void setWidths(float firstWidth, int firstWidthLineCount, float restWidth) { 5301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mFirstWidth = firstWidth; 5401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mFirstWidthLineCount = firstWidthLineCount; 5501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mRestWidth = restWidth; 5601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 57bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien void setIndents(const std::vector<float>& indents) { 58bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien mIndents = indents; 59dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien } 605cdad92c300a65cab89b172e952186f0c5870657Raph Levien bool isConstant() const { 615cdad92c300a65cab89b172e952186f0c5870657Raph Levien // technically mFirstWidthLineCount == 0 would count too, but doesn't actually happen 62bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien return mRestWidth == mFirstWidth && mIndents.empty(); 635cdad92c300a65cab89b172e952186f0c5870657Raph Levien } 6401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float getLineWidth(int line) const { 65dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien float width = (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth; 66bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien if (!mIndents.empty()) { 67bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien if ((size_t)line < mIndents.size()) { 68bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien width -= mIndents[line]; 69dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien } else { 70bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien width -= mIndents.back(); 71dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien } 72dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien } 73dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien return width; 7401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 75879e8a3a479b2cedd05e652f082683a02aa57dcfRaph Levien void clear() { 76879e8a3a479b2cedd05e652f082683a02aa57dcfRaph Levien mIndents.clear(); 77879e8a3a479b2cedd05e652f082683a02aa57dcfRaph Levien } 7801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien private: 7901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float mFirstWidth; 8001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien int mFirstWidthLineCount; 8101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float mRestWidth; 82bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien std::vector<float> mIndents; 8301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}; 8401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 8501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass TabStops { 8601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien public: 8701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void set(const int* stops, size_t nStops, int tabWidth) { 8801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien if (stops != nullptr) { 8901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mStops.assign(stops, stops + nStops); 9001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } else { 9101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mStops.clear(); 9201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 9301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mTabWidth = tabWidth; 9401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 9501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float nextTab(float widthSoFar) const { 9601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien for (size_t i = 0; i < mStops.size(); i++) { 9701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien if (mStops[i] > widthSoFar) { 9801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mStops[i]; 9901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 10001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 10101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return floor(widthSoFar / mTabWidth + 1) * mTabWidth; 10201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 10301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien private: 10401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien std::vector<int> mStops; 10501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien int mTabWidth; 10601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}; 10701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 10801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineBreaker { 10901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien public: 1105cdad92c300a65cab89b172e952186f0c5870657Raph Levien const static int kTab_Shift = 29; // keep synchronized with TAB_MASK in StaticLayout.java 1115cdad92c300a65cab89b172e952186f0c5870657Raph Levien 11201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // Note: Locale persists across multiple invocations (it is not cleaned up by finish()), 11301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // explicitly to avoid the cost of creating ICU BreakIterator objects. It should always 11401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // be set on the first invocation, but callers are encouraged not to call again unless 11501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // locale has actually changed. 11601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // That logic could be here but it's better for performance that it's upstream because of 11701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // the cost of constructing and comparing the ICU Locale object. 1185cdad92c300a65cab89b172e952186f0c5870657Raph Levien // Note: caller is responsible for managing lifetime of hyphenator 119728f42cbd5acd0fa8d8dbe07d0302d41475eb95cRoozbeh Pournader void setLocales(const char* locales, const std::vector<Hyphenator*>& hyphenators); 12001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 12101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void resize(size_t size) { 12201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mTextBuf.resize(size); 12301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mCharWidths.resize(size); 12401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 12501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 12601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien size_t size() const { 12701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mTextBuf.size(); 12801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 12901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 13001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien uint16_t* buffer() { 13101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mTextBuf.data(); 13201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 13301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 13401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float* charWidths() { 13501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mCharWidths.data(); 13601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 13701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 13801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // set text to current contents of buffer 13901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void setText(); 14001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 14101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void setLineWidths(float firstWidth, int firstWidthLineCount, float restWidth); 14201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 143bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien void setIndents(const std::vector<float>& indents); 144dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien 14501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void setTabStops(const int* stops, size_t nStops, int tabWidth) { 14601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien mTabStops.set(stops, nStops, tabWidth); 14701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 14801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 14901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien BreakStrategy getStrategy() const { return mStrategy; } 15001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 15101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void setStrategy(BreakStrategy strategy) { mStrategy = strategy; } 15201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 1533a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka void setJustified(bool justified) { mJustified = justified; } 1543a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka 1550dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader HyphenationFrequency getHyphenationFrequency() const { return mHyphenationFrequency; } 1560dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader 1570dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader void setHyphenationFrequency(HyphenationFrequency frequency) { 1580dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader mHyphenationFrequency = frequency; 1590dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader } 1600dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader 16101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // TODO: this class is actually fairly close to being general and not tied to using 16201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // Minikin to do the shaping of the strings. The main thing that would need to be changed 16301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // is having some kind of callback (or virtual class, or maybe even template), which could 16401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // easily be instantiated with Minikin's Layout. Future work for when needed. 165dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka float addStyleRun(MinikinPaint* paint, const std::shared_ptr<FontCollection>& typeface, 166dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka FontStyle style, size_t start, size_t end, bool isRtl); 16701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 16801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void addReplacement(size_t start, size_t end, float width); 16901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 17001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien size_t computeBreaks(); 17101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 17201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien const int* getBreaks() const { 17301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mBreaks.data(); 17401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 17501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 17601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien const float* getWidths() const { 17701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mWidths.data(); 17801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 17901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 1805cdad92c300a65cab89b172e952186f0c5870657Raph Levien const int* getFlags() const { 18101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien return mFlags.data(); 18201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien } 18301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 18401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void finish(); 18501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 18601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien private: 18701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // ParaWidth is used to hold cumulative width from beginning of paragraph. Note that for 18801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // very large paragraphs, accuracy could degrade using only 32-bit float. Note however 18901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // that float is used extensively on the Java side for this. This is a typedef so that 19001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // we can easily change it based on performance/accuracy tradeoff. 19101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien typedef double ParaWidth; 19201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 19301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // A single candidate break 19401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien struct Candidate { 19501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien size_t offset; // offset to text buffer, in code units 19601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien size_t prev; // index to previous break 19767d1601c603970aecd737cf8b82f6a13648e0820Roozbeh Pournader ParaWidth preBreak; // width of text until this point, if we decide to not break here 19867d1601c603970aecd737cf8b82f6a13648e0820Roozbeh Pournader ParaWidth postBreak; // width of text until this point, if we decide to break here 19901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float penalty; // penalty of this break (for example, hyphen penalty) 20001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float score; // best score found for this break 2015cdad92c300a65cab89b172e952186f0c5870657Raph Levien size_t lineNumber; // only updated for non-constant line widths 2023a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka size_t preSpaceCount; // preceding space count before breaking 2033a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka size_t postSpaceCount; // preceding space count after breaking 204c7ef4000c1e840c3d3b66e85a40ebd34a5a2a8eeRoozbeh Pournader HyphenationType hyphenType; 20501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien }; 20601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 20701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float currentLineWidth() const; 20801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 2093a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka void addWordBreak(size_t offset, ParaWidth preBreak, ParaWidth postBreak, 210c7ef4000c1e840c3d3b66e85a40ebd34a5a2a8eeRoozbeh Pournader size_t preSpaceCount, size_t postSpaceCount, float penalty, HyphenationType hyph); 21101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 21201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void addCandidate(Candidate cand); 21367d1601c603970aecd737cf8b82f6a13648e0820Roozbeh Pournader void pushGreedyBreak(); 21401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 2155cdad92c300a65cab89b172e952186f0c5870657Raph Levien // push an actual break to the output. Takes care of setting flags for tab 216c7ef4000c1e840c3d3b66e85a40ebd34a5a2a8eeRoozbeh Pournader void pushBreak(int offset, float width, uint8_t hyphenEdit); 2175cdad92c300a65cab89b172e952186f0c5870657Raph Levien 2183a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka float getSpaceWidth() const; 2193a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka 22001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien void computeBreaksGreedy(); 22101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 222abae97a39c26e191e350575932611a90e6b04d06Raph Levien void computeBreaksOptimal(bool isRectangular); 2235cdad92c300a65cab89b172e952186f0c5870657Raph Levien 2245cdad92c300a65cab89b172e952186f0c5870657Raph Levien void finishBreaksOptimal(); 22501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 22657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien WordBreaker mWordBreaker; 227c7ef4000c1e840c3d3b66e85a40ebd34a5a2a8eeRoozbeh Pournader icu::Locale mLocale; 22801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien std::vector<uint16_t>mTextBuf; 22901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien std::vector<float>mCharWidths; 23001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 2315cdad92c300a65cab89b172e952186f0c5870657Raph Levien Hyphenator* mHyphenator; 232c7ef4000c1e840c3d3b66e85a40ebd34a5a2a8eeRoozbeh Pournader std::vector<HyphenationType> mHyphBuf; 2335cdad92c300a65cab89b172e952186f0c5870657Raph Levien 23401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // layout parameters 23501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien BreakStrategy mStrategy = kBreakStrategy_Greedy; 2360dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader HyphenationFrequency mHyphenationFrequency = kHyphenationFrequency_Normal; 2373a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka bool mJustified; 23801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien LineWidths mLineWidths; 23901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien TabStops mTabStops; 24001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 24101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // result of line breaking 24201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien std::vector<int> mBreaks; 24301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien std::vector<float> mWidths; 2445cdad92c300a65cab89b172e952186f0c5870657Raph Levien std::vector<int> mFlags; 24501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 24601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien ParaWidth mWidth = 0; 24701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien std::vector<Candidate> mCandidates; 248abae97a39c26e191e350575932611a90e6b04d06Raph Levien float mLinePenalty = 0.0f; 24901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 25001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien // the following are state for greedy breaker (updated while adding style runs) 25101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien size_t mLastBreak; 25201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien size_t mBestBreak; 25301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien float mBestScore; 25401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien ParaWidth mPreBreak; // prebreak of last break 25567d1601c603970aecd737cf8b82f6a13648e0820Roozbeh Pournader uint32_t mLastHyphenation; // hyphen edit of last break kept for next line 25601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien int mFirstTabIndex; 2573a74bcd0b4c4150cd524a37cdfa4e0ffe490cca6Seigo Nonaka size_t mSpaceCount; 258728f42cbd5acd0fa8d8dbe07d0302d41475eb95cRoozbeh Pournader 259728f42cbd5acd0fa8d8dbe07d0302d41475eb95cRoozbeh Pournader FRIEND_TEST(LineBreakerTest, setLocales); 26001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}; 26101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 26214e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka} // namespace minikin 26301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien 26401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#endif // MINIKIN_LINE_BREAKER_H 265