• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bidi_processer.h"
17 #include <unicode/ubidi.h>
18 
19 #include "texgine_exception.h"
20 #include "texgine/utils/exlog.h"
21 #ifdef LOGGER_ENABLE_SCOPE
22 #include "texgine/utils/trace.h"
23 #endif
24 
25 namespace OHOS {
26 namespace Rosen {
27 namespace TextEngine {
ProcessBidiText(const std::vector<VariantSpan> & spans,const TextDirection dir)28 std::vector<VariantSpan> BidiProcesser::ProcessBidiText(const std::vector<VariantSpan> &spans, const TextDirection dir)
29 {
30 #ifdef LOGGER_ENABLE_SCOPE
31     ScopedTrace scope("BidiProcesser::ProcessBidiText");
32 #endif
33     LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "ProcessBidiText");
34     std::vector<VariantSpan> newSpans;
35     for (auto const &span : spans) {
36         auto ts = span.TryToTextSpan();
37         if (ts == nullptr) {
38             newSpans.emplace_back(span);
39             continue;
40         }
41 
42         span.Dump();
43         auto nsis = DoBidiProcess(ts->cgs_, dir);
44         for (auto const &nsi : nsis) {
45             ts->rtl_ = nsi.rtl;
46             VariantSpan vs(ts->CloneWithCharGroups(nsi.cgs));
47             vs.SetTextStyle(span.GetTextStyle());
48             double spanWidth = 0.0;
49             for (const auto &cg : nsi.cgs) {
50                 spanWidth += cg.GetWidth();
51             }
52             vs.TryToTextSpan()->width_ = spanWidth;
53             newSpans.emplace_back(vs);
54         }
55     }
56 
57     return newSpans;
58 }
59 
DoBidiProcess(const CharGroups & cgs,const TextDirection dir)60 std::vector<NewSpanInfo> BidiProcesser::DoBidiProcess(const CharGroups &cgs, const TextDirection dir)
61 {
62     LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "BidiProcesser::doBidiProcess");
63     if (!cgs.IsValid() || cgs.GetSize() == 0) {
64         throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
65     }
66 
67     auto deleter = [](UBiDi *p) {ubidi_close(p);};
68     std::unique_ptr<UBiDi, decltype(deleter)> bidi(ubidi_open(), deleter);
69     if (bidi == nullptr) {
70         throw APIFailedException("ubidi_open is failed");
71     }
72 
73     auto u16vect = cgs.ToUTF16All();
74     auto status = U_ZERO_ERROR;
75     auto level = dir == TextDirection::RTL ? UBIDI_RTL : UBIDI_LTR;
76     ubidi_setPara(bidi.get(), reinterpret_cast<UChar *>(u16vect.data()),
77         u16vect.size(), level, nullptr, &status);
78     if (!U_SUCCESS(status)) {
79         throw APIFailedException("ubidi_setPara failed");
80     }
81 
82     int size = ubidi_countRuns(bidi.get(), &status);
83     std::vector<NewSpanInfo> nsis;
84     for (auto i = 0; i < size; i++) {
85         NewSpanInfo nsi;
86         int start = -1;
87         int length = -1;
88         nsi.rtl = (ubidi_getVisualRun(bidi.get(), i, &start, &length) == UBIDI_RTL);
89         if (start < 0 || length < 0) {
90             throw APIFailedException("ubidi_getVisualRun is failed");
91         }
92 
93         auto cc = cgs.GetSubFromU16RangeAll(start, start + length);
94         LOGEX_FUNC_LINE_DEBUG(Logger::SetToNoReturn) <<
95             "u16[" << start << ", " << start + length << ")" <<
96             " is " << (nsi.rtl ? "rtl" : "ltr") << " ";
97         if (cgs.IsIntersect(cc) == false) {
98             LOGCEX_DEBUG() << "not intersect";
99             continue;
100         }
101 
102         auto ic = cgs.GetIntersect(cc);
103         LOGCEX_DEBUG() << "intersect at cgs" << ic.GetRange();
104         nsi.cgs = ic;
105         nsis.emplace_back(nsi);
106     }
107     if (dir == TextDirection::RTL) {
108         std::reverse(nsis.begin(), nsis.end());
109     }
110     return nsis;
111 }
112 } // namespace TextEngine
113 } // namespace Rosen
114 } // namespace OHOS
115