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
2501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include "unicode/brkiter.h"
2601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include "unicode/locid.h"
2701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include <cmath>
2801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#include <vector>
295cdad92c300a65cab89b172e952186f0c5870657Raph Levien#include "minikin/Hyphenator.h"
3057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include "minikin/WordBreaker.h"
3101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
3201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Leviennamespace android {
3301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
3401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienenum BreakStrategy {
3501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    kBreakStrategy_Greedy = 0,
3601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    kBreakStrategy_HighQuality = 1,
3701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    kBreakStrategy_Balanced = 2
3801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
3901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
400dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournaderenum HyphenationFrequency {
410dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader    kHyphenationFrequency_None = 0,
420dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader    kHyphenationFrequency_Normal = 1,
430dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader    kHyphenationFrequency_Full = 2
440dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader};
450dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader
4601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien// TODO: want to generalize to be able to handle array of line widths
4701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineWidths {
4801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
4901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setWidths(float firstWidth, int firstWidthLineCount, float restWidth) {
5001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mFirstWidth = firstWidth;
5101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mFirstWidthLineCount = firstWidthLineCount;
5201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mRestWidth = restWidth;
5301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
54bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien        void setIndents(const std::vector<float>& indents) {
55bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien            mIndents = indents;
56dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien        }
575cdad92c300a65cab89b172e952186f0c5870657Raph Levien        bool isConstant() const {
585cdad92c300a65cab89b172e952186f0c5870657Raph Levien            // technically mFirstWidthLineCount == 0 would count too, but doesn't actually happen
59bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien            return mRestWidth == mFirstWidth && mIndents.empty();
605cdad92c300a65cab89b172e952186f0c5870657Raph Levien        }
6101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float getLineWidth(int line) const {
62dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            float width = (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth;
63bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien            if (!mIndents.empty()) {
64bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien                if ((size_t)line < mIndents.size()) {
65bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien                    width -= mIndents[line];
66dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                } else {
67bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien                    width -= mIndents.back();
68dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                }
69dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            }
70dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            return width;
7101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
72879e8a3a479b2cedd05e652f082683a02aa57dcfRaph Levien        void clear() {
73879e8a3a479b2cedd05e652f082683a02aa57dcfRaph Levien            mIndents.clear();
74879e8a3a479b2cedd05e652f082683a02aa57dcfRaph Levien        }
7501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
7601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mFirstWidth;
7701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mFirstWidthLineCount;
7801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mRestWidth;
79bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien        std::vector<float> mIndents;
8001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
8101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
8201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass TabStops {
8301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
8401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void set(const int* stops, size_t nStops, int tabWidth) {
8501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            if (stops != nullptr) {
8601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                mStops.assign(stops, stops + nStops);
8701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            } else {
8801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                mStops.clear();
8901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            }
9001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTabWidth = tabWidth;
9101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
9201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float nextTab(float widthSoFar) const {
9301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            for (size_t i = 0; i < mStops.size(); i++) {
9401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                if (mStops[i] > widthSoFar) {
9501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                    return mStops[i];
9601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                }
9701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            }
9801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return floor(widthSoFar / mTabWidth + 1) * mTabWidth;
9901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
10001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
10101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<int> mStops;
10201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mTabWidth;
10301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
10401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
10501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineBreaker {
10601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
1075cdad92c300a65cab89b172e952186f0c5870657Raph Levien        const static int kTab_Shift = 29;  // keep synchronized with TAB_MASK in StaticLayout.java
1085cdad92c300a65cab89b172e952186f0c5870657Raph Levien
10901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // Note: Locale persists across multiple invocations (it is not cleaned up by finish()),
11001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // explicitly to avoid the cost of creating ICU BreakIterator objects. It should always
11101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // be set on the first invocation, but callers are encouraged not to call again unless
11201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // locale has actually changed.
11301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // That logic could be here but it's better for performance that it's upstream because of
11401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // the cost of constructing and comparing the ICU Locale object.
1155cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // Note: caller is responsible for managing lifetime of hyphenator
1165cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void setLocale(const icu::Locale& locale, Hyphenator* hyphenator);
11701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
11801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void resize(size_t size) {
11901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTextBuf.resize(size);
12001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mCharWidths.resize(size);
12101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t size() const {
12401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mTextBuf.size();
12501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        uint16_t* buffer() {
12801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mTextBuf.data();
12901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
13001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float* charWidths() {
13201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mCharWidths.data();
13301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
13401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // set text to current contents of buffer
13601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setText();
13701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setLineWidths(float firstWidth, int firstWidthLineCount, float restWidth);
13901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
140bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien        void setIndents(const std::vector<float>& indents);
141dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien
14201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setTabStops(const int* stops, size_t nStops, int tabWidth) {
14301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTabStops.set(stops, nStops, tabWidth);
14401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
14501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        BreakStrategy getStrategy() const { return mStrategy; }
14701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setStrategy(BreakStrategy strategy) { mStrategy = strategy; }
14901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1500dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        HyphenationFrequency getHyphenationFrequency() const { return mHyphenationFrequency; }
1510dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader
1520dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        void setHyphenationFrequency(HyphenationFrequency frequency) {
1530dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader            mHyphenationFrequency = frequency;
1540dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        }
1550dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader
15601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // TODO: this class is actually fairly close to being general and not tied to using
15701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // Minikin to do the shaping of the strings. The main thing that would need to be changed
15801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // is having some kind of callback (or virtual class, or maybe even template), which could
15901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // easily be instantiated with Minikin's Layout. Future work for when needed.
1605cdad92c300a65cab89b172e952186f0c5870657Raph Levien        float addStyleRun(MinikinPaint* paint, const FontCollection* typeface, FontStyle style,
1615cdad92c300a65cab89b172e952186f0c5870657Raph Levien                size_t start, size_t end, bool isRtl);
16201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void addReplacement(size_t start, size_t end, float width);
16401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t computeBreaks();
16601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        const int* getBreaks() const {
16801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mBreaks.data();
16901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
17001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
17101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        const float* getWidths() const {
17201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mWidths.data();
17301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
17401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1755cdad92c300a65cab89b172e952186f0c5870657Raph Levien        const int* getFlags() const {
17601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mFlags.data();
17701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
17801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
17901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void finish();
18001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
18101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
18201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // ParaWidth is used to hold cumulative width from beginning of paragraph. Note that for
18301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // very large paragraphs, accuracy could degrade using only 32-bit float. Note however
18401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // that float is used extensively on the Java side for this. This is a typedef so that
18501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // we can easily change it based on performance/accuracy tradeoff.
18601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        typedef double ParaWidth;
18701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
18801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // A single candidate break
18901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        struct Candidate {
19001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            size_t offset;  // offset to text buffer, in code units
19101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            size_t prev;  // index to previous break
19201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            ParaWidth preBreak;
19301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            ParaWidth postBreak;
19401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            float penalty;  // penalty of this break (for example, hyphen penalty)
19501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            float score;  // best score found for this break
1965cdad92c300a65cab89b172e952186f0c5870657Raph Levien            size_t lineNumber;  // only updated for non-constant line widths
1975cdad92c300a65cab89b172e952186f0c5870657Raph Levien            uint8_t hyphenEdit;
19801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        };
19901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
20001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float currentLineWidth() const;
20101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2025cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void addWordBreak(size_t offset, ParaWidth preBreak, ParaWidth postBreak, float penalty,
2035cdad92c300a65cab89b172e952186f0c5870657Raph Levien                uint8_t hyph);
20401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
20501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void addCandidate(Candidate cand);
20601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2075cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // push an actual break to the output. Takes care of setting flags for tab
2085cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void pushBreak(int offset, float width, uint8_t hyph);
2095cdad92c300a65cab89b172e952186f0c5870657Raph Levien
21001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void computeBreaksGreedy();
21101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
212abae97a39c26e191e350575932611a90e6b04d06Raph Levien        void computeBreaksOptimal(bool isRectangular);
2135cdad92c300a65cab89b172e952186f0c5870657Raph Levien
2145cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void finishBreaksOptimal();
21501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
21657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien        WordBreaker mWordBreaker;
21701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<uint16_t>mTextBuf;
21801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<float>mCharWidths;
21901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2205cdad92c300a65cab89b172e952186f0c5870657Raph Levien        Hyphenator* mHyphenator;
2215cdad92c300a65cab89b172e952186f0c5870657Raph Levien        std::vector<uint8_t> mHyphBuf;
2225cdad92c300a65cab89b172e952186f0c5870657Raph Levien
22301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // layout parameters
22401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        BreakStrategy mStrategy = kBreakStrategy_Greedy;
2250dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        HyphenationFrequency mHyphenationFrequency = kHyphenationFrequency_Normal;
22601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        LineWidths mLineWidths;
22701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        TabStops mTabStops;
22801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
22901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // result of line breaking
23001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<int> mBreaks;
23101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<float> mWidths;
2325cdad92c300a65cab89b172e952186f0c5870657Raph Levien        std::vector<int> mFlags;
23301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
23401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ParaWidth mWidth = 0;
23501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<Candidate> mCandidates;
236abae97a39c26e191e350575932611a90e6b04d06Raph Levien        float mLinePenalty = 0.0f;
23701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
23801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // the following are state for greedy breaker (updated while adding style runs)
23901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t mLastBreak;
24001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t mBestBreak;
24101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mBestScore;
24201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ParaWidth mPreBreak;  // prebreak of last break
24301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mFirstTabIndex;
24401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
24501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
24601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}  // namespace android
24701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
24801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#endif  // MINIKIN_LINE_BREAKER_H
249