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