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 
25 namespace minikin {
26 
measure(const U16StringPiece & textBuf,bool computeHyphenation,bool computeLayout)27 void 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 
buildLayout(const U16StringPiece & textBuf,const Range & range,const MinikinPaint & paint,Bidi bidiFlags,StartHyphenEdit startHyphen,EndHyphenEdit endHyphen,Layout * layout)58 void 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 
getBounds(const U16StringPiece & textBuf,const Range & range)66 MinikinRect 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