public void finishBreaksOptimal()
        {
            // clear existing greedy break result
            mBreaks.clear();
            mWidths.clear();
            mFlags.clear();
            int nCand = mCandidates.size();
            int prev  = new int();

            for (int i = nCand - 1; i > 0; i = prev)
            {
                prev = mCandidates[i].prev;
                mBreaks.push_back(mCandidates[i].offset);
                mWidths.push_back(mCandidates[i].postBreak - mCandidates[prev].preBreak);
                int flags = HyphenEdit.editForThisLine(mCandidates[i].hyphenType);
                if (prev > 0)
                {
                    flags |= HyphenEdit.editForNextLine(mCandidates[prev].hyphenType);
                }
                mFlags.push_back(flags);
            }
            std::reverse(mBreaks.begin(), mBreaks.end());
            std::reverse(mWidths.begin(), mWidths.end());
            std::reverse(mFlags.begin(), mFlags.end());
        }
        public void pushGreedyBreak()
        {
            Candidate bestCandidate = mCandidates[mBestBreak];

            pushBreak(bestCandidate.offset, bestCandidate.postBreak - mPreBreak, mLastHyphenation | HyphenEdit.editForThisLine(bestCandidate.hyphenType));
            mBestScore = SCORE_INFTY;
        #if VERBOSE_DEBUG
            ALOGD("break: %d %g", mBreaks.back(), mWidths.back());
        #endif
            mLastBreak       = mBestBreak;
            mPreBreak        = bestCandidate.preBreak;
            mLastHyphenation = HyphenEdit.editForNextLine(bestCandidate.hyphenType);
        }
        // TODO: this class is actually fairly close to being general and not tied to
        // using Minikin to do the shaping of the strings. The main thing that would
        // need to be changed is having some kind of callback (or virtual class, or
        // maybe even template), which could easily be instantiated with Minikin's
        // Layout. Future work for when needed.
        public float addStyleRun(MinikinPaint paint, FontCollection typeface, FontStyle style, int start, int end, bool isRtl)
        {
            float width     = 0.0f;
            int   bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;

            float hyphenPenalty = 0.0F;

            if (paint != null)
            {
                width = Layout.measureText(mTextBuf.data(), start, end - start, mTextBuf.size(), bidiFlags, style, paint, typeface, mCharWidths.data() + start);

                // a heuristic that seems to perform well
                hyphenPenalty = 0.5 * paint.size * paint.scaleX * mLineWidths.getLineWidth(0);
                if (mHyphenationFrequency == kHyphenationFrequency_Normal)
                {
                    hyphenPenalty *= 4.0; // TODO: Replace with a better value after some testing
                }

                if (mJustified)
                {
                    // Make hyphenation more aggressive for fully justified text (so that
                    // "normal" in justified mode is the same as "full" in ragged-right).
                    hyphenPenalty *= 0.25;
                }
                else
                {
                    // Line penalty is zero for justified text.
                    mLinePenalty = Math.Max(mLinePenalty, hyphenPenalty * LINE_PENALTY_MULTIPLIER);
                }
            }

            int       current        = (int)mWordBreaker.current();
            int       afterWord      = start;
            int       lastBreak      = start;
            ParaWidth lastBreakWidth = mWidth;
            ParaWidth postBreak      = mWidth;
            int       postSpaceCount = mSpaceCount;

            for (int i = start; i < end; i++)
            {
                UInt16 c = mTextBuf[i];
                if (c == CHAR_TAB)
                {
                    mWidth = mPreBreak + mTabStops.nextTab(mWidth - mPreBreak);
                    if (mFirstTabIndex == INT_MAX)
                    {
                        mFirstTabIndex = (int)i;
                    }
                    // fall back to greedy; other modes don't know how to deal with tabs
                    mStrategy = kBreakStrategy_Greedy;
                }
                else
                {
                    if (isWordSpace(new UInt16(c)))
                    {
                        mSpaceCount += 1;
                    }
                    mWidth += mCharWidths[i];
                    if (!isLineEndSpace(new UInt16(c)))
                    {
                        postBreak      = mWidth;
                        postSpaceCount = mSpaceCount;
                        //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created:
                        //ORIGINAL LINE: afterWord = i + 1;
                        afterWord.CopyFrom(i + 1);
                    }
                }
                if (i + 1 == current != null)
                {
                    int wordStart = mWordBreaker.wordStart();
                    int wordEnd   = mWordBreaker.wordEnd();
                    if (paint != null && mHyphenator != null && mHyphenationFrequency != kHyphenationFrequency_None && wordStart >= start != null && wordEnd > wordStart && wordEnd - wordStart <= LONGEST_HYPHENATED_WORD)
                    {
                        mHyphenator.hyphenate(mHyphBuf, mTextBuf[wordStart], wordEnd - wordStart, mLocale);
        #if VERBOSE_DEBUG
                        string hyphenatedString;
                        for (int j = wordStart; j < wordEnd; j++)
                        {
                            if (mHyphBuf[j - wordStart] == HyphenationType.BREAK_AND_INSERT_HYPHEN)
                            {
                                hyphenatedString.push_back('-');
                            }
                            // Note: only works with ASCII, should do UTF-8 conversion here
                            hyphenatedString.push_back(buffer()[j]);
                        }
                        ALOGD("hyphenated string: %s", hyphenatedString);
        #endif

                        // measure hyphenated substrings
                        for (int j = wordStart; j < wordEnd; j++)
                        {
                            HyphenationType hyph = mHyphBuf[j - wordStart];
                            if (hyph != HyphenationType.DONT_BREAK)
                            {
                                paint.hyphenEdit = HyphenEdit.editForThisLine(hyph);
                                float     firstPartWidth = Layout.measureText(mTextBuf.data(), lastBreak, j - lastBreak, mTextBuf.size(), bidiFlags, style, paint, typeface, null);
                                ParaWidth hyphPostBreak  = lastBreakWidth + firstPartWidth;

                                paint.hyphenEdit = HyphenEdit.editForNextLine(hyph);
                                float     secondPartWidth = Layout.measureText(mTextBuf.data(), j, afterWord - j, mTextBuf.size(), bidiFlags, style, paint, typeface, null);
                                ParaWidth hyphPreBreak    = postBreak - secondPartWidth;

                                addWordBreak(j, hyphPreBreak, hyphPostBreak, postSpaceCount, postSpaceCount, hyphenPenalty, hyph);

                                paint.hyphenEdit = HyphenEdit.NO_EDIT;
                            }
                        }
                    }

                    // Skip break for zero-width characters inside replacement span
                    if (paint != null || current == end || mCharWidths[current] > 0)
                    {
                        float penalty = hyphenPenalty * mWordBreaker.breakBadness();
                        addWordBreak(current, mWidth, postBreak, mSpaceCount, postSpaceCount, penalty, HyphenationType.DONT_BREAK);
                    }
                    //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created:
                    //ORIGINAL LINE: lastBreak = current;
                    lastBreak.CopyFrom(current);
                    lastBreakWidth = mWidth;
                    //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created:
                    //ORIGINAL LINE: current = (int)mWordBreaker.next();
                    current.CopyFrom((int)mWordBreaker.next());
                }
            }

            return(width);
        }