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