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 #ifdef LOGGER_ENABLE_SCOPE
20 #include "texgine/utils/trace.h"
21 #endif
22
23 namespace OHOS {
24 namespace Rosen {
25 namespace TextEngine {
ReverseRTLText(std::vector<VariantSpan> & lineSpans)26 void TextReverser::ReverseRTLText(std::vector<VariantSpan> &lineSpans)
27 {
28 #ifdef LOGGER_ENABLE_SCOPE
29 ScopedTrace scope("Shaper::ReverseRTLText");
30 #endif
31 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "ReverseRTLText");
32 const auto &endit = lineSpans.end();
33 auto rtlSpansBeginIt = endit;
34 auto rtlSpansEndIt = endit;
35 bool rtl = false;
36 for (auto it = lineSpans.begin(); it != lineSpans.end(); it++) {
37 auto ts = it->TryToTextSpan();
38 if (ts != nullptr) {
39 rtl = ts->IsRTL();
40 }
41
42 if (rtl) {
43 rtlSpansBeginIt = rtlSpansBeginIt == endit ? it : rtlSpansBeginIt;
44 rtlSpansEndIt = it;
45 LOGCEX_DEBUG() << "is rtl";
46 continue;
47 } else {
48 LOGCEX_DEBUG() << "no rtl";
49 }
50
51 if (rtlSpansBeginIt == endit) {
52 continue;
53 }
54
55 rtlSpansEndIt++;
56 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "reverse");
57 for (auto i = rtlSpansBeginIt; i != rtlSpansEndIt; i++) {
58 i->Dump();
59 }
60 std::reverse(rtlSpansBeginIt, rtlSpansEndIt);
61 rtlSpansBeginIt = endit;
62 rtlSpansEndIt = endit;
63 }
64
65 if (rtlSpansBeginIt != endit) {
66 rtlSpansEndIt++;
67 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "reverse");
68 for (auto it = rtlSpansBeginIt; it != rtlSpansEndIt; it++) {
69 it->Dump();
70 }
71 std::reverse(rtlSpansBeginIt, rtlSpansEndIt);
72 }
73 }
74
ReverseConDirectionText(std::vector<VariantSpan> & lineSpans,int begin,int end)75 void TextReverser::ReverseConDirectionText(std::vector<VariantSpan> &lineSpans, int begin, int end)
76 {
77 while (begin < end) {
78 if (lineSpans[begin].GetVisibleWidth() == 0) {
79 begin++;
80 }
81
82 if (lineSpans[end].GetVisibleWidth() == 0) {
83 end--;
84 }
85
86 if (begin >= end) {
87 break;
88 }
89
90 auto temp = lineSpans[begin];
91 lineSpans[begin] = lineSpans[end];
92 lineSpans[end] = temp;
93 begin++;
94 end--;
95 }
96 }
97
ProcessTypoDirection(std::vector<VariantSpan> & lineSpans,const TextDirection dir)98 void TextReverser::ProcessTypoDirection(std::vector<VariantSpan> &lineSpans, const TextDirection dir)
99 {
100 #ifdef LOGGER_ENABLE_SCOPE
101 ScopedTrace scope("ProcessTypoDirection");
102 #endif
103 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "ProcessTypoDirection");
104 if (dir == TextDirection::LTR) {
105 return;
106 }
107
108 bool isConDirection = false;
109 int index = 0;
110 ReverseConDirectionText(lineSpans, 0, lineSpans.size() - 1);
111
112 for (auto i = 0; i < static_cast<int>(lineSpans.size()) - 1; i++) {
113 if (lineSpans[i].GetVisibleWidth() == 0 || lineSpans[i + 1].GetVisibleWidth() == 0 ||
114 lineSpans[i].IsRTL() == lineSpans[i + 1].IsRTL()) {
115 isConDirection = true;
116 continue;
117 }
118
119 if (isConDirection == true) {
120 ReverseConDirectionText(lineSpans, index, i);
121 index = i + 1;
122 isConDirection = false;
123 } else {
124 index++;
125 }
126 }
127
128 if (isConDirection) {
129 ReverseConDirectionText(lineSpans, index, lineSpans.size() - 1);
130 }
131 }
132 } // namespace TextEngine
133 } // namespace Rosen
134 } // namespace OHOS
135