diff options
Diffstat (limited to 'src/core/SkBlitter_ARGB32.cpp')
-rw-r--r-- | src/core/SkBlitter_ARGB32.cpp | 325 |
1 files changed, 77 insertions, 248 deletions
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp index dec355a..24ab330 100644 --- a/src/core/SkBlitter_ARGB32.cpp +++ b/src/core/SkBlitter_ARGB32.cpp @@ -1,116 +1,19 @@ -/* libs/graphics/sgl/SkBlitter_ARGB32.cpp -** -** Copyright 2006, The Android Open Source Project -** -** 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. -*/ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ #include "SkCoreBlitters.h" #include "SkColorPriv.h" #include "SkShader.h" #include "SkUtils.h" #include "SkXfermode.h" - -#if defined(SK_SUPPORT_LCDTEXT) -namespace skia_blitter_support { -// subpixel helper functions from SkBlitter_ARGB32_Subpixel.cpp -uint32_t* adjustForSubpixelClip(const SkMask& mask, - const SkIRect& clip, const SkBitmap& device, - int* widthAdjustment, int* heightAdjustment, - const uint32_t** alpha32); -extern uint32_t BlendLCDPixelWithColor(const uint32_t alphaPixel, const uint32_t originalPixel, - const uint32_t sourcePixel); -extern uint32_t BlendLCDPixelWithOpaqueColor(const uint32_t alphaPixel, const uint32_t originalPixel, - const uint32_t sourcePixel); -extern uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t originalPixel); -} - -using namespace skia_blitter_support; -#endif +#include "SkBlitMask.h" /////////////////////////////////////////////////////////////////////////////// -static inline int upscale31To32(int value) { - SkASSERT((unsigned)value <= 31); - return value + (value >> 4); -} - -static inline int blend32(int src, int dst, int scale) { - SkASSERT((unsigned)src <= 0xFF); - SkASSERT((unsigned)dst <= 0xFF); - SkASSERT((unsigned)scale <= 32); - return dst + ((src - dst) * scale >> 5); -} - -static void blit_lcd16_opaque(SkPMColor dst[], const uint16_t src[], - SkPMColor color, int width) { - int srcR = SkGetPackedR32(color); - int srcG = SkGetPackedG32(color); - int srcB = SkGetPackedB32(color); - - for (int i = 0; i < width; i++) { - uint16_t mask = src[i]; - if (0 == mask) { - continue; - } - - SkPMColor d = dst[i]; - - /* We want all of these in 5bits, hence the shifts in case one of them - * (green) is 6bits. - */ - int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); - int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); - int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); - - // Now upscale them to 0..256, so we can use SkAlphaBlend - maskR = upscale31To32(maskR); - maskG = upscale31To32(maskG); - maskB = upscale31To32(maskB); - - int maskA = SkMax32(SkMax32(maskR, maskG), maskB); - - int dstA = SkGetPackedA32(d); - int dstR = SkGetPackedR32(d); - int dstG = SkGetPackedG32(d); - int dstB = SkGetPackedB32(d); - - dst[i] = SkPackARGB32(blend32(0xFF, dstA, maskA), - blend32(srcR, dstR, maskR), - blend32(srcG, dstG, maskG), - blend32(srcB, dstB, maskB)); - } -} - -static void blitmask_lcd16(const SkBitmap& device, const SkMask& mask, - const SkIRect& clip, SkPMColor srcColor) { - int x = clip.fLeft; - int y = clip.fTop; - int width = clip.width(); - int height = clip.height(); - - SkPMColor* dstRow = device.getAddr32(x, y); - const uint16_t* srcRow = mask.getAddrLCD16(x, y); - - do { - blit_lcd16_opaque(dstRow, srcRow, srcColor, width); - dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes()); - srcRow = (const uint16_t*)((const char*)srcRow + mask.fRowBytes); - } while (--height != 0); -} - -////////////////////////////////////////////////////////////////////////////////////// - static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask, const SkIRect& clip, SkPMColor srcColor) { U8CPU alpha = SkGetPackedA32(srcColor); @@ -126,7 +29,7 @@ static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask, int height = clip.height(); SkPMColor* dstRow = device.getAddr32(x, y); - const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr(x, y)); + const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y)); do { proc(dstRow, srcRow, width, alpha); @@ -150,9 +53,6 @@ SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint) fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB); fColor32Proc = SkBlitRow::ColorProcFactory(); - - // init the pro for blitmask - fBlitMaskProc = SkBlitMask::Factory(SkBitmap::kARGB_8888_Config, color); } const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) { @@ -254,84 +154,33 @@ void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { return; } + if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) { + return; + } + if (mask.fFormat == SkMask::kBW_Format) { SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA)); - return; } else if (SkMask::kARGB32_Format == mask.fFormat) { SkARGB32_Blit32(fDevice, mask, clip, fPMColor); - return; - } else if (SkMask::kLCD16_Format == mask.fFormat) { - blitmask_lcd16(fDevice, mask, clip, fPMColor); - return; } - - int x = clip.fLeft; - int y = clip.fTop; - - fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(), - SkBitmap::kARGB_8888_Config, - mask.getAddr(x, y), mask.fRowBytes, - fColor, clip.width(), clip.height()); } void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { SkASSERT(mask.fBounds.contains(clip)); + if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) { + return; + } + if (mask.fFormat == SkMask::kBW_Format) { SkARGB32_BlitBW(fDevice, mask, clip, fPMColor); - return; } else if (SkMask::kARGB32_Format == mask.fFormat) { SkARGB32_Blit32(fDevice, mask, clip, fPMColor); - return; - } else if (SkMask::kLCD16_Format == mask.fFormat) { - blitmask_lcd16(fDevice, mask, clip, fPMColor); - return; } - - int x = clip.fLeft; - int y = clip.fTop; - int width = clip.width(); - int height = clip.height(); - -#if defined(SK_SUPPORT_LCDTEXT) - const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format; - const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format; - - // In LCD mode the masks have either an extra couple of rows or columns on the edges. - if (lcdMode || verticalLCDMode) { - int widthAdjustment, heightAdjustment; - const uint32_t* alpha32; - uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32); - - width += widthAdjustment; - height += heightAdjustment; - - unsigned devRB = fDevice.rowBytes() - (width << 2); - unsigned alphaExtraRowWords = mask.rowWordsLCD() - width; - SkPMColor srcColor = fPMColor; - - do { - unsigned w = width; - do { - const uint32_t alphaPixel = *alpha32++; - const uint32_t originalPixel = *device; - *device++ = BlendLCDPixelWithOpaqueColor(alphaPixel, originalPixel, srcColor); - } while (--w != 0); - device = (uint32_t*)((char*)device + devRB); - alpha32 += alphaExtraRowWords; - } while (--height != 0); - - return; - } -#endif - - fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(), - SkBitmap::kARGB_8888_Config, - mask.getAddr(x, y), mask.fRowBytes, fColor, width, height); } -////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { if (alpha == 0 || fSrcA == 0) { @@ -346,17 +195,9 @@ void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { } unsigned dst_scale = 255 - SkGetPackedA32(color); - uint32_t prevDst = ~device[0]; - uint32_t result SK_INIT_TO_AVOID_WARNING; uint32_t rowBytes = fDevice.rowBytes(); - while (--height >= 0) { - uint32_t dst = device[0]; - if (dst != prevDst) { - result = color + SkAlphaMulQ(dst, dst_scale); - prevDst = dst; - } - device[0] = result; + device[0] = color + SkAlphaMulQ(device[0], dst_scale); device = (uint32_t*)((char*)device + rowBytes); } } @@ -384,74 +225,6 @@ void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) { /////////////////////////////////////////////////////////////////////// -void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { - SkASSERT(mask.fBounds.contains(clip)); - - if (mask.fFormat == SkMask::kBW_Format) { - SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); - - SkARGB32_BlitBW(fDevice, mask, clip, black); - } else if (SkMask::kARGB32_Format == mask.fFormat) { - SkARGB32_Blit32(fDevice, mask, clip, fPMColor); - } else if (SkMask::kLCD16_Format == mask.fFormat) { - blitmask_lcd16(fDevice, mask, clip, fPMColor); - } else { -#if defined(SK_SUPPORT_LCDTEXT) - const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format; - const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format; -#endif - - // In LCD mode the masks have either an extra couple of rows or columns on the edges. - unsigned width = clip.width(); - unsigned height = clip.height(); - - SkASSERT((int)height > 0); - SkASSERT((int)width > 0); - -#if defined(SK_SUPPORT_LCDTEXT) - if (lcdMode || verticalLCDMode) { - int widthAdjustment, heightAdjustment; - const uint32_t* alpha32; - uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32); - - width += widthAdjustment; - height += heightAdjustment; - - unsigned deviceRB = fDevice.rowBytes() - (width << 2); - unsigned alphaExtraRowWords = mask.rowWordsLCD() - width; - - do { - unsigned w = width; - do { - const uint32_t alphaPixel = *alpha32++; - const uint32_t originalPixel = *device; - *device++ = BlendLCDPixelWithBlack(alphaPixel, originalPixel); - } while (--w != 0); - device = (uint32_t*)((char*)device + deviceRB); - alpha32 += alphaExtraRowWords; - } while (--height != 0); - - return; - } -#endif - - uint32_t* device = fDevice.getAddr32(clip.fLeft, clip.fTop); - unsigned maskRB = mask.fRowBytes - width; - unsigned deviceRB = fDevice.rowBytes() - (width << 2); - const uint8_t* alpha = mask.getAddr(clip.fLeft, clip.fTop); - do { - unsigned w = width; - do { - unsigned aa = *alpha++; - *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa)); - device += 1; - } while (--w != 0); - device = (uint32_t*)((char*)device + deviceRB); - alpha += maskRB; - } while (--height != 0); - } -} - void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) { uint32_t* device = fDevice.getAddr32(x, y); @@ -483,7 +256,7 @@ void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], } } -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device, paint) { @@ -525,8 +298,6 @@ void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { } } -/////////////////////////////////////////////////////////////////////////////////////////////// - void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) { SkPMColor* span = fBuffer; @@ -600,3 +371,61 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], } } } + +void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { + // we only handle kA8 with an xfermode + if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) { + this->INHERITED::blitMask(mask, clip); + return; + } + + SkASSERT(mask.fBounds.contains(clip)); + + SkBlitMask::RowProc proc = NULL; + if (!fXfermode) { + unsigned flags = 0; + if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { + flags |= SkBlitMask::kSrcIsOpaque_RowFlag; + } + proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat, + (SkBlitMask::RowFlags)flags); + if (NULL == proc) { + this->INHERITED::blitMask(mask, clip); + return; + } + } + + const int x = clip.fLeft; + const int width = clip.width(); + int y = clip.fTop; + int height = clip.height(); + + char* dstRow = (char*)fDevice.getAddr32(x, y); + const size_t dstRB = fDevice.rowBytes(); + const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); + const size_t maskRB = mask.fRowBytes; + + SkShader* shader = fShader; + SkPMColor* span = fBuffer; + + if (fXfermode) { + SkASSERT(SkMask::kA8_Format == mask.fFormat); + SkXfermode* xfer = fXfermode; + do { + shader->shadeSpan(x, y, span, width); + xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow); + dstRow += dstRB; + maskRow += maskRB; + y += 1; + } while (--height > 0); + } else { + do { + shader->shadeSpan(x, y, span, width); + proc(dstRow, maskRow, span, width); + dstRow += dstRB; + maskRow += maskRB; + y += 1; + } while (--height > 0); + } +} + |