1/*
2 * Copyright (c) 2020-2022 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#ifndef GRAPHIC_LITE_LINE_BREAK_H
17#define GRAPHIC_LITE_LINE_BREAK_H
18
19#include "graphic_config.h"
20#if ENABLE_ICU
21#include <cstdint>
22#include <string>
23
24#include "common/text.h"
25#include "font/ui_font_header.h"
26#include "gfx_utils/file.h"
27#include "gfx_utils/heap_base.h"
28#include "gfx_utils/mem_api.h"
29
30namespace OHOS {
31class UILineBreakProxy;
32/**
33 * @brief Using ICU as the core of lineBreakEngine.
34 *
35 */
36class UILineBreakEngine : public HeapBase {
37public:
38    /**
39     * @brief Get UILineBreakEngine instannce.
40     *
41     * @return UILineBreakEngine&
42     */
43    static UILineBreakEngine& GetInstance();
44
45    /**
46     * @brief Init the line break engine and load the line break rules.
47     *
48     */
49    void Init()
50    {
51        LoadRule();
52    }
53
54    /**
55     * @brief Get the next line break position.
56     *
57     * @param record UILineBreakProxy instance.
58     * @return uint16_t Next line break position.
59     */
60    uint16_t GetNextBreakPos(UILineBreakProxy& record);
61
62    /**
63     * @brief Set the rule file path.
64     *
65     * @param fp File descriptor.
66     * @param offset The offset of rule.
67     * @param size File size.
68     * @return int32_t Result.
69     */
70    int32_t SetRuleBinInfo(int32_t fp, int32_t offset, uint32_t size)
71    {
72        fp_ = fp;
73        offset_ = offset;
74        int32_t fRet = lseek(fp_, offset, SEEK_SET);
75        if (fRet != offset) {
76            return fRet;
77        }
78        size_ = size;
79        return 0;
80    }
81
82    /**
83     * @brief Set the rule file load addr object.
84     *
85     * @param addr The rule file load addr.
86     */
87    void SetRuleFileLoadAddr(char* addr)
88    {
89        addr_ = addr;
90    }
91
92    /**
93     * @brief Get the rule file load addr.
94     *
95     * @return char* The rule file load addr.
96     */
97    char* GetRuleFileLoadAddr() const
98    {
99        return addr_;
100    }
101
102    /**
103     * @brief Get the size of rule file.
104     *
105     * @return int32_t The size of rule file.
106     */
107    int32_t GetRuleFileSize() const
108    {
109        return size_;
110    }
111
112    // 0xFFFF: unlimit the length until the end null.
113    uint32_t GetNextLineAndWidth(const char* text,
114                                 uint16_t fontId,
115                                 uint8_t fontSize,
116                                 int16_t space,
117                                 bool allBreak,
118                                 int16_t& maxWidth,
119                                 int16_t& maxHeight,
120                                 uint16_t& letterIndex,
121                                 SpannableString* spannableString,
122                                 uint16_t len = 0xFFFF,
123                                 bool eliminateTrailingSpaces = false);
124    bool IsBreakPos(uint32_t unicode, uint16_t fontId, uint8_t fontSize, int32_t& state);
125
126private:
127    UILineBreakEngine()
128        : initSuccess_(false), addr_(nullptr), size_(0), fp_(0), offset_(0), lineBreakTrie_(nullptr), stateTbl_(nullptr)
129    {
130    }
131    ~UILineBreakEngine() {}
132
133    void LoadRule();
134    int16_t GetLetterWidth(uint32_t unicode, uint16_t& letterIndex, int16_t& maxHeight,
135                           uint16_t fontId, uint8_t fontSize, SpannableString* spannableString);
136    static constexpr const int32_t LINE_BREAK_STATE_START = 1;
137    static constexpr const int32_t LINE_BREAK_STATE_STOP = 0;
138    bool initSuccess_;
139    char* addr_;
140    int32_t size_;
141    int32_t fp_;
142    int32_t offset_;
143    void* lineBreakTrie_;
144    const void* stateTbl_;
145};
146
147/**
148 * @brief Line break proxy.
149 *
150 */
151class UILineBreakProxy : public HeapBase {
152public:
153    UILineBreakProxy() = delete;
154
155    /**
156     * @brief Construct a new UILineBreakProxy object.
157     *
158     * @param str Input string.
159     * @param len The length of string.
160     */
161    UILineBreakProxy(uint32_t* str, uint16_t len) : str_(str), len_(len), prePos_(0) {}
162
163    ~UILineBreakProxy()
164    {
165        str_ = nullptr;
166        len_ = 0;
167        prePos_ = 0;
168    }
169
170    /**
171     * @brief Get next line break position.
172     *
173     * @return uint16_t Next line break position.
174     */
175    uint16_t GetNextBreakPos()
176    {
177        uint16_t offsetFromPrePos = UILineBreakEngine::GetInstance().GetNextBreakPos(*this);
178        prePos_ += offsetFromPrePos;
179        return prePos_;
180    }
181
182    /**
183     * @brief Get the length of string.
184     *
185     * @return uint16_t The length of string.
186     */
187    uint16_t GetStrLen() const
188    {
189        if (prePos_ < len_) {
190            return len_ - prePos_;
191        }
192        return 0;
193    }
194
195    /**
196     * @brief Get the string.
197     *
198     * @return uint16_t* The str setted.
199     */
200    const uint32_t* GetStr() const
201    {
202        if (prePos_ < len_) {
203            return &(str_[prePos_]);
204        }
205        return nullptr;
206    }
207
208private:
209    uint32_t* str_;
210    uint16_t len_;
211    uint16_t prePos_;
212};
213} // namespace OHOS
214#endif // ENABLE_ICU
215#endif // GRAPHIC_LITE_LINE_BREAK_H
216