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 "text_shaper.h"
17
18 #include "measurer.h"
19 #include "texgine_exception.h"
20 #include "texgine_font.h"
21 #include "texgine_text_blob_builder.h"
22 #include "texgine/typography_types.h"
23 #include "texgine/utils/exlog.h"
24 #include "texgine/utils/trace.h"
25
26 namespace OHOS {
27 namespace Rosen {
28 namespace TextEngine {
29 #define DOUBLE 2
30
Shape(const VariantSpan & span,const TypographyStyle & ys,const std::shared_ptr<FontProviders> & fontProviders) const31 int TextShaper::Shape(const VariantSpan &span, const TypographyStyle &ys,
32 const std::shared_ptr<FontProviders> &fontProviders) const
33 {
34 ScopedTrace scope("TextShaper::ShapeLineSpans");
35 LOGSCOPED(sl, LOGEX_FUNC_LINE_DEBUG(), "TextShaper::ShapeLineSpans");
36 if (span == nullptr) {
37 LOGEX_FUNC_LINE(ERROR) << "span is nullptr";
38 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
39 }
40
41 if (span.TryToAnySpan() != nullptr) {
42 // Shape successed
43 return 0;
44 }
45
46 auto xs = span.GetTextStyle();
47 auto ts = span.TryToTextSpan();
48 auto ret = DoShape(ts, xs, ys, fontProviders);
49 if (ret) {
50 LOGEX_FUNC_LINE(ERROR) << "DoShape failed";
51 // Shape failed
52 return 1;
53 }
54
55 if (!ts->cgs_.IsValid()) {
56 LOGEX_FUNC_LINE(ERROR) << "cgs is inValid";
57 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
58 }
59
60 if (ts->cgs_.GetSize() <= 0) {
61 LOGEX_FUNC_LINE(ERROR) << "cgs have no cg";
62 return 1;
63 }
64
65 if (ts->cgs_.Get(0).typeface == nullptr) {
66 LOGEX_FUNC_LINE(ERROR) << "first cgs have no typeface";
67 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
68 }
69
70 TexgineFont font;
71 font.SetTypeface(ts->cgs_.Get(0).typeface->Get());
72 font.SetSize(xs.fontSize);
73 font.GetMetrics(&ts->tmetrics_);
74
75 auto blob = GenerateTextBlob(font, ts->cgs_, ts->width_, ts->glyphWidths_);
76 if (blob == nullptr) {
77 LOGEX_FUNC_LINE(ERROR) << "Generate text blob is failed";
78 return 1;
79 }
80
81 ts->textBlob_ = blob;
82 return 0;
83 }
84
DoShape(std::shared_ptr<TextSpan> & span,const TextStyle & xs,const TypographyStyle & ys,const std::shared_ptr<FontProviders> & fontProviders)85 int TextShaper::DoShape(std::shared_ptr<TextSpan> &span, const TextStyle &xs,
86 const TypographyStyle &ys, const std::shared_ptr<FontProviders> &fontProviders)
87 {
88 if (fontProviders == nullptr || span == nullptr) {
89 LOGEX_FUNC_LINE(ERROR) << "providers or span is nullptr";
90 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
91 }
92
93 auto families = xs.fontFamilies;
94 if (families.empty()) {
95 families = ys.fontFamilies;
96 }
97
98 auto fontCollection = fontProviders->GenerateFontCollection(families);
99 if (fontCollection == nullptr) {
100 LOGEX_FUNC_LINE(ERROR) << "fontCollection is nullptr";
101 return 1;
102 }
103
104 span->u16vect_ = span->cgs_.ToUTF16();
105 auto measurer = Measurer::Create(span->u16vect_, *fontCollection);
106 if (measurer == nullptr) {
107 return 1;
108 }
109 measurer->SetLocale(xs.locale);
110 measurer->SetRTL(span->rtl_);
111 FontStyles style(xs.fontWeight, xs.fontStyle);
112 measurer->SetFontStyle(style);
113 measurer->SetSize(xs.fontSize);
114 measurer->SetFontFeatures(xs.fontFeature);
115 measurer->SetRange(0, span->u16vect_.size());
116 measurer->SetSpacing(xs.letterSpacing, xs.wordSpacing);
117 if (measurer->Measure(span->cgs_)) {
118 LOGEX_FUNC_LINE(ERROR) << "Measurer::Measure failed";
119 return 1;
120 }
121
122 return 0;
123 }
124
GenerateTextBlob(const TexgineFont & font,const CharGroups & cgs,double & spanWidth,std::vector<double> & glyphWidths) const125 std::shared_ptr<TexgineTextBlob> TextShaper::GenerateTextBlob(const TexgineFont &font, const CharGroups &cgs,
126 double &spanWidth, std::vector<double> &glyphWidths) const
127 {
128 TexgineTextBlobBuilder builder;
129 auto blob = builder.AllocRunPos(font, cgs.GetNumberOfGlyph());
130 if (blob == nullptr || blob->glyphs == nullptr || blob->pos == nullptr) {
131 LOGEX_FUNC_LINE(ERROR) << "allocRunPos return unavailable buffer";
132 throw TEXGINE_EXCEPTION(API_FAILED);
133 }
134
135 auto offset = 0.0;
136 auto index = 0;
137 for (const auto &cg : cgs) {
138 glyphWidths.push_back(cg.GetWidth());
139 auto drawingOffset = offset;
140 offset += cg.GetWidth();
141 for (const auto &[cp, ax, ay, ox, oy] : cg.glyphs) {
142 blob->glyphs[index] = cp;
143 blob->pos[index * DOUBLE] = drawingOffset + ox;
144 blob->pos[index * DOUBLE + 1] = ay - oy;
145 index++;
146 drawingOffset += ax;
147 }
148 }
149
150 spanWidth = offset;
151 return builder.Make();
152 }
153 } // namespace TextEngine
154 } // namespace Rosen
155 } // namespace OHOS
156