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