180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBlitter.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkAntiRun.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColor.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorFilter.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFilterShader.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFlattenableBuffers.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMask.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMaskFilter.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplatesPriv.h"
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTLazy.h"
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h"
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkXfermode.h"
22d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "SkString.h"
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBlitter::~SkBlitter() {}
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkBlitter::isNullBlitter() const { return false; }
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitH(int x, int y, int width) {
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGFAIL("unimplemented");
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          const int16_t runs[]) {
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGFAIL("unimplemented");
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (alpha == 255) {
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->blitRect(x, y, 1, height);
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int16_t runs[2];
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        runs[0] = 1;
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        runs[1] = 0;
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (--height >= 0) {
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->blitAntiH(x, y++, &alpha, runs);
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitRect(int x, int y, int width, int height) {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(width > 0);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--height >= 0) {
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->blitH(x, y++, width);
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/// Default implementation doesn't check for any easy optimizations
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/// such as alpha == 0 or 255; also uses blitV(), which some subclasses
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/// may not support.
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitAntiRect(int x, int y, int width, int height,
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             SkAlpha leftAlpha, SkAlpha rightAlpha) {
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->blitV(x++, y, height, leftAlpha);
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (width > 0) {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->blitRect(x, y, width, height);
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x += width;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->blitV(x, y, height, rightAlpha);
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void bits_to_runs(SkBlitter* blitter, int x, int y,
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                const uint8_t bits[],
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                U8CPU left_mask, int rowBytes,
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                U8CPU right_mask) {
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int inFill = 0;
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int pos = 0;
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--rowBytes >= 0) {
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned b = *bits++ & left_mask;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (rowBytes == 0) {
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            b &= right_mask;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (unsigned test = 0x80; test != 0; test >>= 1) {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (b & test) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (!inFill) {
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    pos = x;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    inFill = true;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (inFill) {
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    blitter->blitH(pos, y, x - pos);
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    inFill = false;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x += 1;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        left_mask = 0xFF;
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // final cleanup
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (inFill) {
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter->blitH(pos, y, x - pos);
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(mask.fBounds.contains(clip));
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (mask.fFormat == SkMask::kBW_Format) {
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int cx = clip.fLeft;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int cy = clip.fTop;
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int maskLeft = mask.fBounds.fLeft;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int mask_rowBytes = mask.fRowBytes;
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int height = clip.height();
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t* bits = mask.getAddr1(cx, cy);
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            while (--height >= 0) {
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                bits += mask_rowBytes;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                cy += 1;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int left_edge = cx - maskLeft;
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(left_edge >= 0);
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int rite_edge = clip.fRight - maskLeft;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(rite_edge > left_edge);
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int left_mask = 0xFF >> (left_edge & 7);
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int rite_mask = 0xFF << (8 - (rite_edge & 7));
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // check for empty right mask, so we don't read off the end (or go slower than we need to)
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (rite_mask == 0) {
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(full_runs >= 0);
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                full_runs -= 1;
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                rite_mask = 0xFF;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (left_mask == 0xFF) {
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                full_runs -= 1;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // back up manually so we can keep in sync with our byte-aligned src
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // have cx reflect our actual starting x-coord
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            cx -= left_edge & 7;
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (full_runs < 0) {
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT((left_mask & rite_mask) != 0);
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                while (--height >= 0) {
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    bits += mask_rowBytes;
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    cy += 1;
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                while (--height >= 0) {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    bits += mask_rowBytes;
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    cy += 1;
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int                         width = clip.width();
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int16_t*                    runs = runStorage.get();
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_memset16((uint16_t*)runs, 1, width);
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        runs[width] = 0;
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int height = clip.height();
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int y = clip.fTop;
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (--height >= 0) {
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->blitAntiH(clip.fLeft, y, aa, runs);
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            aa += mask.fRowBytes;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            y += 1;
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////// these guys are not virtual, just a helpers
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip.quickReject(mask.fBounds)) {
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator clipper(clip, mask.fBounds);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!clipper.done()) {
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& cr = clipper.rect();
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->blitMask(mask, cr);
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clipper.next();
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator clipper(clip, rect);
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!clipper.done()) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& cr = clipper.rect();
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        clipper.next();
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBlitter::blitRegion(const SkRegion& clip) {
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Iterator iter(clip);
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!iter.done()) {
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& cr = iter.rect();
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        iter.next();
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkNullBlitter::blitH(int x, int y, int width) {}
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const int16_t runs[]) {}
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {}
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
242363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkNullBlitter::isNullBlitter() const { return true; }
243363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int compute_anti_width(const int16_t runs[]) {
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int width = 0;
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;) {
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int count = runs[0];
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(count >= 0);
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (count == 0) {
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        width += count;
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        runs += count;
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return width;
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool y_in_rect(int y, const SkIRect& rect) {
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool x_in_rect(int x, const SkIRect& rect) {
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRectClipBlitter::blitH(int left, int y, int width) {
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(width > 0);
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!y_in_rect(y, fClipRect)) {
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int right = left + width;
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (left < fClipRect.fLeft) {
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        left = fClipRect.fLeft;
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (right > fClipRect.fRight) {
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        right = fClipRect.fRight;
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    width = right - left;
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (width > 0) {
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitH(left, y, width);
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  const int16_t runs[]) {
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int x0 = left;
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int x1 = left + compute_anti_width(runs);
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (x1 <= fClipRect.fLeft) {
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(x0 < x1);
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (x0 < fClipRect.fLeft) {
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int dx = fClipRect.fLeft - x0;
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        runs += dx;
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        aa += dx;
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x0 = fClipRect.fLeft;
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (x1 > fClipRect.fRight) {
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x1 = fClipRect.fRight;
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ((int16_t*)runs)[x1 - x0] = 0;
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(compute_anti_width(runs) == x1 - x0);
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBlitter->blitAntiH(x0, y, aa, runs);
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(height > 0);
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!x_in_rect(x, fClipRect)) {
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int y0 = y;
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int y1 = y + height;
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (y0 < fClipRect.fTop) {
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y0 = fClipRect.fTop;
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (y1 > fClipRect.fBottom) {
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y1 = fClipRect.fBottom;
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (y0 < y1) {
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitV(x, y0, y1 - y0, alpha);
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect    r;
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    r.set(left, y, left + width, y + height);
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (r.intersect(fClipRect)) {
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect    r;
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The *true* width of the rectangle blitted is width+2:
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    r.set(left, y, left + width + 2, y + height);
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (r.intersect(fClipRect)) {
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (r.fLeft != left) {
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(r.fLeft > left);
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            leftAlpha = 255;
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (r.fRight != left + width + 2) {
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(r.fRight < left + width + 2);
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            rightAlpha = 255;
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (255 == leftAlpha && 255 == rightAlpha) {
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (1 == r.width()) {
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (r.fLeft == left) {
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(r.fLeft == left + width + 1);
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   leftAlpha, rightAlpha);
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(mask.fBounds.contains(clip));
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect    r = clip;
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (r.intersect(fClipRect)) {
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitMask(mask, r);
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fBlitter->justAnOpaqueColor(value);
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRgnClipBlitter::blitH(int x, int y, int width) {
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Spanerator span(*fRgn, y, x, x + width);
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int left, right;
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (span.next(&left, &right)) {
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(left < right);
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitH(left, y, right - left);
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 const int16_t runs[]) {
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int width = compute_anti_width(runs);
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Spanerator span(*fRgn, y, x, x + width);
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int left, right;
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int prevRite = x;
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (span.next(&left, &right)) {
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(x <= left);
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(left < right);
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // now zero before left
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (left > prevRite) {
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int index = prevRite - x;
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ((uint8_t*)aa)[index] = 0;   // skip runs after right
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prevRite = right;
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (prevRite > x) {
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ((int16_t*)runs)[prevRite - x] = 0;
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (x < 0) {
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int skip = runs[0];
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(skip >= -x);
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            aa += skip;
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            runs += skip;
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x += skip;
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitAntiH(x, y, aa, runs);
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect    bounds;
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bounds.set(x, y, x + 1, y + height);
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator    iter(*fRgn, bounds);
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!iter.done()) {
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& r = iter.rect();
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(bounds.contains(r));
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitV(x, r.fTop, r.height(), alpha);
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        iter.next();
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect    bounds;
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bounds.set(x, y, x + width, y + height);
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator    iter(*fRgn, bounds);
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!iter.done()) {
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& r = iter.rect();
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(bounds.contains(r));
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        iter.next();
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkAlpha leftAlpha, SkAlpha rightAlpha) {
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The *true* width of the rectangle to blit is width + 2
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIRect    bounds;
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bounds.set(x, y, x + width + 2, y + height);
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator    iter(*fRgn, bounds);
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!iter.done()) {
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& r = iter.rect();
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(bounds.contains(r));
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(r.fLeft >= x);
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(r.fRight <= x + width + 2);
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      rightAlpha : 255;
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (1 == r.width()) {
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (r.fLeft == x) {
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                effectiveLeftAlpha);
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(r.fLeft == x + width + 1);
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                effectiveRightAlpha);
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   effectiveLeftAlpha, effectiveRightAlpha);
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        iter.next();
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(mask.fBounds.contains(clip));
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator iter(*fRgn, clip);
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkIRect&       r = iter.rect();
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBlitter*           blitter = fBlitter;
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!iter.done()) {
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter->blitMask(mask, r);
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        iter.next();
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fBlitter->justAnOpaqueColor(value);
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const SkIRect* ir) {
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (clip) {
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& clipR = clip->getBounds();
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter = &fNullBlitter;
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (clip->isRect()) {
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ir == NULL || !clipR.contains(*ir)) {
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fRectBlitter.init(blitter, clipR);
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                blitter = &fRectBlitter;
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRgnBlitter.init(blitter, clip);
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter = &fRgnBlitter;
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return blitter;
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorShader.h"
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass Sk3DShader : public SkShader {
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk3DShader(SkShader* proxy) : fProxy(proxy) {
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSafeRef(proxy);
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMask = NULL;
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual ~Sk3DShader() {
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSafeUnref(fProxy);
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void setMask(const SkMask* mask) { fMask = mask; }
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
580363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            const SkMatrix& matrix) SK_OVERRIDE {
581363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (!this->INHERITED::setContext(device, paint, matrix)) {
582363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return false;
583363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fProxy) {
585363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (!fProxy->setContext(device, paint, matrix)) {
586363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // must keep our set/end context calls balanced
587363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                this->INHERITED::endContext();
588363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return false;
589363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fPMColor = SkPreMultiplyColor(paint.getColor());
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
593363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
594363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
595363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
596363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void endContext() SK_OVERRIDE {
597363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (fProxy) {
598363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fProxy->endContext();
599363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
600363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->INHERITED::endContext();
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
603363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fProxy) {
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fProxy->shadeSpan(x, y, span, count);
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fMask == NULL) {
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fProxy == NULL) {
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                sk_memset32(span, fPMColor, count);
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return;
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fMask->fBounds.contains(x, y));
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fMask->fBounds.contains(x + count - 1, y));
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t          size = fMask->computeImageSize();
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t*  alpha = fMask->getAddr8(x, y);
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t*  mulp = alpha + size;
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t*  addp = mulp + size;
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fProxy) {
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < count; i++) {
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (alpha[i]) {
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor c = span[i];
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (c) {
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        unsigned a = SkGetPackedA32(c);
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        unsigned r = SkGetPackedR32(c);
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        unsigned g = SkGetPackedG32(c);
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        unsigned b = SkGetPackedB32(c);
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        unsigned mul = SkAlpha255To256(mulp[i]);
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        unsigned add = addp[i];
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        span[i] = SkPackARGB32(a, r, g, b);
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    span[i] = 0;
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {    // color
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = SkGetPackedA32(fPMColor);
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned r = SkGetPackedR32(fPMColor);
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned g = SkGetPackedG32(fPMColor);
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned b = SkGetPackedB32(fPMColor);
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < count; i++) {
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (alpha[i]) {
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    unsigned mul = SkAlpha255To256(mulp[i]);
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    unsigned add = addp[i];
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    span[i] = SkPackARGB32( a,
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkFastMin32(SkAlphaMul(r, mul) + add, a),
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkFastMin32(SkAlphaMul(g, mul) + add, a),
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkFastMin32(SkAlphaMul(b, mul) + add, a));
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    span[i] = 0;
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
667d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
668d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    virtual void toString(SkString* str) const SK_OVERRIDE {
669d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        str->append("Sk3DShader: (");
670d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
671d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (NULL != fProxy) {
672d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            str->append("Proxy: ");
673d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            fProxy->toString(str);
674d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
675d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
676d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->INHERITED::toString(str);
677d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
678d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        str->append(")");
679d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
680d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
681d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected:
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk3DShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fProxy = buffer.readFlattenableT<SkShader>();
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPMColor = buffer.readColor();
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMask = NULL;
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->INHERITED::flatten(buffer);
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.writeFlattenable(fProxy);
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.writeColor(fPMColor);
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkShader*       fProxy;
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPMColor       fPMColor;
70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkMask*   fMask;
70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkShader INHERITED;
70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass Sk3DBlitter : public SkBlitter {
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            : fProxy(proxy), f3DShader(shader), fKillProc(killProc) {
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shader->ref();
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual ~Sk3DBlitter() {
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        f3DShader->unref();
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fKillProc(fProxy);
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitH(int x, int y, int width) {
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fProxy->blitH(x, y, width);
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const int16_t runs[]) {
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fProxy->blitAntiH(x, y, antialias, runs);
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitV(int x, int y, int height, SkAlpha alpha) {
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fProxy->blitV(x, y, height, alpha);
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitRect(int x, int y, int width, int height) {
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fProxy->blitRect(x, y, width, height);
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (mask.fFormat == SkMask::k3D_Format) {
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            f3DShader->setMask(&mask);
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fProxy->blitMask(mask, clip);
74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            f3DShader->setMask(NULL);
74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fProxy->blitMask(mask, clip);
74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBlitter*  fProxy;
75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk3DShader* f3DShader;
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void        (*fKillProc)(void*);
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkCoreBlitters.h"
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkAutoCallProc {
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef void (*Proc)(void*);
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoCallProc(void* obj, Proc proc)
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fObj(obj), fProc(proc) {}
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkAutoCallProc() {
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fObj && fProc) {
76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fProc(fObj);
76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* get() const { return fObj; }
77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* detach() {
77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void* obj = fObj;
77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fObj = NULL;
77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return obj;
77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void*   fObj;
78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Proc    fProc;
78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
78380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void destroy_blitter(void* blitter) {
78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkBlitter*)blitter)->~SkBlitter();
78680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
78780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void delete_blitter(void* blitter) {
78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDELETE((SkBlitter*)blitter);
79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool just_solid_color(const SkPaint& paint) {
79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkShader* shader = paint.getShader();
79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == shader ||
79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** By analyzing the paint (with an xfermode), we may decide we can take
80480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    special action. This enum lists our possible actions
80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruenum XferInterp {
80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kNormal_XferInterp,         // no special interpretation, draw normally
80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kSrcOver_XferInterp,        // draw as if in srcover mode
80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    kSkipDrawing_XferInterp     // draw nothing
81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     SkBitmap::Config deviceConfig) {
81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode::Mode  mode;
81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkXfermode::AsMode(xfer, &mode)) {
81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (mode) {
81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkXfermode::kSrc_Mode:
81980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (just_solid_color(paint)) {
82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return kSrcOver_XferInterp;
82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkXfermode::kDst_Mode:
82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return kSkipDrawing_XferInterp;
82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkXfermode::kSrcOver_Mode:
82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return kSrcOver_XferInterp;
82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkXfermode::kDstOver_Mode:
82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (SkBitmap::kRGB_565_Config == deviceConfig) {
82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return kSkipDrawing_XferInterp;
83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkXfermode::kSrcIn_Mode:
83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (SkBitmap::kRGB_565_Config == deviceConfig &&
83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    just_solid_color(paint)) {
83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return kSrcOver_XferInterp;
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkXfermode::kDstIn_Mode:
83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (just_solid_color(paint)) {
84080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return kSkipDrawing_XferInterp;
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return kNormal_XferInterp;
84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBlitter* SkBlitter::Choose(const SkBitmap& device,
85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkMatrix& matrix,
85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkPaint& origPaint,
85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             void* storage, size_t storageSize) {
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(storageSize == 0 || storage != NULL);
85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBlitter*  blitter = NULL;
85780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // which check, in case we're being called by a client with a dummy device
85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // (e.g. they have a bounder that always aborts the draw)
86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkBitmap::kNo_Config == device.getConfig()) {
86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return blitter;
86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkShader* shader = origPaint.getShader();
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkColorFilter* cf = origPaint.getColorFilter();
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode* mode = origPaint.getXfermode();
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk3DShader* shader3D = NULL;
86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (origPaint.getMaskFilter() != NULL &&
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shader3D = SkNEW_ARGS(Sk3DShader, (shader));
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // we know we haven't initialized lazyPaint yet, so just do it
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.writable()->setShader(shader3D)->unref();
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shader = shader3D;
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != mode) {
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (interpret_xfermode(*paint, mode, device.config())) {
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kSrcOver_XferInterp:
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                mode = NULL;
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                paint.writable()->setXfermode(NULL);
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kSkipDrawing_XferInterp:
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return blitter;
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
894363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /*
895363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  If the xfermode is CLEAR, then we can completely ignore the installed
896363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
897363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  will fall into our optimizations for SRC mode.
898363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
899363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
900363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkPaint* p = paint.writable();
901363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        shader = p->setShader(NULL);
902363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        cf = p->setColorFilter(NULL);
903363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
904363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        p->setColor(0);
905363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
906363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == shader) {
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (mode) {
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // xfermodes (and filters) require shaders for our current blitters
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            shader = SkNEW(SkColorShader);
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            paint.writable()->setShader(shader)->unref();
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (cf) {
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // if no shader && no xfermode, we just apply the colorfilter to
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // our color and move on.
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkPaint* writablePaint = paint.writable();
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            writablePaint->setColor(cf->filterColor(paint->getColor()));
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            writablePaint->setColorFilter(NULL);
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            cf = NULL;
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (cf) {
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(shader);
92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        paint.writable()->setShader(shader)->unref();
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // blitters should ignore the presence/absence of a filter, since
92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // if there is one, the shader will take care of it.
92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
930363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /*
931363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  We need to have balanced calls to the shader:
932363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *      setContext
933363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *      endContext
934363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  We make the first call here, in case it fails we can abort the draw.
935363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  The endContext() call is made by the blitter (assuming setContext did
936363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  not fail) in its destructor.
937363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
93880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (shader && !shader->setContext(device, *paint, matrix)) {
939363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
940363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return blitter;
94180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (device.getConfig()) {
94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kA1_Config:
94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter,
94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                  storage, storageSize, (device, *paint));
94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kA8_Config:
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (shader) {
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter,
95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      storage, storageSize, (device, *paint));
95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter,
95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      storage, storageSize, (device, *paint));
95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_4444_Config:
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter = SkBlitter_ChooseD4444(device, *paint, storage, storageSize);
96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kRGB_565_Config:
96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter = SkBlitter_ChooseD565(device, *paint, storage, storageSize);
96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_8888_Config:
96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (shader) {
96980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter,
97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      storage, storageSize, (device, *paint));
97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (paint->getColor() == SK_ColorBLACK) {
97280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter,
97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      storage, storageSize, (device, *paint));
97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (paint->getAlpha() == 0xFF) {
97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter,
97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      storage, storageSize, (device, *paint));
97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter,
97980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      storage, storageSize, (device, *paint));
98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
98180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDEBUGFAIL("unsupported device config");
98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (shader3D) {
99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAutoCallProc  tmp(blitter, proc);
99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (void)tmp.detach();
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return blitter;
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst uint16_t gMask_0F0F = 0xF0F;
100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst uint32_t gMask_00FF00FF = 0xFF00FF;
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : INHERITED(device) {
100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fShader = paint.getShader();
100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fShader);
1010363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(fShader->setContextHasBeenCalled());
101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fShader->ref();
101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fShaderFlags = fShader->getFlags();
101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShaderBlitter::~SkShaderBlitter() {
1017363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(fShader->setContextHasBeenCalled());
1018363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fShader->endContext();
101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fShader->unref();
102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1021