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/SkBlitter.h"
9 
10 #include "include/core/SkColor.h"
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkString.h"
13 #include "include/private/SkColorData.h"
14 #include "include/private/SkTo.h"
15 #include "src/core/SkAntiRun.h"
16 #include "src/core/SkArenaAlloc.h"
17 #include "src/core/SkColorSpacePriv.h"
18 #include "src/core/SkMask.h"
19 #include "src/core/SkMaskFilterBase.h"
20 #include "src/core/SkPaintPriv.h"
21 #include "src/core/SkReadBuffer.h"
22 #include "src/core/SkRegionPriv.h"
23 #include "src/core/SkTLazy.h"
24 #include "src/core/SkUtils.h"
25 #include "src/core/SkWriteBuffer.h"
26 #include "src/core/SkXfermodeInterpretation.h"
27 #include "src/shaders/SkShaderBase.h"
28 
~SkBlitter()29 SkBlitter::~SkBlitter() {}
30 
isNullBlitter() const31 bool SkBlitter::isNullBlitter() const { return false; }
32 
justAnOpaqueColor(uint32_t * value)33 const SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
34     return nullptr;
35 }
36 
37 /*
38 void SkBlitter::blitH(int x, int y, int width) {
39     SkDEBUGFAIL("unimplemented");
40 }
41 
42 
43 void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
44                           const int16_t runs[]) {
45     SkDEBUGFAIL("unimplemented");
46 }
47  */
48 
ScalarToAlpha(SkScalar a)49 inline static SkAlpha ScalarToAlpha(SkScalar a) {
50     SkAlpha alpha = (SkAlpha)(a * 255);
51     return alpha > 247 ? 0xFF : alpha < 8 ? 0 : alpha;
52 }
53 
blitFatAntiRect(const SkRect & rect)54 void SkBlitter::blitFatAntiRect(const SkRect& rect) {
55     SkIRect bounds = rect.roundOut();
56     SkASSERT(bounds.width() >= 3);
57 
58     // skbug.com/7813
59     // To ensure consistency of the threaded backend (a rect that's considered fat in the init-once
60     // phase must also be considered fat in the draw phase), we have to deal with rects with small
61     // heights because the horizontal tiling in the threaded backend may change the height.
62     //
63     // This also implies that we cannot do vertical tiling unless we can blit any rect (not just the
64     // fat one.)
65     if (bounds.height() == 0) {
66         return;
67     }
68 
69     int         runSize = bounds.width() + 1; // +1 so we can set runs[bounds.width()] = 0
70     void*       storage = this->allocBlitMemory(runSize * (sizeof(int16_t) + sizeof(SkAlpha)));
71     int16_t*    runs    = reinterpret_cast<int16_t*>(storage);
72     SkAlpha*    alphas  = reinterpret_cast<SkAlpha*>(runs + runSize);
73 
74     runs[0] = 1;
75     runs[1] = bounds.width() - 2;
76     runs[bounds.width() - 1] = 1;
77     runs[bounds.width()]  = 0;
78 
79     SkScalar partialL = bounds.fLeft + 1 - rect.fLeft;
80     SkScalar partialR = rect.fRight - (bounds.fRight - 1);
81     SkScalar partialT = bounds.fTop + 1 - rect.fTop;
82     SkScalar partialB = rect.fBottom - (bounds.fBottom - 1);
83 
84     if (bounds.height() == 1) {
85         partialT = rect.fBottom - rect.fTop;
86     }
87 
88     alphas[0] = ScalarToAlpha(partialL * partialT);
89     alphas[1] = ScalarToAlpha(partialT);
90     alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialT);
91     this->blitAntiH(bounds.fLeft, bounds.fTop, alphas, runs);
92 
93     if (bounds.height() > 2) {
94         this->blitAntiRect(bounds.fLeft, bounds.fTop + 1, bounds.width() - 2, bounds.height() - 2,
95                            ScalarToAlpha(partialL), ScalarToAlpha(partialR));
96     }
97 
98     if (bounds.height() > 1) {
99         alphas[0] = ScalarToAlpha(partialL * partialB);
100         alphas[1] = ScalarToAlpha(partialB);
101         alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialB);
102         this->blitAntiH(bounds.fLeft, bounds.fBottom - 1, alphas, runs);
103     }
104 }
105 
blitV(int x,int y,int height,SkAlpha alpha)106 void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
107     if (alpha == 255) {
108         this->blitRect(x, y, 1, height);
109     } else {
110         int16_t runs[2];
111         runs[0] = 1;
112         runs[1] = 0;
113 
114         while (--height >= 0) {
115             this->blitAntiH(x, y++, &alpha, runs);
116         }
117     }
118 }
119 
blitRect(int x,int y,int width,int height)120 void SkBlitter::blitRect(int x, int y, int width, int height) {
121     SkASSERT(width > 0);
122     while (--height >= 0) {
123         this->blitH(x, y++, width);
124     }
125 }
126 
127 /// Default implementation doesn't check for easy optimizations
128 /// such as alpha == 255; also uses blitV(), which some subclasses
129 /// may not support.
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)130 void SkBlitter::blitAntiRect(int x, int y, int width, int height,
131                              SkAlpha leftAlpha, SkAlpha rightAlpha) {
132     if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0
133         this->blitV(x, y, height, leftAlpha);
134     }
135     x++;
136     if (width > 0) {
137         this->blitRect(x, y, width, height);
138         x += width;
139     }
140     if (rightAlpha > 0) {
141         this->blitV(x, y, height, rightAlpha);
142     }
143 }
144 
145 //////////////////////////////////////////////////////////////////////////////
146 
bits_to_runs(SkBlitter * blitter,int x,int y,const uint8_t bits[],uint8_t left_mask,ptrdiff_t rowBytes,uint8_t right_mask)147 static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
148                                 const uint8_t bits[],
149                                 uint8_t left_mask, ptrdiff_t rowBytes,
150                                 uint8_t right_mask) {
151     int inFill = 0;
152     int pos = 0;
153 
154     while (--rowBytes >= 0) {
155         uint8_t b = *bits++ & left_mask;
156         if (rowBytes == 0) {
157             b &= right_mask;
158         }
159 
160         for (uint8_t test = 0x80U; test != 0; test >>= 1) {
161             if (b & test) {
162                 if (!inFill) {
163                     pos = x;
164                     inFill = true;
165                 }
166             } else {
167                 if (inFill) {
168                     blitter->blitH(pos, y, x - pos);
169                     inFill = false;
170                 }
171             }
172             x += 1;
173         }
174         left_mask = 0xFFU;
175     }
176 
177     // final cleanup
178     if (inFill) {
179         blitter->blitH(pos, y, x - pos);
180     }
181 }
182 
183 // maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8.
generate_right_mask(int maskBitCount)184 static uint8_t generate_right_mask(int maskBitCount) {
185     return static_cast<uint8_t>((0xFF00U >> maskBitCount) & 0xFF);
186 }
187 
blitMask(const SkMask & mask,const SkIRect & clip)188 void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
189     SkASSERT(mask.fBounds.contains(clip));
190 
191     if (mask.fFormat == SkMask::kLCD16_Format) {
192         return; // needs to be handled by subclass
193     }
194 
195     if (mask.fFormat == SkMask::kBW_Format) {
196         int cx = clip.fLeft;
197         int cy = clip.fTop;
198         int maskLeft = mask.fBounds.fLeft;
199         int maskRowBytes = mask.fRowBytes;
200         int height = clip.height();
201 
202         const uint8_t* bits = mask.getAddr1(cx, cy);
203 
204         SkDEBUGCODE(const uint8_t* endOfImage =
205             mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
206             + ((mask.fBounds.width() + 7) >> 3));
207 
208         if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
209             while (--height >= 0) {
210                 int affectedRightBit = mask.fBounds.width() - 1;
211                 ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
212                 SkASSERT(bits + rowBytes <= endOfImage);
213                 U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
214                 bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
215                 bits += maskRowBytes;
216                 cy += 1;
217             }
218         } else {
219             // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all
220             // addressing into the bit mask is relative to that point. Since this is an address
221             // calculated from a arbitrary bit in that byte, calculate the left most bit.
222             int bitsLeft = cx - ((cx - maskLeft) & 7);
223 
224             // Everything is relative to the bitsLeft.
225             int leftEdge = cx - bitsLeft;
226             SkASSERT(leftEdge >= 0);
227             int rightEdge = clip.fRight - bitsLeft;
228             SkASSERT(rightEdge > leftEdge);
229 
230             // Calculate left byte and mask
231             const uint8_t* leftByte = bits;
232             U8CPU leftMask = 0xFFU >> (leftEdge & 7);
233 
234             // Calculate right byte and mask
235             int affectedRightBit = rightEdge - 1;
236             const uint8_t* rightByte = bits + (affectedRightBit >> 3);
237             U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
238 
239             // leftByte and rightByte are byte locations therefore, to get a count of bytes the
240             // code must add one.
241             ptrdiff_t rowBytes = rightByte - leftByte + 1;
242 
243             while (--height >= 0) {
244                 SkASSERT(bits + rowBytes <= endOfImage);
245                 bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
246                 bits += maskRowBytes;
247                 cy += 1;
248             }
249         }
250     } else {
251         int                         width = clip.width();
252         SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
253         int16_t*                    runs = runStorage.get();
254         const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
255 
256         sk_memset16((uint16_t*)runs, 1, width);
257         runs[width] = 0;
258 
259         int height = clip.height();
260         int y = clip.fTop;
261         while (--height >= 0) {
262             this->blitAntiH(clip.fLeft, y, aa, runs);
263             aa += mask.fRowBytes;
264             y += 1;
265         }
266     }
267 }
268 
269 /////////////////////// these guys are not virtual, just a helpers
270 
blitMaskRegion(const SkMask & mask,const SkRegion & clip)271 void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
272     if (clip.quickReject(mask.fBounds)) {
273         return;
274     }
275 
276     SkRegion::Cliperator clipper(clip, mask.fBounds);
277 
278     while (!clipper.done()) {
279         const SkIRect& cr = clipper.rect();
280         this->blitMask(mask, cr);
281         clipper.next();
282     }
283 }
284 
blitRectRegion(const SkIRect & rect,const SkRegion & clip)285 void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
286     SkRegion::Cliperator clipper(clip, rect);
287 
288     while (!clipper.done()) {
289         const SkIRect& cr = clipper.rect();
290         this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
291         clipper.next();
292     }
293 }
294 
blitRegion(const SkRegion & clip)295 void SkBlitter::blitRegion(const SkRegion& clip) {
296     SkRegionPriv::VisitSpans(clip, [this](const SkIRect& r) {
297         this->blitRect(r.left(), r.top(), r.width(), r.height());
298     });
299 }
300 
301 ///////////////////////////////////////////////////////////////////////////////
302 
blitH(int x,int y,int width)303 void SkNullBlitter::blitH(int x, int y, int width) {}
304 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])305 void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
306                               const int16_t runs[]) {}
307 
blitV(int x,int y,int height,SkAlpha alpha)308 void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
309 
blitRect(int x,int y,int width,int height)310 void SkNullBlitter::blitRect(int x, int y, int width, int height) {}
311 
blitMask(const SkMask & mask,const SkIRect & clip)312 void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
313 
justAnOpaqueColor(uint32_t * value)314 const SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
315     return nullptr;
316 }
317 
isNullBlitter() const318 bool SkNullBlitter::isNullBlitter() const { return true; }
319 
320 ///////////////////////////////////////////////////////////////////////////////
321 
compute_anti_width(const int16_t runs[])322 static int compute_anti_width(const int16_t runs[]) {
323     int width = 0;
324 
325     for (;;) {
326         int count = runs[0];
327 
328         SkASSERT(count >= 0);
329         if (count == 0) {
330             break;
331         }
332         width += count;
333         runs += count;
334     }
335     return width;
336 }
337 
y_in_rect(int y,const SkIRect & rect)338 static inline bool y_in_rect(int y, const SkIRect& rect) {
339     return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
340 }
341 
x_in_rect(int x,const SkIRect & rect)342 static inline bool x_in_rect(int x, const SkIRect& rect) {
343     return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
344 }
345 
blitH(int left,int y,int width)346 void SkRectClipBlitter::blitH(int left, int y, int width) {
347     SkASSERT(width > 0);
348 
349     if (!y_in_rect(y, fClipRect)) {
350         return;
351     }
352 
353     int right = left + width;
354 
355     if (left < fClipRect.fLeft) {
356         left = fClipRect.fLeft;
357     }
358     if (right > fClipRect.fRight) {
359         right = fClipRect.fRight;
360     }
361 
362     width = right - left;
363     if (width > 0) {
364         fBlitter->blitH(left, y, width);
365     }
366 }
367 
blitAntiH(int left,int y,const SkAlpha aa[],const int16_t runs[])368 void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
369                                   const int16_t runs[]) {
370     if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
371         return;
372     }
373 
374     int x0 = left;
375     int x1 = left + compute_anti_width(runs);
376 
377     if (x1 <= fClipRect.fLeft) {
378         return;
379     }
380 
381     SkASSERT(x0 < x1);
382     if (x0 < fClipRect.fLeft) {
383         int dx = fClipRect.fLeft - x0;
384         SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
385         runs += dx;
386         aa += dx;
387         x0 = fClipRect.fLeft;
388     }
389 
390     SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
391     if (x1 > fClipRect.fRight) {
392         x1 = fClipRect.fRight;
393         SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
394         ((int16_t*)runs)[x1 - x0] = 0;
395     }
396 
397     SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
398     SkASSERT(compute_anti_width(runs) == x1 - x0);
399 
400     fBlitter->blitAntiH(x0, y, aa, runs);
401 }
402 
blitV(int x,int y,int height,SkAlpha alpha)403 void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
404     SkASSERT(height > 0);
405 
406     if (!x_in_rect(x, fClipRect)) {
407         return;
408     }
409 
410     int y0 = y;
411     int y1 = y + height;
412 
413     if (y0 < fClipRect.fTop) {
414         y0 = fClipRect.fTop;
415     }
416     if (y1 > fClipRect.fBottom) {
417         y1 = fClipRect.fBottom;
418     }
419 
420     if (y0 < y1) {
421         fBlitter->blitV(x, y0, y1 - y0, alpha);
422     }
423 }
424 
blitRect(int left,int y,int width,int height)425 void SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
426     SkIRect    r;
427 
428     r.setLTRB(left, y, left + width, y + height);
429     if (r.intersect(fClipRect)) {
430         fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
431     }
432 }
433 
blitAntiRect(int left,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)434 void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
435                                      SkAlpha leftAlpha, SkAlpha rightAlpha) {
436     SkIRect    r;
437 
438     // The *true* width of the rectangle blitted is width+2:
439     r.setLTRB(left, y, left + width + 2, y + height);
440     if (r.intersect(fClipRect)) {
441         if (r.fLeft != left) {
442             SkASSERT(r.fLeft > left);
443             leftAlpha = 255;
444         }
445         if (r.fRight != left + width + 2) {
446             SkASSERT(r.fRight < left + width + 2);
447             rightAlpha = 255;
448         }
449         if (255 == leftAlpha && 255 == rightAlpha) {
450             fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
451         } else if (1 == r.width()) {
452             if (r.fLeft == left) {
453                 fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
454             } else {
455                 SkASSERT(r.fLeft == left + width + 1);
456                 fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
457             }
458         } else {
459             fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
460                                    leftAlpha, rightAlpha);
461         }
462     }
463 }
464 
blitMask(const SkMask & mask,const SkIRect & clip)465 void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
466     SkASSERT(mask.fBounds.contains(clip));
467 
468     SkIRect    r = clip;
469 
470     if (r.intersect(fClipRect)) {
471         fBlitter->blitMask(mask, r);
472     }
473 }
474 
justAnOpaqueColor(uint32_t * value)475 const SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
476     return fBlitter->justAnOpaqueColor(value);
477 }
478 
479 ///////////////////////////////////////////////////////////////////////////////
480 
blitH(int x,int y,int width)481 void SkRgnClipBlitter::blitH(int x, int y, int width) {
482     SkRegion::Spanerator span(*fRgn, y, x, x + width);
483     int left, right;
484 
485     while (span.next(&left, &right)) {
486         SkASSERT(left < right);
487         fBlitter->blitH(left, y, right - left);
488     }
489 }
490 
blitAntiH(int x,int y,const SkAlpha aa[],const int16_t runs[])491 void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
492                                  const int16_t runs[]) {
493     int width = compute_anti_width(runs);
494     SkRegion::Spanerator span(*fRgn, y, x, x + width);
495     int left, right;
496     SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
497 
498     int prevRite = x;
499     while (span.next(&left, &right)) {
500         SkASSERT(x <= left);
501         SkASSERT(left < right);
502         SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
503 
504         SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
505 
506         // now zero before left
507         if (left > prevRite) {
508             int index = prevRite - x;
509             ((uint8_t*)aa)[index] = 0;   // skip runs after right
510             ((int16_t*)runs)[index] = SkToS16(left - prevRite);
511         }
512 
513         prevRite = right;
514     }
515 
516     if (prevRite > x) {
517         ((int16_t*)runs)[prevRite - x] = 0;
518 
519         if (x < 0) {
520             int skip = runs[0];
521             SkASSERT(skip >= -x);
522             aa += skip;
523             runs += skip;
524             x += skip;
525         }
526         fBlitter->blitAntiH(x, y, aa, runs);
527     }
528 }
529 
blitV(int x,int y,int height,SkAlpha alpha)530 void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
531     SkIRect    bounds;
532     bounds.setXYWH(x, y, 1, height);
533 
534     SkRegion::Cliperator    iter(*fRgn, bounds);
535 
536     while (!iter.done()) {
537         const SkIRect& r = iter.rect();
538         SkASSERT(bounds.contains(r));
539 
540         fBlitter->blitV(x, r.fTop, r.height(), alpha);
541         iter.next();
542     }
543 }
544 
blitRect(int x,int y,int width,int height)545 void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
546     SkIRect    bounds;
547     bounds.setXYWH(x, y, width, height);
548 
549     SkRegion::Cliperator    iter(*fRgn, bounds);
550 
551     while (!iter.done()) {
552         const SkIRect& r = iter.rect();
553         SkASSERT(bounds.contains(r));
554 
555         fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
556         iter.next();
557     }
558 }
559 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)560 void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
561                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
562     // The *true* width of the rectangle to blit is width + 2
563     SkIRect    bounds;
564     bounds.setXYWH(x, y, width + 2, height);
565 
566     SkRegion::Cliperator    iter(*fRgn, bounds);
567 
568     while (!iter.done()) {
569         const SkIRect& r = iter.rect();
570         SkASSERT(bounds.contains(r));
571         SkASSERT(r.fLeft >= x);
572         SkASSERT(r.fRight <= x + width + 2);
573 
574         SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
575         SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
576                                       rightAlpha : 255;
577 
578         if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
579             fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
580         } else if (1 == r.width()) {
581             if (r.fLeft == x) {
582                 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
583                                 effectiveLeftAlpha);
584             } else {
585                 SkASSERT(r.fLeft == x + width + 1);
586                 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
587                                 effectiveRightAlpha);
588             }
589         } else {
590             fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
591                                    effectiveLeftAlpha, effectiveRightAlpha);
592         }
593         iter.next();
594     }
595 }
596 
597 
blitMask(const SkMask & mask,const SkIRect & clip)598 void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
599     SkASSERT(mask.fBounds.contains(clip));
600 
601     SkRegion::Cliperator iter(*fRgn, clip);
602     const SkIRect&       r = iter.rect();
603     SkBlitter*           blitter = fBlitter;
604 
605     while (!iter.done()) {
606         blitter->blitMask(mask, r);
607         iter.next();
608     }
609 }
610 
justAnOpaqueColor(uint32_t * value)611 const SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
612     return fBlitter->justAnOpaqueColor(value);
613 }
614 
615 ///////////////////////////////////////////////////////////////////////////////
616 
apply(SkBlitter * blitter,const SkRegion * clip,const SkIRect * ir)617 SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
618                                    const SkIRect* ir) {
619     if (clip) {
620         const SkIRect& clipR = clip->getBounds();
621 
622         if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
623             blitter = &fNullBlitter;
624         } else if (clip->isRect()) {
625             if (ir == nullptr || !clipR.contains(*ir)) {
626                 fRectBlitter.init(blitter, clipR);
627                 blitter = &fRectBlitter;
628             }
629         } else {
630             fRgnBlitter.init(blitter, clip);
631             blitter = &fRgnBlitter;
632         }
633     }
634     return blitter;
635 }
636 
637 ///////////////////////////////////////////////////////////////////////////////
638 
639 #include "src/core/SkCoreBlitters.h"
640 
641 // hack for testing, not to be exposed to clients
642 bool gSkForceRasterPipelineBlitter;
643 
UseRasterPipelineBlitter(const SkPixmap & device,const SkPaint & paint,const SkMatrix & matrix)644 bool SkBlitter::UseRasterPipelineBlitter(const SkPixmap& device, const SkPaint& paint,
645                                          const SkMatrix& matrix) {
646     if (gSkForceRasterPipelineBlitter) {
647         return true;
648     }
649 #if 0 || defined(SK_FORCE_RASTER_PIPELINE_BLITTER)
650     return true;
651 #else
652 
653     const SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
654 
655     // The legacy blitters cannot handle any of these complex features (anymore).
656     if (device.alphaType() == kUnpremul_SkAlphaType        ||
657         matrix.hasPerspective()                            ||
658         paint.getColorFilter()                             ||
659         paint.getBlendMode() > SkBlendMode::kLastCoeffMode ||
660         paint.getFilterQuality() == kHigh_SkFilterQuality  ||
661         (mf && mf->getFormat() == SkMask::k3D_Format)) {
662         return true;
663     }
664 
665     // All the real legacy fast paths are for shaders and SrcOver.
666     // Choosing SkRasterPipelineBlitter will also let us to hit its single-color memset path.
667     if (!paint.getShader() && paint.getBlendMode() != SkBlendMode::kSrcOver) {
668         return true;
669     }
670 
671     auto cs = device.colorSpace();
672     // We check (indirectly via makeContext()) later on if the shader can handle the colorspace
673     // in legacy mode, so here we just focus on if a single color needs raster-pipeline.
674     if (cs && !paint.getShader()) {
675         if (!paint.getColor4f().fitsInBytes() || !cs->isSRGB()) {
676             return true;
677         }
678     }
679 
680     // Only kN32 and 565 are handled by legacy blitters now, 565 mostly just for Android.
681     return device.colorType() != kN32_SkColorType
682         && device.colorType() != kRGB_565_SkColorType;
683 #endif
684 }
685 
Choose(const SkPixmap & device,const SkMatrix & matrix,const SkPaint & origPaint,SkArenaAlloc * alloc,bool drawCoverage)686 SkBlitter* SkBlitter::Choose(const SkPixmap& device,
687                              const SkMatrix& matrix,
688                              const SkPaint& origPaint,
689                              SkArenaAlloc* alloc,
690                              bool drawCoverage) {
691     SkASSERT(alloc);
692 
693     if (kUnknown_SkColorType == device.colorType()) {
694         return alloc->make<SkNullBlitter>();
695     }
696 
697     // We may tweak the original paint as we go.
698     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
699 
700     // We have the most fast-paths for SrcOver, so see if we can act like SrcOver.
701     if (paint->getBlendMode() != SkBlendMode::kSrcOver) {
702         switch (SkInterpretXfermode(*paint, SkColorTypeIsAlwaysOpaque(device.colorType()))) {
703             case kSrcOver_SkXfermodeInterpretation:
704                 paint.writable()->setBlendMode(SkBlendMode::kSrcOver);
705                 break;
706             case kSkipDrawing_SkXfermodeInterpretation:
707                 return alloc->make<SkNullBlitter>();
708             default:
709                 break;
710         }
711     }
712 
713     // A Clear blend mode will ignore the entire color pipeline, as if Src mode with 0x00000000.
714     if (paint->getBlendMode() == SkBlendMode::kClear) {
715         SkPaint* p = paint.writable();
716         p->setShader(nullptr);
717         p->setColorFilter(nullptr);
718         p->setBlendMode(SkBlendMode::kSrc);
719         p->setColor(0x00000000);
720     }
721 
722 #ifndef SK_SUPPORT_LEGACY_COLORFILTER_NO_SHADER
723     if (paint->getColorFilter() && !paint->getShader()) {
724         // apply the filter to the paint's color, and then remove the filter
725         auto dstCS = device.colorSpace();
726         SkPaint* p = paint.writable();
727         p->setColor(p->getColorFilter()->filterColor4f(p->getColor4f(), sk_srgb_singleton(), dstCS),
728                     dstCS);
729         p->setColorFilter(nullptr);
730     }
731 #endif
732 
733     if (drawCoverage) {
734         if (device.colorType() == kAlpha_8_SkColorType) {
735             SkASSERT(!paint->getShader());
736             SkASSERT(paint->isSrcOver());
737             return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
738         }
739         return alloc->make<SkNullBlitter>();
740     }
741 
742     if (paint->isDither() && !SkPaintPriv::ShouldDither(*paint, device.colorType())) {
743         paint.writable()->setDither(false);
744     }
745 
746 #if defined(SK_USE_SKVM_BLITTER)
747     if (auto blitter = SkCreateSkVMBlitter(device, *paint, matrix, alloc)) {
748         return blitter;
749     }
750 #endif
751 
752     // We'll end here for many interesting cases: color spaces, color filters, most color types.
753     if (UseRasterPipelineBlitter(device, *paint, matrix)) {
754         auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
755         SkASSERT(blitter);
756         return blitter;
757     }
758 
759     // Everything but legacy kN32_SkColorType and kRGB_565_SkColorType should already be handled.
760     SkASSERT(device.colorType() == kN32_SkColorType ||
761              device.colorType() == kRGB_565_SkColorType);
762 
763     // And we should either have a shader, be blending with SrcOver, or both.
764     SkASSERT(paint->getShader() || paint->getBlendMode() == SkBlendMode::kSrcOver);
765 
766     // Legacy blitters keep their shader state on a shader context.
767     SkShaderBase::Context* shaderContext = nullptr;
768     if (paint->getShader()) {
769         shaderContext = as_SB(paint->getShader())->makeContext(
770                 {*paint, matrix, nullptr, device.colorType(), device.colorSpace()},
771                 alloc);
772 
773         // Creating the context isn't always possible... we'll just fall back to raster pipeline.
774         if (!shaderContext) {
775             auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
776             SkASSERT(blitter);
777             return blitter;
778         }
779     }
780 
781     switch (device.colorType()) {
782         case kN32_SkColorType:
783             if (shaderContext) {
784                 return alloc->make<SkARGB32_Shader_Blitter>(device, *paint, shaderContext);
785             } else if (paint->getColor() == SK_ColorBLACK) {
786                 return alloc->make<SkARGB32_Black_Blitter>(device, *paint);
787             } else if (paint->getAlpha() == 0xFF) {
788                 return alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
789             } else {
790                 return alloc->make<SkARGB32_Blitter>(device, *paint);
791             }
792 
793         case kRGB_565_SkColorType:
794             if (shaderContext && SkRGB565_Shader_Blitter::Supports(device, *paint)) {
795                 return alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext);
796             } else {
797                 return SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
798             }
799 
800         default:
801             SkASSERT(false);
802             return alloc->make<SkNullBlitter>();
803     }
804 }
805 
806 ///////////////////////////////////////////////////////////////////////////////
807 
SkShaderBlitter(const SkPixmap & device,const SkPaint & paint,SkShaderBase::Context * shaderContext)808 SkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
809                                  SkShaderBase::Context* shaderContext)
810         : INHERITED(device)
811         , fShader(paint.getShader())
812         , fShaderContext(shaderContext) {
813     SkASSERT(fShader);
814     SkASSERT(fShaderContext);
815 
816     fShader->ref();
817     fShaderFlags = fShaderContext->getFlags();
818     fConstInY = SkToBool(fShaderFlags & SkShaderBase::kConstInY32_Flag);
819 }
820 
~SkShaderBlitter()821 SkShaderBlitter::~SkShaderBlitter() {
822     fShader->unref();
823 }
824 
825 ///////////////////////////////////////////////////////////////////////////////////////////////////
826 
827 #ifdef SK_DEBUG
828 
blitH(int x,int y,int width)829 void SkRectClipCheckBlitter::blitH(int x, int y, int width) {
830     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
831     fBlitter->blitH(x, y, width);
832 }
833 
blitAntiH(int x,int y,const SkAlpha aa[],const int16_t runs[])834 void SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
835     const int16_t* iter = runs;
836     for (; *iter; iter += *iter)
837         ;
838     int width = iter - runs;
839     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
840     fBlitter->blitAntiH(x, y, aa, runs);
841 }
842 
blitV(int x,int y,int height,SkAlpha alpha)843 void SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
844     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
845     fBlitter->blitV(x, y, height, alpha);
846 }
847 
blitRect(int x,int y,int width,int height)848 void SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
849     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
850     fBlitter->blitRect(x, y, width, height);
851 }
852 
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)853 void SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
854                                      SkAlpha leftAlpha, SkAlpha rightAlpha) {
855     bool skipLeft = !leftAlpha;
856     bool skipRight = !rightAlpha;
857 #ifdef SK_DEBUG
858     SkIRect r = SkIRect::MakeXYWH(x + skipLeft, y, width + 2 - skipRight - skipLeft, height);
859     SkASSERT(r.isEmpty() || fClipRect.contains(r));
860 #endif
861     fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
862 }
863 
blitMask(const SkMask & mask,const SkIRect & clip)864 void SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
865     SkASSERT(mask.fBounds.contains(clip));
866     SkASSERT(fClipRect.contains(clip));
867     fBlitter->blitMask(mask, clip);
868 }
869 
justAnOpaqueColor(uint32_t * value)870 const SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
871     return fBlitter->justAnOpaqueColor(value);
872 }
873 
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)874 void SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
875     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1)));
876     fBlitter->blitAntiH2(x, y, a0, a1);
877 }
878 
blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)879 void SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
880     SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2)));
881     fBlitter->blitAntiV2(x, y, a0, a1);
882 }
883 
884 #endif
885