• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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/font.h"
17 
18 #include "modules/skunicode/include/SkUnicode.h"
19 
20 #include "impl_factory.h"
21 #include "impl_interface/font_impl.h"
22 #include "text/font_mgr.h"
23 #include "utils/log.h"
24 #include "font_harfbuzz.h"
25 
26 
27 namespace OHOS {
28 namespace Rosen {
29 namespace Drawing {
30 constexpr const char* LANGUAGE_HAN = "zh-Hans";
31 constexpr size_t COUNT_REQUESTED = 32;
32 #ifdef USE_M133_SKIA
33 using SkFeaturesArray = skia_private::STArray<COUNT_REQUESTED, hb_feature_t>;
34 #else
35 using SkFeaturesArray = SkSTArray<COUNT_REQUESTED, hb_feature_t>;
36 #endif
37 
Font()38 Font::Font() : fontImpl_(ImplFactory::CreateFontImpl()) {}
39 
Font(std::shared_ptr<Typeface> typeface,scalar size,scalar scaleX,scalar skewX)40 Font::Font(std::shared_ptr<Typeface> typeface, scalar size, scalar scaleX, scalar skewX)
41     : fontImpl_(ImplFactory::CreateFontImpl(typeface, size, scaleX, skewX)) {}
42 
Font(const Font & font)43 Font::Font(const Font& font) : fontImpl_(ImplFactory::CreateFontImpl(font)) {}
44 
SetEdging(FontEdging edging)45 void Font::SetEdging(FontEdging edging)
46 {
47     fontImpl_->SetEdging(edging);
48 }
49 
SetBaselineSnap(bool baselineSnap)50 void Font::SetBaselineSnap(bool baselineSnap)
51 {
52     fontImpl_->SetBaselineSnap(baselineSnap);
53 }
54 
SetForceAutoHinting(bool isForceAutoHinting)55 void Font::SetForceAutoHinting(bool isForceAutoHinting)
56 {
57     fontImpl_->SetForceAutoHinting(isForceAutoHinting);
58 }
59 
SetSubpixel(bool isSubpixel)60 void Font::SetSubpixel(bool isSubpixel)
61 {
62     fontImpl_->SetSubpixel(isSubpixel);
63 }
64 
SetHinting(FontHinting hintingLevel)65 void Font::SetHinting(FontHinting hintingLevel)
66 {
67     fontImpl_->SetHinting(hintingLevel);
68 }
69 
SetEmbeddedBitmaps(bool embeddedBitmaps)70 void Font::SetEmbeddedBitmaps(bool embeddedBitmaps)
71 {
72     fontImpl_->SetEmbeddedBitmaps(embeddedBitmaps);
73 }
74 
SetTypeface(std::shared_ptr<Typeface> typeface)75 void Font::SetTypeface(std::shared_ptr<Typeface> typeface)
76 {
77     fontImpl_->SetTypeface(typeface);
78 }
79 
SetSize(scalar textSize)80 void Font::SetSize(scalar textSize)
81 {
82     fontImpl_->SetSize(textSize);
83 }
84 
SetEmbolden(bool isEmbolden)85 void Font::SetEmbolden(bool isEmbolden)
86 {
87     fontImpl_->SetEmbolden(isEmbolden);
88 }
89 
SetScaleX(scalar scaleX)90 void Font::SetScaleX(scalar scaleX)
91 {
92     fontImpl_->SetScaleX(scaleX);
93 }
94 
SetSkewX(scalar skewX)95 void Font::SetSkewX(scalar skewX)
96 {
97     fontImpl_->SetSkewX(skewX);
98 }
99 
SetLinearMetrics(bool isLinearMetrics)100 void Font::SetLinearMetrics(bool isLinearMetrics)
101 {
102     fontImpl_->SetLinearMetrics(isLinearMetrics);
103 }
104 
GetMetrics(FontMetrics * metrics) const105 scalar Font::GetMetrics(FontMetrics* metrics) const
106 {
107     return fontImpl_->GetMetrics(metrics);
108 }
109 
GetWidths(const uint16_t glyphs[],int count,scalar widths[]) const110 void Font::GetWidths(const uint16_t glyphs[], int count, scalar widths[]) const
111 {
112     fontImpl_->GetWidths(glyphs, count, widths);
113 }
114 
GetWidths(const uint16_t glyphs[],int count,scalar widths[],Rect bounds[]) const115 void Font::GetWidths(const uint16_t glyphs[], int count, scalar widths[], Rect bounds[]) const
116 {
117     fontImpl_->GetWidths(glyphs, count, widths, bounds);
118 }
119 
GetSize() const120 scalar Font::GetSize() const
121 {
122     return fontImpl_->GetSize();
123 }
124 
GetTypeface() const125 std::shared_ptr<Typeface> Font::GetTypeface() const
126 {
127     return fontImpl_->GetTypeface();
128 }
129 
GetEdging() const130 FontEdging Font::GetEdging() const
131 {
132     return fontImpl_->GetEdging();
133 }
134 
GetHinting() const135 FontHinting Font::GetHinting() const
136 {
137     return fontImpl_->GetHinting();
138 }
139 
IsEmbeddedBitmaps() const140 bool Font::IsEmbeddedBitmaps() const
141 {
142     return fontImpl_->IsEmbeddedBitmaps();
143 }
144 
GetScaleX() const145 scalar Font::GetScaleX() const
146 {
147     return fontImpl_->GetScaleX();
148 }
149 
GetSkewX() const150 scalar Font::GetSkewX() const
151 {
152     return fontImpl_->GetSkewX();
153 }
154 
IsBaselineSnap() const155 bool Font::IsBaselineSnap() const
156 {
157     return fontImpl_->IsBaselineSnap();
158 }
159 
IsForceAutoHinting() const160 bool Font::IsForceAutoHinting() const
161 {
162     return fontImpl_->IsForceAutoHinting();
163 }
164 
IsSubpixel() const165 bool Font::IsSubpixel() const
166 {
167     return fontImpl_->IsSubpixel();
168 }
169 
IsLinearMetrics() const170 bool Font::IsLinearMetrics() const
171 {
172     return fontImpl_->IsLinearMetrics();
173 }
174 
IsEmbolden() const175 bool Font::IsEmbolden() const
176 {
177     return fontImpl_->IsEmbolden();
178 }
179 
UnicharToGlyph(int32_t uni) const180 uint16_t Font::UnicharToGlyph(int32_t uni) const
181 {
182     return fontImpl_->UnicharToGlyph(uni);
183 }
184 
ValidateAndCopyFontFeaturesToHbFeatures(const Drawing::DrawingFontFeatures & fontFeatures,SkFeaturesArray & hbFeatures)185 void ValidateAndCopyFontFeaturesToHbFeatures(const Drawing::DrawingFontFeatures& fontFeatures,
186     SkFeaturesArray& hbFeatures)
187 {
188     for (const auto& featureMap : fontFeatures) {
189         for (const auto& [key, value] : featureMap) {
190             if (key.size() != 4) { // 4 OpenType font feature name is fixed to be 4 chars.
191                 LOGW("Invalid feature name. font feature name has to be 4 chars");
192                 continue;
193             }
194             SkFourByteTag tag = SkSetFourByteTag(key[0], key[1], key[2], key[3]);
195             hbFeatures.push_back({(hb_tag_t)tag, (uint32_t)value, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END});
196         }
197     }
198 }
199 
UnicharToGlyphWithFeatures(const char * uni,std::shared_ptr<Drawing::DrawingFontFeatures> fontFeatures) const200 uint16_t Font::UnicharToGlyphWithFeatures(const char* uni,
201     std::shared_ptr<Drawing::DrawingFontFeatures> fontFeatures) const
202 {
203     if (fontFeatures == nullptr) {
204         LOGE("font features is null, return glyphId as 0");
205         return 0;
206     }
207 
208     const size_t utf8Bytes = strlen(uni);
209     const char* utf8Start = uni;
210     const char* utf8End = utf8Start + utf8Bytes;
211 
212     FontHarfbuzz::HBBuffer buffer(hb_buffer_create());
213     hb_buffer_t *buffer1 = buffer.get();
214     SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer1);
215     hb_buffer_set_content_type(buffer1, HB_BUFFER_CONTENT_TYPE_UNICODE);
216     hb_buffer_set_cluster_level(buffer1, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
217     hb_buffer_add_utf8(buffer1, uni, 0, utf8Bytes, 0);
218 
219     const char* utf8Current = utf8Start;
220     while (utf8Current < utf8End) {
221         uint32_t cluster = utf8Current - uni;
222         SkUnichar val = SkUTF::NextUTF8(&utf8Current, utf8End);
223         hb_codepoint_t u = val < 0 ? 0XFFDD : static_cast<hb_codepoint_t>(val);
224         hb_buffer_add(buffer1, u, cluster);
225     }
226 
227     const hb_language_t language = hb_language_from_string(LANGUAGE_HAN, -1);
228     hb_buffer_set_language(buffer1, language);
229     hb_buffer_guess_segment_properties(buffer1);
230 
231     FontHarfbuzz::HBFont hbFont;
232     {
233         std::shared_ptr<Typeface> typeface = GetTypeface();
234         if (!typeface) {
235             LOGW("typeface is null, return glyphId as 0");
236             return 0;
237         }
238         FontHarfbuzz::HBFont typefaceFont(FontHarfbuzz::CreateTypefaceHbFont(*typeface));
239         hbFont = FontHarfbuzz::CreateSubHbFont(*this, typefaceFont);
240     }
241 
242     SkFeaturesArray hbFeatures;
243     ValidateAndCopyFontFeaturesToHbFeatures(*fontFeatures, hbFeatures);
244     hb_shape(hbFont.get(), buffer1, hbFeatures.data(), hbFeatures.size());
245     if (hb_buffer_get_length(buffer1) == 0) {
246         LOGW("buffer is empty, return glyphId as 0");
247         return 0;
248     }
249 
250     hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer1, nullptr);
251     if (info == nullptr) {
252         LOGW("glyph info generate failed, return glyphId as 0");
253         return 0;
254     }
255     return info[0].codepoint;
256 }
257 
TextToGlyphs(const void * text,size_t byteLength,TextEncoding encoding,uint16_t glyphs[],int maxGlyphCount) const258 int Font::TextToGlyphs(const void* text, size_t byteLength, TextEncoding encoding,
259     uint16_t glyphs[], int maxGlyphCount) const
260 {
261     return fontImpl_->TextToGlyphs(text, byteLength, encoding, glyphs, maxGlyphCount);
262 }
263 
MeasureText(const void * text,size_t byteLength,TextEncoding encoding,Rect * bounds) const264 scalar Font::MeasureText(const void* text, size_t byteLength, TextEncoding encoding, Rect* bounds) const
265 {
266     return fontImpl_->MeasureText(text, byteLength, encoding, bounds);
267 }
268 
MeasureText(const void * text,size_t byteLength,TextEncoding encoding,Rect * bounds,const Brush * brush,const Pen * pen) const269 scalar Font::MeasureText(const void* text, size_t byteLength, TextEncoding encoding, Rect* bounds, const Brush* brush,
270     const Pen* pen) const
271 {
272     if (brush != nullptr && pen != nullptr) {
273         LOGE("Font::MeasureText brush and pen are both not nullptr");
274         return 0.0f;
275     }
276     return fontImpl_->MeasureText(text, byteLength, encoding, bounds, brush, pen);
277 }
278 
GetWidthsBounds(const uint16_t glyphs[],int count,float widths[],Rect bounds[],const Brush * brush,const Pen * pen) const279 void Font::GetWidthsBounds(
280     const uint16_t glyphs[], int count, float widths[], Rect bounds[], const Brush* brush, const Pen* pen) const
281 {
282     if (brush != nullptr && pen != nullptr) {
283         LOGE("Font::GetWidthsBounds brush and pen are both not nullptr");
284         return;
285     }
286     fontImpl_->GetWidthsBounds(glyphs, count, widths, bounds, brush, pen);
287 }
288 
GetPos(const uint16_t glyphs[],int count,Point points[],Point origin) const289 void Font::GetPos(const uint16_t glyphs[], int count, Point points[], Point origin) const
290 {
291     fontImpl_->GetPos(glyphs, count, points, origin);
292 }
293 
GetSpacing() const294 float Font::GetSpacing() const
295 {
296     return fontImpl_->GetSpacing();
297 }
298 
MeasureSingleCharacter(int32_t unicode) const299 scalar Font::MeasureSingleCharacter(int32_t unicode) const
300 {
301     scalar textWidth = 0.0f;
302     uint16_t glyph = UnicharToGlyph(unicode);
303     if (glyph != 0) {
304         textWidth = MeasureText(&glyph, sizeof(uint16_t), TextEncoding::GLYPH_ID);
305     } else {
306         std::shared_ptr<Font> fallbackFont = GetFallbackFont(unicode);
307         if (fallbackFont) {
308             uint16_t fallbackGlyph = fallbackFont->UnicharToGlyph(unicode);
309             textWidth = fallbackFont->MeasureText(&fallbackGlyph, sizeof(uint16_t), TextEncoding::GLYPH_ID);
310         }
311     }
312     return textWidth;
313 }
314 
MeasureSingleCharacterWithFeatures(const char * unicode,int32_t unicodeId,std::shared_ptr<Drawing::DrawingFontFeatures> fontFeatures) const315 scalar Font::MeasureSingleCharacterWithFeatures(const char* unicode, int32_t unicodeId,
316     std::shared_ptr<Drawing::DrawingFontFeatures> fontFeatures) const
317 {
318     scalar textWidth = 0.0f;
319     uint16_t glyph = UnicharToGlyphWithFeatures(unicode, fontFeatures);
320     if (glyph != 0) {
321         textWidth = MeasureText(&glyph, sizeof(uint16_t), TextEncoding::GLYPH_ID);
322     } else {
323         std::shared_ptr<Font> fallbackFont = GetFallbackFont(unicodeId);
324         if (fallbackFont) {
325             uint16_t fallbackGlyph = fallbackFont->UnicharToGlyphWithFeatures(unicode, fontFeatures);
326             textWidth = fallbackFont->MeasureText(&fallbackGlyph, sizeof(uint16_t), TextEncoding::GLYPH_ID);
327         }
328     }
329     return textWidth;
330 }
331 
GetFallbackFont(int32_t unicode) const332 std::shared_ptr<Font> Font::GetFallbackFont(int32_t unicode) const
333 {
334     std::shared_ptr<FontMgr> fontMgr = FontMgr::CreateDefaultFontMgr();
335     if (fontMgr == nullptr) {
336         LOGE("Font::GetFallbackFont, default fontMgr is nullptr.");
337         return nullptr;
338     }
339     std::shared_ptr<Typeface> currentTypeface = GetTypeface();
340     std::shared_ptr<Typeface> fallbackTypeface = nullptr;
341     if (currentTypeface) {
342         fallbackTypeface = std::shared_ptr<Typeface>(fontMgr->MatchFamilyStyleCharacter(nullptr,
343             currentTypeface->GetFontStyle(), nullptr, 0, unicode < 0 ? 0xFFFD : unicode));
344     } else {
345         std::shared_ptr<Typeface> defaultTypeface = Typeface::MakeDefault();
346         fallbackTypeface = std::shared_ptr<Typeface>(fontMgr->MatchFamilyStyleCharacter(nullptr, defaultTypeface
347             ? defaultTypeface->GetFontStyle() : FontStyle(), nullptr, 0, unicode < 0 ? 0xFFFD : unicode));
348     }
349     if (fallbackTypeface == nullptr) {
350         LOGE("Font::GetFallbackFont, fallback typeface is nullptr.");
351         return nullptr;
352     }
353     std::shared_ptr<Font> fallbackFont = std::make_shared<Font>(*this);
354     fallbackFont->SetTypeface(fallbackTypeface);
355     return fallbackFont;
356 }
357 
CountText(const void * text,size_t byteLength,TextEncoding encoding) const358 int Font::CountText(const void* text, size_t byteLength, TextEncoding encoding) const
359 {
360     return fontImpl_->CountText(text, byteLength, encoding);
361 }
362 
GetPathForGlyph(uint16_t glyph,Path * path) const363 bool Font::GetPathForGlyph(uint16_t glyph, Path* path) const
364 {
365     return fontImpl_->GetPathForGlyph(glyph, path);
366 }
367 
GetTextPath(const void * text,size_t byteLength,TextEncoding encoding,float x,float y,Path * path) const368 void Font::GetTextPath(const void* text, size_t byteLength, TextEncoding encoding, float x, float y, Path* path) const
369 {
370     fontImpl_->GetTextPath(text, byteLength, encoding, x, y, path);
371 }
372 
SetThemeFontFollowed(bool followed)373 void Font::SetThemeFontFollowed(bool followed)
374 {
375     themeFontFollowed_ = followed;
376 }
377 
IsThemeFontFollowed() const378 bool Font::IsThemeFontFollowed() const
379 {
380     return themeFontFollowed_;
381 }
382 } // namespace Drawing
383 } // namespace Rosen
384 } // namespace OHOS
385