1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Minikin"
18#include "minikin/MeasuredText.h"
19
20#include "minikin/Layout.h"
21
22#include "LayoutUtils.h"
23#include "LineBreakerUtil.h"
24
25namespace minikin {
26
27void MeasuredText::measure(const U16StringPiece& textBuf, bool computeHyphenation,
28                           bool computeLayout) {
29    if (textBuf.size() == 0) {
30        return;
31    }
32    LayoutPieces* piecesOut = computeLayout ? &layoutPieces : nullptr;
33    CharProcessor proc(textBuf);
34    for (const auto& run : runs) {
35        const Range& range = run->getRange();
36        const uint32_t runOffset = range.getStart();
37        run->getMetrics(textBuf, widths.data() + runOffset, extents.data() + runOffset, piecesOut);
38
39        if (!computeHyphenation || !run->canHyphenate()) {
40            continue;
41        }
42
43        proc.updateLocaleIfNecessary(*run);
44        for (uint32_t i = range.getStart(); i < range.getEnd(); ++i) {
45            proc.feedChar(i, textBuf[i], widths[i]);
46
47            const uint32_t nextCharOffset = i + 1;
48            if (nextCharOffset != proc.nextWordBreak) {
49                continue;  // Wait until word break point.
50            }
51
52            populateHyphenationPoints(textBuf, *run, *proc.hyphenator, proc.contextRange(),
53                                      proc.wordRange(), &hyphenBreaks, piecesOut);
54        }
55    }
56}
57
58void MeasuredText::buildLayout(const U16StringPiece& textBuf, const Range& range,
59                               const MinikinPaint& paint, Bidi bidiFlags,
60                               StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
61                               Layout* layout) {
62    layout->doLayoutWithPrecomputedPieces(textBuf, range, bidiFlags, paint, startHyphen, endHyphen,
63                                          layoutPieces);
64}
65
66MinikinRect MeasuredText::getBounds(const U16StringPiece& textBuf, const Range& range) {
67    MinikinRect rect;
68    float advance = 0.0f;
69    for (const auto& run : runs) {
70        const Range& runRange = run->getRange();
71        if (!Range::intersects(range, runRange)) {
72            continue;
73        }
74        std::pair<float, MinikinRect> next =
75                run->getBounds(textBuf, Range::intersection(runRange, range), layoutPieces);
76        MinikinRect nextRect = next.second;
77        nextRect.offset(advance, 0);
78        rect.join(nextRect);
79        advance += next.first;
80    }
81    return rect;
82}
83
84}  // namespace minikin
85