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