LineBreaker.h revision dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3f
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"
3001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
3101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Leviennamespace android {
3201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
3301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienenum BreakStrategy {
3401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    kBreakStrategy_Greedy = 0,
3501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    kBreakStrategy_HighQuality = 1,
3601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    kBreakStrategy_Balanced = 2
3701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
3801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
3901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien// TODO: want to generalize to be able to handle array of line widths
4001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineWidths {
4101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
4201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setWidths(float firstWidth, int firstWidthLineCount, float restWidth) {
4301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mFirstWidth = firstWidth;
4401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mFirstWidthLineCount = firstWidthLineCount;
4501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mRestWidth = restWidth;
4601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
47dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien        void setMargins(const std::vector<float>& margins) {
48dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            mMargins = margins;
49dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien        }
505cdad92c300a65cab89b172e952186f0c5870657Raph Levien        bool isConstant() const {
515cdad92c300a65cab89b172e952186f0c5870657Raph Levien            // technically mFirstWidthLineCount == 0 would count too, but doesn't actually happen
52dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            return mRestWidth == mFirstWidth && mMargins.empty();
535cdad92c300a65cab89b172e952186f0c5870657Raph Levien        }
5401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float getLineWidth(int line) const {
55dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            float width = (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth;
56dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            if (!mMargins.empty()) {
57dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                if ((size_t)line < mMargins.size()) {
58dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                    width -= mMargins[line];
59dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                } else {
60dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                    width -= mMargins.back();
61dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien                }
62dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            }
63dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien            return width;
6401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
6501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
6601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mFirstWidth;
6701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mFirstWidthLineCount;
6801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mRestWidth;
69dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien        std::vector<float> mMargins;
7001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
7101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
7201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass TabStops {
7301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
7401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void set(const int* stops, size_t nStops, int tabWidth) {
7501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            if (stops != nullptr) {
7601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                mStops.assign(stops, stops + nStops);
7701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            } else {
7801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                mStops.clear();
7901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            }
8001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTabWidth = tabWidth;
8101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
8201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float nextTab(float widthSoFar) const {
8301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            for (size_t i = 0; i < mStops.size(); i++) {
8401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                if (mStops[i] > widthSoFar) {
8501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                    return mStops[i];
8601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien                }
8701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            }
8801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return floor(widthSoFar / mTabWidth + 1) * mTabWidth;
8901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
9001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
9101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<int> mStops;
9201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mTabWidth;
9301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
9401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
9501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levienclass LineBreaker {
9601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    public:
975cdad92c300a65cab89b172e952186f0c5870657Raph Levien        const static int kTab_Shift = 29;  // keep synchronized with TAB_MASK in StaticLayout.java
985cdad92c300a65cab89b172e952186f0c5870657Raph Levien
9901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ~LineBreaker() {
10001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            utext_close(&mUText);
10101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            delete mBreakIterator;
10201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
10301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
10401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // Note: Locale persists across multiple invocations (it is not cleaned up by finish()),
10501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // explicitly to avoid the cost of creating ICU BreakIterator objects. It should always
10601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // be set on the first invocation, but callers are encouraged not to call again unless
10701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // locale has actually changed.
10801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // That logic could be here but it's better for performance that it's upstream because of
10901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // the cost of constructing and comparing the ICU Locale object.
1105cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // Note: caller is responsible for managing lifetime of hyphenator
1115cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void setLocale(const icu::Locale& locale, Hyphenator* hyphenator);
11201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
11301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void resize(size_t size) {
11401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTextBuf.resize(size);
11501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mCharWidths.resize(size);
11601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
11701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
11801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t size() const {
11901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mTextBuf.size();
12001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        uint16_t* buffer() {
12301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mTextBuf.data();
12401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
12601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float* charWidths() {
12701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mCharWidths.data();
12801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
12901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // set text to current contents of buffer
13101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setText();
13201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
13301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setLineWidths(float firstWidth, int firstWidthLineCount, float restWidth);
13401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
135dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien        void setMargins(const std::vector<float>& margins);
136dc7bc6e39e1ef6b713b927baf24db8b4f02f1a3fRaph Levien
13701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setTabStops(const int* stops, size_t nStops, int tabWidth) {
13801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            mTabStops.set(stops, nStops, tabWidth);
13901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
14001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        BreakStrategy getStrategy() const { return mStrategy; }
14201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void setStrategy(BreakStrategy strategy) { mStrategy = strategy; }
14401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
14501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // TODO: this class is actually fairly close to being general and not tied to using
14601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // Minikin to do the shaping of the strings. The main thing that would need to be changed
14701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // is having some kind of callback (or virtual class, or maybe even template), which could
14801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // easily be instantiated with Minikin's Layout. Future work for when needed.
1495cdad92c300a65cab89b172e952186f0c5870657Raph Levien        float addStyleRun(MinikinPaint* paint, const FontCollection* typeface, FontStyle style,
1505cdad92c300a65cab89b172e952186f0c5870657Raph Levien                size_t start, size_t end, bool isRtl);
15101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
15201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void addReplacement(size_t start, size_t end, float width);
15301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
15401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t computeBreaks();
15501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
15601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        const int* getBreaks() const {
15701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mBreaks.data();
15801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
15901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        const float* getWidths() const {
16101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mWidths.data();
16201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
16301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1645cdad92c300a65cab89b172e952186f0c5870657Raph Levien        const int* getFlags() const {
16501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            return mFlags.data();
16601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        }
16701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
16801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void finish();
16901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
17001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien    private:
17101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // ParaWidth is used to hold cumulative width from beginning of paragraph. Note that for
17201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // very large paragraphs, accuracy could degrade using only 32-bit float. Note however
17301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // that float is used extensively on the Java side for this. This is a typedef so that
17401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // we can easily change it based on performance/accuracy tradeoff.
17501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        typedef double ParaWidth;
17601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
17701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // A single candidate break
17801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        struct Candidate {
17901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            size_t offset;  // offset to text buffer, in code units
18001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            size_t prev;  // index to previous break
18101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            ParaWidth preBreak;
18201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            ParaWidth postBreak;
18301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            float penalty;  // penalty of this break (for example, hyphen penalty)
18401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien            float score;  // best score found for this break
1855cdad92c300a65cab89b172e952186f0c5870657Raph Levien            size_t lineNumber;  // only updated for non-constant line widths
1865cdad92c300a65cab89b172e952186f0c5870657Raph Levien            uint8_t hyphenEdit;
18701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        };
18801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
18901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float currentLineWidth() const;
19001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1915cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // compute shrink/stretch penalty for line
1925cdad92c300a65cab89b172e952186f0c5870657Raph Levien        float computeScore(float delta, bool atEnd);
1935cdad92c300a65cab89b172e952186f0c5870657Raph Levien
1945cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void addWordBreak(size_t offset, ParaWidth preBreak, ParaWidth postBreak, float penalty,
1955cdad92c300a65cab89b172e952186f0c5870657Raph Levien                uint8_t hyph);
19601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
19701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void addCandidate(Candidate cand);
19801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
1995cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // push an actual break to the output. Takes care of setting flags for tab
2005cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void pushBreak(int offset, float width, uint8_t hyph);
2015cdad92c300a65cab89b172e952186f0c5870657Raph Levien
20201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        void computeBreaksGreedy();
20301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2045cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void computeBreaksOptimal();
2055cdad92c300a65cab89b172e952186f0c5870657Raph Levien
2065cdad92c300a65cab89b172e952186f0c5870657Raph Levien        // special case when LineWidth is constant (layout is rectangle)
2075cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void computeBreaksOptimalRect();
2085cdad92c300a65cab89b172e952186f0c5870657Raph Levien
2095cdad92c300a65cab89b172e952186f0c5870657Raph Levien        void finishBreaksOptimal();
21001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
21101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        icu::BreakIterator* mBreakIterator = nullptr;
21201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        UText mUText = UTEXT_INITIALIZER;
21301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<uint16_t>mTextBuf;
21401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<float>mCharWidths;
21501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
2165cdad92c300a65cab89b172e952186f0c5870657Raph Levien        Hyphenator* mHyphenator;
2175cdad92c300a65cab89b172e952186f0c5870657Raph Levien        std::vector<uint8_t> mHyphBuf;
2185cdad92c300a65cab89b172e952186f0c5870657Raph Levien
21901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // layout parameters
22001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        BreakStrategy mStrategy = kBreakStrategy_Greedy;
22101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        LineWidths mLineWidths;
22201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        TabStops mTabStops;
22301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
22401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // result of line breaking
22501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<int> mBreaks;
22601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<float> mWidths;
2275cdad92c300a65cab89b172e952186f0c5870657Raph Levien        std::vector<int> mFlags;
22801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
22901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ParaWidth mWidth = 0;
23001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        std::vector<Candidate> mCandidates;
23101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
23201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        // the following are state for greedy breaker (updated while adding style runs)
23301f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t mLastBreak;
23401f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        size_t mBestBreak;
23501f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        float mBestScore;
23601f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        ParaWidth mPreBreak;  // prebreak of last break
23701f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien        int mFirstTabIndex;
23801f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien};
23901f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
24001f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien}  // namespace android
24101f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien
24201f526614431e3a0a6e1a48039e00b8a9b7d6fbfRaph Levien#endif  // MINIKIN_LINE_BREAKER_H
243