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 "SkArenaAlloc.h"
9#include "SkBlitter.h"
10#include "SkAntiRun.h"
11#include "SkColor.h"
12#include "SkColorFilter.h"
13#include "SkReadBuffer.h"
14#include "SkWriteBuffer.h"
15#include "SkMask.h"
16#include "SkMaskFilterBase.h"
17#include "SkPaintPriv.h"
18#include "SkShaderBase.h"
19#include "SkString.h"
20#include "SkTLazy.h"
21#include "SkUtils.h"
22#include "SkXfermodeInterpretation.h"
23
24SkBlitter::~SkBlitter() {}
25
26bool SkBlitter::isNullBlitter() const { return false; }
27
28const SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
29    return nullptr;
30}
31
32/*
33void SkBlitter::blitH(int x, int y, int width) {
34    SkDEBUGFAIL("unimplemented");
35}
36
37
38void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
39                          const int16_t runs[]) {
40    SkDEBUGFAIL("unimplemented");
41}
42 */
43
44inline static SkAlpha ScalarToAlpha(SkScalar a) {
45    SkAlpha alpha = (SkAlpha)(a * 255);
46    return alpha > 247 ? 0xFF : alpha < 8 ? 0 : alpha;
47}
48
49void SkBlitter::blitFatAntiRect(const SkRect& rect) {
50    SkIRect bounds = rect.roundOut();
51    SkASSERT(bounds.width() >= 3 && bounds.height() >= 3);
52
53    int         runSize = bounds.width() + 1; // +1 so we can set runs[bounds.width()] = 0
54    void*       storage = this->allocBlitMemory(runSize * (sizeof(int16_t) + sizeof(SkAlpha)));
55    int16_t*    runs    = reinterpret_cast<int16_t*>(storage);
56    SkAlpha*    alphas  = reinterpret_cast<SkAlpha*>(runs + runSize);
57
58    runs[0] = 1;
59    runs[1] = bounds.width() - 2;
60    runs[bounds.width() - 1] = 1;
61    runs[bounds.width()]  = 0;
62
63    SkScalar partialL = bounds.fLeft + 1 - rect.fLeft;
64    SkScalar partialR = rect.fRight - (bounds.fRight - 1);
65    SkScalar partialT = bounds.fTop + 1 - rect.fTop;
66    SkScalar partialB = rect.fBottom - (bounds.fBottom - 1);
67
68    alphas[0] = ScalarToAlpha(partialL * partialT);
69    alphas[1] = ScalarToAlpha(partialT);
70    alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialT);
71    this->blitAntiH(bounds.fLeft, bounds.fTop, alphas, runs);
72
73    this->blitAntiRect(bounds.fLeft, bounds.fTop + 1, bounds.width() - 2, bounds.height() - 2,
74                       ScalarToAlpha(partialL), ScalarToAlpha(partialR));
75
76    alphas[0] = ScalarToAlpha(partialL * partialB);
77    alphas[1] = ScalarToAlpha(partialB);
78    alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialB);
79    this->blitAntiH(bounds.fLeft, bounds.fBottom - 1, alphas, runs);
80}
81
82void SkBlitter::blitCoverageDeltas(SkCoverageDeltaList* deltas, const SkIRect& clip,
83                                   bool isEvenOdd, bool isInverse, bool isConvex) {
84    int         runSize = clip.width() + 1; // +1 so we can set runs[clip.width()] = 0
85    void*       storage = this->allocBlitMemory(runSize * (sizeof(int16_t) + sizeof(SkAlpha)));
86    int16_t*    runs    = reinterpret_cast<int16_t*>(storage);
87    SkAlpha*    alphas  = reinterpret_cast<SkAlpha*>(runs + runSize);
88    runs[clip.width()]  = 0; // we must set the last run to 0 so blitAntiH can stop there
89
90    bool canUseMask = !deltas->forceRLE() &&
91                      SkCoverageDeltaMask::CanHandle(SkIRect::MakeLTRB(0, 0, clip.width(), 1));
92    const SkAntiRect& antiRect = deltas->getAntiRect();
93    for(int y = deltas->top(); y < deltas->bottom(); ++y) {
94        // If antiRect is non-empty and we're at its top row, blit it and skip to the bottom
95        if (antiRect.fHeight && y == antiRect.fY) {
96            this->blitAntiRect(antiRect.fX, antiRect.fY, antiRect.fWidth, antiRect.fHeight,
97                               antiRect.fLeftAlpha, antiRect.fRightAlpha);
98            y += antiRect.fHeight - 1; // -1 because ++y in the for loop
99            continue;
100        }
101
102        // If there are too many deltas, sorting will be slow. Using a mask is much faster.
103        // This is such an important optimization that will bring ~2x speedup for benches like
104        // path_fill_small_long_line and path_stroke_small_sawtooth.
105        if (canUseMask && !deltas->sorted(y) && deltas->count(y) << 3 >= clip.width()) {
106            SkIRect rowIR = SkIRect::MakeLTRB(clip.fLeft, y, clip.fRight, y + 1);
107            SkSTArenaAlloc<SkCoverageDeltaMask::MAX_SIZE> alloc;
108            SkCoverageDeltaMask mask(&alloc, rowIR);
109            for(int i = 0; i < deltas->count(y); ++i) {
110                const SkCoverageDelta& delta = deltas->getDelta(y, i);
111                mask.addDelta(delta.fX, y, delta.fDelta);
112            }
113            mask.convertCoverageToAlpha(isEvenOdd, isInverse, isConvex);
114            this->blitMask(mask.prepareSkMask(), rowIR);
115            continue;
116        }
117
118        // The normal flow of blitting deltas starts from here. First sort deltas.
119        deltas->sort(y);
120
121        int     i = 0;              // init delta index to 0
122        int     lastX = clip.fLeft; // init x to clip.fLeft
123        SkFixed coverage = 0;       // init coverage to 0
124
125        // skip deltas with x less than clip.fLeft; they must be precision errors
126        for(; i < deltas->count(y) && deltas->getDelta(y, i).fX < clip.fLeft; ++i);
127        for(; i < deltas->count(y) && deltas->getDelta(y, i).fX < clip.fRight; ++i) {
128            const SkCoverageDelta& delta = deltas->getDelta(y, i);
129            SkASSERT(delta.fX >= lastX);    // delta must be x sorted
130            if (delta.fX > lastX) {         // we have proceeded to a new x (different from lastX)
131                SkAlpha alpha = isConvex ? ConvexCoverageToAlpha(coverage, isInverse)
132                                         : CoverageToAlpha(coverage, isEvenOdd, isInverse);
133                alphas[lastX - clip.fLeft]  = alpha;            // set alpha at lastX
134                runs[lastX - clip.fLeft]    = delta.fX - lastX; // set the run length
135                lastX                       = delta.fX;         // now set lastX to current x
136            }
137            coverage += delta.fDelta; // cumulate coverage with the current delta
138        }
139
140        // Set the alpha and run length from the right-most delta to the right clip boundary
141        SkAlpha alpha = isConvex ? ConvexCoverageToAlpha(coverage, isInverse)
142                                 : CoverageToAlpha(coverage, isEvenOdd, isInverse);
143        alphas[lastX - clip.fLeft]  = alpha;
144        runs[lastX - clip.fLeft]    = clip.fRight - lastX;
145
146        this->blitAntiH(clip.fLeft, y, alphas, runs); // finally blit the current row
147    }
148}
149
150void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
151    if (alpha == 255) {
152        this->blitRect(x, y, 1, height);
153    } else {
154        int16_t runs[2];
155        runs[0] = 1;
156        runs[1] = 0;
157
158        while (--height >= 0) {
159            this->blitAntiH(x, y++, &alpha, runs);
160        }
161    }
162}
163
164void SkBlitter::blitRect(int x, int y, int width, int height) {
165    SkASSERT(width > 0);
166    while (--height >= 0) {
167        this->blitH(x, y++, width);
168    }
169}
170
171/// Default implementation doesn't check for easy optimizations
172/// such as alpha == 255; also uses blitV(), which some subclasses
173/// may not support.
174void SkBlitter::blitAntiRect(int x, int y, int width, int height,
175                             SkAlpha leftAlpha, SkAlpha rightAlpha) {
176    if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0
177        this->blitV(x, y, height, leftAlpha);
178    }
179    x++;
180    if (width > 0) {
181        this->blitRect(x, y, width, height);
182        x += width;
183    }
184    if (rightAlpha > 0) {
185        this->blitV(x, y, height, rightAlpha);
186    }
187}
188
189//////////////////////////////////////////////////////////////////////////////
190
191static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
192                                const uint8_t bits[],
193                                uint8_t left_mask, ptrdiff_t rowBytes,
194                                uint8_t right_mask) {
195    int inFill = 0;
196    int pos = 0;
197
198    while (--rowBytes >= 0) {
199        uint8_t b = *bits++ & left_mask;
200        if (rowBytes == 0) {
201            b &= right_mask;
202        }
203
204        for (uint8_t test = 0x80U; test != 0; test >>= 1) {
205            if (b & test) {
206                if (!inFill) {
207                    pos = x;
208                    inFill = true;
209                }
210            } else {
211                if (inFill) {
212                    blitter->blitH(pos, y, x - pos);
213                    inFill = false;
214                }
215            }
216            x += 1;
217        }
218        left_mask = 0xFFU;
219    }
220
221    // final cleanup
222    if (inFill) {
223        blitter->blitH(pos, y, x - pos);
224    }
225}
226
227// maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8.
228static uint8_t generate_right_mask(int maskBitCount) {
229    return static_cast<uint8_t>(0xFF00U >> maskBitCount);
230}
231
232void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
233    SkASSERT(mask.fBounds.contains(clip));
234
235    if (mask.fFormat == SkMask::kLCD16_Format) {
236        return; // needs to be handled by subclass
237    }
238
239    if (mask.fFormat == SkMask::kBW_Format) {
240        int cx = clip.fLeft;
241        int cy = clip.fTop;
242        int maskLeft = mask.fBounds.fLeft;
243        int maskRowBytes = mask.fRowBytes;
244        int height = clip.height();
245
246        const uint8_t* bits = mask.getAddr1(cx, cy);
247
248        SkDEBUGCODE(const uint8_t* endOfImage =
249            mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
250            + ((mask.fBounds.width() + 7) >> 3));
251
252        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
253            while (--height >= 0) {
254                int affectedRightBit = mask.fBounds.width() - 1;
255                ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
256                SkASSERT(bits + rowBytes <= endOfImage);
257                U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
258                bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
259                bits += maskRowBytes;
260                cy += 1;
261            }
262        } else {
263            // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all
264            // addressing into the bit mask is relative to that point. Since this is an address
265            // calculated from a arbitrary bit in that byte, calculate the left most bit.
266            int bitsLeft = cx - ((cx - maskLeft) & 7);
267
268            // Everything is relative to the bitsLeft.
269            int leftEdge = cx - bitsLeft;
270            SkASSERT(leftEdge >= 0);
271            int rightEdge = clip.fRight - bitsLeft;
272            SkASSERT(rightEdge > leftEdge);
273
274            // Calculate left byte and mask
275            const uint8_t* leftByte = bits;
276            U8CPU leftMask = 0xFFU >> (leftEdge & 7);
277
278            // Calculate right byte and mask
279            int affectedRightBit = rightEdge - 1;
280            const uint8_t* rightByte = bits + (affectedRightBit >> 3);
281            U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
282
283            // leftByte and rightByte are byte locations therefore, to get a count of bytes the
284            // code must add one.
285            ptrdiff_t rowBytes = rightByte - leftByte + 1;
286
287            while (--height >= 0) {
288                SkASSERT(bits + rowBytes <= endOfImage);
289                bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
290                bits += maskRowBytes;
291                cy += 1;
292            }
293        }
294    } else {
295        int                         width = clip.width();
296        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
297        int16_t*                    runs = runStorage.get();
298        const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
299
300        sk_memset16((uint16_t*)runs, 1, width);
301        runs[width] = 0;
302
303        int height = clip.height();
304        int y = clip.fTop;
305        while (--height >= 0) {
306            this->blitAntiH(clip.fLeft, y, aa, runs);
307            aa += mask.fRowBytes;
308            y += 1;
309        }
310    }
311}
312
313/////////////////////// these guys are not virtual, just a helpers
314
315void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
316    if (clip.quickReject(mask.fBounds)) {
317        return;
318    }
319
320    SkRegion::Cliperator clipper(clip, mask.fBounds);
321
322    while (!clipper.done()) {
323        const SkIRect& cr = clipper.rect();
324        this->blitMask(mask, cr);
325        clipper.next();
326    }
327}
328
329void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
330    SkRegion::Cliperator clipper(clip, rect);
331
332    while (!clipper.done()) {
333        const SkIRect& cr = clipper.rect();
334        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
335        clipper.next();
336    }
337}
338
339void SkBlitter::blitRegion(const SkRegion& clip) {
340    SkRegion::Iterator iter(clip);
341
342    while (!iter.done()) {
343        const SkIRect& cr = iter.rect();
344        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
345        iter.next();
346    }
347}
348
349///////////////////////////////////////////////////////////////////////////////
350
351void SkNullBlitter::blitH(int x, int y, int width) {}
352
353void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
354                              const int16_t runs[]) {}
355
356void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
357
358void SkNullBlitter::blitRect(int x, int y, int width, int height) {}
359
360void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
361
362const SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
363    return nullptr;
364}
365
366bool SkNullBlitter::isNullBlitter() const { return true; }
367
368///////////////////////////////////////////////////////////////////////////////
369
370static int compute_anti_width(const int16_t runs[]) {
371    int width = 0;
372
373    for (;;) {
374        int count = runs[0];
375
376        SkASSERT(count >= 0);
377        if (count == 0) {
378            break;
379        }
380        width += count;
381        runs += count;
382    }
383    return width;
384}
385
386static inline bool y_in_rect(int y, const SkIRect& rect) {
387    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
388}
389
390static inline bool x_in_rect(int x, const SkIRect& rect) {
391    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
392}
393
394void SkRectClipBlitter::blitH(int left, int y, int width) {
395    SkASSERT(width > 0);
396
397    if (!y_in_rect(y, fClipRect)) {
398        return;
399    }
400
401    int right = left + width;
402
403    if (left < fClipRect.fLeft) {
404        left = fClipRect.fLeft;
405    }
406    if (right > fClipRect.fRight) {
407        right = fClipRect.fRight;
408    }
409
410    width = right - left;
411    if (width > 0) {
412        fBlitter->blitH(left, y, width);
413    }
414}
415
416void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
417                                  const int16_t runs[]) {
418    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
419        return;
420    }
421
422    int x0 = left;
423    int x1 = left + compute_anti_width(runs);
424
425    if (x1 <= fClipRect.fLeft) {
426        return;
427    }
428
429    SkASSERT(x0 < x1);
430    if (x0 < fClipRect.fLeft) {
431        int dx = fClipRect.fLeft - x0;
432        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
433        runs += dx;
434        aa += dx;
435        x0 = fClipRect.fLeft;
436    }
437
438    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
439    if (x1 > fClipRect.fRight) {
440        x1 = fClipRect.fRight;
441        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
442        ((int16_t*)runs)[x1 - x0] = 0;
443    }
444
445    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
446    SkASSERT(compute_anti_width(runs) == x1 - x0);
447
448    fBlitter->blitAntiH(x0, y, aa, runs);
449}
450
451void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
452    SkASSERT(height > 0);
453
454    if (!x_in_rect(x, fClipRect)) {
455        return;
456    }
457
458    int y0 = y;
459    int y1 = y + height;
460
461    if (y0 < fClipRect.fTop) {
462        y0 = fClipRect.fTop;
463    }
464    if (y1 > fClipRect.fBottom) {
465        y1 = fClipRect.fBottom;
466    }
467
468    if (y0 < y1) {
469        fBlitter->blitV(x, y0, y1 - y0, alpha);
470    }
471}
472
473void SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
474    SkIRect    r;
475
476    r.set(left, y, left + width, y + height);
477    if (r.intersect(fClipRect)) {
478        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
479    }
480}
481
482void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
483                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
484    SkIRect    r;
485
486    // The *true* width of the rectangle blitted is width+2:
487    r.set(left, y, left + width + 2, y + height);
488    if (r.intersect(fClipRect)) {
489        if (r.fLeft != left) {
490            SkASSERT(r.fLeft > left);
491            leftAlpha = 255;
492        }
493        if (r.fRight != left + width + 2) {
494            SkASSERT(r.fRight < left + width + 2);
495            rightAlpha = 255;
496        }
497        if (255 == leftAlpha && 255 == rightAlpha) {
498            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
499        } else if (1 == r.width()) {
500            if (r.fLeft == left) {
501                fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
502            } else {
503                SkASSERT(r.fLeft == left + width + 1);
504                fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
505            }
506        } else {
507            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
508                                   leftAlpha, rightAlpha);
509        }
510    }
511}
512
513void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
514    SkASSERT(mask.fBounds.contains(clip));
515
516    SkIRect    r = clip;
517
518    if (r.intersect(fClipRect)) {
519        fBlitter->blitMask(mask, r);
520    }
521}
522
523const SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
524    return fBlitter->justAnOpaqueColor(value);
525}
526
527///////////////////////////////////////////////////////////////////////////////
528
529void SkRgnClipBlitter::blitH(int x, int y, int width) {
530    SkRegion::Spanerator span(*fRgn, y, x, x + width);
531    int left, right;
532
533    while (span.next(&left, &right)) {
534        SkASSERT(left < right);
535        fBlitter->blitH(left, y, right - left);
536    }
537}
538
539void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
540                                 const int16_t runs[]) {
541    int width = compute_anti_width(runs);
542    SkRegion::Spanerator span(*fRgn, y, x, x + width);
543    int left, right;
544    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
545
546    int prevRite = x;
547    while (span.next(&left, &right)) {
548        SkASSERT(x <= left);
549        SkASSERT(left < right);
550        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
551
552        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
553
554        // now zero before left
555        if (left > prevRite) {
556            int index = prevRite - x;
557            ((uint8_t*)aa)[index] = 0;   // skip runs after right
558            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
559        }
560
561        prevRite = right;
562    }
563
564    if (prevRite > x) {
565        ((int16_t*)runs)[prevRite - x] = 0;
566
567        if (x < 0) {
568            int skip = runs[0];
569            SkASSERT(skip >= -x);
570            aa += skip;
571            runs += skip;
572            x += skip;
573        }
574        fBlitter->blitAntiH(x, y, aa, runs);
575    }
576}
577
578void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
579    SkIRect    bounds;
580    bounds.set(x, y, x + 1, y + height);
581
582    SkRegion::Cliperator    iter(*fRgn, bounds);
583
584    while (!iter.done()) {
585        const SkIRect& r = iter.rect();
586        SkASSERT(bounds.contains(r));
587
588        fBlitter->blitV(x, r.fTop, r.height(), alpha);
589        iter.next();
590    }
591}
592
593void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
594    SkIRect    bounds;
595    bounds.set(x, y, x + width, y + height);
596
597    SkRegion::Cliperator    iter(*fRgn, bounds);
598
599    while (!iter.done()) {
600        const SkIRect& r = iter.rect();
601        SkASSERT(bounds.contains(r));
602
603        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
604        iter.next();
605    }
606}
607
608void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
609                                    SkAlpha leftAlpha, SkAlpha rightAlpha) {
610    // The *true* width of the rectangle to blit is width + 2
611    SkIRect    bounds;
612    bounds.set(x, y, x + width + 2, y + height);
613
614    SkRegion::Cliperator    iter(*fRgn, bounds);
615
616    while (!iter.done()) {
617        const SkIRect& r = iter.rect();
618        SkASSERT(bounds.contains(r));
619        SkASSERT(r.fLeft >= x);
620        SkASSERT(r.fRight <= x + width + 2);
621
622        SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
623        SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
624                                      rightAlpha : 255;
625
626        if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
627            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
628        } else if (1 == r.width()) {
629            if (r.fLeft == x) {
630                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
631                                effectiveLeftAlpha);
632            } else {
633                SkASSERT(r.fLeft == x + width + 1);
634                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
635                                effectiveRightAlpha);
636            }
637        } else {
638            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
639                                   effectiveLeftAlpha, effectiveRightAlpha);
640        }
641        iter.next();
642    }
643}
644
645
646void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
647    SkASSERT(mask.fBounds.contains(clip));
648
649    SkRegion::Cliperator iter(*fRgn, clip);
650    const SkIRect&       r = iter.rect();
651    SkBlitter*           blitter = fBlitter;
652
653    while (!iter.done()) {
654        blitter->blitMask(mask, r);
655        iter.next();
656    }
657}
658
659const SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
660    return fBlitter->justAnOpaqueColor(value);
661}
662
663///////////////////////////////////////////////////////////////////////////////
664
665SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
666                                   const SkIRect* ir) {
667    if (clip) {
668        const SkIRect& clipR = clip->getBounds();
669
670        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
671            blitter = &fNullBlitter;
672        } else if (clip->isRect()) {
673            if (ir == nullptr || !clipR.contains(*ir)) {
674                fRectBlitter.init(blitter, clipR);
675                blitter = &fRectBlitter;
676            }
677        } else {
678            fRgnBlitter.init(blitter, clip);
679            blitter = &fRgnBlitter;
680        }
681    }
682    return blitter;
683}
684
685///////////////////////////////////////////////////////////////////////////////
686
687#include "SkColorShader.h"
688#include "SkColorData.h"
689
690class Sk3DShader : public SkShaderBase {
691public:
692    Sk3DShader(sk_sp<SkShader> proxy) : fProxy(std::move(proxy)) {}
693
694    Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
695        SkShaderBase::Context* proxyContext = nullptr;
696        if (fProxy) {
697            proxyContext = as_SB(fProxy)->makeContext(rec, alloc);
698            if (!proxyContext) {
699                return nullptr;
700            }
701        }
702        return alloc->make<Sk3DShaderContext>(*this, rec, proxyContext);
703    }
704
705    class Sk3DShaderContext : public Context {
706    public:
707        // Calls proxyContext's destructor but will NOT free its memory.
708        Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec,
709                          Context* proxyContext)
710            : INHERITED(shader, rec)
711            , fMask(nullptr)
712            , fProxyContext(proxyContext)
713        {
714            if (!fProxyContext) {
715                fPMColor = SkPreMultiplyColor(rec.fPaint->getColor());
716            }
717        }
718
719        ~Sk3DShaderContext() override = default;
720
721        void set3DMask(const SkMask* mask) override { fMask = mask; }
722
723        void shadeSpan(int x, int y, SkPMColor span[], int count) override {
724            if (fProxyContext) {
725                fProxyContext->shadeSpan(x, y, span, count);
726            }
727
728            if (fMask == nullptr) {
729                if (fProxyContext == nullptr) {
730                    sk_memset32(span, fPMColor, count);
731                }
732                return;
733            }
734
735            SkASSERT(fMask->fBounds.contains(x, y));
736            SkASSERT(fMask->fBounds.contains(x + count - 1, y));
737
738            size_t          size = fMask->computeImageSize();
739            const uint8_t*  alpha = fMask->getAddr8(x, y);
740            const uint8_t*  mulp = alpha + size;
741            const uint8_t*  addp = mulp + size;
742
743            if (fProxyContext) {
744                for (int i = 0; i < count; i++) {
745                    if (alpha[i]) {
746                        SkPMColor c = span[i];
747                        if (c) {
748                            unsigned a = SkGetPackedA32(c);
749                            unsigned r = SkGetPackedR32(c);
750                            unsigned g = SkGetPackedG32(c);
751                            unsigned b = SkGetPackedB32(c);
752
753                            unsigned mul = SkAlpha255To256(mulp[i]);
754                            unsigned add = addp[i];
755
756                            r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
757                            g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
758                            b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
759
760                            span[i] = SkPackARGB32(a, r, g, b);
761                        }
762                    } else {
763                        span[i] = 0;
764                    }
765                }
766            } else {    // color
767                unsigned a = SkGetPackedA32(fPMColor);
768                unsigned r = SkGetPackedR32(fPMColor);
769                unsigned g = SkGetPackedG32(fPMColor);
770                unsigned b = SkGetPackedB32(fPMColor);
771                for (int i = 0; i < count; i++) {
772                    if (alpha[i]) {
773                        unsigned mul = SkAlpha255To256(mulp[i]);
774                        unsigned add = addp[i];
775
776                        span[i] = SkPackARGB32( a,
777                                        SkFastMin32(SkAlphaMul(r, mul) + add, a),
778                                        SkFastMin32(SkAlphaMul(g, mul) + add, a),
779                                        SkFastMin32(SkAlphaMul(b, mul) + add, a));
780                    } else {
781                        span[i] = 0;
782                    }
783                }
784            }
785        }
786
787    private:
788        // Unowned.
789        const SkMask* fMask;
790        // Memory is unowned.
791        Context*      fProxyContext;
792        SkPMColor     fPMColor;
793
794        typedef Context INHERITED;
795    };
796
797#ifndef SK_IGNORE_TO_STRING
798    void toString(SkString* str) const override {
799        str->append("Sk3DShader: (");
800
801        if (fProxy) {
802            str->append("Proxy: ");
803            as_SB(fProxy)->toString(str);
804        }
805
806        this->INHERITED::toString(str);
807
808        str->append(")");
809    }
810#endif
811
812    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
813
814protected:
815    void flatten(SkWriteBuffer& buffer) const override {
816        buffer.writeFlattenable(fProxy.get());
817    }
818
819private:
820    sk_sp<SkShader> fProxy;
821
822    typedef SkShaderBase INHERITED;
823};
824
825sk_sp<SkFlattenable> Sk3DShader::CreateProc(SkReadBuffer& buffer) {
826    return sk_make_sp<Sk3DShader>(buffer.readShader());
827}
828
829class Sk3DBlitter : public SkBlitter {
830public:
831    Sk3DBlitter(SkBlitter* proxy, SkShaderBase::Context* shaderContext)
832        : fProxy(proxy)
833        , fShaderContext(shaderContext)
834    {}
835
836    void blitH(int x, int y, int width) override {
837        fProxy->blitH(x, y, width);
838    }
839
840    void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
841        fProxy->blitAntiH(x, y, antialias, runs);
842    }
843
844    void blitV(int x, int y, int height, SkAlpha alpha) override {
845        fProxy->blitV(x, y, height, alpha);
846    }
847
848    void blitRect(int x, int y, int width, int height) override {
849        fProxy->blitRect(x, y, width, height);
850    }
851
852    void blitMask(const SkMask& mask, const SkIRect& clip) override {
853        if (mask.fFormat == SkMask::k3D_Format) {
854            fShaderContext->set3DMask(&mask);
855
856            ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
857            fProxy->blitMask(mask, clip);
858            ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
859
860            fShaderContext->set3DMask(nullptr);
861        } else {
862            fProxy->blitMask(mask, clip);
863        }
864    }
865
866private:
867    // Both pointers are unowned. They will be deleted by SkSmallAllocator.
868    SkBlitter*              fProxy;
869    SkShaderBase::Context*  fShaderContext;
870};
871
872///////////////////////////////////////////////////////////////////////////////
873
874#include "SkCoreBlitters.h"
875
876SkShaderBase::ContextRec::DstType SkBlitter::PreferredShaderDest(const SkImageInfo& dstInfo) {
877    return (dstInfo.gammaCloseToSRGB() || dstInfo.colorType() == kRGBA_F16_SkColorType)
878            ? SkShaderBase::ContextRec::kPM4f_DstType
879            : SkShaderBase::ContextRec::kPMColor_DstType;
880}
881
882// hack for testing, not to be exposed to clients
883bool gSkForceRasterPipelineBlitter;
884
885bool SkBlitter::UseRasterPipelineBlitter(const SkPixmap& device, const SkPaint& paint,
886                                         const SkMatrix& matrix) {
887    if (gSkForceRasterPipelineBlitter) {
888        return true;
889    }
890    if (device.info().alphaType() == kUnpremul_SkAlphaType) {
891        return true;
892    }
893#if 0 || defined(SK_FORCE_RASTER_PIPELINE_BLITTER)
894    return true;
895#else
896    // By policy we choose not to handle legacy 8888 with SkRasterPipelineBlitter.
897    if (device.colorSpace()) {
898        return true;
899    }
900    if (paint.getColorFilter()) {
901        return true;
902    }
903    if (paint.getFilterQuality() == kHigh_SkFilterQuality) {
904        return true;
905    }
906    // ... unless the blend mode is complicated enough.
907    if (paint.getBlendMode() > SkBlendMode::kLastSeparableMode) {
908        return true;
909    }
910    if (matrix.hasPerspective()) {
911        return true;
912    }
913    // ... or unless the shader is raster pipeline-only.
914    if (paint.getShader() && as_SB(paint.getShader())->isRasterPipelineOnly(matrix)) {
915        return true;
916    }
917
918    // Added support only for shaders (and other constraints) for android
919    if (device.colorType() == kRGB_565_SkColorType) {
920        return false;
921    }
922
923    return device.colorType() != kN32_SkColorType;
924#endif
925}
926
927SkBlitter* SkBlitter::Choose(const SkPixmap& device,
928                             const SkMatrix& matrix,
929                             const SkPaint& origPaint,
930                             SkArenaAlloc* alloc,
931                             bool drawCoverage) {
932    SkASSERT(alloc != nullptr);
933
934    // which check, in case we're being called by a client with a dummy device
935    // (e.g. they have a bounder that always aborts the draw)
936    if (kUnknown_SkColorType == device.colorType() ||
937            (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
938        return alloc->make<SkNullBlitter>();
939    }
940
941    auto* shader = as_SB(origPaint.getShader());
942    SkColorFilter* cf = origPaint.getColorFilter();
943    SkBlendMode mode = origPaint.getBlendMode();
944    sk_sp<Sk3DShader> shader3D;
945
946    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
947
948    if (origPaint.getMaskFilter() != nullptr &&
949            as_MFB(origPaint.getMaskFilter())->getFormat() == SkMask::k3D_Format) {
950        shader3D = sk_make_sp<Sk3DShader>(sk_ref_sp(shader));
951        // we know we haven't initialized lazyPaint yet, so just do it
952        paint.writable()->setShader(shader3D);
953        shader = as_SB(shader3D.get());
954    }
955
956    if (mode != SkBlendMode::kSrcOver) {
957        bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType();
958        switch (SkInterpretXfermode(*paint, deviceIsOpaque)) {
959            case kSrcOver_SkXfermodeInterpretation:
960                mode = SkBlendMode::kSrcOver;
961                paint.writable()->setBlendMode(mode);
962                break;
963            case kSkipDrawing_SkXfermodeInterpretation:{
964                return alloc->make<SkNullBlitter>();
965            }
966            default:
967                break;
968        }
969    }
970
971    /*
972     *  If the xfermode is CLEAR, then we can completely ignore the installed
973     *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
974     *  will fall into our optimizations for SRC mode.
975     */
976    if (mode == SkBlendMode::kClear) {
977        SkPaint* p = paint.writable();
978        p->setShader(nullptr);
979        shader = nullptr;
980        p->setColorFilter(nullptr);
981        cf = nullptr;
982        p->setBlendMode(mode = SkBlendMode::kSrc);
983        p->setColor(0);
984    }
985
986    if (kAlpha_8_SkColorType == device.colorType() && drawCoverage) {
987        SkASSERT(nullptr == shader);
988        SkASSERT(paint->isSrcOver());
989        return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
990    }
991
992    if (paint->isDither() && !SkPaintPriv::ShouldDither(*paint, device.colorType())) {
993        // Disable dithering when not needed.
994        paint.writable()->setDither(false);
995    }
996
997    if (UseRasterPipelineBlitter(device, *paint, matrix)) {
998        auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
999        SkASSERT(blitter);
1000        return blitter;
1001    }
1002
1003    if (nullptr == shader) {
1004        if (mode != SkBlendMode::kSrcOver) {
1005            // xfermodes (and filters) require shaders for our current blitters
1006            paint.writable()->setShader(SkShader::MakeColorShader(paint->getColor()));
1007            paint.writable()->setAlpha(0xFF);
1008            shader = as_SB(paint->getShader());
1009        } else if (cf) {
1010            // if no shader && no xfermode, we just apply the colorfilter to
1011            // our color and move on.
1012            SkPaint* writablePaint = paint.writable();
1013            writablePaint->setColor(cf->filterColor(paint->getColor()));
1014            writablePaint->setColorFilter(nullptr);
1015            cf = nullptr;
1016        }
1017    }
1018
1019    if (cf) {
1020        SkASSERT(shader);
1021        paint.writable()->setShader(shader->makeWithColorFilter(sk_ref_sp(cf)));
1022        shader = as_SB(paint->getShader());
1023        // blitters should ignore the presence/absence of a filter, since
1024        // if there is one, the shader will take care of it.
1025    }
1026
1027    /*
1028     *  We create a SkShader::Context object, and store it on the blitter.
1029     */
1030    SkShaderBase::Context* shaderContext = nullptr;
1031    if (shader) {
1032        const SkShaderBase::ContextRec rec(*paint, matrix, nullptr,
1033                                       PreferredShaderDest(device.info()),
1034                                       device.colorSpace());
1035        // Try to create the ShaderContext
1036        shaderContext = shader->makeContext(rec, alloc);
1037        if (!shaderContext) {
1038            return alloc->make<SkNullBlitter>();
1039        }
1040        SkASSERT(shaderContext);
1041    }
1042
1043    SkBlitter*  blitter = nullptr;
1044    switch (device.colorType()) {
1045        case kN32_SkColorType:
1046            // sRGB and general color spaces are handled via raster pipeline.
1047            SkASSERT(!device.colorSpace());
1048
1049            if (shader) {
1050                blitter = alloc->make<SkARGB32_Shader_Blitter>(device, *paint, shaderContext);
1051            } else if (paint->getColor() == SK_ColorBLACK) {
1052                blitter = alloc->make<SkARGB32_Black_Blitter>(device, *paint);
1053            } else if (paint->getAlpha() == 0xFF) {
1054                blitter = alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
1055            } else {
1056                blitter = alloc->make<SkARGB32_Blitter>(device, *paint);
1057            }
1058            break;
1059        case kRGB_565_SkColorType:
1060            if (shader && SkRGB565_Shader_Blitter::Supports(device, *paint)) {
1061                blitter = alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext);
1062            } else {
1063                blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
1064            }
1065            break;
1066
1067        default:
1068            // should have been handled via raster pipeline.
1069            SkASSERT(false);
1070            break;
1071    }
1072
1073    if (!blitter) {
1074        blitter = alloc->make<SkNullBlitter>();
1075    }
1076
1077    if (shader3D) {
1078        SkBlitter* innerBlitter = blitter;
1079        // FIXME - comment about allocator
1080        // innerBlitter was allocated by allocator, which will delete it.
1081        // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to
1082        // wrapper the blitter to notify it when we see an emboss mask.
1083        blitter = alloc->make<Sk3DBlitter>(innerBlitter, shaderContext);
1084    }
1085    return blitter;
1086}
1087
1088///////////////////////////////////////////////////////////////////////////////
1089
1090SkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
1091                                 SkShaderBase::Context* shaderContext)
1092        : INHERITED(device)
1093        , fShader(paint.getShader())
1094        , fShaderContext(shaderContext) {
1095    SkASSERT(fShader);
1096    SkASSERT(fShaderContext);
1097
1098    fShader->ref();
1099    fShaderFlags = fShaderContext->getFlags();
1100    fConstInY = SkToBool(fShaderFlags & SkShaderBase::kConstInY32_Flag);
1101}
1102
1103SkShaderBlitter::~SkShaderBlitter() {
1104    fShader->unref();
1105}
1106
1107///////////////////////////////////////////////////////////////////////////////////////////////////
1108
1109#ifdef SK_DEBUG
1110
1111void SkRectClipCheckBlitter::blitH(int x, int y, int width) {
1112    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
1113    fBlitter->blitH(x, y, width);
1114}
1115
1116void SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
1117    const int16_t* iter = runs;
1118    for (; *iter; iter += *iter)
1119        ;
1120    int width = iter - runs;
1121    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
1122    fBlitter->blitAntiH(x, y, aa, runs);
1123}
1124
1125void SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
1126    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
1127    fBlitter->blitV(x, y, height, alpha);
1128}
1129
1130void SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
1131    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
1132    fBlitter->blitRect(x, y, width, height);
1133}
1134
1135void SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
1136                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
1137    bool skipLeft = !leftAlpha;
1138    bool skipRight = !rightAlpha;
1139    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x + skipLeft, y,
1140            width + 2 - skipRight - skipLeft, height)));
1141    fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
1142}
1143
1144void SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1145    SkASSERT(mask.fBounds.contains(clip));
1146    SkASSERT(fClipRect.contains(clip));
1147    fBlitter->blitMask(mask, clip);
1148}
1149
1150const SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
1151    return fBlitter->justAnOpaqueColor(value);
1152}
1153
1154void SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
1155    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1)));
1156    fBlitter->blitAntiH2(x, y, a0, a1);
1157}
1158
1159void SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
1160    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2)));
1161    fBlitter->blitAntiV2(x, y, a0, a1);
1162}
1163
1164#endif
1165