1 /* libs/graphics/sgl/SkBlitter.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkBlitter.h"
19 #include "SkAntiRun.h"
20 #include "SkColor.h"
21 #include "SkColorFilter.h"
22 #include "SkMask.h"
23 #include "SkMaskFilter.h"
24 #include "SkTemplatesPriv.h"
25 #include "SkUtils.h"
26 #include "SkXfermode.h"
27
~SkBlitter()28 SkBlitter::~SkBlitter() {}
29
justAnOpaqueColor(uint32_t * value)30 const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value)
31 {
32 return NULL;
33 }
34
blitH(int x,int y,int width)35 void SkBlitter::blitH(int x, int y, int width)
36 {
37 SkASSERT(!"unimplemented");
38 }
39
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])40 void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
41 {
42 SkASSERT(!"unimplemented");
43 }
44
blitV(int x,int y,int height,SkAlpha alpha)45 void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha)
46 {
47 if (alpha == 255)
48 this->blitRect(x, y, 1, height);
49 else
50 {
51 int16_t runs[2];
52 runs[0] = 1;
53 runs[1] = 0;
54
55 while (--height >= 0)
56 this->blitAntiH(x, y++, &alpha, runs);
57 }
58 }
59
blitRect(int x,int y,int width,int height)60 void SkBlitter::blitRect(int x, int y, int width, int height)
61 {
62 while (--height >= 0)
63 this->blitH(x, y++, width);
64 }
65
66 //////////////////////////////////////////////////////////////////////////////
67
bits_to_runs(SkBlitter * blitter,int x,int y,const uint8_t bits[],U8CPU left_mask,int rowBytes,U8CPU right_mask)68 static inline void bits_to_runs(SkBlitter* blitter, int x, int y, const uint8_t bits[],
69 U8CPU left_mask, int rowBytes, U8CPU right_mask)
70 {
71 int inFill = 0;
72 int pos = 0;
73
74 while (--rowBytes >= 0)
75 {
76 unsigned b = *bits++ & left_mask;
77 if (rowBytes == 0)
78 b &= right_mask;
79
80 for (unsigned test = 0x80; test != 0; test >>= 1)
81 {
82 if (b & test)
83 {
84 if (!inFill)
85 {
86 pos = x;
87 inFill = true;
88 }
89 }
90 else
91 {
92 if (inFill)
93 {
94 blitter->blitH(pos, y, x - pos);
95 inFill = false;
96 }
97 }
98 x += 1;
99 }
100 left_mask = 0xFF;
101 }
102
103 // final cleanup
104 if (inFill)
105 blitter->blitH(pos, y, x - pos);
106 }
107
blitMask(const SkMask & mask,const SkIRect & clip)108 void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
109 {
110 SkASSERT(mask.fBounds.contains(clip));
111
112 if (mask.fFormat == SkMask::kBW_Format)
113 {
114 int cx = clip.fLeft;
115 int cy = clip.fTop;
116 int maskLeft = mask.fBounds.fLeft;
117 int mask_rowBytes = mask.fRowBytes;
118 int height = clip.height();
119
120 const uint8_t* bits = mask.getAddr1(cx, cy);
121
122 if (cx == maskLeft && clip.fRight == mask.fBounds.fRight)
123 {
124 while (--height >= 0)
125 {
126 bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
127 bits += mask_rowBytes;
128 cy += 1;
129 }
130 }
131 else
132 {
133 int left_edge = cx - maskLeft;
134 SkASSERT(left_edge >= 0);
135 int rite_edge = clip.fRight - maskLeft;
136 SkASSERT(rite_edge > left_edge);
137
138 int left_mask = 0xFF >> (left_edge & 7);
139 int rite_mask = 0xFF << (8 - (rite_edge & 7));
140 int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
141
142 // check for empty right mask, so we don't read off the end (or go slower than we need to)
143 if (rite_mask == 0)
144 {
145 SkASSERT(full_runs >= 0);
146 full_runs -= 1;
147 rite_mask = 0xFF;
148 }
149 if (left_mask == 0xFF)
150 full_runs -= 1;
151
152 // back up manually so we can keep in sync with our byte-aligned src
153 // have cx reflect our actual starting x-coord
154 cx -= left_edge & 7;
155
156 if (full_runs < 0)
157 {
158 SkASSERT((left_mask & rite_mask) != 0);
159 while (--height >= 0)
160 {
161 bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
162 bits += mask_rowBytes;
163 cy += 1;
164 }
165 }
166 else
167 {
168 while (--height >= 0)
169 {
170 bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
171 bits += mask_rowBytes;
172 cy += 1;
173 }
174 }
175 }
176 }
177 else
178 {
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.getAddr(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 {
191 this->blitAntiH(clip.fLeft, y, aa, runs);
192 aa += mask.fRowBytes;
193 y += 1;
194 }
195 }
196 }
197
198 /////////////////////// these guys are not virtual, just a helpers
199
blitMaskRegion(const SkMask & mask,const SkRegion & clip)200 void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
201 if (clip.quickReject(mask.fBounds)) {
202 return;
203 }
204
205 SkRegion::Cliperator clipper(clip, mask.fBounds);
206
207 while (!clipper.done()) {
208 const SkIRect& cr = clipper.rect();
209 this->blitMask(mask, cr);
210 clipper.next();
211 }
212 }
213
blitRectRegion(const SkIRect & rect,const SkRegion & clip)214 void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
215 SkRegion::Cliperator clipper(clip, rect);
216
217 while (!clipper.done()) {
218 const SkIRect& cr = clipper.rect();
219 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
220 clipper.next();
221 }
222 }
223
blitRegion(const SkRegion & clip)224 void SkBlitter::blitRegion(const SkRegion& clip) {
225 SkRegion::Iterator iter(clip);
226
227 while (!iter.done()) {
228 const SkIRect& cr = iter.rect();
229 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
230 iter.next();
231 }
232 }
233
234 ///////////////////////////////////////////////////////////////////////////////////////
235 ///////////////////////////////////////////////////////////////////////////////////////
236
blitH(int x,int y,int width)237 void SkNullBlitter::blitH(int x, int y, int width)
238 {
239 }
240
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])241 void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
242 {
243 }
244
blitV(int x,int y,int height,SkAlpha alpha)245 void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha)
246 {
247 }
248
blitRect(int x,int y,int width,int height)249 void SkNullBlitter::blitRect(int x, int y, int width, int height)
250 {
251 }
252
blitMask(const SkMask & mask,const SkIRect & clip)253 void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
254 {
255 }
256
justAnOpaqueColor(uint32_t * value)257 const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value)
258 {
259 return NULL;
260 }
261
262 ///////////////////////////////////////////////////////////////////////////////////////
263 ///////////////////////////////////////////////////////////////////////////////////////
264
compute_anti_width(const int16_t runs[])265 static int compute_anti_width(const int16_t runs[])
266 {
267 int width = 0;
268
269 for (;;)
270 {
271 int count = runs[0];
272
273 SkASSERT(count >= 0);
274 if (count == 0)
275 break;
276 width += count;
277 runs += count;
278
279 SkASSERT(width < 20000);
280 }
281 return width;
282 }
283
y_in_rect(int y,const SkIRect & rect)284 static inline bool y_in_rect(int y, const SkIRect& rect)
285 {
286 return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
287 }
288
x_in_rect(int x,const SkIRect & rect)289 static inline bool x_in_rect(int x, const SkIRect& rect)
290 {
291 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
292 }
293
blitH(int left,int y,int width)294 void SkRectClipBlitter::blitH(int left, int y, int width)
295 {
296 SkASSERT(width > 0);
297
298 if (!y_in_rect(y, fClipRect))
299 return;
300
301 int right = left + width;
302
303 if (left < fClipRect.fLeft)
304 left = fClipRect.fLeft;
305 if (right > fClipRect.fRight)
306 right = fClipRect.fRight;
307
308 width = right - left;
309 if (width > 0)
310 fBlitter->blitH(left, y, width);
311 }
312
blitAntiH(int left,int y,const SkAlpha aa[],const int16_t runs[])313 void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], const int16_t runs[])
314 {
315 if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight)
316 return;
317
318 int x0 = left;
319 int x1 = left + compute_anti_width(runs);
320
321 if (x1 <= fClipRect.fLeft)
322 return;
323
324 SkASSERT(x0 < x1);
325 if (x0 < fClipRect.fLeft)
326 {
327 int dx = fClipRect.fLeft - x0;
328 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
329 runs += dx;
330 aa += dx;
331 x0 = fClipRect.fLeft;
332 }
333
334 SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
335 if (x1 > fClipRect.fRight)
336 {
337 x1 = fClipRect.fRight;
338 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
339 ((int16_t*)runs)[x1 - x0] = 0;
340 }
341
342 SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
343 SkASSERT(compute_anti_width(runs) == x1 - x0);
344
345 fBlitter->blitAntiH(x0, y, aa, runs);
346 }
347
blitV(int x,int y,int height,SkAlpha alpha)348 void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha)
349 {
350 SkASSERT(height > 0);
351
352 if (!x_in_rect(x, fClipRect))
353 return;
354
355 int y0 = y;
356 int y1 = y + height;
357
358 if (y0 < fClipRect.fTop)
359 y0 = fClipRect.fTop;
360 if (y1 > fClipRect.fBottom)
361 y1 = fClipRect.fBottom;
362
363 if (y0 < y1)
364 fBlitter->blitV(x, y0, y1 - y0, alpha);
365 }
366
blitRect(int left,int y,int width,int height)367 void SkRectClipBlitter::blitRect(int left, int y, int width, int height)
368 {
369 SkIRect r;
370
371 r.set(left, y, left + width, y + height);
372 if (r.intersect(fClipRect))
373 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
374 }
375
blitMask(const SkMask & mask,const SkIRect & clip)376 void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
377 {
378 SkASSERT(mask.fBounds.contains(clip));
379
380 SkIRect r = clip;
381
382 if (r.intersect(fClipRect))
383 fBlitter->blitMask(mask, r);
384 }
385
justAnOpaqueColor(uint32_t * value)386 const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value)
387 {
388 return fBlitter->justAnOpaqueColor(value);
389 }
390
391 ///////////////////////////////////////////////////////////////////////////////////////
392 ///////////////////////////////////////////////////////////////////////////////////////
393
blitH(int x,int y,int width)394 void SkRgnClipBlitter::blitH(int x, int y, int width)
395 {
396 SkRegion::Spanerator span(*fRgn, y, x, x + width);
397 int left, right;
398
399 while (span.next(&left, &right))
400 {
401 SkASSERT(left < right);
402 fBlitter->blitH(left, y, right - left);
403 }
404 }
405
blitAntiH(int x,int y,const SkAlpha aa[],const int16_t runs[])406 void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[])
407 {
408 int width = compute_anti_width(runs);
409 SkRegion::Spanerator span(*fRgn, y, x, x + width);
410 int left, right;
411 SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
412
413 int prevRite = x;
414 while (span.next(&left, &right))
415 {
416 SkASSERT(x <= left);
417 SkASSERT(left < right);
418 SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
419
420 SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
421
422 // now zero before left
423 if (left > prevRite)
424 {
425 int index = prevRite - x;
426 ((uint8_t*)aa)[index] = 0; // skip runs after right
427 ((int16_t*)runs)[index] = SkToS16(left - prevRite);
428 }
429
430 prevRite = right;
431 }
432
433 if (prevRite > x)
434 {
435 ((int16_t*)runs)[prevRite - x] = 0;
436
437 if (x < 0) {
438 int skip = runs[0];
439 SkASSERT(skip >= -x);
440 aa += skip;
441 runs += skip;
442 x += skip;
443 }
444 fBlitter->blitAntiH(x, y, aa, runs);
445 }
446 }
447
blitV(int x,int y,int height,SkAlpha alpha)448 void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha)
449 {
450 SkIRect bounds;
451 bounds.set(x, y, x + 1, y + height);
452
453 SkRegion::Cliperator iter(*fRgn, bounds);
454
455 while (!iter.done())
456 {
457 const SkIRect& r = iter.rect();
458 SkASSERT(bounds.contains(r));
459
460 fBlitter->blitV(x, r.fTop, r.height(), alpha);
461 iter.next();
462 }
463 }
464
blitRect(int x,int y,int width,int height)465 void SkRgnClipBlitter::blitRect(int x, int y, int width, int height)
466 {
467 SkIRect bounds;
468 bounds.set(x, y, x + width, y + height);
469
470 SkRegion::Cliperator iter(*fRgn, bounds);
471
472 while (!iter.done())
473 {
474 const SkIRect& r = iter.rect();
475 SkASSERT(bounds.contains(r));
476
477 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
478 iter.next();
479 }
480 }
481
blitMask(const SkMask & mask,const SkIRect & clip)482 void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
483 {
484 SkASSERT(mask.fBounds.contains(clip));
485
486 SkRegion::Cliperator iter(*fRgn, clip);
487 const SkIRect& r = iter.rect();
488 SkBlitter* blitter = fBlitter;
489
490 while (!iter.done())
491 {
492 blitter->blitMask(mask, r);
493 iter.next();
494 }
495 }
496
justAnOpaqueColor(uint32_t * value)497 const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value)
498 {
499 return fBlitter->justAnOpaqueColor(value);
500 }
501
502 ///////////////////////////////////////////////////////////////////////////////////////
503 ///////////////////////////////////////////////////////////////////////////////////////
504
apply(SkBlitter * blitter,const SkRegion * clip,const SkIRect * ir)505 SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, const SkIRect* ir)
506 {
507 if (clip)
508 {
509 const SkIRect& clipR = clip->getBounds();
510
511 if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir)))
512 blitter = &fNullBlitter;
513 else if (clip->isRect())
514 {
515 if (ir == NULL || !clipR.contains(*ir))
516 {
517 fRectBlitter.init(blitter, clipR);
518 blitter = &fRectBlitter;
519 }
520 }
521 else
522 {
523 fRgnBlitter.init(blitter, clip);
524 blitter = &fRgnBlitter;
525 }
526 }
527 return blitter;
528 }
529
530 ///////////////////////////////////////////////////////////////////////////////////////
531 ///////////////////////////////////////////////////////////////////////////////////////
532
533 #include "SkColorShader.h"
534 #include "SkColorPriv.h"
535
536 class Sk3DShader : public SkShader {
537 public:
Sk3DShader(SkShader * proxy)538 Sk3DShader(SkShader* proxy) : fProxy(proxy)
539 {
540 proxy->safeRef();
541 fMask = NULL;
542 }
~Sk3DShader()543 virtual ~Sk3DShader()
544 {
545 fProxy->safeUnref();
546 }
setMask(const SkMask * mask)547 void setMask(const SkMask* mask) { fMask = mask; }
548
setContext(const SkBitmap & device,const SkPaint & paint,const SkMatrix & matrix)549 virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
550 {
551 if (fProxy)
552 return fProxy->setContext(device, paint, matrix);
553 else
554 {
555 fPMColor = SkPreMultiplyColor(paint.getColor());
556 return this->INHERITED::setContext(device, paint, matrix);
557 }
558 }
shadeSpan(int x,int y,SkPMColor span[],int count)559 virtual void shadeSpan(int x, int y, SkPMColor span[], int count)
560 {
561 if (fProxy)
562 fProxy->shadeSpan(x, y, span, count);
563
564 if (fMask == NULL)
565 {
566 if (fProxy == NULL)
567 sk_memset32(span, fPMColor, count);
568 return;
569 }
570
571 SkASSERT(fMask->fBounds.contains(x, y));
572 SkASSERT(fMask->fBounds.contains(x + count - 1, y));
573
574 size_t size = fMask->computeImageSize();
575 const uint8_t* alpha = fMask->getAddr(x, y);
576 const uint8_t* mulp = alpha + size;
577 const uint8_t* addp = mulp + size;
578
579 if (fProxy)
580 {
581 for (int i = 0; i < count; i++)
582 {
583 if (alpha[i])
584 {
585 SkPMColor c = span[i];
586 if (c)
587 {
588 unsigned a = SkGetPackedA32(c);
589 unsigned r = SkGetPackedR32(c);
590 unsigned g = SkGetPackedG32(c);
591 unsigned b = SkGetPackedB32(c);
592
593 unsigned mul = SkAlpha255To256(mulp[i]);
594 unsigned add = addp[i];
595
596 r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
597 g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
598 b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
599
600 span[i] = SkPackARGB32(a, r, g, b);
601 }
602 }
603 else
604 span[i] = 0;
605 }
606 }
607 else // color
608 {
609 unsigned a = SkGetPackedA32(fPMColor);
610 unsigned r = SkGetPackedR32(fPMColor);
611 unsigned g = SkGetPackedG32(fPMColor);
612 unsigned b = SkGetPackedB32(fPMColor);
613 for (int i = 0; i < count; i++)
614 {
615 if (alpha[i])
616 {
617 unsigned mul = SkAlpha255To256(mulp[i]);
618 unsigned add = addp[i];
619
620 span[i] = SkPackARGB32( a,
621 SkFastMin32(SkAlphaMul(r, mul) + add, a),
622 SkFastMin32(SkAlphaMul(g, mul) + add, a),
623 SkFastMin32(SkAlphaMul(b, mul) + add, a));
624 }
625 else
626 span[i] = 0;
627 }
628 }
629 }
630
beginSession()631 virtual void beginSession()
632 {
633 this->INHERITED::beginSession();
634 if (fProxy)
635 fProxy->beginSession();
636 }
637
endSession()638 virtual void endSession()
639 {
640 if (fProxy)
641 fProxy->endSession();
642 this->INHERITED::endSession();
643 }
644
645 protected:
Sk3DShader(SkFlattenableReadBuffer & buffer)646 Sk3DShader(SkFlattenableReadBuffer& buffer) :
647 INHERITED(buffer)
648 {
649 fProxy = static_cast<SkShader*>(buffer.readFlattenable());
650 fPMColor = buffer.readU32();
651 fMask = NULL;
652 }
653
flatten(SkFlattenableWriteBuffer & buffer)654 virtual void flatten(SkFlattenableWriteBuffer& buffer)
655 {
656 this->INHERITED::flatten(buffer);
657 buffer.writeFlattenable(fProxy);
658 buffer.write32(fPMColor);
659 }
660
getFactory()661 virtual Factory getFactory()
662 {
663 return CreateProc;
664 }
665
666 private:
CreateProc(SkFlattenableReadBuffer & buffer)667 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
668 {
669 return SkNEW_ARGS(Sk3DShader, (buffer));
670 }
671
672 SkShader* fProxy;
673 SkPMColor fPMColor;
674 const SkMask* fMask;
675
676 typedef SkShader INHERITED;
677 };
678
679 class Sk3DBlitter : public SkBlitter {
680 public:
Sk3DBlitter(SkBlitter * proxy,Sk3DShader * shader,void (* killProc)(void *))681 Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
682 : fProxy(proxy), f3DShader(shader), fKillProc(killProc)
683 {
684 shader->ref();
685 }
~Sk3DBlitter()686 virtual ~Sk3DBlitter()
687 {
688 f3DShader->unref();
689 fKillProc(fProxy);
690 }
691
blitH(int x,int y,int width)692 virtual void blitH(int x, int y, int width)
693 {
694 fProxy->blitH(x, y, width);
695 }
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])696 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
697 {
698 fProxy->blitAntiH(x, y, antialias, runs);
699 }
blitV(int x,int y,int height,SkAlpha alpha)700 virtual void blitV(int x, int y, int height, SkAlpha alpha)
701 {
702 fProxy->blitV(x, y, height, alpha);
703 }
blitRect(int x,int y,int width,int height)704 virtual void blitRect(int x, int y, int width, int height)
705 {
706 fProxy->blitRect(x, y, width, height);
707 }
blitMask(const SkMask & mask,const SkIRect & clip)708 virtual void blitMask(const SkMask& mask, const SkIRect& clip)
709 {
710 if (mask.fFormat == SkMask::k3D_Format)
711 {
712 f3DShader->setMask(&mask);
713
714 ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
715 fProxy->blitMask(mask, clip);
716 ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
717
718 f3DShader->setMask(NULL);
719 }
720 else
721 fProxy->blitMask(mask, clip);
722 }
723 private:
724 SkBlitter* fProxy;
725 Sk3DShader* f3DShader;
726 void (*fKillProc)(void*);
727 };
728
729 ///////////////////////////////////////////////////////////////////////////////////////
730 ///////////////////////////////////////////////////////////////////////////////////////
731
732 #include "SkCoreBlitters.h"
733
734 class SkAutoRestoreShader {
735 public:
SkAutoRestoreShader(const SkPaint & p)736 SkAutoRestoreShader(const SkPaint& p) : fPaint((SkPaint*)&p)
737 {
738 fShader = fPaint->getShader();
739 fShader->safeRef();
740 }
~SkAutoRestoreShader()741 ~SkAutoRestoreShader()
742 {
743 fPaint->setShader(fShader);
744 fShader->safeUnref();
745 }
746 private:
747 SkPaint* fPaint;
748 SkShader* fShader;
749 };
750
751 class SkAutoCallProc {
752 public:
753 typedef void (*Proc)(void*);
SkAutoCallProc(void * obj,Proc proc)754 SkAutoCallProc(void* obj, Proc proc)
755 : fObj(obj), fProc(proc)
756 {
757 }
~SkAutoCallProc()758 ~SkAutoCallProc()
759 {
760 if (fObj && fProc)
761 fProc(fObj);
762 }
get() const763 void* get() const { return fObj; }
detach()764 void* detach()
765 {
766 void* obj = fObj;
767 fObj = NULL;
768 return obj;
769 }
770 private:
771 void* fObj;
772 Proc fProc;
773 };
774
destroy_blitter(void * blitter)775 static void destroy_blitter(void* blitter)
776 {
777 ((SkBlitter*)blitter)->~SkBlitter();
778 }
779
delete_blitter(void * blitter)780 static void delete_blitter(void* blitter)
781 {
782 SkDELETE((SkBlitter*)blitter);
783 }
784
just_solid_color(const SkPaint & paint)785 static bool just_solid_color(const SkPaint& paint) {
786 if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
787 SkShader* shader = paint.getShader();
788 if (NULL == shader ||
789 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
790 return true;
791 }
792 }
793 return false;
794 }
795
796 /** By analyzing the paint (with an xfermode), we may decide we can take
797 special action. This enum lists our possible actions
798 */
799 enum XferInterp {
800 kNormal_XferInterp, // no special interpretation, draw normally
801 kSrcOver_XferInterp, // draw as if in srcover mode
802 kSkipDrawing_XferInterp // draw nothing
803 };
804
interpret_xfermode(const SkPaint & paint,SkXfermode * xfer,SkBitmap::Config deviceConfig)805 static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
806 SkBitmap::Config deviceConfig) {
807 SkXfermode::Mode mode;
808
809 if (SkXfermode::IsMode(xfer, &mode)) {
810 switch (mode) {
811 case SkXfermode::kSrc_Mode:
812 if (just_solid_color(paint)) {
813 return kSrcOver_XferInterp;
814 }
815 break;
816 case SkXfermode::kDst_Mode:
817 return kSkipDrawing_XferInterp;
818 case SkXfermode::kSrcOver_Mode:
819 return kSrcOver_XferInterp;
820 case SkXfermode::kDstOver_Mode:
821 if (SkBitmap::kRGB_565_Config == deviceConfig) {
822 return kSkipDrawing_XferInterp;
823 }
824 break;
825 case SkXfermode::kSrcIn_Mode:
826 if (SkBitmap::kRGB_565_Config == deviceConfig &&
827 just_solid_color(paint)) {
828 return kSrcOver_XferInterp;
829 }
830 break;
831 case SkXfermode::kDstIn_Mode:
832 if (just_solid_color(paint)) {
833 return kSkipDrawing_XferInterp;
834 }
835 break;
836 default:
837 break;
838 }
839 }
840 return kNormal_XferInterp;
841 }
842
Choose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint,void * storage,size_t storageSize)843 SkBlitter* SkBlitter::Choose(const SkBitmap& device,
844 const SkMatrix& matrix,
845 const SkPaint& paint,
846 void* storage, size_t storageSize)
847 {
848 SkASSERT(storageSize == 0 || storage != NULL);
849
850 SkBlitter* blitter = NULL;
851
852 // which check, in case we're being called by a client with a dummy device
853 // (e.g. they have a bounder that always aborts the draw)
854 if (SkBitmap::kNo_Config == device.getConfig())
855 {
856 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
857 return blitter;
858 }
859
860 SkAutoRestoreShader restore(paint);
861 SkShader* shader = paint.getShader();
862
863 Sk3DShader* shader3D = NULL;
864 if (paint.getMaskFilter() != NULL && paint.getMaskFilter()->getFormat() == SkMask::k3D_Format)
865 {
866 shader3D = SkNEW_ARGS(Sk3DShader, (shader));
867 ((SkPaint*)&paint)->setShader(shader3D)->unref();
868 shader = shader3D;
869 }
870
871 SkXfermode* mode = paint.getXfermode();
872 if (NULL != mode) {
873 switch (interpret_xfermode(paint, mode, device.config())) {
874 case kSrcOver_XferInterp:
875 mode = NULL;
876 break;
877 case kSkipDrawing_XferInterp:
878 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
879 return blitter;
880 default:
881 break;
882 }
883 }
884
885 if (NULL == shader && (NULL != mode || paint.getColorFilter() != NULL))
886 {
887 // xfermodes require shaders for our current set of blitters
888 shader = SkNEW(SkColorShader);
889 ((SkPaint*)&paint)->setShader(shader)->unref();
890 }
891
892 if (paint.getColorFilter() != NULL)
893 {
894 SkASSERT(shader);
895 shader = SkNEW_ARGS(SkFilterShader, (shader, paint.getColorFilter()));
896 ((SkPaint*)&paint)->setShader(shader)->unref();
897 }
898
899 if (shader && !shader->setContext(device, paint, matrix)) {
900 return SkNEW(SkNullBlitter);
901 }
902
903 switch (device.getConfig()) {
904 case SkBitmap::kA1_Config:
905 SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter, storage, storageSize, (device, paint));
906 break;
907
908 case SkBitmap::kA8_Config:
909 if (shader)
910 SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter, storage, storageSize, (device, paint));
911 else
912 SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter, storage, storageSize, (device, paint));
913 break;
914
915 case SkBitmap::kARGB_4444_Config:
916 blitter = SkBlitter_ChooseD4444(device, paint, storage, storageSize);
917 break;
918
919 case SkBitmap::kRGB_565_Config:
920 if (shader)
921 {
922 if (mode)
923 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter, storage, storageSize, (device, paint));
924 else if (shader->canCallShadeSpan16())
925 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, storage, storageSize, (device, paint));
926 else
927 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, storage, storageSize, (device, paint));
928 } else {
929 SkColor color = paint.getColor();
930 if (0 == SkColorGetA(color)) {
931 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
932 } else if (SK_ColorBLACK == color) {
933 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage,
934 storageSize, (device, paint));
935 } else if (0xFF == SkColorGetA(color)) {
936 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage,
937 storageSize, (device, paint));
938 } else {
939 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage,
940 storageSize, (device, paint));
941 }
942 }
943 break;
944
945 case SkBitmap::kARGB_8888_Config:
946 if (shader)
947 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter, storage, storageSize, (device, paint));
948 else if (paint.getColor() == SK_ColorBLACK)
949 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter, storage, storageSize, (device, paint));
950 else if (paint.getAlpha() == 0xFF)
951 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter, storage, storageSize, (device, paint));
952 else
953 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter, storage, storageSize, (device, paint));
954 break;
955
956 default:
957 SkASSERT(!"unsupported device config");
958 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
959 }
960
961 if (shader3D)
962 {
963 void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
964 SkAutoCallProc tmp(blitter, proc);
965
966 blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
967 (void)tmp.detach();
968 }
969 return blitter;
970 }
971
972 //////////////////////////////////////////////////////////////////////////////////////////////////////
973
974 const uint16_t gMask_0F0F = 0xF0F;
975 const uint32_t gMask_00FF00FF = 0xFF00FF;
976
977 //////////////////////////////////////////////////////////////////////////////////////////////////////
978
SkShaderBlitter(const SkBitmap & device,const SkPaint & paint)979 SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
980 : INHERITED(device) {
981 fShader = paint.getShader();
982 SkASSERT(fShader);
983
984 fShader->ref();
985 fShader->beginSession();
986 fShaderFlags = fShader->getFlags();
987 }
988
~SkShaderBlitter()989 SkShaderBlitter::~SkShaderBlitter() {
990 fShader->endSession();
991 fShader->unref();
992 }
993
994