LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkBlitter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 177 564 31.4 %
Date: 2017-07-14 16:53:18 Functions: 23 73 31.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13