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