blob: faf29c171213b6f677187551cea1856e8d1a80f5 [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
reed@android.com845fdac2009-06-23 03:01:32 +000028SkBlitter::~SkBlitter() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +000029
30const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value)
31{
32 return NULL;
33}
34
35void SkBlitter::blitH(int x, int y, int width)
36{
37 SkASSERT(!"unimplemented");
38}
39
40void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
41{
42 SkASSERT(!"unimplemented");
43}
44
45void 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
60void 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
68static 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
108void 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
200void 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
214void 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
224void 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
237void SkNullBlitter::blitH(int x, int y, int width)
238{
239}
240
241void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
242{
243}
244
245void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha)
246{
247}
248
249void SkNullBlitter::blitRect(int x, int y, int width, int height)
250{
251}
252
253void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
254{
255}
256
257const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value)
258{
259 return NULL;
260}
261
262///////////////////////////////////////////////////////////////////////////////////////
263///////////////////////////////////////////////////////////////////////////////////////
264
265static 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
284static inline bool y_in_rect(int y, const SkIRect& rect)
285{
286 return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
287}
288
289static inline bool x_in_rect(int x, const SkIRect& rect)
290{
291 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
292}
293
294void 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
313void 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
348void 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
367void 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
376void 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
386const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value)
387{
388 return fBlitter->justAnOpaqueColor(value);
389}
390
391///////////////////////////////////////////////////////////////////////////////////////
392///////////////////////////////////////////////////////////////////////////////////////
393
394void 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
406void 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
448void 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
465void 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
482void 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
497const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value)
498{
499 return fBlitter->justAnOpaqueColor(value);
500}
501
502///////////////////////////////////////////////////////////////////////////////////////
503///////////////////////////////////////////////////////////////////////////////////////
504
505SkBlitter* 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
536class Sk3DShader : public SkShader {
537public:
538 Sk3DShader(SkShader* proxy) : fProxy(proxy)
539 {
540 proxy->safeRef();
541 fMask = NULL;
542 }
543 virtual ~Sk3DShader()
544 {
545 fProxy->safeUnref();
546 }
547 void setMask(const SkMask* mask) { fMask = mask; }
548
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 }
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
631 virtual void beginSession()
632 {
633 this->INHERITED::beginSession();
634 if (fProxy)
635 fProxy->beginSession();
636 }
637
638 virtual void endSession()
639 {
640 if (fProxy)
641 fProxy->endSession();
642 this->INHERITED::endSession();
643 }
644
645protected:
646 Sk3DShader(SkFlattenableReadBuffer& buffer) :
647 INHERITED(buffer)
648 {
649 fProxy = static_cast<SkShader*>(buffer.readFlattenable());
650 fPMColor = buffer.readU32();
651 fMask = NULL;
652 }
653
654 virtual void flatten(SkFlattenableWriteBuffer& buffer)
655 {
656 this->INHERITED::flatten(buffer);
657 buffer.writeFlattenable(fProxy);
658 buffer.write32(fPMColor);
659 }
660
661 virtual Factory getFactory()
662 {
663 return CreateProc;
664 }
665
666private:
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
679class Sk3DBlitter : public SkBlitter {
680public:
681 Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
682 : fProxy(proxy), f3DShader(shader), fKillProc(killProc)
683 {
684 shader->ref();
685 }
686 virtual ~Sk3DBlitter()
687 {
688 f3DShader->unref();
689 fKillProc(fProxy);
690 }
691
692 virtual void blitH(int x, int y, int width)
693 {
694 fProxy->blitH(x, y, width);
695 }
696 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
697 {
698 fProxy->blitAntiH(x, y, antialias, runs);
699 }
700 virtual void blitV(int x, int y, int height, SkAlpha alpha)
701 {
702 fProxy->blitV(x, y, height, alpha);
703 }
704 virtual void blitRect(int x, int y, int width, int height)
705 {
706 fProxy->blitRect(x, y, width, height);
707 }
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 }
723private:
724 SkBlitter* fProxy;
725 Sk3DShader* f3DShader;
726 void (*fKillProc)(void*);
727};
728
729///////////////////////////////////////////////////////////////////////////////////////
730///////////////////////////////////////////////////////////////////////////////////////
731
732#include "SkCoreBlitters.h"
733
734class SkAutoRestoreShader {
735public:
736 SkAutoRestoreShader(const SkPaint& p) : fPaint((SkPaint*)&p)
737 {
738 fShader = fPaint->getShader();
739 fShader->safeRef();
740 }
741 ~SkAutoRestoreShader()
742 {
743 fPaint->setShader(fShader);
744 fShader->safeUnref();
745 }
746private:
747 SkPaint* fPaint;
748 SkShader* fShader;
749};
750
751class SkAutoCallProc {
752public:
753 typedef void (*Proc)(void*);
754 SkAutoCallProc(void* obj, Proc proc)
755 : fObj(obj), fProc(proc)
756 {
757 }
758 ~SkAutoCallProc()
759 {
760 if (fObj && fProc)
761 fProc(fObj);
762 }
763 void* get() const { return fObj; }
764 void* detach()
765 {
766 void* obj = fObj;
767 fObj = NULL;
768 return obj;
769 }
770private:
771 void* fObj;
772 Proc fProc;
773};
774
775static void destroy_blitter(void* blitter)
776{
777 ((SkBlitter*)blitter)->~SkBlitter();
778}
779
780static void delete_blitter(void* blitter)
781{
782 SkDELETE((SkBlitter*)blitter);
783}
784
reed@android.comd252db02009-04-01 18:31:44 +0000785static 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 */
799enum 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
805static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
806 SkBitmap::Config deviceConfig) {
reed@android.com845fdac2009-06-23 03:01:32 +0000807 SkXfermode::Mode mode;
reed@android.comd252db02009-04-01 18:31:44 +0000808
reed@android.com845fdac2009-06-23 03:01:32 +0000809 if (SkXfermode::IsMode(xfer, &mode)) {
reed@android.comd252db02009-04-01 18:31:44 +0000810 switch (mode) {
reed@android.com845fdac2009-06-23 03:01:32 +0000811 case SkXfermode::kSrc_Mode:
reed@android.comd252db02009-04-01 18:31:44 +0000812 if (just_solid_color(paint)) {
813 return kSrcOver_XferInterp;
814 }
815 break;
reed@android.com845fdac2009-06-23 03:01:32 +0000816 case SkXfermode::kDst_Mode:
reed@android.comd252db02009-04-01 18:31:44 +0000817 return kSkipDrawing_XferInterp;
reed@android.com845fdac2009-06-23 03:01:32 +0000818 case SkXfermode::kSrcOver_Mode:
reed@android.comd252db02009-04-01 18:31:44 +0000819 return kSrcOver_XferInterp;
reed@android.com845fdac2009-06-23 03:01:32 +0000820 case SkXfermode::kDstOver_Mode:
reed@android.comd252db02009-04-01 18:31:44 +0000821 if (SkBitmap::kRGB_565_Config == deviceConfig) {
822 return kSkipDrawing_XferInterp;
823 }
824 break;
reed@android.com845fdac2009-06-23 03:01:32 +0000825 case SkXfermode::kSrcIn_Mode:
reed@android.comd252db02009-04-01 18:31:44 +0000826 if (SkBitmap::kRGB_565_Config == deviceConfig &&
827 just_solid_color(paint)) {
828 return kSrcOver_XferInterp;
829 }
830 break;
reed@android.com845fdac2009-06-23 03:01:32 +0000831 case SkXfermode::kDstIn_Mode:
reed@android.comd252db02009-04-01 18:31:44 +0000832 if (just_solid_color(paint)) {
833 return kSkipDrawing_XferInterp;
834 }
835 break;
836 default:
837 break;
838 }
839 }
840 return kNormal_XferInterp;
841}
842
reed@android.com8a1c16f2008-12-17 15:59:43 +0000843SkBlitter* 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();
reed@android.comd252db02009-04-01 18:31:44 +0000872 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
reed@android.com8a1c16f2008-12-17 15:59:43 +0000885 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 bool doDither = paint.isDither();
900
901 if (shader)
902 {
903 if (!shader->setContext(device, paint, matrix))
904 return SkNEW(SkNullBlitter);
905
906 // disable dither if our shader is natively 16bit (no need to upsample)
907 if (shader->getFlags() & SkShader::kIntrinsicly16_Flag)
908 doDither = false;
909 }
910
911 switch (device.getConfig()) {
912 case SkBitmap::kA1_Config:
913 SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter, storage, storageSize, (device, paint));
914 break;
915
916 case SkBitmap::kA8_Config:
917 if (shader)
918 SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter, storage, storageSize, (device, paint));
919 else
920 SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter, storage, storageSize, (device, paint));
921 break;
922
923 case SkBitmap::kARGB_4444_Config:
924 blitter = SkBlitter_ChooseD4444(device, paint, storage, storageSize);
925 break;
926
927 case SkBitmap::kRGB_565_Config:
928 if (shader)
929 {
930 if (mode)
931 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter, storage, storageSize, (device, paint));
932 else if (SkShader::CanCallShadeSpan16(shader->getFlags()) && !doDither)
933 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, storage, storageSize, (device, paint));
934 else
935 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, storage, storageSize, (device, paint));
reed@android.com9a74d312009-06-15 15:56:35 +0000936 } else {
937 SkColor color = paint.getColor();
938 if (0 == SkColorGetA(color)) {
939 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
940 } else if (SK_ColorBLACK == color) {
941 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage,
942 storageSize, (device, paint));
943 } else if (0xFF == SkColorGetA(color)) {
944 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage,
945 storageSize, (device, paint));
946 } else {
947 SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage,
948 storageSize, (device, paint));
949 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000950 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000951 break;
952
953 case SkBitmap::kARGB_8888_Config:
954 if (shader)
955 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter, storage, storageSize, (device, paint));
956 else if (paint.getColor() == SK_ColorBLACK)
957 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter, storage, storageSize, (device, paint));
958 else if (paint.getAlpha() == 0xFF)
959 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter, storage, storageSize, (device, paint));
960 else
961 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter, storage, storageSize, (device, paint));
962 break;
963
964 default:
965 SkASSERT(!"unsupported device config");
966 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
967 }
968
969 if (shader3D)
970 {
971 void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
972 SkAutoCallProc tmp(blitter, proc);
973
974 blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
975 (void)tmp.detach();
976 }
977 return blitter;
978}
979
980//////////////////////////////////////////////////////////////////////////////////////////////////////
981
982const uint16_t gMask_0F0F = 0xF0F;
983const uint32_t gMask_00FF00FF = 0xFF00FF;
984
985//////////////////////////////////////////////////////////////////////////////////////////////////////
986
987SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
reed@android.com5119bdb2009-06-12 21:27:03 +0000988 : INHERITED(device) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000989 fShader = paint.getShader();
990 SkASSERT(fShader);
991
992 fShader->ref();
993 fShader->beginSession();
reed@android.com5119bdb2009-06-12 21:27:03 +0000994 fShaderFlags = fShader->getFlags();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000995}
996
reed@android.com5119bdb2009-06-12 21:27:03 +0000997SkShaderBlitter::~SkShaderBlitter() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998 fShader->endSession();
999 fShader->unref();
1000}
1001