diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
commit | ae2c20f398933a9e86c387dcc465ec0f71065ffc (patch) | |
tree | de668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/sgl/SkBlitter.cpp | |
parent | 09911bf300f1a419907a9412154760efd0b7abc3 (diff) | |
download | chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2 |
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/sgl/SkBlitter.cpp')
-rw-r--r-- | skia/sgl/SkBlitter.cpp | 923 |
1 files changed, 923 insertions, 0 deletions
diff --git a/skia/sgl/SkBlitter.cpp b/skia/sgl/SkBlitter.cpp new file mode 100644 index 0000000..95a67c7 --- /dev/null +++ b/skia/sgl/SkBlitter.cpp @@ -0,0 +1,923 @@ +/* libs/graphics/sgl/SkBlitter.cpp +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkBlitter.h" +#include "SkAntiRun.h" +#include "SkColor.h" +#include "SkColorFilter.h" +#include "SkMask.h" +#include "SkMaskFilter.h" +#include "SkTemplatesPriv.h" +#include "SkUtils.h" +#include "SkXfermode.h" + +SkBlitter::~SkBlitter() +{ +} + +const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) +{ + return NULL; +} + +void SkBlitter::blitH(int x, int y, int width) +{ + SkASSERT(!"unimplemented"); +} + +void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) +{ + SkASSERT(!"unimplemented"); +} + +void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) +{ + if (alpha == 255) + this->blitRect(x, y, 1, height); + else + { + int16_t runs[2]; + runs[0] = 1; + runs[1] = 0; + + while (--height >= 0) + this->blitAntiH(x, y++, &alpha, runs); + } +} + +void SkBlitter::blitRect(int x, int y, int width, int height) +{ + while (--height >= 0) + this->blitH(x, y++, width); +} + +////////////////////////////////////////////////////////////////////////////// + +static inline void bits_to_runs(SkBlitter* blitter, int x, int y, const uint8_t bits[], + U8CPU left_mask, int rowBytes, U8CPU right_mask) +{ + int inFill = 0; + int pos = 0; + + while (--rowBytes >= 0) + { + unsigned b = *bits++ & left_mask; + if (rowBytes == 0) + b &= right_mask; + + for (unsigned test = 0x80; test != 0; test >>= 1) + { + if (b & test) + { + if (!inFill) + { + pos = x; + inFill = true; + } + } + else + { + if (inFill) + { + blitter->blitH(pos, y, x - pos); + inFill = false; + } + } + x += 1; + } + left_mask = 0xFF; + } + + // final cleanup + if (inFill) + blitter->blitH(pos, y, x - pos); +} + +void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) +{ + SkASSERT(mask.fBounds.contains(clip)); + + if (mask.fFormat == SkMask::kBW_Format) + { + int cx = clip.fLeft; + int cy = clip.fTop; + int maskLeft = mask.fBounds.fLeft; + int mask_rowBytes = mask.fRowBytes; + int height = clip.height(); + + const uint8_t* bits = mask.getAddr1(cx, cy); + + if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) + { + while (--height >= 0) + { + bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF); + bits += mask_rowBytes; + cy += 1; + } + } + else + { + int left_edge = cx - maskLeft; + SkASSERT(left_edge >= 0); + int rite_edge = clip.fRight - maskLeft; + SkASSERT(rite_edge > left_edge); + + int left_mask = 0xFF >> (left_edge & 7); + int rite_mask = 0xFF << (8 - (rite_edge & 7)); + int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3); + + // check for empty right mask, so we don't read off the end (or go slower than we need to) + if (rite_mask == 0) + { + SkASSERT(full_runs >= 0); + full_runs -= 1; + rite_mask = 0xFF; + } + if (left_mask == 0xFF) + full_runs -= 1; + + // back up manually so we can keep in sync with our byte-aligned src + // have cx reflect our actual starting x-coord + cx -= left_edge & 7; + + if (full_runs < 0) + { + SkASSERT((left_mask & rite_mask) != 0); + while (--height >= 0) + { + bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask); + bits += mask_rowBytes; + cy += 1; + } + } + else + { + while (--height >= 0) + { + bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask); + bits += mask_rowBytes; + cy += 1; + } + } + } + } + else + { + int width = clip.width(); + SkAutoSTMalloc<64, int16_t> runStorage(width + 1); + int16_t* runs = runStorage.get(); + const uint8_t* aa = mask.getAddr(clip.fLeft, clip.fTop); + + sk_memset16((uint16_t*)runs, 1, width); + runs[width] = 0; + + int height = clip.height(); + int y = clip.fTop; + while (--height >= 0) + { + this->blitAntiH(clip.fLeft, y, aa, runs); + aa += mask.fRowBytes; + y += 1; + } + } +} + +/////////////////////// these guys are not virtual, just a helpers + +void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) { + if (clip.quickReject(mask.fBounds)) { + return; + } + + SkRegion::Cliperator clipper(clip, mask.fBounds); + + while (!clipper.done()) { + const SkIRect& cr = clipper.rect(); + this->blitMask(mask, cr); + clipper.next(); + } +} + +void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) { + SkRegion::Cliperator clipper(clip, rect); + + while (!clipper.done()) { + const SkIRect& cr = clipper.rect(); + this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); + clipper.next(); + } +} + +void SkBlitter::blitRegion(const SkRegion& clip) { + SkRegion::Iterator iter(clip); + + while (!iter.done()) { + const SkIRect& cr = iter.rect(); + this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); + iter.next(); + } +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +void SkNullBlitter::blitH(int x, int y, int width) +{ +} + +void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) +{ +} + +void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) +{ +} + +void SkNullBlitter::blitRect(int x, int y, int width, int height) +{ +} + +void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) +{ +} + +const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) +{ + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +static int compute_anti_width(const int16_t runs[]) +{ + int width = 0; + + for (;;) + { + int count = runs[0]; + + SkASSERT(count >= 0); + if (count == 0) + break; + width += count; + runs += count; + + SkASSERT(width < 20000); + } + return width; +} + +static inline bool y_in_rect(int y, const SkIRect& rect) +{ + return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); +} + +static inline bool x_in_rect(int x, const SkIRect& rect) +{ + return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); +} + +void SkRectClipBlitter::blitH(int left, int y, int width) +{ + SkASSERT(width > 0); + + if (!y_in_rect(y, fClipRect)) + return; + + int right = left + width; + + if (left < fClipRect.fLeft) + left = fClipRect.fLeft; + if (right > fClipRect.fRight) + right = fClipRect.fRight; + + width = right - left; + if (width > 0) + fBlitter->blitH(left, y, width); +} + +void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], const int16_t runs[]) +{ + if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) + return; + + int x0 = left; + int x1 = left + compute_anti_width(runs); + + if (x1 <= fClipRect.fLeft) + return; + + SkASSERT(x0 < x1); + if (x0 < fClipRect.fLeft) + { + int dx = fClipRect.fLeft - x0; + SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx); + runs += dx; + aa += dx; + x0 = fClipRect.fLeft; + } + + SkASSERT(x0 < x1 && runs[x1 - x0] == 0); + if (x1 > fClipRect.fRight) + { + x1 = fClipRect.fRight; + SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0); + ((int16_t*)runs)[x1 - x0] = 0; + } + + SkASSERT(x0 < x1 && runs[x1 - x0] == 0); + SkASSERT(compute_anti_width(runs) == x1 - x0); + + fBlitter->blitAntiH(x0, y, aa, runs); +} + +void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) +{ + SkASSERT(height > 0); + + if (!x_in_rect(x, fClipRect)) + return; + + int y0 = y; + int y1 = y + height; + + if (y0 < fClipRect.fTop) + y0 = fClipRect.fTop; + if (y1 > fClipRect.fBottom) + y1 = fClipRect.fBottom; + + if (y0 < y1) + fBlitter->blitV(x, y0, y1 - y0, alpha); +} + +void SkRectClipBlitter::blitRect(int left, int y, int width, int height) +{ + SkIRect r; + + r.set(left, y, left + width, y + height); + if (r.intersect(fClipRect)) + fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); +} + +void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) +{ + SkASSERT(mask.fBounds.contains(clip)); + + SkIRect r = clip; + + if (r.intersect(fClipRect)) + fBlitter->blitMask(mask, r); +} + +const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) +{ + return fBlitter->justAnOpaqueColor(value); +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +void SkRgnClipBlitter::blitH(int x, int y, int width) +{ + SkRegion::Spanerator span(*fRgn, y, x, x + width); + int left, right; + + while (span.next(&left, &right)) + { + SkASSERT(left < right); + fBlitter->blitH(left, y, right - left); + } +} + +void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) +{ + int width = compute_anti_width(runs); + SkRegion::Spanerator span(*fRgn, y, x, x + width); + int left, right; + SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();) + + int prevRite = x; + while (span.next(&left, &right)) + { + SkASSERT(x <= left); + SkASSERT(left < right); + SkASSERT(left >= bounds.fLeft && right <= bounds.fRight); + + SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left); + + // now zero before left + if (left > prevRite) + { + int index = prevRite - x; + ((uint8_t*)aa)[index] = 0; // skip runs after right + ((int16_t*)runs)[index] = SkToS16(left - prevRite); + } + + prevRite = right; + } + + if (prevRite > x) + { + ((int16_t*)runs)[prevRite - x] = 0; + + if (x < 0) { + int skip = runs[0]; + SkASSERT(skip >= -x); + aa += skip; + runs += skip; + x += skip; + } + fBlitter->blitAntiH(x, y, aa, runs); + } +} + +void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) +{ + SkIRect bounds; + bounds.set(x, y, x + 1, y + height); + + SkRegion::Cliperator iter(*fRgn, bounds); + + while (!iter.done()) + { + const SkIRect& r = iter.rect(); + SkASSERT(bounds.contains(r)); + + fBlitter->blitV(x, r.fTop, r.height(), alpha); + iter.next(); + } +} + +void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) +{ + SkIRect bounds; + bounds.set(x, y, x + width, y + height); + + SkRegion::Cliperator iter(*fRgn, bounds); + + while (!iter.done()) + { + const SkIRect& r = iter.rect(); + SkASSERT(bounds.contains(r)); + + fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); + iter.next(); + } +} + +void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) +{ + SkASSERT(mask.fBounds.contains(clip)); + + SkRegion::Cliperator iter(*fRgn, clip); + const SkIRect& r = iter.rect(); + SkBlitter* blitter = fBlitter; + + while (!iter.done()) + { + blitter->blitMask(mask, r); + iter.next(); + } +} + +const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) +{ + return fBlitter->justAnOpaqueColor(value); +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, const SkIRect* ir) +{ + if (clip) + { + const SkIRect& clipR = clip->getBounds(); + + if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) + blitter = &fNullBlitter; + else if (clip->isRect()) + { + if (ir == NULL || !clipR.contains(*ir)) + { + fRectBlitter.init(blitter, clipR); + blitter = &fRectBlitter; + } + } + else + { + fRgnBlitter.init(blitter, clip); + blitter = &fRgnBlitter; + } + } + return blitter; +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +#include "SkColorShader.h" +#include "SkColorPriv.h" + +class Sk3DShader : public SkShader { +public: + Sk3DShader(SkShader* proxy) : fProxy(proxy) + { + proxy->safeRef(); + fMask = NULL; + } + virtual ~Sk3DShader() + { + fProxy->safeUnref(); + } + void setMask(const SkMask* mask) { fMask = mask; } + + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) + { + if (fProxy) + return fProxy->setContext(device, paint, matrix); + else + { + fPMColor = SkPreMultiplyColor(paint.getColor()); + return this->INHERITED::setContext(device, paint, matrix); + } + } + virtual void shadeSpan(int x, int y, SkPMColor span[], int count) + { + if (fProxy) + fProxy->shadeSpan(x, y, span, count); + + if (fMask == NULL) + { + if (fProxy == NULL) + sk_memset32(span, fPMColor, count); + return; + } + + SkASSERT(fMask->fBounds.contains(x, y)); + SkASSERT(fMask->fBounds.contains(x + count - 1, y)); + + size_t size = fMask->computeImageSize(); + const uint8_t* alpha = fMask->getAddr(x, y); + const uint8_t* mulp = alpha + size; + const uint8_t* addp = mulp + size; + + if (fProxy) + { + for (int i = 0; i < count; i++) + { + if (alpha[i]) + { + SkPMColor c = span[i]; + if (c) + { + unsigned a = SkGetPackedA32(c); + unsigned r = SkGetPackedR32(c); + unsigned g = SkGetPackedG32(c); + unsigned b = SkGetPackedB32(c); + + unsigned mul = SkAlpha255To256(mulp[i]); + unsigned add = addp[i]; + + r = SkFastMin32(SkAlphaMul(r, mul) + add, a); + g = SkFastMin32(SkAlphaMul(g, mul) + add, a); + b = SkFastMin32(SkAlphaMul(b, mul) + add, a); + + span[i] = SkPackARGB32(a, r, g, b); + } + } + else + span[i] = 0; + } + } + else // color + { + unsigned a = SkGetPackedA32(fPMColor); + unsigned r = SkGetPackedR32(fPMColor); + unsigned g = SkGetPackedG32(fPMColor); + unsigned b = SkGetPackedB32(fPMColor); + for (int i = 0; i < count; i++) + { + if (alpha[i]) + { + unsigned mul = SkAlpha255To256(mulp[i]); + unsigned add = addp[i]; + + span[i] = SkPackARGB32( a, + SkFastMin32(SkAlphaMul(r, mul) + add, a), + SkFastMin32(SkAlphaMul(g, mul) + add, a), + SkFastMin32(SkAlphaMul(b, mul) + add, a)); + } + else + span[i] = 0; + } + } + } + + virtual void beginSession() + { + this->INHERITED::beginSession(); + if (fProxy) + fProxy->beginSession(); + } + + virtual void endSession() + { + if (fProxy) + fProxy->endSession(); + this->INHERITED::endSession(); + } + +protected: + Sk3DShader(SkFlattenableReadBuffer& buffer) : + INHERITED(buffer) + { + fProxy = static_cast<SkShader*>(buffer.readFlattenable()); + fPMColor = buffer.readU32(); + fMask = NULL; + } + + virtual void flatten(SkFlattenableWriteBuffer& buffer) + { + this->INHERITED::flatten(buffer); + buffer.writeFlattenable(fProxy); + buffer.write32(fPMColor); + } + + virtual Factory getFactory() + { + return CreateProc; + } + +private: + static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) + { + return SkNEW_ARGS(Sk3DShader, (buffer)); + } + + SkShader* fProxy; + SkPMColor fPMColor; + const SkMask* fMask; + + typedef SkShader INHERITED; +}; + +class Sk3DBlitter : public SkBlitter { +public: + Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*)) + : fProxy(proxy), f3DShader(shader), fKillProc(killProc) + { + shader->ref(); + } + virtual ~Sk3DBlitter() + { + f3DShader->unref(); + fKillProc(fProxy); + } + + virtual void blitH(int x, int y, int width) + { + fProxy->blitH(x, y, width); + } + virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) + { + fProxy->blitAntiH(x, y, antialias, runs); + } + virtual void blitV(int x, int y, int height, SkAlpha alpha) + { + fProxy->blitV(x, y, height, alpha); + } + virtual void blitRect(int x, int y, int width, int height) + { + fProxy->blitRect(x, y, width, height); + } + virtual void blitMask(const SkMask& mask, const SkIRect& clip) + { + if (mask.fFormat == SkMask::k3D_Format) + { + f3DShader->setMask(&mask); + + ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; + fProxy->blitMask(mask, clip); + ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; + + f3DShader->setMask(NULL); + } + else + fProxy->blitMask(mask, clip); + } +private: + SkBlitter* fProxy; + Sk3DShader* f3DShader; + void (*fKillProc)(void*); +}; + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +#include "SkCoreBlitters.h" + +class SkAutoRestoreShader { +public: + SkAutoRestoreShader(const SkPaint& p) : fPaint((SkPaint*)&p) + { + fShader = fPaint->getShader(); + fShader->safeRef(); + } + ~SkAutoRestoreShader() + { + fPaint->setShader(fShader); + fShader->safeUnref(); + } +private: + SkPaint* fPaint; + SkShader* fShader; +}; + +class SkAutoCallProc { +public: + typedef void (*Proc)(void*); + SkAutoCallProc(void* obj, Proc proc) + : fObj(obj), fProc(proc) + { + } + ~SkAutoCallProc() + { + if (fObj && fProc) + fProc(fObj); + } + void* get() const { return fObj; } + void* detach() + { + void* obj = fObj; + fObj = NULL; + return obj; + } +private: + void* fObj; + Proc fProc; +}; + +static void destroy_blitter(void* blitter) +{ + ((SkBlitter*)blitter)->~SkBlitter(); +} + +static void delete_blitter(void* blitter) +{ + SkDELETE((SkBlitter*)blitter); +} + +SkBlitter* SkBlitter::Choose(const SkBitmap& device, + const SkMatrix& matrix, + const SkPaint& paint, + void* storage, size_t storageSize) +{ + SkASSERT(storageSize == 0 || storage != NULL); + + SkBlitter* blitter = NULL; + + // which check, in case we're being called by a client with a dummy device + // (e.g. they have a bounder that always aborts the draw) + if (SkBitmap::kNo_Config == device.getConfig()) + { + SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); + return blitter; + } + + SkAutoRestoreShader restore(paint); + SkShader* shader = paint.getShader(); + + Sk3DShader* shader3D = NULL; + if (paint.getMaskFilter() != NULL && paint.getMaskFilter()->getFormat() == SkMask::k3D_Format) + { + shader3D = SkNEW_ARGS(Sk3DShader, (shader)); + ((SkPaint*)&paint)->setShader(shader3D)->unref(); + shader = shader3D; + } + + SkXfermode* mode = paint.getXfermode(); + if (NULL == shader && (NULL != mode || paint.getColorFilter() != NULL)) + { + // xfermodes require shaders for our current set of blitters + shader = SkNEW(SkColorShader); + ((SkPaint*)&paint)->setShader(shader)->unref(); + } + + if (paint.getColorFilter() != NULL) + { + SkASSERT(shader); + shader = SkNEW_ARGS(SkFilterShader, (shader, paint.getColorFilter())); + ((SkPaint*)&paint)->setShader(shader)->unref(); + } + + bool doDither = paint.isDither(); + + if (shader) + { + if (!shader->setContext(device, paint, matrix)) + return SkNEW(SkNullBlitter); + + // disable dither if our shader is natively 16bit (no need to upsample) + if (shader->getFlags() & SkShader::kIntrinsicly16_Flag) + doDither = false; + } + + switch (device.getConfig()) { + case SkBitmap::kA1_Config: + SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter, storage, storageSize, (device, paint)); + break; + + case SkBitmap::kA8_Config: + if (shader) + SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter, storage, storageSize, (device, paint)); + else + SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter, storage, storageSize, (device, paint)); + break; + + case SkBitmap::kARGB_4444_Config: + blitter = SkBlitter_ChooseD4444(device, paint, storage, storageSize); + break; + + case SkBitmap::kRGB_565_Config: + if (shader) + { + if (mode) + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter, storage, storageSize, (device, paint)); + else if (SkShader::CanCallShadeSpan16(shader->getFlags()) && !doDither) + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, storage, storageSize, (device, paint)); + else + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, storage, storageSize, (device, paint)); + } + else if (paint.getColor() == SK_ColorBLACK) + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage, storageSize, (device, paint)); + else + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage, storageSize, (device, paint)); + break; + + case SkBitmap::kARGB_8888_Config: + if (shader) + SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter, storage, storageSize, (device, paint)); + else if (paint.getColor() == SK_ColorBLACK) + SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter, storage, storageSize, (device, paint)); + else if (paint.getAlpha() == 0xFF) + SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter, storage, storageSize, (device, paint)); + else + SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter, storage, storageSize, (device, paint)); + break; + + default: + SkASSERT(!"unsupported device config"); + SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); + } + + if (shader3D) + { + void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter; + SkAutoCallProc tmp(blitter, proc); + + blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc)); + (void)tmp.detach(); + } + return blitter; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +const uint16_t gMask_0F0F = 0xF0F; +const uint32_t gMask_00FF00FF = 0xFF00FF; + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint) + : INHERITED(device) +{ + fShader = paint.getShader(); + SkASSERT(fShader); + + fShader->ref(); + fShader->beginSession(); +} + +SkShaderBlitter::~SkShaderBlitter() +{ + fShader->endSession(); + fShader->unref(); +} + |