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