summaryrefslogtreecommitdiff
path: root/include/minikin/LineBreaker.h
blob: 7fee1b7a01f3e4cbb38dfafa45a9c313bceb6c78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A module for breaking paragraphs into lines, supporting high quality
 * hyphenation and justification.
 */

#ifndef MINIKIN_LINE_BREAKER_H
#define MINIKIN_LINE_BREAKER_H

#include <deque>
#include <vector>

#include "minikin/FontCollection.h"
#include "minikin/Layout.h"
#include "minikin/Macros.h"
#include "minikin/MeasuredText.h"
#include "minikin/MinikinFont.h"
#include "minikin/Range.h"
#include "minikin/U16StringPiece.h"

namespace minikin {

enum class BreakStrategy : uint8_t {
    Greedy = 0,
    HighQuality = 1,
    Balanced = 2,
};

enum class HyphenationFrequency : uint8_t {
    None = 0,
    Normal = 1,
    Full = 2,
};

class Hyphenator;
class WordBreaker;

class TabStops {
public:
    // Caller must free stops. stops can be nullprt.
    TabStops(const float* stops, size_t nStops, float tabWidth)
            : mStops(stops), mStopsSize(nStops), mTabWidth(tabWidth) {}

    float nextTab(float widthSoFar) const {
        for (size_t i = 0; i < mStopsSize; i++) {
            if (mStops[i] > widthSoFar) {
                return mStops[i];
            }
        }
        if (mTabWidth == 0) {
            return 0;
        }
        return floor(widthSoFar / mTabWidth + 1) * mTabWidth;
    }

private:
    const float* mStops;
    size_t mStopsSize;
    float mTabWidth;
};

// Implement this for the additional information during line breaking.
// The functions in this class's interface may be called several times. The implementation
// must return the same value for the same input.
class LineWidth {
public:
    virtual ~LineWidth() {}

    // Called to find out the width for the line. This must not return negative values.
    virtual float getAt(size_t lineNo) const = 0;

    // Called to find out the minimum line width. This mut not return negative values.
    virtual float getMin() const = 0;
};

struct LineBreakResult {
public:
    LineBreakResult() = default;

    // Following five vectors have the same length.
    // TODO: Introduce individual line info struct if copy cost in JNI is negligible.
    std::vector<int> breakPoints;
    std::vector<float> widths;
    std::vector<float> ascents;
    std::vector<float> descents;
    std::vector<int> flags;
    std::vector<MinikinRect> bounds;

    LineBreakResult(LineBreakResult&&) = default;
    LineBreakResult& operator=(LineBreakResult&&) = default;

    void reverse() {
        std::reverse(breakPoints.begin(), breakPoints.end());
        std::reverse(widths.begin(), widths.end());
        std::reverse(ascents.begin(), ascents.end());
        std::reverse(descents.begin(), descents.end());
        std::reverse(flags.begin(), flags.end());
        std::reverse(bounds.begin(), bounds.end());
    }

private:
    MINIKIN_PREVENT_COPY_AND_ASSIGN(LineBreakResult);
};

LineBreakResult breakIntoLines(const U16StringPiece& textBuffer, BreakStrategy strategy,
                               HyphenationFrequency frequency, bool justified,
                               const MeasuredText& measuredText, const LineWidth& lineWidth,
                               const TabStops& tabStops, bool useBoundsForWidth);

}  // namespace minikin

#endif  // MINIKIN_LINE_BREAKER_H