LineBreaker.h revision 57b6dae9894b9362ef04517ff477fd491f9d433b
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        }
7201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
7301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mFirstWidth;
7401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mFirstWidthLineCount;
7501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mRestWidth;
76bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien        std::vector<float> mIndents;
7701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
7801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
7901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass TabStops {
8001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
8101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void set(const int* stops, size_t nStops, int tabWidth) {
8201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            if (stops != nullptr) {
8301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                mStops.assign(stops, stops + nStops);
8401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            } else {
8501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                mStops.clear();
8601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            }
8701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTabWidth = tabWidth;
8801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
8901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float nextTab(float widthSoFar) const {
9001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            for (size_t i = 0; i < mStops.size(); i++) {
9101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                if (mStops[i] > widthSoFar) {
9201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                    return mStops[i];
9301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                }
9401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            }
9501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return floor(widthSoFar / mTabWidth + 1) * mTabWidth;
9601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
9701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
9801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<int> mStops;
9901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mTabWidth;
10001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
10101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
10201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineBreaker {
10301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
1045cdad92c300a65cab89b172e952186f0c5870657Raph Levien        const static int kTab_Shift = 29;  // keep synchronized with TAB_MASK in StaticLayout.java
1055cdad92c300a65cab89b172e952186f0c5870657Raph Levien
10601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // Note: Locale persists across multiple invocations (it is not cleaned up by finish()),
10701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // explicitly to avoid the cost of creating ICU BreakIterator objects. It should always
10801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // be set on the first invocation, but callers are encouraged not to call again unless
10901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // locale has actually changed.
11001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // That logic could be here but it's better for performance that it's upstream because of
11101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // the cost of constructing and comparing the ICU Locale object.
1125cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // Note: caller is responsible for managing lifetime of hyphenator
1135cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void setLocale(const icu::Locale& locale, Hyphenator* hyphenator);
11401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
11501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void resize(size_t size) {
11601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTextBuf.resize(size);
11701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mCharWidths.resize(size);
11801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
11901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t size() const {
12101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mTextBuf.size();
12201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        uint16_t* buffer() {
12501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mTextBuf.data();
12601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float* charWidths() {
12901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mCharWidths.data();
13001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
13101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // set text to current contents of buffer
13301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setText();
13401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setLineWidths(float firstWidth, int firstWidthLineCount, float restWidth);
13601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
137bb86b433f97a301c11800806b1ce5331fa227d4aRaph Levien        void setIndents(const std::vector<float>& indents);
138dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien
13901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setTabStops(const int* stops, size_t nStops, int tabWidth) {
14001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTabStops.set(stops, nStops, tabWidth);
14101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
14201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        BreakStrategy getStrategy() const { return mStrategy; }
14401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setStrategy(BreakStrategy strategy) { mStrategy = strategy; }
14601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1470dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        HyphenationFrequency getHyphenationFrequency() const { return mHyphenationFrequency; }
1480dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader
1490dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        void setHyphenationFrequency(HyphenationFrequency frequency) {
1500dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader            mHyphenationFrequency = frequency;
1510dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        }
1520dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader
15301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // TODO: this class is actually fairly close to being general and not tied to using
15401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // Minikin to do the shaping of the strings. The main thing that would need to be changed
15501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // is having some kind of callback (or virtual class, or maybe even template), which could
15601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // easily be instantiated with Minikin's Layout. Future work for when needed.
1575cdad92c300a65cab89b172e952186f0c5870657Raph Levien        float addStyleRun(MinikinPaint* paint, const FontCollection* typeface, FontStyle style,
1585cdad92c300a65cab89b172e952186f0c5870657Raph Levien                size_t start, size_t end, bool isRtl);
15901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void addReplacement(size_t start, size_t end, float width);
16101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t computeBreaks();
16301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        const int* getBreaks() const {
16501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mBreaks.data();
16601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
16701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        const float* getWidths() const {
16901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mWidths.data();
17001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
17101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1725cdad92c300a65cab89b172e952186f0c5870657Raph Levien        const int* getFlags() const {
17301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mFlags.data();
17401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
17501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
17601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void finish();
17701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
17801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
17901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // ParaWidth is used to hold cumulative width from beginning of paragraph. Note that for
18001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // very large paragraphs, accuracy could degrade using only 32-bit float. Note however
18101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // that float is used extensively on the Java side for this. This is a typedef so that
18201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // we can easily change it based on performance/accuracy tradeoff.
18301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        typedef double ParaWidth;
18401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
18501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // A single candidate break
18601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        struct Candidate {
18701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            size_t offset;  // offset to text buffer, in code units
18801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            size_t prev;  // index to previous break
18901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            ParaWidth preBreak;
19001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            ParaWidth postBreak;
19101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            float penalty;  // penalty of this break (for example, hyphen penalty)
19201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            float score;  // best score found for this break
1935cdad92c300a65cab89b172e952186f0c5870657Raph Levien            size_t lineNumber;  // only updated for non-constant line widths
1945cdad92c300a65cab89b172e952186f0c5870657Raph Levien            uint8_t hyphenEdit;
19501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        };
19601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
19701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float currentLineWidth() const;
19801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1995cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void addWordBreak(size_t offset, ParaWidth preBreak, ParaWidth postBreak, float penalty,
2005cdad92c300a65cab89b172e952186f0c5870657Raph Levien                uint8_t hyph);
20101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
20201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void addCandidate(Candidate cand);
20301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2045cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // push an actual break to the output. Takes care of setting flags for tab
2055cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void pushBreak(int offset, float width, uint8_t hyph);
2065cdad92c300a65cab89b172e952186f0c5870657Raph Levien
20701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void computeBreaksGreedy();
20801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
209abae97a39c26e191e350575932611a90e6b04d06Raph Levien        void computeBreaksOptimal(bool isRectangular);
2105cdad92c300a65cab89b172e952186f0c5870657Raph Levien
2115cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void finishBreaksOptimal();
21201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
21357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien        WordBreaker mWordBreaker;
21401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<uint16_t>mTextBuf;
21501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<float>mCharWidths;
21601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2175cdad92c300a65cab89b172e952186f0c5870657Raph Levien        Hyphenator* mHyphenator;
2185cdad92c300a65cab89b172e952186f0c5870657Raph Levien        std::vector<uint8_t> mHyphBuf;
2195cdad92c300a65cab89b172e952186f0c5870657Raph Levien
22001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // layout parameters
22101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        BreakStrategy mStrategy = kBreakStrategy_Greedy;
2220dc07c0be325b7c12c50729e04c4b2785a673fd7Roozbeh Pournader        HyphenationFrequency mHyphenationFrequency = kHyphenationFrequency_Normal;
22301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        LineWidths mLineWidths;
22401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        TabStops mTabStops;
22501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
22601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // result of line breaking
22701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<int> mBreaks;
22801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<float> mWidths;
2295cdad92c300a65cab89b172e952186f0c5870657Raph Levien        std::vector<int> mFlags;
23001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
23101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ParaWidth mWidth = 0;
23201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<Candidate> mCandidates;
233abae97a39c26e191e350575932611a90e6b04d06Raph Levien        float mLinePenalty = 0.0f;
23401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
23501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // the following are state for greedy breaker (updated while adding style runs)
23601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t mLastBreak;
23701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t mBestBreak;
23801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mBestScore;
23901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ParaWidth mPreBreak;  // prebreak of last break
24001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mFirstTabIndex;
24101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
24201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
24301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}  // namespace android
24401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
24501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#endif  // MINIKIN_LINE_BREAKER_H
246