Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / core / SkDraw.cpp
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "src/core/SkDraw.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkPathEffect.h"
15 #include "include/core/SkRRect.h"
16 #include "include/core/SkShader.h"
17 #include "include/core/SkString.h"
18 #include "include/core/SkStrokeRec.h"
19 #include "include/private/SkColorData.h"
20 #include "include/private/SkImageInfoPriv.h"
21 #include "include/private/SkMacros.h"
22 #include "include/private/SkTemplates.h"
23 #include "include/private/SkTo.h"
24 #include "src/core/SkArenaAlloc.h"
25 #include "src/core/SkAutoBlitterChoose.h"
26 #include "src/core/SkBlendModePriv.h"
27 #include "src/core/SkBlitter.h"
28 #include "src/core/SkDevice.h"
29 #include "src/core/SkDrawProcs.h"
30 #include "src/core/SkMaskFilterBase.h"
31 #include "src/core/SkMatrixUtils.h"
32 #include "src/core/SkPathEffectBase.h"
33 #include "src/core/SkPathPriv.h"
34 #include "src/core/SkRasterClip.h"
35 #include "src/core/SkRectPriv.h"
36 #include "src/core/SkSamplingPriv.h"
37 #include "src/core/SkScan.h"
38 #include "src/core/SkStroke.h"
39 #include "src/core/SkTLazy.h"
40 #include "src/core/SkUtils.h"
41
42 #include <utility>
43
44 static SkPaint make_paint_with_image(const SkPaint& origPaint, const SkBitmap& bitmap,
45                                      const SkSamplingOptions& sampling,
46                                      SkMatrix* matrix = nullptr) {
47     SkPaint paint(origPaint);
48     paint.setShader(SkMakeBitmapShaderForPaint(origPaint, bitmap, SkTileMode::kClamp,
49                                                SkTileMode::kClamp, sampling, matrix,
50                                                kNever_SkCopyPixelsMode));
51     return paint;
52 }
53
54 ///////////////////////////////////////////////////////////////////////////////
55
56 SkDraw::SkDraw() {}
57
58 bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
59     if (fRC->isEmpty()) {
60         return false;
61     }
62
63     SkMatrix inverse;
64     if (!fMatrixProvider->localToDevice().invert(&inverse)) {
65         return false;
66     }
67
68     SkIRect devBounds = fRC->getBounds();
69     // outset to have slop for antialasing and hairlines
70     devBounds.outset(1, 1);
71     inverse.mapRect(localBounds, SkRect::Make(devBounds));
72     return true;
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////
76
77 void SkDraw::drawPaint(const SkPaint& paint) const {
78     SkDEBUGCODE(this->validate();)
79
80     if (fRC->isEmpty()) {
81         return;
82     }
83
84     SkIRect    devRect;
85     devRect.setWH(fDst.width(), fDst.height());
86
87     SkAutoBlitterChoose blitter(*this, nullptr, paint);
88     SkScan::FillIRect(devRect, *fRC, blitter.get());
89 }
90
91 ///////////////////////////////////////////////////////////////////////////////
92
93 struct PtProcRec {
94     SkCanvas::PointMode fMode;
95     const SkPaint*  fPaint;
96     const SkRegion* fClip;
97     const SkRasterClip* fRC;
98
99     // computed values
100     SkRect   fClipBounds;
101     SkScalar fRadius;
102
103     typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
104                          SkBlitter*);
105
106     bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
107               const SkRasterClip*);
108     Proc chooseProc(SkBlitter** blitter);
109
110 private:
111     SkAAClipBlitterWrapper fWrapper;
112 };
113
114 static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
115                                  int count, SkBlitter* blitter) {
116     SkASSERT(rec.fClip->isRect());
117     const SkIRect& r = rec.fClip->getBounds();
118
119     for (int i = 0; i < count; i++) {
120         int x = SkScalarFloorToInt(devPts[i].fX);
121         int y = SkScalarFloorToInt(devPts[i].fY);
122         if (r.contains(x, y)) {
123             blitter->blitH(x, y, 1);
124         }
125     }
126 }
127
128 static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
129                                     const SkPoint devPts[], int count,
130                                     SkBlitter* blitter) {
131     SkASSERT(rec.fRC->isRect());
132     const SkIRect& r = rec.fRC->getBounds();
133     uint32_t value;
134     const SkPixmap* dst = blitter->justAnOpaqueColor(&value);
135     SkASSERT(dst);
136
137     uint16_t* addr = dst->writable_addr16(0, 0);
138     size_t    rb = dst->rowBytes();
139
140     for (int i = 0; i < count; i++) {
141         int x = SkScalarFloorToInt(devPts[i].fX);
142         int y = SkScalarFloorToInt(devPts[i].fY);
143         if (r.contains(x, y)) {
144             ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
145         }
146     }
147 }
148
149 static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
150                                     const SkPoint devPts[], int count,
151                                     SkBlitter* blitter) {
152     SkASSERT(rec.fRC->isRect());
153     const SkIRect& r = rec.fRC->getBounds();
154     uint32_t value;
155     const SkPixmap* dst = blitter->justAnOpaqueColor(&value);
156     SkASSERT(dst);
157
158     SkPMColor* addr = dst->writable_addr32(0, 0);
159     size_t     rb = dst->rowBytes();
160
161     for (int i = 0; i < count; i++) {
162         int x = SkScalarFloorToInt(devPts[i].fX);
163         int y = SkScalarFloorToInt(devPts[i].fY);
164         if (r.contains(x, y)) {
165             ((SkPMColor*)((char*)addr + y * rb))[x] = value;
166         }
167     }
168 }
169
170 static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
171                             int count, SkBlitter* blitter) {
172     for (int i = 0; i < count; i++) {
173         int x = SkScalarFloorToInt(devPts[i].fX);
174         int y = SkScalarFloorToInt(devPts[i].fY);
175         if (rec.fClip->contains(x, y)) {
176             blitter->blitH(x, y, 1);
177         }
178     }
179 }
180
181 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
182                               int count, SkBlitter* blitter) {
183     for (int i = 0; i < count; i += 2) {
184         SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter);
185     }
186 }
187
188 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
189                               int count, SkBlitter* blitter) {
190     SkScan::HairLine(devPts, count, *rec.fRC, blitter);
191 }
192
193 // aa versions
194
195 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
196                               int count, SkBlitter* blitter) {
197     for (int i = 0; i < count; i += 2) {
198         SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter);
199     }
200 }
201
202 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
203                               int count, SkBlitter* blitter) {
204     SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter);
205 }
206
207 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
208
209 static SkRect make_square_rad(SkPoint center, SkScalar radius) {
210     return {
211         center.fX - radius, center.fY - radius,
212         center.fX + radius, center.fY + radius
213     };
214 }
215
216 static SkXRect make_xrect(const SkRect& r) {
217     SkASSERT(SkRectPriv::FitsInFixed(r));
218     return {
219         SkScalarToFixed(r.fLeft), SkScalarToFixed(r.fTop),
220         SkScalarToFixed(r.fRight), SkScalarToFixed(r.fBottom)
221     };
222 }
223
224 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
225                            int count, SkBlitter* blitter) {
226     for (int i = 0; i < count; i++) {
227         SkRect r = make_square_rad(devPts[i], rec.fRadius);
228         if (r.intersect(rec.fClipBounds)) {
229             SkScan::FillXRect(make_xrect(r), *rec.fRC, blitter);
230         }
231     }
232 }
233
234 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
235                            int count, SkBlitter* blitter) {
236     for (int i = 0; i < count; i++) {
237         SkRect r = make_square_rad(devPts[i], rec.fRadius);
238         if (r.intersect(rec.fClipBounds)) {
239             SkScan::AntiFillXRect(make_xrect(r), *rec.fRC, blitter);
240         }
241     }
242 }
243
244 // If this returns true, then chooseProc() must return a valid proc
245 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
246                      const SkMatrix* matrix, const SkRasterClip* rc) {
247     if ((unsigned)mode > (unsigned)SkCanvas::kPolygon_PointMode) {
248         return false;
249     }
250     if (paint.getPathEffect() || paint.getMaskFilter()) {
251         return false;
252     }
253     SkScalar width = paint.getStrokeWidth();
254     SkScalar radius = -1;   // sentinel value, a "valid" value must be > 0
255
256     if (0 == width) {
257         radius = 0.5f;
258     } else if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
259                matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) {
260         SkScalar sx = matrix->get(SkMatrix::kMScaleX);
261         SkScalar sy = matrix->get(SkMatrix::kMScaleY);
262         if (SkScalarNearlyZero(sx - sy)) {
263             radius = SkScalarHalf(width * SkScalarAbs(sx));
264         }
265     }
266     if (radius > 0) {
267         SkRect clipBounds = SkRect::Make(rc->getBounds());
268         // if we return true, the caller may assume that the constructed shapes can be represented
269         // using SkFixed (after clipping), so we preflight that here.
270         if (!SkRectPriv::FitsInFixed(clipBounds)) {
271             return false;
272         }
273         fMode = mode;
274         fPaint = &paint;
275         fClip = nullptr;
276         fRC = rc;
277         fClipBounds = clipBounds;
278         fRadius = radius;
279         return true;
280     }
281     return false;
282 }
283
284 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
285     Proc proc = nullptr;
286
287     SkBlitter* blitter = *blitterPtr;
288     if (fRC->isBW()) {
289         fClip = &fRC->bwRgn();
290     } else {
291         fWrapper.init(*fRC, blitter);
292         fClip = &fWrapper.getRgn();
293         blitter = fWrapper.getBlitter();
294         *blitterPtr = blitter;
295     }
296
297     // for our arrays
298     SkASSERT(0 == SkCanvas::kPoints_PointMode);
299     SkASSERT(1 == SkCanvas::kLines_PointMode);
300     SkASSERT(2 == SkCanvas::kPolygon_PointMode);
301     SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
302
303     if (fPaint->isAntiAlias()) {
304         if (0 == fPaint->getStrokeWidth()) {
305             static const Proc gAAProcs[] = {
306                 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
307             };
308             proc = gAAProcs[fMode];
309         } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
310             SkASSERT(SkCanvas::kPoints_PointMode == fMode);
311             proc = aa_square_proc;
312         }
313     } else {    // BW
314         if (fRadius <= 0.5f) {    // small radii and hairline
315             if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
316                 uint32_t value;
317                 const SkPixmap* bm = blitter->justAnOpaqueColor(&value);
318                 if (bm && kRGB_565_SkColorType == bm->colorType()) {
319                     proc = bw_pt_rect_16_hair_proc;
320                 } else if (bm && kN32_SkColorType == bm->colorType()) {
321                     proc = bw_pt_rect_32_hair_proc;
322                 } else {
323                     proc = bw_pt_rect_hair_proc;
324                 }
325             } else {
326                 static Proc gBWProcs[] = {
327                     bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
328                 };
329                 proc = gBWProcs[fMode];
330             }
331         } else {
332             proc = bw_square_proc;
333         }
334     }
335     return proc;
336 }
337
338 // each of these costs 8-bytes of stack space, so don't make it too large
339 // must be even for lines/polygon to work
340 #define MAX_DEV_PTS     32
341
342 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
343                         const SkPoint pts[], const SkPaint& paint,
344                         SkBaseDevice* device) const {
345     // if we're in lines mode, force count to be even
346     if (SkCanvas::kLines_PointMode == mode) {
347         count &= ~(size_t)1;
348     }
349
350     if ((long)count <= 0) {
351         return;
352     }
353
354     SkASSERT(pts != nullptr);
355     SkDEBUGCODE(this->validate();)
356
357      // nothing to draw
358     if (fRC->isEmpty()) {
359         return;
360     }
361
362     if (!SkScalarsAreFinite(&pts[0].fX, count * 2)) {
363         return;
364     }
365
366     SkMatrix ctm = fMatrixProvider->localToDevice();
367     PtProcRec rec;
368     if (!device && rec.init(mode, paint, &ctm, fRC)) {
369         SkAutoBlitterChoose blitter(*this, nullptr, paint);
370
371         SkPoint             devPts[MAX_DEV_PTS];
372         SkBlitter*          bltr = blitter.get();
373         PtProcRec::Proc     proc = rec.chooseProc(&bltr);
374         // we have to back up subsequent passes if we're in polygon mode
375         const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
376
377         do {
378             int n = SkToInt(count);
379             if (n > MAX_DEV_PTS) {
380                 n = MAX_DEV_PTS;
381             }
382             ctm.mapPoints(devPts, pts, n);
383             if (!SkScalarsAreFinite(&devPts[0].fX, n * 2)) {
384                 return;
385             }
386             proc(rec, devPts, n, bltr);
387             pts += n - backup;
388             SkASSERT(SkToInt(count) >= n);
389             count -= n;
390             if (count > 0) {
391                 count += backup;
392             }
393         } while (count != 0);
394     } else {
395         switch (mode) {
396             case SkCanvas::kPoints_PointMode: {
397                 // temporarily mark the paint as filling.
398                 SkPaint newPaint(paint);
399                 newPaint.setStyle(SkPaint::kFill_Style);
400
401                 SkScalar width = newPaint.getStrokeWidth();
402                 SkScalar radius = SkScalarHalf(width);
403
404                 if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
405                     if (device) {
406                         for (size_t i = 0; i < count; ++i) {
407                             SkRect r = SkRect::MakeLTRB(pts[i].fX - radius, pts[i].fY - radius,
408                                                         pts[i].fX + radius, pts[i].fY + radius);
409                             device->drawOval(r, newPaint);
410                         }
411                     } else {
412                         SkPath     path;
413                         SkMatrix   preMatrix;
414
415                         path.addCircle(0, 0, radius);
416                         for (size_t i = 0; i < count; i++) {
417                             preMatrix.setTranslate(pts[i].fX, pts[i].fY);
418                             // pass true for the last point, since we can modify
419                             // then path then
420                             path.setIsVolatile((count-1) == i);
421                             this->drawPath(path, newPaint, &preMatrix, (count-1) == i);
422                         }
423                     }
424                 } else {
425                     SkRect  r;
426
427                     for (size_t i = 0; i < count; i++) {
428                         r.fLeft = pts[i].fX - radius;
429                         r.fTop = pts[i].fY - radius;
430                         r.fRight = r.fLeft + width;
431                         r.fBottom = r.fTop + width;
432                         if (device) {
433                             device->drawRect(r, newPaint);
434                         } else {
435                             this->drawRect(r, newPaint);
436                         }
437                     }
438                 }
439                 break;
440             }
441             case SkCanvas::kLines_PointMode:
442                 if (2 == count && paint.getPathEffect()) {
443                     // most likely a dashed line - see if it is one of the ones
444                     // we can accelerate
445                     SkStrokeRec stroke(paint);
446                     SkPathEffectBase::PointData pointData;
447
448                     SkPath path = SkPath::Line(pts[0], pts[1]);
449
450                     SkRect cullRect = SkRect::Make(fRC->getBounds());
451
452                     if (as_PEB(paint.getPathEffect())->asPoints(&pointData, path, stroke, ctm,
453                                                                 &cullRect)) {
454                         // 'asPoints' managed to find some fast path
455
456                         SkPaint newP(paint);
457                         newP.setPathEffect(nullptr);
458                         newP.setStyle(SkPaint::kFill_Style);
459
460                         if (!pointData.fFirst.isEmpty()) {
461                             if (device) {
462                                 device->drawPath(pointData.fFirst, newP);
463                             } else {
464                                 this->drawPath(pointData.fFirst, newP);
465                             }
466                         }
467
468                         if (!pointData.fLast.isEmpty()) {
469                             if (device) {
470                                 device->drawPath(pointData.fLast, newP);
471                             } else {
472                                 this->drawPath(pointData.fLast, newP);
473                             }
474                         }
475
476                         if (pointData.fSize.fX == pointData.fSize.fY) {
477                             // The rest of the dashed line can just be drawn as points
478                             SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
479
480                             if (SkPathEffectBase::PointData::kCircles_PointFlag & pointData.fFlags) {
481                                 newP.setStrokeCap(SkPaint::kRound_Cap);
482                             } else {
483                                 newP.setStrokeCap(SkPaint::kButt_Cap);
484                             }
485
486                             if (device) {
487                                 device->drawPoints(SkCanvas::kPoints_PointMode,
488                                                    pointData.fNumPoints,
489                                                    pointData.fPoints,
490                                                    newP);
491                             } else {
492                                 this->drawPoints(SkCanvas::kPoints_PointMode,
493                                                  pointData.fNumPoints,
494                                                  pointData.fPoints,
495                                                  newP,
496                                                  device);
497                             }
498                             break;
499                         } else {
500                             // The rest of the dashed line must be drawn as rects
501                             SkASSERT(!(SkPathEffectBase::PointData::kCircles_PointFlag &
502                                       pointData.fFlags));
503
504                             SkRect r;
505
506                             for (int i = 0; i < pointData.fNumPoints; ++i) {
507                                 r.setLTRB(pointData.fPoints[i].fX - pointData.fSize.fX,
508                                           pointData.fPoints[i].fY - pointData.fSize.fY,
509                                           pointData.fPoints[i].fX + pointData.fSize.fX,
510                                           pointData.fPoints[i].fY + pointData.fSize.fY);
511                                 if (device) {
512                                     device->drawRect(r, newP);
513                                 } else {
514                                     this->drawRect(r, newP);
515                                 }
516                             }
517                         }
518
519                         break;
520                     }
521                 }
522                 [[fallthrough]]; // couldn't take fast path
523             case SkCanvas::kPolygon_PointMode: {
524                 count -= 1;
525                 SkPath path;
526                 SkPaint p(paint);
527                 p.setStyle(SkPaint::kStroke_Style);
528                 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
529                 path.setIsVolatile(true);
530                 for (size_t i = 0; i < count; i += inc) {
531                     path.moveTo(pts[i]);
532                     path.lineTo(pts[i+1]);
533                     if (device) {
534                         device->drawPath(path, p, true);
535                     } else {
536                         this->drawPath(path, p, nullptr, true);
537                     }
538                     path.rewind();
539                 }
540                 break;
541             }
542         }
543     }
544 }
545
546 static inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) {
547     SkASSERT(matrix.rectStaysRect());
548     SkASSERT(SkPaint::kFill_Style != paint.getStyle());
549
550     SkVector size;
551     SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
552     matrix.mapVectors(&size, &pt, 1);
553     return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY));
554 }
555
556 static bool easy_rect_join(const SkRect& rect, const SkPaint& paint, const SkMatrix& matrix,
557                            SkPoint* strokeSize) {
558     if (rect.isEmpty() || SkPaint::kMiter_Join != paint.getStrokeJoin() ||
559         paint.getStrokeMiter() < SK_ScalarSqrt2) {
560         return false;
561     }
562
563     *strokeSize = compute_stroke_size(paint, matrix);
564     return true;
565 }
566
567 SkDraw::RectType SkDraw::ComputeRectType(const SkRect& rect,
568                                          const SkPaint& paint,
569                                          const SkMatrix& matrix,
570                                          SkPoint* strokeSize) {
571     RectType rtype;
572     const SkScalar width = paint.getStrokeWidth();
573     const bool zeroWidth = (0 == width);
574     SkPaint::Style style = paint.getStyle();
575
576     if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
577         style = SkPaint::kFill_Style;
578     }
579
580     if (paint.getPathEffect() || paint.getMaskFilter() ||
581         !matrix.rectStaysRect() || SkPaint::kStrokeAndFill_Style == style) {
582         rtype = kPath_RectType;
583     } else if (SkPaint::kFill_Style == style) {
584         rtype = kFill_RectType;
585     } else if (zeroWidth) {
586         rtype = kHair_RectType;
587     } else if (easy_rect_join(rect, paint, matrix, strokeSize)) {
588         rtype = kStroke_RectType;
589     } else {
590         rtype = kPath_RectType;
591     }
592     return rtype;
593 }
594
595 static const SkPoint* rect_points(const SkRect& r) {
596     return reinterpret_cast<const SkPoint*>(&r);
597 }
598
599 static SkPoint* rect_points(SkRect& r) {
600     return reinterpret_cast<SkPoint*>(&r);
601 }
602
603 static void draw_rect_as_path(const SkDraw& orig, const SkRect& prePaintRect,
604                               const SkPaint& paint, const SkMatrixProvider* matrixProvider) {
605     SkDraw draw(orig);
606     draw.fMatrixProvider = matrixProvider;
607     SkPath  tmp;
608     tmp.addRect(prePaintRect);
609     tmp.setFillType(SkPathFillType::kWinding);
610     draw.drawPath(tmp, paint, nullptr, true);
611 }
612
613 void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint,
614                       const SkMatrix* paintMatrix, const SkRect* postPaintRect) const {
615     SkDEBUGCODE(this->validate();)
616
617     // nothing to draw
618     if (fRC->isEmpty()) {
619         return;
620     }
621
622     const SkMatrixProvider* matrixProvider = fMatrixProvider;
623     SkTLazy<SkPreConcatMatrixProvider> preConcatMatrixProvider;
624     if (paintMatrix) {
625         SkASSERT(postPaintRect);
626         matrixProvider = preConcatMatrixProvider.init(*matrixProvider, *paintMatrix);
627     } else {
628         SkASSERT(!postPaintRect);
629     }
630
631     SkMatrix ctm = fMatrixProvider->localToDevice();
632     SkPoint strokeSize;
633     RectType rtype = ComputeRectType(prePaintRect, paint, ctm, &strokeSize);
634
635     if (kPath_RectType == rtype) {
636         draw_rect_as_path(*this, prePaintRect, paint, matrixProvider);
637         return;
638     }
639
640     SkRect devRect;
641     const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect;
642     // skip the paintMatrix when transforming the rect by the CTM
643     ctm.mapPoints(rect_points(devRect), rect_points(paintRect), 2);
644     devRect.sort();
645
646     // look for the quick exit, before we build a blitter
647     SkRect bbox = devRect;
648     if (paint.getStyle() != SkPaint::kFill_Style) {
649         // extra space for hairlines
650         if (paint.getStrokeWidth() == 0) {
651             bbox.outset(1, 1);
652         } else {
653             // For kStroke_RectType, strokeSize is already computed.
654             const SkPoint& ssize = (kStroke_RectType == rtype)
655                 ? strokeSize
656                 : compute_stroke_size(paint, ctm);
657             bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y()));
658         }
659     }
660     if (SkPathPriv::TooBigForMath(bbox)) {
661         return;
662     }
663
664     if (!SkRectPriv::FitsInFixed(bbox) && rtype != kHair_RectType) {
665         draw_rect_as_path(*this, prePaintRect, paint, matrixProvider);
666         return;
667     }
668
669     SkIRect ir = bbox.roundOut();
670     if (fRC->quickReject(ir)) {
671         return;
672     }
673
674     SkAutoBlitterChoose blitterStorage(*this, matrixProvider, paint);
675     const SkRasterClip& clip = *fRC;
676     SkBlitter*          blitter = blitterStorage.get();
677
678     // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
679     // case we are also hairline (if we've gotten to here), which devolves to
680     // effectively just kFill
681     switch (rtype) {
682         case kFill_RectType:
683             if (paint.isAntiAlias()) {
684                 SkScan::AntiFillRect(devRect, clip, blitter);
685             } else {
686                 SkScan::FillRect(devRect, clip, blitter);
687             }
688             break;
689         case kStroke_RectType:
690             if (paint.isAntiAlias()) {
691                 SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter);
692             } else {
693                 SkScan::FrameRect(devRect, strokeSize, clip, blitter);
694             }
695             break;
696         case kHair_RectType:
697             if (paint.isAntiAlias()) {
698                 SkScan::AntiHairRect(devRect, clip, blitter);
699             } else {
700                 SkScan::HairRect(devRect, clip, blitter);
701             }
702             break;
703         default:
704             SkDEBUGFAIL("bad rtype");
705     }
706 }
707
708 static SkScalar fast_len(const SkVector& vec) {
709     SkScalar x = SkScalarAbs(vec.fX);
710     SkScalar y = SkScalarAbs(vec.fY);
711     if (x < y) {
712         using std::swap;
713         swap(x, y);
714     }
715     return x + SkScalarHalf(y);
716 }
717
718 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
719                                    SkScalar* coverage) {
720     SkASSERT(strokeWidth > 0);
721     // We need to try to fake a thick-stroke with a modulated hairline.
722
723     if (matrix.hasPerspective()) {
724         return false;
725     }
726
727     SkVector src[2], dst[2];
728     src[0].set(strokeWidth, 0);
729     src[1].set(0, strokeWidth);
730     matrix.mapVectors(dst, src, 2);
731     SkScalar len0 = fast_len(dst[0]);
732     SkScalar len1 = fast_len(dst[1]);
733     if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
734         if (coverage) {
735             *coverage = SkScalarAve(len0, len1);
736         }
737         return true;
738     }
739     return false;
740 }
741
742 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
743     SkDEBUGCODE(this->validate());
744
745     if (fRC->isEmpty()) {
746         return;
747     }
748
749     SkMatrix ctm = fMatrixProvider->localToDevice();
750     {
751         // TODO: Investigate optimizing these options. They are in the same
752         // order as SkDraw::drawPath, which handles each case. It may be
753         // that there is no way to optimize for these using the SkRRect path.
754         SkScalar coverage;
755         if (SkDrawTreatAsHairline(paint, ctm, &coverage)) {
756             goto DRAW_PATH;
757         }
758
759         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
760             goto DRAW_PATH;
761         }
762     }
763
764     if (paint.getMaskFilter()) {
765         // Transform the rrect into device space.
766         SkRRect devRRect;
767         if (rrect.transform(ctm, &devRRect)) {
768             SkAutoBlitterChoose blitter(*this, nullptr, paint);
769             if (as_MFB(paint.getMaskFilter())->filterRRect(devRRect, ctm, *fRC, blitter.get())) {
770                 return;  // filterRRect() called the blitter, so we're done
771             }
772         }
773     }
774
775 DRAW_PATH:
776     // Now fall back to the default case of using a path.
777     SkPath path;
778     path.addRRect(rrect);
779     this->drawPath(path, paint, nullptr, true);
780 }
781
782 void SkDraw::drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawCoverage,
783                          SkBlitter* customBlitter, bool doFill) const {
784     if (SkPathPriv::TooBigForMath(devPath)) {
785         return;
786     }
787     SkBlitter* blitter = nullptr;
788     SkAutoBlitterChoose blitterStorage;
789     if (nullptr == customBlitter) {
790         blitter = blitterStorage.choose(*this, nullptr, paint, drawCoverage);
791     } else {
792         blitter = customBlitter;
793     }
794
795     if (paint.getMaskFilter()) {
796         SkStrokeRec::InitStyle style = doFill ? SkStrokeRec::kFill_InitStyle
797                                               : SkStrokeRec::kHairline_InitStyle;
798         if (as_MFB(paint.getMaskFilter())
799                     ->filterPath(devPath, fMatrixProvider->localToDevice(), *fRC, blitter, style)) {
800             return;  // filterPath() called the blitter, so we're done
801         }
802     }
803
804     void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
805     if (doFill) {
806         if (paint.isAntiAlias()) {
807             proc = SkScan::AntiFillPath;
808         } else {
809             proc = SkScan::FillPath;
810         }
811     } else {    // hairline
812         if (paint.isAntiAlias()) {
813             switch (paint.getStrokeCap()) {
814                 case SkPaint::kButt_Cap:
815                     proc = SkScan::AntiHairPath;
816                     break;
817                 case SkPaint::kSquare_Cap:
818                     proc = SkScan::AntiHairSquarePath;
819                     break;
820                 case SkPaint::kRound_Cap:
821                     proc = SkScan::AntiHairRoundPath;
822                     break;
823             }
824         } else {
825             switch (paint.getStrokeCap()) {
826                 case SkPaint::kButt_Cap:
827                     proc = SkScan::HairPath;
828                     break;
829                 case SkPaint::kSquare_Cap:
830                     proc = SkScan::HairSquarePath;
831                     break;
832                 case SkPaint::kRound_Cap:
833                     proc = SkScan::HairRoundPath;
834                     break;
835             }
836         }
837     }
838
839     proc(devPath, *fRC, blitter);
840 }
841
842 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
843                       const SkMatrix* prePathMatrix, bool pathIsMutable,
844                       bool drawCoverage, SkBlitter* customBlitter) const {
845     SkDEBUGCODE(this->validate();)
846
847     // nothing to draw
848     if (fRC->isEmpty()) {
849         return;
850     }
851
852     SkPath*         pathPtr = (SkPath*)&origSrcPath;
853     bool            doFill = true;
854     SkPath          tmpPathStorage;
855     SkPath*         tmpPath = &tmpPathStorage;
856     const SkMatrixProvider*            matrixProvider = fMatrixProvider;
857     SkTLazy<SkPreConcatMatrixProvider> preConcatMatrixProvider;
858     tmpPath->setIsVolatile(true);
859
860     if (prePathMatrix) {
861         if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style) {
862             SkPath* result = pathPtr;
863
864             if (!pathIsMutable) {
865                 result = tmpPath;
866                 pathIsMutable = true;
867             }
868             pathPtr->transform(*prePathMatrix, result);
869             pathPtr = result;
870         } else {
871             matrixProvider = preConcatMatrixProvider.init(*matrixProvider, *prePathMatrix);
872         }
873     }
874
875     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
876
877     {
878         SkScalar coverage;
879         if (SkDrawTreatAsHairline(origPaint, matrixProvider->localToDevice(), &coverage)) {
880             const auto bm = origPaint.asBlendMode();
881             if (SK_Scalar1 == coverage) {
882                 paint.writable()->setStrokeWidth(0);
883             } else if (bm && SkBlendMode_SupportsCoverageAsAlpha(bm.value())) {
884                 U8CPU newAlpha;
885 #if 0
886                 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
887                                                      origPaint.getAlpha()));
888 #else
889                 // this is the old technique, which we preserve for now so
890                 // we don't change previous results (testing)
891                 // the new way seems fine, its just (a tiny bit) different
892                 int scale = (int)(coverage * 256);
893                 newAlpha = origPaint.getAlpha() * scale >> 8;
894 #endif
895                 SkPaint* writablePaint = paint.writable();
896                 writablePaint->setStrokeWidth(0);
897                 writablePaint->setAlpha(newAlpha);
898             }
899         }
900     }
901
902     if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
903         SkRect cullRect;
904         const SkRect* cullRectPtr = nullptr;
905         if (this->computeConservativeLocalClipBounds(&cullRect)) {
906             cullRectPtr = &cullRect;
907         }
908         doFill = paint->getFillPath(*pathPtr, tmpPath, cullRectPtr,
909                                     fMatrixProvider->localToDevice());
910         pathPtr = tmpPath;
911     }
912
913     // avoid possibly allocating a new path in transform if we can
914     SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath;
915
916     // transform the path into device space
917     pathPtr->transform(matrixProvider->localToDevice(), devPathPtr);
918
919 #if defined(SK_BUILD_FOR_FUZZER)
920     if (devPathPtr->countPoints() > 1000) {
921         return;
922     }
923 #endif
924
925     this->drawDevPath(*devPathPtr, *paint, drawCoverage, customBlitter, doFill);
926 }
927
928 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
929                         const SkRect& srcR) {
930     SkRect  dstR;
931     m.mapRect(&dstR, srcR);
932     return c.quickReject(dstR.roundOut());
933 }
934
935 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
936                         int width, int height) {
937     SkRect  r;
938     r.setIWH(width, height);
939     return clipped_out(matrix, clip, r);
940 }
941
942 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, const SkPixmap& pmap) {
943     return clip.isBW() || clip.quickContains(SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height()));
944 }
945
946 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
947                         const SkRect* dstBounds, const SkSamplingOptions& sampling,
948                         const SkPaint& origPaint) const {
949     SkDEBUGCODE(this->validate();)
950
951     // nothing to draw
952     if (fRC->isEmpty() ||
953             bitmap.width() == 0 || bitmap.height() == 0 ||
954             bitmap.colorType() == kUnknown_SkColorType) {
955         return;
956     }
957
958     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
959     if (origPaint.getStyle() != SkPaint::kFill_Style) {
960         paint.writable()->setStyle(SkPaint::kFill_Style);
961     }
962
963     SkPreConcatMatrixProvider matrixProvider(*fMatrixProvider, prematrix);
964     SkMatrix matrix = matrixProvider.localToDevice();
965
966     if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
967         return;
968     }
969
970     if (!SkColorTypeIsAlphaOnly(bitmap.colorType()) &&
971         SkTreatAsSprite(matrix, bitmap.dimensions(), sampling, *paint)) {
972         //
973         // It is safe to call lock pixels now, since we know the matrix is
974         // (more or less) identity.
975         //
976         SkPixmap pmap;
977         if (!bitmap.peekPixels(&pmap)) {
978             return;
979         }
980         int ix = SkScalarRoundToInt(matrix.getTranslateX());
981         int iy = SkScalarRoundToInt(matrix.getTranslateY());
982         if (clipHandlesSprite(*fRC, ix, iy, pmap)) {
983             SkSTArenaAlloc<kSkBlitterContextSize> allocator;
984             // blitter will be owned by the allocator.
985             SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, *paint, pmap, ix, iy, &allocator,
986                                                          fRC->clipShader());
987             if (blitter) {
988                 SkScan::FillIRect(SkIRect::MakeXYWH(ix, iy, pmap.width(), pmap.height()),
989                                   *fRC, blitter);
990                 return;
991             }
992             // if !blitter, then we fall-through to the slower case
993         }
994     }
995
996     // now make a temp draw on the stack, and use it
997     //
998     SkDraw draw(*this);
999     draw.fMatrixProvider = &matrixProvider;
1000
1001     SkPaint paintWithShader = make_paint_with_image(*paint, bitmap, sampling);
1002     const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
1003     if (dstBounds) {
1004         this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds);
1005     } else {
1006         draw.drawRect(srcBounds, paintWithShader);
1007     }
1008 }
1009
1010 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& origPaint) const {
1011     SkDEBUGCODE(this->validate();)
1012
1013     // nothing to draw
1014     if (fRC->isEmpty() ||
1015             bitmap.width() == 0 || bitmap.height() == 0 ||
1016             bitmap.colorType() == kUnknown_SkColorType) {
1017         return;
1018     }
1019
1020     const SkIRect bounds = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
1021
1022     if (fRC->quickReject(bounds)) {
1023         return; // nothing to draw
1024     }
1025
1026     SkPaint paint(origPaint);
1027     paint.setStyle(SkPaint::kFill_Style);
1028
1029     SkPixmap pmap;
1030     if (!bitmap.peekPixels(&pmap)) {
1031         return;
1032     }
1033
1034     if (nullptr == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, pmap)) {
1035         // blitter will be owned by the allocator.
1036         SkSTArenaAlloc<kSkBlitterContextSize> allocator;
1037         SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, paint, pmap, x, y, &allocator,
1038                                                      fRC->clipShader());
1039         if (blitter) {
1040             SkScan::FillIRect(bounds, *fRC, blitter);
1041             return;
1042         }
1043     }
1044
1045     SkMatrix        matrix;
1046     SkRect          r;
1047
1048     // get a scalar version of our rect
1049     r.set(bounds);
1050
1051     // create shader with offset
1052     matrix.setTranslate(r.fLeft, r.fTop);
1053     SkPaint paintWithShader = make_paint_with_image(paint, bitmap, SkSamplingOptions(), &matrix);
1054     SkDraw draw(*this);
1055     SkOverrideDeviceMatrixProvider matrixProvider(SkMatrix::I());
1056     draw.fMatrixProvider = &matrixProvider;
1057     // call ourself with a rect
1058     draw.drawRect(r, paintWithShader);
1059 }
1060
1061 ////////////////////////////////////////////////////////////////////////////////////////////////
1062
1063 #ifdef SK_DEBUG
1064
1065 void SkDraw::validate() const {
1066     SkASSERT(fMatrixProvider != nullptr);
1067     SkASSERT(fRC != nullptr);
1068
1069     const SkIRect&  cr = fRC->getBounds();
1070     SkIRect         br;
1071
1072     br.setWH(fDst.width(), fDst.height());
1073     SkASSERT(cr.isEmpty() || br.contains(cr));
1074 }
1075
1076 #endif
1077
1078 ////////////////////////////////////////////////////////////////////////////////////////////////
1079
1080 #include "include/core/SkPath.h"
1081 #include "include/core/SkRegion.h"
1082 #include "src/core/SkBlitter.h"
1083 #include "src/core/SkDraw.h"
1084
1085 bool SkDraw::ComputeMaskBounds(const SkRect& devPathBounds, const SkIRect& clipBounds,
1086                                const SkMaskFilter* filter, const SkMatrix* filterMatrix,
1087                                SkIRect* bounds) {
1088     //  init our bounds from the path
1089     *bounds = devPathBounds.makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut();
1090
1091     SkIPoint margin = SkIPoint::Make(0, 0);
1092     if (filter) {
1093         SkASSERT(filterMatrix);
1094
1095         SkMask srcM, dstM;
1096
1097         srcM.fBounds = *bounds;
1098         srcM.fFormat = SkMask::kA8_Format;
1099         if (!as_MFB(filter)->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
1100             return false;
1101         }
1102     }
1103
1104     // trim the bounds to reflect the clip (plus whatever slop the filter needs)
1105     // Ugh. Guard against gigantic margins from wacky filters. Without this
1106     // check we can request arbitrary amounts of slop beyond our visible
1107     // clip, and bring down the renderer (at least on finite RAM machines
1108     // like handsets, etc.). Need to balance this invented value between
1109     // quality of large filters like blurs, and the corresponding memory
1110     // requests.
1111     static constexpr int kMaxMargin = 128;
1112     if (!bounds->intersect(clipBounds.makeOutset(std::min(margin.fX, kMaxMargin),
1113                                                  std::min(margin.fY, kMaxMargin)))) {
1114         return false;
1115     }
1116
1117     return true;
1118 }
1119
1120 static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
1121                            SkStrokeRec::InitStyle style) {
1122     SkDraw draw;
1123     if (!draw.fDst.reset(mask)) {
1124         return;
1125     }
1126
1127     SkRasterClip    clip;
1128     SkMatrix        matrix;
1129     SkPaint         paint;
1130
1131     clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
1132     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
1133                         -SkIntToScalar(mask.fBounds.fTop));
1134
1135     SkMatrixProvider matrixProvider(matrix);
1136     draw.fRC             = &clip;
1137     draw.fMatrixProvider = &matrixProvider;
1138     paint.setAntiAlias(true);
1139     switch (style) {
1140         case SkStrokeRec::kHairline_InitStyle:
1141             SkASSERT(!paint.getStrokeWidth());
1142             paint.setStyle(SkPaint::kStroke_Style);
1143             break;
1144         case SkStrokeRec::kFill_InitStyle:
1145             SkASSERT(paint.getStyle() == SkPaint::kFill_Style);
1146             break;
1147
1148     }
1149     draw.drawPath(devPath, paint);
1150 }
1151
1152 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect& clipBounds,
1153                         const SkMaskFilter* filter, const SkMatrix* filterMatrix,
1154                         SkMask* mask, SkMask::CreateMode mode,
1155                         SkStrokeRec::InitStyle style) {
1156     if (devPath.isEmpty()) {
1157         return false;
1158     }
1159
1160     if (SkMask::kJustRenderImage_CreateMode != mode) {
1161         // By using infinite bounds for inverse fills, ComputeMaskBounds is able to clip it to
1162         // 'clipBounds' outset by whatever extra margin the mask filter requires.
1163         static const SkRect kInverseBounds = { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity,
1164                                                SK_ScalarInfinity, SK_ScalarInfinity};
1165         SkRect pathBounds = devPath.isInverseFillType() ? kInverseBounds
1166                                                         : devPath.getBounds();
1167         if (!ComputeMaskBounds(pathBounds, clipBounds, filter,
1168                                filterMatrix, &mask->fBounds))
1169             return false;
1170     }
1171
1172     if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
1173         mask->fFormat = SkMask::kA8_Format;
1174         mask->fRowBytes = mask->fBounds.width();
1175         size_t size = mask->computeImageSize();
1176         if (0 == size) {
1177             // we're too big to allocate the mask, abort
1178             return false;
1179         }
1180         mask->fImage = SkMask::AllocImage(size, SkMask::kZeroInit_Alloc);
1181     }
1182
1183     if (SkMask::kJustComputeBounds_CreateMode != mode) {
1184         draw_into_mask(*mask, devPath, style);
1185     }
1186
1187     return true;
1188 }