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