1b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka/*
2b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * Copyright (C) 2017 The Android Open Source Project
3b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka *
4b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License");
5b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * you may not use this file except in compliance with the License.
6b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * You may obtain a copy of the License at
7b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka *
8b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka *      http://www.apache.org/licenses/LICENSE-2.0
9b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka *
10b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * Unless required by applicable law or agreed to in writing, software
11b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS,
12b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * See the License for the specific language governing permissions and
14b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka * limitations under the License.
15b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka */
16b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
17b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka#ifndef MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H
18b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka#define MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H
19b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
200385197086b0f08a39e7f6c9cee6f178ecb2746fSeigo Nonaka#include <algorithm>
210385197086b0f08a39e7f6c9cee6f178ecb2746fSeigo Nonaka
22b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka#include "minikin/LineBreaker.h"
23b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
24b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonakanamespace minikin {
25b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonakanamespace android {
26b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
270dcb27d502afcb34f59ac85c886ec13a5fdaa0ddSeigo Nonakaclass AndroidLineWidth : public LineWidth {
286c8722e217ff5238f0b849152d7936959a728103Seigo Nonakapublic:
296c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    AndroidLineWidth(float firstWidth, int32_t firstLineCount, float restWidth,
306c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                     const std::vector<float>& indents, const std::vector<float>& leftPaddings,
316c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                     const std::vector<float>& rightPaddings, int32_t indentsAndPaddingsOffset)
326c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            : mFirstWidth(firstWidth),
336c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mFirstLineCount(firstLineCount),
346c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mRestWidth(restWidth),
356c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mIndents(indents),
366c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mLeftPaddings(leftPaddings),
376c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mRightPaddings(rightPaddings),
386c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mOffset(indentsAndPaddingsOffset) {}
396c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka
406c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    float getAt(size_t lineNo) const override {
416c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        const float width = ((ssize_t)lineNo < (ssize_t)mFirstLineCount) ? mFirstWidth : mRestWidth;
420385197086b0f08a39e7f6c9cee6f178ecb2746fSeigo Nonaka        return std::max(0.0f, width - get(mIndents, lineNo));
436c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    }
446c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka
456c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    float getMin() const override {
466c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        // A simpler algorithm would have been simply looping until the larger of
476c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        // mFirstLineCount and mIndents.size()-mOffset, but that does unnecessary calculations
486c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        // when mFirstLineCount is large. Instead, we measure the first line, all the lines that
496c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        // have an indent, and the first line after firstWidth ends and restWidth starts.
506c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        float minWidth = std::min(getAt(0), getAt(mFirstLineCount));
516c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        for (size_t lineNo = 1; lineNo + mOffset < mIndents.size(); lineNo++) {
526c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            minWidth = std::min(minWidth, getAt(lineNo));
53b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka        }
546c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        return minWidth;
556c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    }
56b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
576c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    float getLeftPaddingAt(size_t lineNo) const override { return get(mLeftPaddings, lineNo); }
58b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
596c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    float getRightPaddingAt(size_t lineNo) const override { return get(mRightPaddings, lineNo); }
60b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
616c8722e217ff5238f0b849152d7936959a728103Seigo Nonakaprivate:
626c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    float get(const std::vector<float>& vec, size_t lineNo) const {
636c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        if (vec.empty()) {
646c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            return 0;
65b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka        }
666c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        const size_t index = lineNo + mOffset;
676c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        if (index < vec.size()) {
686c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            return vec[index];
696c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        } else {
706c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            return vec.back();
71b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka        }
726c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    }
736c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka
746c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const float mFirstWidth;
756c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const int32_t mFirstLineCount;
766c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const float mRestWidth;
776c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const std::vector<float>& mIndents;
786c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const std::vector<float>& mLeftPaddings;
796c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const std::vector<float>& mRightPaddings;
806c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const int32_t mOffset;
81b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka};
82b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
83b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonakaclass StaticLayoutNative {
846c8722e217ff5238f0b849152d7936959a728103Seigo Nonakapublic:
856c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    StaticLayoutNative(BreakStrategy strategy, HyphenationFrequency frequency, bool isJustified,
866c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                       std::vector<float>&& indents, std::vector<float>&& leftPaddings,
876c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                       std::vector<float>&& rightPaddings)
886c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            : mStrategy(strategy),
896c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mFrequency(frequency),
906c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mIsJustified(isJustified),
916c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mIndents(std::move(indents)),
926c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka              mLeftPaddings(std::move(leftPaddings)),
93b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka              mRightPaddings(std::move(rightPaddings)) {}
94b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
950948fbb63636111c193365e01dbe952defd700f3Seigo Nonaka    LineBreakResult computeBreaks(const U16StringPiece& textBuf, const MeasuredText& measuredText,
966c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                  // Line width arguments
976c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                  float firstWidth, int32_t firstWidthLineCount, float restWidth,
986c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                  int32_t indentsOffset,
996c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                  // Tab stop arguments
1006c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                  const int32_t* tabStops, int32_t tabStopSize,
1016c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                  int32_t defaultTabStopWidth) const {
1026c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        AndroidLineWidth lineWidth(firstWidth, firstWidthLineCount, restWidth, mIndents,
1036c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka                                   mLeftPaddings, mRightPaddings, indentsOffset);
1040948fbb63636111c193365e01dbe952defd700f3Seigo Nonaka        return breakIntoLines(textBuf, mStrategy, mFrequency, mIsJustified, measuredText, lineWidth,
1050948fbb63636111c193365e01dbe952defd700f3Seigo Nonaka                              TabStops(tabStops, tabStopSize, defaultTabStopWidth));
1066c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    }
1076c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka
1086c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    inline BreakStrategy getStrategy() const { return mStrategy; }
1096c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    inline HyphenationFrequency getFrequency() const { return mFrequency; }
1106c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    inline bool isJustified() const { return mIsJustified; }
1116c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka
1126c8722e217ff5238f0b849152d7936959a728103Seigo Nonakaprivate:
1136c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const BreakStrategy mStrategy;
1146c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const HyphenationFrequency mFrequency;
1156c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const bool mIsJustified;
1166c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const std::vector<float> mIndents;
1176c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const std::vector<float> mLeftPaddings;
1186c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    const std::vector<float> mRightPaddings;
119b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka};
120b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
121b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka}  // namespace android
122b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka}  // namespace minikin
123b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka
124b27a39233e1cc2d1230b02fe859969c9811095aaSeigo Nonaka#endif  // MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H
125