1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.. All rights reserved.
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 "drawing_painter_impl.h"
17
18 #include <array>
19
20 #include "include/core/SkBlurTypes.h"
21 #include "include/core/SkMaskFilter.h"
22 #include "include/effects/SkDashPathEffect.h"
23 #include "include/effects/SkDiscretePathEffect.h"
24 #include "skia_adapter/skia_paint.h"
25 #include "skia_adapter/skia_path.h"
26 #include "skia_adapter/skia_text_blob.h"
27
28 #ifdef HM_SYMBOL_TXT_ENABLE
29 #include <parameters.h>
30
31 const bool G_IS_HM_SYMBOL_TXT_ENABLE =
32 (std::atoi(OHOS::system::GetParameter("persist.sys.graphic.hmsymboltxt.enable", "1").c_str()) != 0);
33 #else
34 const bool G_IS_HM_SYMBOL_TXT_ENABLE = true;
35 #endif
36
37
38 namespace OHOS {
39 namespace Rosen {
40 namespace SPText {
ConvertDecorStyle(const ParagraphPainter::DecorationStyle & decorStyle,Drawing::Paint::PaintStyle drawStyle=Drawing::Paint::PAINT_STROKE)41 static Drawing::Paint ConvertDecorStyle(const ParagraphPainter::DecorationStyle& decorStyle,
42 Drawing::Paint::PaintStyle drawStyle = Drawing::Paint::PAINT_STROKE)
43 {
44 Drawing::Paint paint;
45 paint.SetStyle(drawStyle);
46 paint.SetAntiAlias(true);
47 paint.SetColor(PaintRecord::ToRSColor(decorStyle.getColor()));
48 paint.SetWidth(decorStyle.getStrokeWidth());
49 if (decorStyle.getDashPathEffect().has_value()) {
50 auto dashPathEffect = decorStyle.getDashPathEffect().value();
51 Drawing::scalar intervals[] = {dashPathEffect.fOnLength, dashPathEffect.fOffLength,
52 dashPathEffect.fOnLength, dashPathEffect.fOffLength};
53 size_t count = sizeof(intervals) / sizeof(intervals[0]);
54 auto pathEffect1 = Drawing::PathEffect::CreateDashPathEffect(intervals, count, 0.0f);
55 auto pathEffect2 = Drawing::PathEffect::CreateDiscretePathEffect(0, 0);
56 auto pathEffect = Drawing::PathEffect::CreateComposePathEffect(*pathEffect1.get(), *pathEffect2.get());
57 paint.SetPathEffect(pathEffect);
58 }
59 return paint;
60 }
61
ToDrawingRect(const SkRect & skRect)62 static Drawing::Rect ToDrawingRect(const SkRect& skRect)
63 {
64 Drawing::Rect rect;
65 rect.SetLeft(skRect.fLeft);
66 rect.SetTop(skRect.fTop);
67 rect.SetRight(skRect.fRight);
68 rect.SetBottom(skRect.fBottom);
69 return rect;
70 }
71
ToDrawingRoundRect(const SkRRect & skRRect)72 static Drawing::RoundRect ToDrawingRoundRect(const SkRRect& skRRect)
73 {
74 Drawing::Rect rect;
75 rect.SetLeft(skRRect.rect().fLeft);
76 rect.SetTop(skRRect.rect().fTop);
77 rect.SetRight(skRRect.rect().fRight);
78 rect.SetBottom(skRRect.rect().fBottom);
79 Drawing::scalar ltRadius = skRRect.radii(SkRRect::Corner::kUpperLeft_Corner).x();
80 Drawing::scalar rtRadius = skRRect.radii(SkRRect::Corner::kUpperRight_Corner).x();
81 Drawing::scalar rbRadius = skRRect.radii(SkRRect::Corner::kLowerRight_Corner).x();
82 Drawing::scalar lbRadius = skRRect.radii(SkRRect::Corner::kLowerLeft_Corner).x();
83 Drawing::Point leftTop = {ltRadius, ltRadius};
84 Drawing::Point rightTop = {rtRadius, rtRadius};
85 Drawing::Point rightBottom = {rbRadius, rbRadius};
86 Drawing::Point leftBottom = {lbRadius, lbRadius};
87 Drawing::RoundRect roundRect(rect, {leftTop, rightTop, rightBottom, leftBottom});
88 return roundRect;
89 }
90
RSCanvasParagraphPainter(Drawing::Canvas * canvas,const std::vector<PaintRecord> & paints)91 RSCanvasParagraphPainter::RSCanvasParagraphPainter(Drawing::Canvas* canvas, const std::vector<PaintRecord>& paints)
92 : canvas_(canvas), paints_(paints)
93 {}
94
DrawSymbolSkiaTxt(RSTextBlob * blob,const RSPoint & offset,const PaintRecord & pr)95 void RSCanvasParagraphPainter::DrawSymbolSkiaTxt(RSTextBlob* blob, const RSPoint& offset,
96 const PaintRecord &pr)
97 {
98 HMSymbolRun hmSymbolRun = HMSymbolRun();
99 symbolCount_++;
100 const uint32_t length32Bit = 32;
101 auto symbolSpanId = (static_cast<uint64_t>(paragraphId_) << length32Bit) + symbolCount_;
102 hmSymbolRun.SetAnimation(animationFunc_);
103 hmSymbolRun.SetSymbolId(symbolSpanId);
104 if (pr.pen.has_value() && pr.brush.has_value()) {
105 canvas_->AttachBrush(pr.brush.value());
106 canvas_->AttachPen(pr.pen.value());
107 hmSymbolRun.DrawSymbol(canvas_, blob, offset, pr.symbol);
108 canvas_->DetachPen();
109 canvas_->DetachBrush();
110 } else if (pr.pen.has_value() && !pr.brush.has_value()) {
111 canvas_->AttachPen(pr.pen.value());
112 hmSymbolRun.DrawSymbol(canvas_, blob, offset, pr.symbol);
113 canvas_->DetachPen();
114 } else if (!pr.pen.has_value() && pr.brush.has_value()) {
115 canvas_->AttachBrush(pr.brush.value());
116 hmSymbolRun.DrawSymbol(canvas_, blob, offset, pr.symbol);
117 canvas_->DetachBrush();
118 } else {
119 Drawing::Brush brush;
120 brush.SetColor(pr.color);
121 canvas_->AttachBrush(brush);
122 hmSymbolRun.DrawSymbol(canvas_, blob, offset, pr.symbol);
123 canvas_->DetachBrush();
124 }
125 }
126
drawTextBlob(const std::shared_ptr<RSTextBlob> & blob,SkScalar x,SkScalar y,const SkPaintOrID & paint)127 void RSCanvasParagraphPainter::drawTextBlob(const std::shared_ptr<RSTextBlob>& blob, SkScalar x, SkScalar y,
128 const SkPaintOrID& paint)
129 {
130 SkASSERT(!std::holds_alternative<SkPaint>(paint));
131 const PaintRecord& pr = paints_[std::get<PaintID>(paint)];
132
133 if (pr.isSymbolGlyph && G_IS_HM_SYMBOL_TXT_ENABLE) {
134 std::vector<RSPoint> points;
135 RSTextBlob::GetDrawingPointsForTextBlob(blob.get(), points);
136 RSPoint offset;
137 if (points.size() > 0) {
138 offset = RSPoint{ x + points[0].GetX(), y + points[0].GetY() };
139 } else {
140 offset = RSPoint{ x, y };
141 }
142 DrawSymbolSkiaTxt(blob.get(), offset, pr);
143 } else if (pr.pen.has_value() && pr.brush.has_value()) {
144 canvas_->AttachPen(pr.pen.value());
145 canvas_->DrawTextBlob(blob.get(), x, y);
146 canvas_->DetachPen();
147 canvas_->AttachBrush(pr.brush.value());
148 canvas_->DrawTextBlob(blob.get(), x, y);
149 canvas_->DetachBrush();
150 } else if (pr.pen.has_value() && !pr.brush.has_value()) {
151 canvas_->AttachPen(pr.pen.value());
152 canvas_->DrawTextBlob(blob.get(), x, y);
153 canvas_->DetachPen();
154 } else if (!pr.pen.has_value() && pr.brush.has_value()) {
155 canvas_->AttachBrush(pr.brush.value());
156 canvas_->DrawTextBlob(blob.get(), x, y);
157 canvas_->DetachBrush();
158 } else {
159 Drawing::Brush brush;
160 if (blob != nullptr && blob->IsEmoji()) {
161 brush.SetBlenderEnabled(false);
162 }
163 brush.SetColor(pr.color);
164 canvas_->AttachBrush(brush);
165 canvas_->DrawTextBlob(blob.get(), x, y);
166 canvas_->DetachBrush();
167 }
168 }
169
SymbolAnimation(const PaintRecord & pr)170 void RSCanvasParagraphPainter::SymbolAnimation(const PaintRecord &pr)
171 {
172 auto painterSymbolAnimationConfig = std::make_shared<TextEngine::SymbolAnimationConfig>();
173 if (painterSymbolAnimationConfig == nullptr) {
174 return;
175 }
176 painterSymbolAnimationConfig->effectStrategy = pr.symbol.GetEffectStrategy();
177 if (animationFunc_ != nullptr) {
178 animationFunc_(painterSymbolAnimationConfig);
179 }
180 }
181
drawTextShadow(const std::shared_ptr<RSTextBlob> & blob,SkScalar x,SkScalar y,SkColor color,SkScalar blurSigma)182 void RSCanvasParagraphPainter::drawTextShadow(const std::shared_ptr<RSTextBlob>& blob, SkScalar x, SkScalar y,
183 SkColor color, SkScalar blurSigma)
184 {
185 Drawing::Filter filter;
186 filter.SetMaskFilter(Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, blurSigma, false));
187
188 Drawing::Brush brush;
189 brush.SetColor(PaintRecord::ToRSColor(color));
190 brush.SetAntiAlias(true);
191 brush.SetFilter(filter);
192
193 canvas_->AttachBrush(brush);
194 canvas_->DrawTextBlob(blob.get(), x, y);
195 canvas_->DetachBrush();
196 }
197
drawRect(const SkRect & rect,const SkPaintOrID & paint)198 void RSCanvasParagraphPainter::drawRect(const SkRect& rect, const SkPaintOrID& paint)
199 {
200 SkASSERT(!std::holds_alternative<SkPaint>(paint));
201 const PaintRecord& pr = paints_[std::get<PaintID>(paint)];
202 Drawing::Rect rsRect = ToDrawingRect(rect);
203
204 if (pr.pen.has_value()) {
205 canvas_->AttachPen(pr.pen.value());
206 canvas_->DrawRect(rsRect);
207 canvas_->DetachPen();
208 }
209 if (pr.brush.has_value()) {
210 canvas_->AttachBrush(pr.brush.value());
211 canvas_->DrawRect(rsRect);
212 canvas_->DetachBrush();
213 }
214 }
215
drawRRect(const SkRRect & rrect,const SkColor color)216 void RSCanvasParagraphPainter::drawRRect(const SkRRect& rrect, const SkColor color)
217 {
218 Drawing::RoundRect rsRRect = ToDrawingRoundRect(rrect);
219 Drawing::Brush brush;
220 brush.SetColor(PaintRecord::ToRSColor(color));
221 brush.SetAntiAlias(false);
222 canvas_->AttachBrush(brush);
223 canvas_->DrawRoundRect(rsRRect);
224 canvas_->DetachBrush();
225 }
226
drawFilledRect(const SkRect & rect,const DecorationStyle & decorStyle)227 void RSCanvasParagraphPainter::drawFilledRect(const SkRect& rect, const DecorationStyle& decorStyle)
228 {
229 Drawing::Paint paint = ConvertDecorStyle(decorStyle, Drawing::Paint::PAINT_FILL);
230 Drawing::Rect rsRect = ToDrawingRect(rect);
231
232 canvas_->AttachPaint(paint);
233 canvas_->DrawRect(rsRect);
234 canvas_->DetachPaint();
235 }
236
drawPath(const RSPath & path,const DecorationStyle & decorStyle)237 void RSCanvasParagraphPainter::drawPath(const RSPath& path, const DecorationStyle& decorStyle)
238 {
239 Drawing::Paint paint = ConvertDecorStyle(decorStyle);
240
241 canvas_->AttachPaint(paint);
242 canvas_->DrawPath(path);
243 canvas_->DetachPaint();
244 }
245
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const DecorationStyle & decorStyle)246 void RSCanvasParagraphPainter::drawLine(
247 SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const DecorationStyle& decorStyle)
248 {
249 Drawing::Paint paint = ConvertDecorStyle(decorStyle);
250 Drawing::Point point0(x0, y0);
251 Drawing::Point point1(x1, y1);
252
253 canvas_->AttachPaint(paint);
254 canvas_->DrawLine(point0, point1);
255 canvas_->DetachPaint();
256 }
257
clipRect(const SkRect & rect)258 void RSCanvasParagraphPainter::clipRect(const SkRect& rect)
259 {
260 Drawing::Rect rsRect = ToDrawingRect(rect);
261 canvas_->ClipRect(rsRect);
262 }
263
translate(SkScalar dx,SkScalar dy)264 void RSCanvasParagraphPainter::translate(SkScalar dx, SkScalar dy)
265 {
266 canvas_->Translate(dx, dy);
267 }
268
save()269 void RSCanvasParagraphPainter::save()
270 {
271 canvas_->Save();
272 }
273
restore()274 void RSCanvasParagraphPainter::restore()
275 {
276 canvas_->Restore();
277 }
278 } // namespace SPText
279 } // namespace Rosen
280 } // namespace OHOS
281