• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 "skia_text_blob.h"
17 
18 #include <map>
19 #include "include/core/SkFontTypes.h"
20 #include "include/core/SkPaint.h"
21 #include "include/core/SkRSXform.h"
22 #include "include/core/SkSerialProcs.h"
23 
24 #include "skia_adapter/skia_convert_utils.h"
25 #include "skia_adapter/skia_data.h"
26 #include "skia_adapter/skia_font.h"
27 #include "skia_adapter/skia_path.h"
28 #include "skia_adapter/skia_typeface.h"
29 #include "utils/log.h"
30 #include "skia_adapter/skia_path_effect.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 namespace Drawing {
35 static const std::map<Drawing::Paint::PaintStyle, SkPaint::Style> PAINT_STYLE = {
36     {Drawing::Paint::PaintStyle::PAINT_FILL, SkPaint::kFill_Style},
37     {Drawing::Paint::PaintStyle::PAINT_STROKE, SkPaint::kStroke_Style},
38     {Drawing::Paint::PaintStyle::PAINT_FILL_STROKE, SkPaint::kStrokeAndFill_Style},
39 };
40 
SkiaTextBlob(sk_sp<SkTextBlob> skTextBlob)41 SkiaTextBlob::SkiaTextBlob(sk_sp<SkTextBlob> skTextBlob) : skTextBlob_(skTextBlob) {}
42 
GetTextBlob() const43 sk_sp<SkTextBlob> SkiaTextBlob::GetTextBlob() const
44 {
45     return skTextBlob_;
46 }
47 
MakeFromText(const void * text,size_t byteLength,const Font & font,TextEncoding encoding)48 std::shared_ptr<TextBlob> SkiaTextBlob::MakeFromText(const void* text, size_t byteLength,
49     const Font& font, TextEncoding encoding)
50 {
51     auto skiaFont = font.GetImpl<SkiaFont>();
52     if (!skiaFont) {
53         LOGD("skiaFont nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
54         return nullptr;
55     }
56     SkTextEncoding skEncoding = static_cast<SkTextEncoding>(encoding);
57     sk_sp<SkTextBlob> skTextBlob = SkTextBlob::MakeFromText(text, byteLength, skiaFont->GetFont(), skEncoding);
58     if (!skTextBlob) {
59         LOGD("skTextBlob nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
60         return nullptr;
61     }
62     std::shared_ptr<TextBlobImpl> textBlobImpl = std::make_shared<SkiaTextBlob>(skTextBlob);
63     return std::make_shared<TextBlob>(textBlobImpl);
64 }
65 
MakeFromPosText(const void * text,size_t byteLength,const Point pos[],const Font & font,TextEncoding encoding)66 std::shared_ptr<TextBlob> SkiaTextBlob::MakeFromPosText(const void* text, size_t byteLength,
67     const Point pos[], const Font& font, TextEncoding encoding)
68 {
69     auto skiaFont = font.GetImpl<SkiaFont>();
70     if (!skiaFont) {
71         LOGD("skiaFont nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
72         return nullptr;
73     }
74 
75     SkTextEncoding skEncoding = static_cast<SkTextEncoding>(encoding);
76     auto skFont = skiaFont->GetFont();
77     const int count = skFont.countText(text, byteLength, skEncoding);
78     SkPoint skPts[count];
79     for (int i = 0; i < count; ++i) {
80         skPts[i] = {pos[i].GetX(), pos[i].GetY()};
81     }
82     sk_sp<SkTextBlob> skTextBlob = SkTextBlob::MakeFromPosText(text, byteLength, skPts, skFont, skEncoding);
83     if (!skTextBlob) {
84         LOGD("skTextBlob nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
85         return nullptr;
86     }
87     std::shared_ptr<TextBlobImpl> textBlobImpl = std::make_shared<SkiaTextBlob>(skTextBlob);
88     return std::make_shared<TextBlob>(textBlobImpl);
89 }
90 
MakeFromRSXform(const void * text,size_t byteLength,const RSXform xform[],const Font & font,TextEncoding encoding)91 std::shared_ptr<TextBlob> SkiaTextBlob::MakeFromRSXform(const void* text, size_t byteLength,
92     const RSXform xform[], const Font& font, TextEncoding encoding)
93 {
94     auto skiaFont = font.GetImpl<SkiaFont>();
95     if (!skiaFont) {
96         LOGD("skiaFont nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
97         return nullptr;
98     }
99     SkTextEncoding skEncoding = static_cast<SkTextEncoding>(encoding);
100     sk_sp<SkTextBlob> skTextBlob =
101         SkTextBlob::MakeFromRSXform(text, byteLength, xform ? reinterpret_cast<const SkRSXform*>(xform) : nullptr,
102             skiaFont->GetFont(), skEncoding);
103     if (!skTextBlob) {
104         LOGD("skTextBlob nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
105         return nullptr;
106     }
107     std::shared_ptr<TextBlobImpl> textBlobImpl = std::make_shared<SkiaTextBlob>(skTextBlob);
108     return std::make_shared<TextBlob>(textBlobImpl);
109 }
110 
Serialize(void * ctx) const111 std::shared_ptr<Data> SkiaTextBlob::Serialize(void* ctx) const
112 {
113     if (!skTextBlob_) {
114         LOGD("skTextBlob nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
115         return nullptr;
116     }
117     SkSerialProcs procs;
118     procs.fTypefaceProc = &SkiaTypeface::SerializeTypeface;
119     procs.fTypefaceCtx = ctx;
120     auto skData = skTextBlob_->serialize(procs);
121     auto data = std::make_shared<Data>();
122     auto skiaData = data->GetImpl<SkiaData>();
123     if (!skiaData) {
124         LOGD("skiaData nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
125         return nullptr;
126     }
127     skiaData->SetSkData(skData);
128     return data;
129 }
130 
Deserialize(const void * data,size_t size,void * ctx)131 std::shared_ptr<TextBlob> SkiaTextBlob::Deserialize(const void* data, size_t size, void* ctx)
132 {
133     SkDeserialProcs procs;
134     procs.fTypefaceProc = &SkiaTypeface::DeserializeTypeface;
135     procs.fTypefaceCtx = ctx;
136     sk_sp<SkTextBlob> skTextBlob = SkTextBlob::Deserialize(data, size, procs);
137     if (!skTextBlob) {
138         LOGD("skTextBlob nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
139         return nullptr;
140     }
141     std::shared_ptr<TextBlobImpl> textBlobImpl = std::make_shared<SkiaTextBlob>(skTextBlob);
142     return std::make_shared<TextBlob>(textBlobImpl);
143 }
144 
ConvertSkStyle(Paint::PaintStyle style)145 static SkPaint::Style ConvertSkStyle(Paint::PaintStyle style)
146 {
147     if (PAINT_STYLE.find(style) != PAINT_STYLE.end()) {
148         return PAINT_STYLE.at(style);
149     } else {
150         return SkPaint::kStrokeAndFill_Style;
151     }
152 }
153 
ConvertSkPaint(const Paint * drawingPaint,SkPaint & skPaint)154 static void ConvertSkPaint(const Paint* drawingPaint, SkPaint &skPaint)
155 {
156     if (drawingPaint == nullptr) {
157         return;
158     }
159     skPaint.setStyle(ConvertSkStyle(drawingPaint->GetStyle()));
160     skPaint.setAntiAlias(drawingPaint->IsAntiAlias());
161     Color color = drawingPaint->GetColor();
162     skPaint.setColor(Color::ColorQuadSetARGB(color.GetAlpha(), color.GetRed(), color.GetGreen(), color.GetGreen()));
163     skPaint.setStrokeWidth(drawingPaint->GetWidth());
164     const std::shared_ptr<PathEffect> effect = drawingPaint->GetPathEffect();
165     if (effect != nullptr) {
166         SkiaPathEffect *skiaEffect = effect->GetImpl<SkiaPathEffect>();
167         if (skiaEffect != nullptr) {
168             skPaint.setPathEffect(skiaEffect->GetPathEffect());
169         }
170     }
171 }
172 
GetIntercepts(const float bounds[],float intervals[],const Paint * paint) const173 int SkiaTextBlob::GetIntercepts(const float bounds[], float intervals[], const Paint* paint) const
174 {
175     if (skTextBlob_ && paint != nullptr) {
176         SkPaint skPaint;
177         ConvertSkPaint(paint, skPaint);
178         return skTextBlob_->getIntercepts(bounds, intervals, &skPaint);
179     }
180     return 0;
181 }
182 
GetDrawingGlyphIDforTextBlob(const TextBlob * blob,std::vector<uint16_t> & glyphIds)183 void SkiaTextBlob::GetDrawingGlyphIDforTextBlob(const TextBlob* blob, std::vector<uint16_t>& glyphIds)
184 {
185     SkTextBlob* skTextBlob = nullptr;
186     if (blob) {
187         auto skiaBlobImpl = blob->GetImpl<SkiaTextBlob>();
188         if (skiaBlobImpl != nullptr) {
189             skTextBlob = skiaBlobImpl->GetTextBlob().get();
190         }
191     }
192     GetGlyphIDforTextBlob(skTextBlob, glyphIds);
193 }
194 
GetDrawingPathforTextBlob(uint16_t glyphId,const TextBlob * blob)195 Path SkiaTextBlob::GetDrawingPathforTextBlob(uint16_t glyphId, const TextBlob* blob)
196 {
197     SkTextBlob* skTextBlob = nullptr;
198     if (blob) {
199         auto skiaBlobImpl = blob->GetImpl<SkiaTextBlob>();
200         if (skiaBlobImpl != nullptr) {
201             skTextBlob = skiaBlobImpl->GetTextBlob().get();
202         }
203     }
204     SkPath skPath = GetPathforTextBlob(glyphId, skTextBlob);
205     Path path;
206     path.GetImpl<SkiaPath>()->SetPath(skPath);
207     return path;
208 }
209 
GetDrawingPointsForTextBlob(const TextBlob * blob,std::vector<Point> & points)210 void SkiaTextBlob::GetDrawingPointsForTextBlob(const TextBlob* blob, std::vector<Point>& points)
211 {
212     if (blob == nullptr) {
213         return;
214     }
215     SkTextBlob* skTextBlob = nullptr;
216     if (blob) {
217         auto skiaBlobImpl = blob->GetImpl<SkiaTextBlob>();
218         if (skiaBlobImpl != nullptr) {
219             skTextBlob = skiaBlobImpl->GetTextBlob().get();
220         }
221     }
222     std::vector<SkPoint> skPoints;
223     GetPointsForTextBlob(skTextBlob, skPoints);
224 
225     points.reserve(skPoints.size());
226     for (const auto& p : skPoints) {
227         points.emplace_back(p.x(), p.y());
228     }
229 }
230 
Bounds() const231 std::shared_ptr<Rect> SkiaTextBlob::Bounds() const
232 {
233     if (skTextBlob_) {
234         auto bounds = skTextBlob_->bounds();
235         return std::make_shared<Rect>(bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
236     }
237     return nullptr;
238 }
239 
UniqueID() const240 uint32_t SkiaTextBlob::UniqueID() const
241 {
242     if (skTextBlob_) {
243         return skTextBlob_->uniqueID();
244     }
245     return 0;
246 }
247 } // namespace Drawing
248 } // namespace Rosen
249 } // namespace OHOS