• 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 #ifndef ROSEN_MODULES_TEXGINE_SRC_MEASURER_IMPL_H
17 #define ROSEN_MODULES_TEXGINE_SRC_MEASURER_IMPL_H
18 
19 #include <iomanip>
20 #include <list>
21 #include <queue>
22 #include <mutex>
23 
24 #include <hb.h>
25 #include <hb-icu.h>
26 #include <unicode/utf16.h>
27 #include <unicode/uchar.h>
28 
29 #include "measurer.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace TextEngine {
34 struct MeasuringRun {
35     size_t start;
36     size_t end;
37     hb_script_t script = HB_SCRIPT_INVALID;
38     std::shared_ptr<Typeface> typeface = nullptr;
39 };
40 
41 class MeasurerImpl : public Measurer {
42 public:
43     MeasurerImpl(const std::vector<uint16_t> &text, const FontCollection &fontCollection);
44 
45     /*
46      * @brief Get word boundary of text
47      */
48     const std::vector<Boundary> &GetWordBoundary() const override;
49 
50     /*
51      * @brief Measure font
52      * @param cgs The output parameter, after measurer will generate char groups
53      * @return 0 is measurer successed
54      *         1 is measurer failed
55      */
56     int Measure(CharGroups &cgs) override;
57 
58     /*
59      * @brief Seeks typeface for text, this should be private, now is for UT testing
60      * @param runs Input and output parameter, intermediate products of measurement
61      */
62     void SeekTypeface(std::list<struct MeasuringRun> &runs);
63 
64     /*
65      * @brief Seeks script for text, this should be private, now is for UT testing
66      * @param runs Input and output parameter, intermediate products of measurement
67      */
68     void SeekScript(std::list<struct MeasuringRun> &runs);
69 
70     /*
71      * @brief Text shaping, after this, information such as the width and height of the
72      *         text will be obtain. This should be private, now is for UT testing
73      * @param cgs The output parameter, char groups of text
74      * @param runs Input and output parameter, intermediate products of measurement
75      * @param boundary The word boundarys of text
76      * @return 0 is shape successed
77      *         1 is shape failed
78      */
79     int Shape(CharGroups &cgs, std::list<struct MeasuringRun> &runs, std::vector<Boundary> boundaries);
80 
81     /*
82      * @brief Generate font features required for shaping.
83      *        This should be private, now is for UT testing.
84      * @param fontFeatures The output parameter. Will passed to harfbuzz
85      * @param ff Font features user want
86      */
87     void GenerateHBFeatures(std::vector<hb_feature_t> &fontFeatures, const FontFeatures* ff);
88 
89 private:
90     struct MeasurerCacheKey {
91         std::vector<uint16_t> text = {};
92         FontStyles style;
93         std::string locale = "";
94         bool rtl = false;
95         double size = 16.0; // default TextStyle fontSize_
96         size_t startIndex = 0;
97         size_t endIndex = 0;
98         double letterSpacing = 0;
99         double wordSpacing = 0;
100 
101         bool operator <(const struct MeasurerCacheKey &rhs) const
102         {
103             if (startIndex != rhs.startIndex) {
104                 return startIndex < rhs.startIndex;
105             }
106             if (endIndex != rhs.endIndex) {
107                 return endIndex < rhs.endIndex;
108             }
109             if (text != rhs.text) {
110                 return text < rhs.text;
111             }
112             if (rtl != rhs.rtl) {
113                 return rtl < rhs.rtl;
114             }
115             if (size != rhs.size) {
116                 return size < rhs.size;
117             }
118             if (style != rhs.style) {
119                 return style < rhs.style;
120             }
121             if (locale != rhs.locale) {
122                 return locale < rhs.locale;
123             }
124             if (letterSpacing != rhs.letterSpacing) {
125                 return letterSpacing < rhs.letterSpacing;
126             }
127             if (wordSpacing != rhs.wordSpacing) {
128                 return wordSpacing < rhs.wordSpacing;
129             }
130             return false;
131         }
132     };
133     struct MeasurerCacheVal {
134         CharGroups cgs;
135         std::vector<Boundary> boundaries = {};
136     };
137 
138     void DoSeekScript(std::list<struct MeasuringRun> &runs, hb_unicode_funcs_t* icuGetUnicodeFuncs);
139     int DoShape(CharGroups &cgs, MeasuringRun &run, size_t &index);
140     int GetGlyphs(CharGroups &cgs, MeasuringRun &run, size_t &index, hb_buffer_t* hbuffer,
141         std::shared_ptr<TextEngine::Typeface> typeface);
142     void DoCgsByCluster(std::map<uint32_t, TextEngine::CharGroup> &cgsByCluster);
143     void HbDestroy(hb_buffer_t* hbuffer, hb_font_t* hfont, hb_face_t* hface, hb_unicode_funcs_t* icuGetUnicodeFuncs);
144     void UpdateCache();
145     void GetInitKey(struct MeasurerCacheKey &key) const;
146     static inline std::mutex mutex_;
147     static inline std::map<struct MeasurerCacheKey, struct MeasurerCacheVal> cache_;
148     std::vector<Boundary> boundaries_ = {};
149 };
150 
151 hb_blob_t* HbFaceReferenceTableTypeface(hb_face_t* face, hb_tag_t tag, void* context);
152 } // namespace TextEngine
153 } // namespace Rosen
154 } // namespace OHOS
155 
156 #endif // ROSEN_MODULES_TEXGINE_SRC_MEASURER_IMPL_H