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