• 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 "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