1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "text_reverser.h"
17
18 #include "texgine/utils/exlog.h"
19 #include "texgine/utils/trace.h"
20
21 namespace OHOS {
22 namespace Rosen {
23 namespace TextEngine {
ReverseRTLText(std::vector<VariantSpan> & lineSpans)24 void TextReverser::ReverseRTLText(std::vector<VariantSpan> &lineSpans)
25 {
26 ScopedTrace scope("Shaper::ReverseRTLText");
27 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "ReverseRTLText");
28 const auto &endit = lineSpans.end();
29 auto rtlSpansBeginIt = endit;
30 auto rtlSpansEndIt = endit;
31 bool rtl = false;
32 for (auto it = lineSpans.begin(); it != lineSpans.end(); it++) {
33 auto ts = it->TryToTextSpan();
34 if (ts != nullptr) {
35 rtl = ts->IsRTL();
36 }
37
38 if (rtl) {
39 rtlSpansBeginIt = rtlSpansBeginIt == endit ? it : rtlSpansBeginIt;
40 rtlSpansEndIt = it;
41 LOGCEX_DEBUG() << "is rtl";
42 continue;
43 } else {
44 LOGCEX_DEBUG() << "no rtl";
45 }
46
47 if (rtlSpansBeginIt == endit) {
48 continue;
49 }
50
51 rtlSpansEndIt++;
52 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "reverse");
53 for (auto i = rtlSpansBeginIt; i != rtlSpansEndIt; i++) {
54 i->Dump();
55 }
56 std::reverse(rtlSpansBeginIt, rtlSpansEndIt);
57 rtlSpansBeginIt = endit;
58 rtlSpansEndIt = endit;
59 }
60
61 if (rtlSpansBeginIt != endit) {
62 rtlSpansEndIt++;
63 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "reverse");
64 for (auto it = rtlSpansBeginIt; it != rtlSpansEndIt; it++) {
65 it->Dump();
66 }
67 std::reverse(rtlSpansBeginIt, rtlSpansEndIt);
68 }
69 }
70
ReverseConDirectionText(std::vector<VariantSpan> & lineSpans,int begin,int end)71 void TextReverser::ReverseConDirectionText(std::vector<VariantSpan> &lineSpans, int begin, int end)
72 {
73 while (begin < end) {
74 if (lineSpans[begin].GetVisibleWidth() == 0) {
75 begin++;
76 }
77
78 if (lineSpans[end].GetVisibleWidth() == 0) {
79 end--;
80 }
81
82 if (begin >= end) {
83 break;
84 }
85
86 auto temp = lineSpans[begin];
87 lineSpans[begin] = lineSpans[end];
88 lineSpans[end] = temp;
89 begin++;
90 end--;
91 }
92 }
93
ProcessTypoDirection(std::vector<VariantSpan> & lineSpans,const TextDirection dir)94 void TextReverser::ProcessTypoDirection(std::vector<VariantSpan> &lineSpans, const TextDirection dir)
95 {
96 ScopedTrace scope("ProcessTypoDirection");
97 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "ProcessTypoDirection");
98 if (dir == TextDirection::LTR) {
99 return;
100 }
101
102 bool isConDirection = false;
103 int index = 0;
104 ReverseConDirectionText(lineSpans, 0, lineSpans.size() - 1);
105
106 for (auto i = 0; i < static_cast<int>(lineSpans.size()) - 1; i++) {
107 if (lineSpans[i].GetVisibleWidth() == 0 || lineSpans[i + 1].GetVisibleWidth() == 0 ||
108 lineSpans[i].IsRTL() == lineSpans[i + 1].IsRTL()) {
109 isConDirection = true;
110 continue;
111 }
112
113 if (isConDirection == true) {
114 ReverseConDirectionText(lineSpans, index, i);
115 index = i + 1;
116 isConDirection = false;
117 } else {
118 index++;
119 }
120 }
121
122 if (isConDirection) {
123 ReverseConDirectionText(lineSpans, index, lineSpans.size() - 1);
124 }
125 }
126 } // namespace TextEngine
127 } // namespace Rosen
128 } // namespace OHOS
129