diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/animator/SkDrawBitmap.cpp | 9 | ||||
-rw-r--r-- | src/core/SkBitmap.cpp | 68 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 5 | ||||
-rw-r--r-- | src/core/SkBlitter_A1.cpp | 50 | ||||
-rw-r--r-- | src/core/SkCoreBlitters.h | 16 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 91 | ||||
-rw-r--r-- | src/effects/SkTransparentShader.cpp | 3 | ||||
-rw-r--r-- | src/pdf/SkPDFImage.cpp | 56 | ||||
-rw-r--r-- | src/utils/debugger/SkObjectParser.cpp | 4 |
9 files changed, 223 insertions, 79 deletions
diff --git a/src/animator/SkDrawBitmap.cpp b/src/animator/SkDrawBitmap.cpp index 327e81365a..568401d0e6 100644 --- a/src/animator/SkDrawBitmap.cpp +++ b/src/animator/SkDrawBitmap.cpp @@ -75,10 +75,11 @@ void SkDrawBitmap::dump(SkAnimateMaker* maker) { const char* formatName; switch (format) { case 0: formatName = "none"; break; - case 1: formatName = "A8"; break; - case 2: formatName = "Index8"; break; - case 3: formatName = "RGB16"; break; - case 4: formatName = "RGB32"; break; + case 1: formatName = "A1"; break; + case 2: formatName = "A8"; break; + case 3: formatName = "Index8"; break; + case 4: formatName = "RGB16"; break; + case 5: formatName = "RGB32"; break; } SkDebugf("format=\"%s\" />\n", formatName); } diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 38594f8f3c..2fae75ae38 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -161,6 +161,7 @@ int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { int bpp; switch (config) { case kNo_Config: + case kA1_Config: bpp = 0; // not applicable break; case kA8_Config: @@ -193,6 +194,11 @@ size_t SkBitmap::ComputeRowBytes(Config c, int width) { switch (c) { case kNo_Config: break; + case kA1_Config: + rowBytes.set(width); + rowBytes.add(7); + rowBytes.shiftRight(3); + break; case kA8_Config: case kIndex8_Config: rowBytes.set(width); @@ -269,6 +275,7 @@ static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType, case SkBitmap::kNo_Config: alphaType = kIgnore_SkAlphaType; break; + case SkBitmap::kA1_Config: case SkBitmap::kA8_Config: if (kUnpremul_SkAlphaType == alphaType) { alphaType = kPremul_SkAlphaType; @@ -284,8 +291,6 @@ static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType, case SkBitmap::kRGB_565_Config: alphaType = kOpaque_SkAlphaType; break; - default: - return false; } if (canonical) { *canonical = alphaType; @@ -601,6 +606,8 @@ void* SkBitmap::getAddr(int x, int y) const { case SkBitmap::kIndex8_Config: base += x; break; + case SkBitmap::kA1_Config: + base += x >> 3; break; default: SkDEBUGFAIL("Can't return addr for config"); @@ -616,6 +623,15 @@ SkColor SkBitmap::getColor(int x, int y) const { SkASSERT((unsigned)y < (unsigned)this->height()); switch (this->config()) { + case SkBitmap::kA1_Config: { + uint8_t* addr = this->getAddr1(x, y); + uint8_t mask = 1 << (7 - (x % 8)); + if (addr[0] & mask) { + return SK_ColorBLACK; + } else { + return 0; + } + } case SkBitmap::kA8_Config: { uint8_t* addr = this->getAddr8(x, y); return SkColorSetA(0, addr[0]); @@ -638,7 +654,6 @@ SkColor SkBitmap::getColor(int x, int y) const { return SkUnPreMultiply::PMColorToColor(addr[0]); } case kNo_Config: - default: SkASSERT(false); return 0; } @@ -656,6 +671,9 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { const int width = bm.width(); switch (bm.config()) { + case SkBitmap::kA1_Config: { + // TODO + } break; case SkBitmap::kA8_Config: { unsigned a = 0xFF; for (int y = 0; y < height; ++y) { @@ -761,6 +779,38 @@ void SkBitmap::internalErase(const SkIRect& area, } switch (fConfig) { + case kA1_Config: { + uint8_t* p = this->getAddr1(area.fLeft, area.fTop); + const int left = area.fLeft >> 3; + const int right = area.fRight >> 3; + + int middle = right - left - 1; + + uint8_t leftMask = 0xFF >> (area.fLeft & 7); + uint8_t rightMask = ~(0xFF >> (area.fRight & 7)); + if (left == right) { + leftMask &= rightMask; + rightMask = 0; + } + + a = (a >> 7) ? 0xFF : 0; + while (--height >= 0) { + uint8_t* startP = p; + + *p = (*p & ~leftMask) | (a & leftMask); + p++; + if (middle > 0) { + memset(p, a, middle); + p += middle; + } + if (rightMask) { + *p = (*p & ~rightMask) | (a & rightMask); + } + + p = startP + rowBytes; + } + break; + } case kA8_Config: { uint8_t* p = this->getAddr8(area.fLeft, area.fTop); while (--height >= 0) { @@ -846,6 +896,7 @@ static size_t get_sub_offset(const SkBitmap& bm, int x, int y) { break; case SkBitmap::kNo_Config: + case SkBitmap::kA1_Config: default: return SUB_OFFSET_FAILURE; } @@ -888,6 +939,8 @@ bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t r case SkBitmap::kNo_Config: // Fall through. + case SkBitmap::kA1_Config: + // Fall through. default: return false; } @@ -968,6 +1021,7 @@ bool SkBitmap::canCopyTo(Config dstConfig) const { case kRGB_565_Config: case kARGB_8888_Config: break; + case kA1_Config: case kIndex8_Config: if (!sameConfigs) { return false; @@ -978,6 +1032,12 @@ bool SkBitmap::canCopyTo(Config dstConfig) const { default: return false; } + + // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config + if (this->config() == kA1_Config && !sameConfigs) { + return false; + } + return true; } @@ -1621,7 +1681,7 @@ void SkBitmap::validate() const { void SkBitmap::toString(SkString* str) const { static const char* gConfigNames[kConfigCount] = { - "NONE", "A8", "INDEX8", "565", "4444", "8888" + "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888" }; str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 9682d5572a..dc7946a4bd 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -945,6 +945,11 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, switch (device.config()) { + case SkBitmap::kA1_Config: + SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter, + storage, storageSize, (device, *paint)); + break; + case SkBitmap::kA8_Config: if (drawCoverage) { SkASSERT(NULL == shader); diff --git a/src/core/SkBlitter_A1.cpp b/src/core/SkBlitter_A1.cpp new file mode 100644 index 0000000000..b64afe2ae9 --- /dev/null +++ b/src/core/SkBlitter_A1.cpp @@ -0,0 +1,50 @@ + +/* + * 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" + +SkA1_Blitter::SkA1_Blitter(const SkBitmap& device, const SkPaint& paint) + : INHERITED(device) { + fSrcA = paint.getAlpha(); +} + +void SkA1_Blitter::blitH(int x, int y, int width) { + SkASSERT(x >= 0 && y >= 0 && + (unsigned)(x + width) <= (unsigned)fDevice.width()); + + if (fSrcA <= 0x7F) { + return; + } + uint8_t* dst = fDevice.getAddr1(x, y); + int right = x + width; + + int left_mask = 0xFF >> (x & 7); + int rite_mask = 0xFF << (8 - (right & 7)); + int full_runs = (right >> 3) - ((x + 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; + } + if (full_runs < 0) { + SkASSERT((left_mask & rite_mask) != 0); + *dst |= (left_mask & rite_mask); + } else { + *dst++ |= left_mask; + memset(dst, 0xFF, full_runs); + dst += full_runs; + *dst |= rite_mask; + } +} diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index 1605a5273d..673b874545 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -162,6 +162,22 @@ private: /////////////////////////////////////////////////////////////////////////////// +class SkA1_Blitter : public SkRasterBlitter { +public: + SkA1_Blitter(const SkBitmap& device, const SkPaint& paint); + virtual void blitH(int x, int y, int width) SK_OVERRIDE; + +private: + uint8_t fSrcA; + + // illegal + SkA1_Blitter& operator=(const SkA1_Blitter&); + + typedef SkRasterBlitter INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + /* These return the correct subclass of blitter for their device config. Currently, they make the following assumptions about the state of the diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index f4f23911b0..1d6c2f79a5 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -523,54 +523,10 @@ static void pack4xHToLCD32(const SkBitmap& src, const SkMask& dst, } } -static inline int convert_8_to_1(unsigned byte) { - SkASSERT(byte <= 0xFF); - return byte >> 7; -} - -static uint8_t pack_8_to_1(const uint8_t alpha[8]) { - unsigned bits = 0; - for (int i = 0; i < 8; ++i) { - bits |= convert_8_to_1(alpha[i]); - bits <<= 1; - } - return SkToU8(bits); -} - -static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) { - const int height = mask.fBounds.height(); - const int width = mask.fBounds.width(); - const int octs = width >> 3; - const int leftOverBits = width & 7; - - uint8_t* dst = mask.fImage; - const int dstPad = mask.fRowBytes - SkAlign8(width); - SkASSERT(dstPad >= 0); - - const int srcPad = srcRB - width; - SkASSERT(srcPad >= 0); - - for (int y = 0; y < height; ++y) { - for (int i = 0; i < octs; ++i) { - *dst++ = pack_8_to_1(src); - src += 8; - } - if (leftOverBits > 0) { - unsigned bits = 0; - int shift = 7; - for (int i = 0; i < leftOverBits; ++i, --shift) { - bits |= convert_8_to_1(*src++ >> 7) << shift; - } - *dst++ = bits; - } - src += srcPad; - dst += dstPad; - } -} - static void generateMask(const SkMask& mask, const SkPath& path, const SkMaskGamma::PreBlend& maskPreBlend) { - SkPaint paint; + SkBitmap::Config config; + SkPaint paint; int srcW = mask.fBounds.width(); int srcH = mask.fBounds.height(); @@ -582,25 +538,27 @@ static void generateMask(const SkMask& mask, const SkPath& path, matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), -SkIntToScalar(mask.fBounds.fTop)); - SkBitmap::Config config = SkBitmap::kA8_Config; - paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat); - switch (mask.fFormat) { - case SkMask::kBW_Format: - dstRB = 0; // signals we need a copy - break; - case SkMask::kA8_Format: - break; - case SkMask::kLCD16_Format: - case SkMask::kLCD32_Format: - // TODO: trigger off LCD orientation - dstW = 4*dstW - 8; - matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1), - -SkIntToScalar(mask.fBounds.fTop)); - matrix.postScale(SkIntToScalar(4), SK_Scalar1); - dstRB = 0; // signals we need a copy - break; - default: - SkDEBUGFAIL("unexpected mask format"); + if (SkMask::kBW_Format == mask.fFormat) { + config = SkBitmap::kA1_Config; + paint.setAntiAlias(false); + } else { + config = SkBitmap::kA8_Config; + paint.setAntiAlias(true); + switch (mask.fFormat) { + case SkMask::kA8_Format: + break; + case SkMask::kLCD16_Format: + case SkMask::kLCD32_Format: + // TODO: trigger off LCD orientation + dstW = 4*dstW - 8; + matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1), + -SkIntToScalar(mask.fBounds.fTop)); + matrix.postScale(SkIntToScalar(4), SK_Scalar1); + dstRB = 0; // signals we need a copy + break; + default: + SkDEBUGFAIL("unexpected mask format"); + } } SkRasterClip clip; @@ -629,9 +587,6 @@ static void generateMask(const SkMask& mask, const SkPath& path, draw.drawPath(path, paint); switch (mask.fFormat) { - case SkMask::kBW_Format: - packA8ToA1(mask, bm.getAddr8(0, 0), bm.rowBytes()); - break; case SkMask::kA8_Format: if (maskPreBlend.isApplicable()) { applyLUTToA8Mask(mask, maskPreBlend.fG); diff --git a/src/effects/SkTransparentShader.cpp b/src/effects/SkTransparentShader.cpp index 1d7e80877e..970e74faa8 100644 --- a/src/effects/SkTransparentShader.cpp +++ b/src/effects/SkTransparentShader.cpp @@ -94,6 +94,9 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { } break; } + case SkBitmap::kA1_Config: + SkDEBUGFAIL("kA1_Config umimplemented at this time"); + break; default: // to avoid warnings break; } diff --git a/src/pdf/SkPDFImage.cpp b/src/pdf/SkPDFImage.cpp index 81adcc20d6..a99c9fe390 100644 --- a/src/pdf/SkPDFImage.cpp +++ b/src/pdf/SkPDFImage.cpp @@ -36,6 +36,7 @@ static size_t get_uncompressed_size(const SkBitmap& bitmap, return srcRect.width() * 3 * srcRect.height(); case SkBitmap::kARGB_8888_Config: return srcRect.width() * 3 * srcRect.height(); + case SkBitmap::kA1_Config: case SkBitmap::kA8_Config: return 1; default: @@ -165,6 +166,48 @@ static SkStream* extract_argb8888_data(const SkBitmap& bitmap, return stream; } +static SkStream* extract_a1_alpha(const SkBitmap& bitmap, + const SkIRect& srcRect, + bool* isOpaque, + bool* isTransparent) { + const int alphaRowBytes = (srcRect.width() + 7) / 8; + SkStream* stream = SkNEW_ARGS(SkMemoryStream, + (alphaRowBytes * srcRect.height())); + uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase(); + + int offset1 = srcRect.fLeft % 8; + int offset2 = 8 - offset1; + + for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { + uint8_t* src = bitmap.getAddr1(0, y); + // This may read up to one byte after src, but the + // potentially invalid bits are never used for computation. + for (int x = srcRect.fLeft; x < srcRect.fRight; x += 8) { + if (offset1) { + alphaDst[0] = src[x / 8] << offset1 | + src[x / 8 + 1] >> offset2; + } else { + alphaDst[0] = src[x / 8]; + } + if (x + 7 < srcRect.fRight) { + *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE; + *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT; + } + alphaDst++; + } + // Calculate the mask of bits we're interested in within the + // last byte of alphaDst. + // width mod 8 == 1 -> 0x80 ... width mod 8 == 7 -> 0xFE + uint8_t mask = ~((1 << (8 - (srcRect.width() % 8))) - 1); + if (srcRect.width() % 8) { + *isOpaque &= (alphaDst[-1] & mask) == (SK_AlphaOPAQUE & mask); + *isTransparent &= + (alphaDst[-1] & mask) == (SK_AlphaTRANSPARENT & mask); + } + } + return stream; +} + static SkStream* extract_a8_alpha(const SkBitmap& bitmap, const SkIRect& srcRect, bool* isOpaque, @@ -240,6 +283,14 @@ static SkStream* extract_image_data(const SkBitmap& bitmap, stream = extract_argb8888_data(bitmap, srcRect, extractAlpha, &isOpaque, &transparent); break; + case SkBitmap::kA1_Config: + if (!extractAlpha) { + stream = create_black_image(); + } else { + stream = extract_a1_alpha(bitmap, srcRect, + &isOpaque, &transparent); + } + break; case SkBitmap::kA8_Config: if (!extractAlpha) { stream = create_black_image(); @@ -523,7 +574,8 @@ SkPDFImage::SkPDFImage(SkStream* stream, insertName("Type", "XObject"); insertName("Subtype", "Image"); - bool alphaOnly = (config == SkBitmap::kA8_Config); + bool alphaOnly = (config == SkBitmap::kA1_Config || + config == SkBitmap::kA8_Config); if (!isAlpha && alphaOnly) { // For alpha only images, we stretch a single pixel of black for @@ -549,6 +601,8 @@ SkPDFImage::SkPDFImage(SkStream* stream, int bitsPerComp = 8; if (config == SkBitmap::kARGB_4444_Config) { bitsPerComp = 4; + } else if (isAlpha && config == SkBitmap::kA1_Config) { + bitsPerComp = 1; } insertInt("BitsPerComponent", bitsPerComp); diff --git a/src/utils/debugger/SkObjectParser.cpp b/src/utils/debugger/SkObjectParser.cpp index ebbd40018e..54ae0773fd 100644 --- a/src/utils/debugger/SkObjectParser.cpp +++ b/src/utils/debugger/SkObjectParser.cpp @@ -26,9 +26,9 @@ SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) { mBitmap->appendS32(bitmap.height()); const char* gConfigStrings[] = { - "None", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888" + "None", "A1", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888" }; - SkASSERT(SkBitmap::kConfigCount == SK_ARRAY_COUNT(gConfigStrings)); + SkASSERT(SkBitmap::kConfigCount == 7); mBitmap->append(" Config: "); mBitmap->append(gConfigStrings[bitmap.config()]); |