diff options
Diffstat (limited to 'src')
30 files changed, 374 insertions, 469 deletions
diff --git a/src/animator/SkDrawBitmap.cpp b/src/animator/SkDrawBitmap.cpp index 568401d0e6..327e81365a 100644 --- a/src/animator/SkDrawBitmap.cpp +++ b/src/animator/SkDrawBitmap.cpp @@ -75,11 +75,10 @@ void SkDrawBitmap::dump(SkAnimateMaker* maker) { const char* formatName; switch (format) { case 0: formatName = "none"; 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; + case 1: formatName = "A8"; break; + case 2: formatName = "Index8"; break; + case 3: formatName = "RGB16"; break; + case 4: formatName = "RGB32"; break; } SkDebugf("format=\"%s\" />\n", formatName); } diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 429d09216a..9d4aa87c85 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -161,7 +161,6 @@ int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { int bpp; switch (config) { case kNo_Config: - case kA1_Config: bpp = 0; // not applicable break; case kA8_Config: @@ -194,11 +193,6 @@ 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); @@ -275,7 +269,6 @@ 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; @@ -291,6 +284,8 @@ 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; @@ -606,8 +601,6 @@ 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"); @@ -623,15 +616,6 @@ 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]); @@ -654,6 +638,7 @@ SkColor SkBitmap::getColor(int x, int y) const { return SkUnPreMultiply::PMColorToColor(addr[0]); } case kNo_Config: + default: SkASSERT(false); return 0; } @@ -671,9 +656,6 @@ 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) { @@ -779,38 +761,6 @@ 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) { @@ -896,7 +846,6 @@ 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; } @@ -939,8 +888,6 @@ 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; } @@ -1021,7 +968,6 @@ 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; @@ -1032,12 +978,6 @@ 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; } @@ -1683,7 +1623,7 @@ void SkBitmap::validate() const { void SkBitmap::toString(SkString* str) const { static const char* gConfigNames[kConfigCount] = { - "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888" + "NONE", "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 dc7946a4bd..9682d5572a 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -945,11 +945,6 @@ 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 deleted file mode 100644 index b64afe2ae9..0000000000 --- a/src/core/SkBlitter_A1.cpp +++ /dev/null @@ -1,50 +0,0 @@ - -/* - * 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 673b874545..1605a5273d 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -162,22 +162,6 @@ 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/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp index faa3f89049..a78b197a55 100644 --- a/src/core/SkGlyphCache.cpp +++ b/src/core/SkGlyphCache.cpp @@ -87,8 +87,6 @@ SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca fGlyphArray.setReserve(kMinGlyphCount); - fMetricsCount = 0; - fAdvanceCount = 0; fAuxProcList = NULL; } @@ -320,11 +318,9 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { if (kJustAdvance_MetricsType == mtype) { fScalerContext->getAdvance(glyph); - fAdvanceCount += 1; } else { SkASSERT(kFull_MetricsType == mtype); fScalerContext->getMetrics(glyph); - fMetricsCount += 1; } return glyph; diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index 52a8132f72..7b2ebb844e 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -211,8 +211,6 @@ private: SkTDArray<SkGlyph*> fGlyphArray; SkChunkAlloc fGlyphAlloc; - int fMetricsCount, fAdvanceCount; - struct CharGlyphRec { uint32_t fID; // unichar + subpixel SkGlyph* fGlyph; diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index d6948dd83f..91a76e151f 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -2005,11 +2005,7 @@ enum FlatFlags { }; // The size of a flat paint's POD fields -// Include an SkScalar for hinting scale factor whether it is -// supported or not so that an SKP is valid whether it was -// created with support or not. - -static const uint32_t kPODPaintSize = 6 * sizeof(SkScalar) + +static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 1 * sizeof(SkColor) + 1 * sizeof(uint16_t) + 6 * sizeof(uint8_t); @@ -2046,8 +2042,6 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { ptr = write_scalar(ptr, this->getTextSize()); ptr = write_scalar(ptr, this->getTextScaleX()); ptr = write_scalar(ptr, this->getTextSkewX()); - // Dummy value for obsolete hinting scale factor. TODO: remove with next picture version - ptr = write_scalar(ptr, SK_Scalar1); ptr = write_scalar(ptr, this->getStrokeWidth()); ptr = write_scalar(ptr, this->getStrokeMiter()); *ptr++ = this->getColor(); @@ -2064,8 +2058,6 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { buffer.writeScalar(fTextSize); buffer.writeScalar(fTextScaleX); buffer.writeScalar(fTextSkewX); - // Dummy value for obsolete hinting scale factor. TODO: remove with next picture version - buffer.writeScalar(SK_Scalar1); buffer.writeScalar(fWidth); buffer.writeScalar(fMiterLimit); buffer.writeColor(fColor); @@ -2120,8 +2112,6 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { this->setTextSize(read_scalar(pod)); this->setTextScaleX(read_scalar(pod)); this->setTextSkewX(read_scalar(pod)); - // Skip the hinting scalar factor, which is not supported. - read_scalar(pod); this->setStrokeWidth(read_scalar(pod)); this->setStrokeMiter(read_scalar(pod)); this->setColor(*pod++); diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index 4acc549377..2520e6b9c9 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -266,11 +266,20 @@ void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) { #include "SkStream.h" +static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; + bool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { if (NULL == stream) { return false; } + // Check magic bytes. + char magic[sizeof(kMagic)]; + stream->read(magic, sizeof(kMagic)); + if (0 != memcmp(magic, kMagic, sizeof(kMagic))) { + return false; + } + SkPictInfo info; if (!stream->read(&info, sizeof(SkPictInfo))) { return false; @@ -341,6 +350,10 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag; } + // Write 8 magic bytes to ID this file format. + SkASSERT(sizeof(kMagic) == 8); + stream->write(kMagic, sizeof(kMagic)); + stream->write(&info, sizeof(info)); if (playback) { stream->writeBool(true); diff --git a/src/core/SkScaledImageCache.cpp b/src/core/SkScaledImageCache.cpp index ea29843c92..55eadb849e 100644 --- a/src/core/SkScaledImageCache.cpp +++ b/src/core/SkScaledImageCache.cpp @@ -49,7 +49,7 @@ static uint32_t compute_hash(const uint32_t data[], int count) { return hash; } -struct Key { +struct SkScaledImageCache::Key { Key(uint32_t genID, SkScalar scaleX, SkScalar scaleY, @@ -129,22 +129,24 @@ struct SkScaledImageCache::Rec { #include "SkTDynamicHash.h" namespace { // can't use static functions w/ template parameters -const Key& key_from_rec(const SkScaledImageCache::Rec& rec) { +const SkScaledImageCache::Key& key_from_rec(const SkScaledImageCache::Rec& rec) { return rec.fKey; } -uint32_t hash_from_key(const Key& key) { +uint32_t hash_from_key(const SkScaledImageCache::Key& key) { return key.fHash; } -bool eq_rec_key(const SkScaledImageCache::Rec& rec, const Key& key) { +bool eq_rec_key(const SkScaledImageCache::Rec& rec, const SkScaledImageCache::Key& key) { return rec.fKey == key; } } class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec, - Key, key_from_rec, hash_from_key, - eq_rec_key> {}; + SkScaledImageCache::Key, + key_from_rec, + hash_from_key, + eq_rec_key> {}; /////////////////////////////////////////////////////////////////////////////// @@ -187,17 +189,22 @@ SkScaledImageCache::~SkScaledImageCache() { //////////////////////////////////////////////////////////////////////////////// -/** - This private method is the fully general record finder. All other - record finders should call this funtion. */ + SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds) { - if (bounds.isEmpty()) { + const Key key(genID, scaleX, scaleY, bounds); + return this->findAndLock(key); +} + +/** + This private method is the fully general record finder. All other + record finders should call this function or the one above. */ +SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkScaledImageCache::Key& key) { + if (key.fBounds.isEmpty()) { return NULL; } - Key key(genID, scaleX, scaleY, bounds); #ifdef USE_HASH Rec* rec = fHash->find(key); #else @@ -275,8 +282,14 @@ SkScaledImageCache::ID* SkScaledImageCache::findAndLockMip(const SkBitmap& orig, /** This private method is the fully general record adder. All other record adders should call this funtion. */ -void SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) { +SkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) { SkASSERT(rec); + // See if we already have this key (racy inserts, etc.) + Rec* existing = this->findAndLock(rec->fKey); + if (existing != NULL) { + return rec_to_id(existing); + } + this->addToHead(rec); SkASSERT(1 == rec->fLockCount); #ifdef USE_HASH @@ -285,6 +298,7 @@ void SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) { #endif // We may (now) be overbudget, so see if we need to purge something. this->purgeAsNeeded(); + return rec_to_id(rec); } SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID, @@ -293,8 +307,7 @@ SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID, const SkBitmap& bitmap) { Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height)); Rec* rec = SkNEW_ARGS(Rec, (key, bitmap)); - this->addAndLock(rec); - return rec_to_id(rec); + return this->addAndLock(rec); } SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, @@ -311,8 +324,7 @@ SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, } Key key(orig.getGenerationID(), scaleX, scaleY, bounds); Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); - this->addAndLock(rec); - return rec_to_id(rec); + return this->addAndLock(rec); } SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, @@ -323,8 +335,7 @@ SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, } Key key(orig.getGenerationID(), 0, 0, bounds); Rec* rec = SkNEW_ARGS(Rec, (key, mip)); - this->addAndLock(rec); - return rec_to_id(rec); + return this->addAndLock(rec); } void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { diff --git a/src/core/SkScaledImageCache.h b/src/core/SkScaledImageCache.h index fee69d2d58..44ef1f8a2c 100644 --- a/src/core/SkScaledImageCache.h +++ b/src/core/SkScaledImageCache.h @@ -126,6 +126,7 @@ public: public: struct Rec; + struct Key; private: Rec* fHead; Rec* fTail; @@ -139,7 +140,8 @@ private: Rec* findAndLock(uint32_t generationID, SkScalar sx, SkScalar sy, const SkIRect& bounds); - void addAndLock(Rec* rec); + Rec* findAndLock(const Key& key); + ID* addAndLock(Rec* rec); void purgeAsNeeded(); diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index 1d6c2f79a5..4996a73f8d 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -352,16 +352,16 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) { glyph->fHeight = SkToU16(ir.height()); if (glyph->fWidth > 0) { - switch (fRec.fMaskFormat) { - case SkMask::kLCD16_Format: - case SkMask::kLCD32_Format: - glyph->fWidth += 2; - glyph->fLeft -= 1; - break; - default: - break; + switch (fRec.fMaskFormat) { + case SkMask::kLCD16_Format: + case SkMask::kLCD32_Format: + glyph->fWidth += 2; + glyph->fLeft -= 1; + break; + default: + break; + } } - } } } @@ -523,10 +523,54 @@ 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 <<= 1; + bits |= convert_8_to_1(alpha[i]); + } + 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)/8; + 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) { - SkBitmap::Config config; - SkPaint paint; + SkPaint paint; int srcW = mask.fBounds.width(); int srcH = mask.fBounds.height(); @@ -538,27 +582,25 @@ static void generateMask(const SkMask& mask, const SkPath& path, matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), -SkIntToScalar(mask.fBounds.fTop)); - 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"); - } + 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"); } SkRasterClip clip; @@ -587,6 +629,9 @@ 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/core/SkScalerContext.h b/src/core/SkScalerContext.h index 2820b5ac2d..e4950edee3 100644 --- a/src/core/SkScalerContext.h +++ b/src/core/SkScalerContext.h @@ -202,16 +202,57 @@ protected: Rec fRec; unsigned fBaseGlyphCount; - virtual unsigned generateGlyphCount() = 0; - virtual uint16_t generateCharToGlyph(SkUnichar) = 0; - virtual void generateAdvance(SkGlyph*) = 0; - virtual void generateMetrics(SkGlyph*) = 0; - virtual void generateImage(const SkGlyph&) = 0; - virtual void generatePath(const SkGlyph&, SkPath*) = 0; + /** Generates the contents of glyph.fAdvanceX and glyph.fAdvanceY. + * May call getMetrics if that would be just as fast. + */ + virtual void generateAdvance(SkGlyph* glyph) = 0; + + /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft, + * as well as fAdvanceX and fAdvanceY if not already set. + * + * TODO: fMaskFormat is set by getMetrics later; cannot be set here. + */ + virtual void generateMetrics(SkGlyph* glyph) = 0; + + /** Generates the contents of glyph.fImage. + * When called, glyph.fImage will be pointing to a pre-allocated, + * uninitialized region of memory of size glyph.computeImageSize(). + * This method may change glyph.fMaskFormat if the new image size is + * less than or equal to the old image size. + * + * Because glyph.computeImageSize() will determine the size of fImage, + * generateMetrics will be called before generateImage. + */ + virtual void generateImage(const SkGlyph& glyph) = 0; + + /** Sets the passed path to the glyph outline. + * If this cannot be done the path is set to empty; + * this is indistinguishable from a glyph with an empty path. + * This does not set glyph.fPath. + * + * TODO: path is always glyph.fPath, no reason to pass separately. + */ + virtual void generatePath(const SkGlyph& glyph, SkPath* path) = 0; + + /** Retrieves font metrics. + * TODO: there is now a vertical bit, no need for two parameters. + */ virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY) = 0; - // default impl returns 0, indicating failure. - virtual SkUnichar generateGlyphToChar(uint16_t); + + /** Returns the number of glyphs in the font. */ + virtual unsigned generateGlyphCount() = 0; + + /** Returns the glyph id for the given unichar. + * If there is no 1:1 mapping from the unichar to a glyph id, returns 0. + */ + virtual uint16_t generateCharToGlyph(SkUnichar unichar) = 0; + + /** Returns the unichar for the given glyph id. + * If there is no 1:1 mapping from the glyph id to a unichar, returns 0. + * The default implementation always returns 0, indicating failure. + */ + virtual SkUnichar generateGlyphToChar(uint16_t glyphId); void forceGenerateImageFromPath() { fGenerateImageFromPath = true; } diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp index e30b89f199..643dfb1372 100644 --- a/src/core/SkString.cpp +++ b/src/core/SkString.cpp @@ -634,5 +634,17 @@ SkString SkStringPrintf(const char* format, ...) { return formattedOutput; } +void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) { + const char* end = str + strlen(str); + while (str != end) { + // Find a token. + const size_t len = strcspn(str, delimiters); + out->push_back().set(str, len); + str += len; + // Skip any delimiters. + str += strspn(str, delimiters); + } +} + #undef VSNPRINTF #undef SNPRINTF diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp index a92c1b9b6f..4a8ac47247 100644 --- a/src/core/SkValidatingReadBuffer.cpp +++ b/src/core/SkValidatingReadBuffer.cpp @@ -203,7 +203,7 @@ bool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) { uint32_t SkValidatingReadBuffer::getArrayCount() { const size_t inc = sizeof(uint32_t); fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); - return *(uint32_t*)fReader.peek(); + return fError ? 0 : *(uint32_t*)fReader.peek(); } void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) { diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp index b4d8689f33..5be633ea54 100644 --- a/src/effects/SkDropShadowImageFilter.cpp +++ b/src/effects/SkDropShadowImageFilter.cpp @@ -15,10 +15,21 @@ #include "SkFlattenableBuffers.h" SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor color, SkImageFilter* input) - : SkImageFilter(input) + : INHERITED(input) , fDx(dx) , fDy(dy) - , fSigma(sigma) + , fSigmaX(sigma) + , fSigmaY(sigma) + , fColor(color) +{ +} + +SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, SkImageFilter* input, const CropRect* cropRect) + : INHERITED(input, cropRect) + , fDx(dx) + , fDy(dy) + , fSigmaX(sigmaX) + , fSigmaY(sigmaY) , fColor(color) { } @@ -27,11 +38,13 @@ SkDropShadowImageFilter::SkDropShadowImageFilter(SkFlattenableReadBuffer& buffer : INHERITED(1, buffer) { fDx = buffer.readScalar(); fDy = buffer.readScalar(); - fSigma = buffer.readScalar(); + fSigmaX = buffer.readScalar(); + fSigmaY = buffer.readScalar(); fColor = buffer.readColor(); buffer.validate(SkScalarIsFinite(fDx) && SkScalarIsFinite(fDy) && - SkScalarIsFinite(fSigma)); + SkScalarIsFinite(fSigmaX) && + SkScalarIsFinite(fSigmaY)); } void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const @@ -39,7 +52,8 @@ void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const this->INHERITED::flatten(buffer); buffer.writeScalar(fDx); buffer.writeScalar(fDy); - buffer.writeScalar(fSigma); + buffer.writeScalar(fSigmaX); + buffer.writeScalar(fSigmaY); buffer.writeColor(fColor); } @@ -49,17 +63,26 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) return false; - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.height())); + SkIRect bounds; + src.getBounds(&bounds); + if (!this->applyCropRect(&bounds, matrix)) { + return false; + } + + SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); SkCanvas canvas(device.get()); - SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(fSigma, fSigma)); + SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(fSigmaX, fSigmaY)); SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode)); SkPaint paint; paint.setImageFilter(blurFilter.get()); paint.setColorFilter(colorFilter.get()); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); canvas.drawBitmap(src, fDx, fDy, &paint); canvas.drawBitmap(src, 0, 0); *result = device->accessBitmap(false); + loc->fX += bounds.fLeft; + loc->fY += bounds.fTop; return true; } diff --git a/src/effects/SkTransparentShader.cpp b/src/effects/SkTransparentShader.cpp index 970e74faa8..1d7e80877e 100644 --- a/src/effects/SkTransparentShader.cpp +++ b/src/effects/SkTransparentShader.cpp @@ -94,9 +94,6 @@ 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/fonts/SkGScalerContext.cpp b/src/fonts/SkGScalerContext.cpp index f0543c571a..551b01c961 100644 --- a/src/fonts/SkGScalerContext.cpp +++ b/src/fonts/SkGScalerContext.cpp @@ -176,6 +176,8 @@ SkScalerContext* SkGTypeface::onCreateScalerContext( void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const { fProxy->filterRec(rec); + rec->setHinting(SkPaint::kNo_Hinting); + rec->fMaskFormat = SkMask::kARGB32_Format; } SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics( diff --git a/src/gpu/GrBinHashKey.h b/src/gpu/GrBinHashKey.h index 7d4aa0fbe8..585a1a1c01 100644 --- a/src/gpu/GrBinHashKey.h +++ b/src/gpu/GrBinHashKey.h @@ -13,37 +13,19 @@ #include "GrTypes.h" /** - * Hash function class that can take a data chunk of any predetermined length. The hash function - * used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html). - * - * Keys are computed from ENTRY objects. ENTRY must be fully ordered by a member: - * int compare(const GrTBinHashKey<ENTRY, ..>& k); - * which returns negative if the ENTRY < k, 0 if it equals k, and positive if k < the ENTRY. - * Additionally, ENTRY must be flattenable into the key using setKeyData. - * - * This class satisfies the requirements to be a key for a GrTHashTable. + * GrBinHashKey is a hash key class that can take a data chunk of any predetermined + * length. The hash function used is the One-at-a-Time Hash + * (http://burtleburtle.net/bob/hash/doobs.html). */ -template<typename ENTRY, size_t KEY_SIZE> -class GrTBinHashKey { +template<size_t KEY_SIZE> +class GrBinHashKey { public: enum { kKeySize = KEY_SIZE }; - GrTBinHashKey() { + GrBinHashKey() { this->reset(); } - GrTBinHashKey(const GrTBinHashKey<ENTRY, KEY_SIZE>& other) { - *this = other; - } - - GrTBinHashKey<ENTRY, KEY_SIZE>& operator=(const GrTBinHashKey<ENTRY, KEY_SIZE>& other) { - memcpy(this, &other, sizeof(*this)); - return *this; - } - - ~GrTBinHashKey() { - } - void reset() { fHash = 0; #ifdef SK_DEBUG @@ -52,39 +34,49 @@ public: } void setKeyData(const uint32_t* SK_RESTRICT data) { - SkASSERT(GrIsALIGN4(KEY_SIZE)); + SK_COMPILE_ASSERT(KEY_SIZE % 4 == 0, key_size_mismatch); memcpy(&fData, data, KEY_SIZE); uint32_t hash = 0; size_t len = KEY_SIZE; while (len >= 4) { hash += *data++; - hash += (fHash << 10); + hash += (hash << 10); hash ^= (hash >> 6); len -= 4; } - hash += (fHash << 3); - hash ^= (fHash >> 11); - hash += (fHash << 15); + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); #ifdef SK_DEBUG fIsValid = true; #endif fHash = hash; } - int compare(const GrTBinHashKey<ENTRY, KEY_SIZE>& key) const { + bool operator==(const GrBinHashKey<KEY_SIZE>& key) const { SkASSERT(fIsValid && key.fIsValid); - return memcmp(fData, key.fData, KEY_SIZE); - } - - static bool EQ(const ENTRY& entry, const GrTBinHashKey<ENTRY, KEY_SIZE>& key) { - SkASSERT(key.fIsValid); - return 0 == entry.compare(key); + if (fHash != key.fHash) { + return false; + } + for (size_t i = 0; i < SK_ARRAY_COUNT(fData); ++i) { + if (fData[i] != key.fData[i]) { + return false; + } + } + return true; } - static bool LT(const ENTRY& entry, const GrTBinHashKey<ENTRY, KEY_SIZE>& key) { - SkASSERT(key.fIsValid); - return entry.compare(key) < 0; + bool operator<(const GrBinHashKey<KEY_SIZE>& key) const { + SkASSERT(fIsValid && key.fIsValid); + for (size_t i = 0; i < SK_ARRAY_COUNT(fData); ++i) { + if (fData[i] < key.fData[i]) { + return true; + } else if (fData[i] > key.fData[i]) { + return false; + } + } + return false; } uint32_t getHash() const { @@ -94,12 +86,12 @@ public: const uint8_t* getData() const { SkASSERT(fIsValid); - return fData; + return reinterpret_cast<const uint8_t*>(fData); } private: uint32_t fHash; - uint8_t fData[KEY_SIZE]; // Buffer for key storage + uint32_t fData[KEY_SIZE / sizeof(uint32_t)]; // Buffer for key storage. #ifdef SK_DEBUG public: diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index 38378ac771..ca30732bbc 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -54,7 +54,7 @@ public: } GrResourceKey() { - fKey.fHashedKey.reset(); + fKey.reset(); } void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) { @@ -63,41 +63,34 @@ public: //!< returns hash value [0..kHashMask] for the key int getHash() const { - return fKey.fHashedKey.getHash() & kHashMask; + return fKey.getHash() & kHashMask; } bool isScratch() const { return ScratchDomain() == - *reinterpret_cast<const GrCacheID::Domain*>(fKey.fHashedKey.getData() + + *reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() + kCacheIDDomainOffset); } ResourceType getResourceType() const { - return *reinterpret_cast<const ResourceType*>(fKey.fHashedKey.getData() + + return *reinterpret_cast<const ResourceType*>(fKey.getData() + kResourceTypeOffset); } ResourceFlags getResourceFlags() const { - return *reinterpret_cast<const ResourceFlags*>(fKey.fHashedKey.getData() + + return *reinterpret_cast<const ResourceFlags*>(fKey.getData() + kResourceFlagsOffset); } - int compare(const GrResourceKey& other) const { - return fKey.fHashedKey.compare(other.fKey.fHashedKey); - } - - static bool LT(const GrResourceKey& a, const GrResourceKey& b) { - return a.compare(b) < 0; - } - - static bool EQ(const GrResourceKey& a, const GrResourceKey& b) { - return 0 == a.compare(b); - } + bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; } + bool operator<(const GrResourceKey& other) const { return fKey < other.fKey; } - inline static bool LT(const GrResourceEntry& entry, const GrResourceKey& key); - inline static bool EQ(const GrResourceEntry& entry, const GrResourceKey& key); - inline static bool LT(const GrResourceEntry& a, const GrResourceEntry& b); - inline static bool EQ(const GrResourceEntry& a, const GrResourceEntry& b); + static bool LessThan(const GrResourceEntry& entry, const GrResourceKey& key); + static bool Equals(const GrResourceEntry& entry, const GrResourceKey& key); +#ifdef SK_DEBUG + static bool LessThan(const GrResourceEntry& a, const GrResourceEntry& b); + static bool Equals(const GrResourceEntry& a, const GrResourceEntry& b); +#endif private: enum { @@ -125,21 +118,9 @@ private: memcpy(k + kResourceTypeOffset, &type, sizeof(ResourceType)); memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags)); memset(k + kPadOffset, 0, kPadSize); - fKey.fHashedKey.setKeyData(keyData.fKey32); + fKey.setKeyData(keyData.fKey32); } - - struct Key; - typedef GrTBinHashKey<Key, kKeySize> HashedKey; - - struct Key { - int compare(const HashedKey& hashedKey) const { - return fHashedKey.compare(hashedKey); - } - - HashedKey fHashedKey; - }; - - Key fKey; + GrBinHashKey<kKeySize> fKey; }; // The cache listens for these messages to purge junk resources proactively. @@ -174,21 +155,23 @@ private: friend class GrDLinkedList; }; -bool GrResourceKey::LT(const GrResourceEntry& entry, const GrResourceKey& key) { - return LT(entry.key(), key); +inline bool GrResourceKey::LessThan(const GrResourceEntry& entry, const GrResourceKey& key) { + return entry.key() < key; } -bool GrResourceKey::EQ(const GrResourceEntry& entry, const GrResourceKey& key) { - return EQ(entry.key(), key); +inline bool GrResourceKey::Equals(const GrResourceEntry& entry, const GrResourceKey& key) { + return entry.key() == key; } -bool GrResourceKey::LT(const GrResourceEntry& a, const GrResourceEntry& b) { - return LT(a.key(), b.key()); +#ifdef SK_DEBUG +inline bool GrResourceKey::LessThan(const GrResourceEntry& a, const GrResourceEntry& b) { + return a.key() < b.key(); } -bool GrResourceKey::EQ(const GrResourceEntry& a, const GrResourceEntry& b) { - return EQ(a.key(), b.key()); +inline bool GrResourceKey::Equals(const GrResourceEntry& a, const GrResourceEntry& b) { + return a.key() == b.key(); } +#endif /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrTHashTable.h b/src/gpu/GrTHashTable.h index 3b32977846..83462c70c9 100644 --- a/src/gpu/GrTHashTable.h +++ b/src/gpu/GrTHashTable.h @@ -16,8 +16,10 @@ /** * Key needs - * static bool EQ(const Entry&, const HashKey&); - * static bool LT(const Entry&, const HashKey&); + * static bool Equals(const Entry&, const Key&); + * static bool LessThan(const Entry&, const Key&); + * static bool Equals(const Entry&, const Entry&); for SK_DEBUG if GrTHashTable::validate() is called + * static bool LessThan(const Entry&, const Entry&); for SK_DEBUG if GrTHashTable::validate() is called * uint32_t getHash() const; * * Allows duplicate key entries but on find you may get @@ -90,7 +92,7 @@ int GrTHashTable<T, Key, kHashBits>::searchArray(const Key& key) const { int low = 0; while (high > low) { int index = (low + high) >> 1; - if (Key::LT(*array[index], key)) { + if (Key::LessThan(*array[index], key)) { low = index + 1; } else { high = index; @@ -98,15 +100,15 @@ int GrTHashTable<T, Key, kHashBits>::searchArray(const Key& key) const { } // check if we found it - if (Key::EQ(*array[high], key)) { + if (Key::Equals(*array[high], key)) { // above search should have found the first occurrence if there // are multiple. - SkASSERT(0 == high || Key::LT(*array[high - 1], key)); + SkASSERT(0 == high || Key::LessThan(*array[high - 1], key)); return high; } // now return the ~ of where we should insert it - if (Key::LT(*array[high], key)) { + if (Key::LessThan(*array[high], key)) { high += 1; } return ~high; @@ -119,7 +121,7 @@ T* GrTHashTable<T, Key, kHashBits>::find(const Key& key, Filter filter) const { int hashIndex = hash2Index(key.getHash()); T* elem = fHash[hashIndex]; - if (NULL != elem && Key::EQ(*elem, key) && filter(elem)) { + if (NULL != elem && Key::Equals(*elem, key) && filter(elem)) { return elem; } @@ -133,9 +135,9 @@ T* GrTHashTable<T, Key, kHashBits>::find(const Key& key, Filter filter) const { // above search should have found the first occurrence if there // are multiple. - SkASSERT(0 == index || Key::LT(*array[index - 1], key)); + SkASSERT(0 == index || Key::LessThan(*array[index - 1], key)); - for ( ; index < count() && Key::EQ(*array[index], key); ++index) { + for ( ; index < count() && Key::Equals(*array[index], key); ++index) { if (filter(fSorted[index])) { // update the hash fHash[hashIndex] = fSorted[index]; @@ -192,8 +194,8 @@ template <typename T, typename Key, size_t kHashBits> void GrTHashTable<T, Key, kHashBits>::validate() const { int count = fSorted.count(); for (int i = 1; i < count; i++) { - SkASSERT(Key::LT(*fSorted[i - 1], *fSorted[i]) || - Key::EQ(*fSorted[i - 1], *fSorted[i])); + SkASSERT(Key::LessThan(*fSorted[i - 1], *fSorted[i]) || + Key::Equals(*fSorted[i - 1], *fSorted[i])); } } diff --git a/src/gpu/GrTextStrike_impl.h b/src/gpu/GrTextStrike_impl.h index 42971855ff..0691eaa643 100644 --- a/src/gpu/GrTextStrike_impl.h +++ b/src/gpu/GrTextStrike_impl.h @@ -19,10 +19,10 @@ public: intptr_t getHash() const { return fFontScalerKey->getHash(); } - static bool LT(const GrTextStrike& strike, const Key& key) { + static bool LessThan(const GrTextStrike& strike, const Key& key) { return *strike.getFontScalerKey() < *key.fFontScalerKey; } - static bool EQ(const GrTextStrike& strike, const Key& key) { + static bool Equals(const GrTextStrike& strike, const Key& key) { return *strike.getFontScalerKey() == *key.fFontScalerKey; } @@ -88,10 +88,10 @@ public: uint32_t getHash() const { return fPackedID; } - static bool LT(const GrGlyph& glyph, const Key& key) { + static bool LessThan(const GrGlyph& glyph, const Key& key) { return glyph.fPackedID < key.fPackedID; } - static bool EQ(const GrGlyph& glyph, const Key& key) { + static bool Equals(const GrGlyph& glyph, const Key& key) { return glyph.fPackedID == key.fPackedID; } diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp index 651486665b..1ca9357c6b 100644 --- a/src/gpu/SkGrFontScaler.cpp +++ b/src/gpu/SkGrFontScaler.cpp @@ -85,6 +85,8 @@ GrMaskFormat SkGrFontScaler::getMaskFormat() { return kA8_GrMaskFormat; case SkMask::kLCD16_Format: return kA565_GrMaskFormat; + // TODO: properly support kARGB32_Format. + case SkMask::kARGB32_Format: case SkMask::kLCD32_Format: return kA888_GrMaskFormat; default: diff --git a/src/gpu/effects/GrTextureStripAtlas.h b/src/gpu/effects/GrTextureStripAtlas.h index e56e736d77..e06e273e26 100644 --- a/src/gpu/effects/GrTextureStripAtlas.h +++ b/src/gpu/effects/GrTextureStripAtlas.h @@ -136,12 +136,15 @@ private: // Hash table entry for atlases class AtlasEntry; - typedef GrTBinHashKey<AtlasEntry, sizeof(GrTextureStripAtlas::Desc)> AtlasHashKey; + class AtlasHashKey : public GrBinHashKey<sizeof(GrTextureStripAtlas::Desc)> { + public: + static bool Equals(const AtlasEntry& entry, const AtlasHashKey& key); + static bool LessThan(const AtlasEntry& entry, const AtlasHashKey& key); + }; class AtlasEntry : public ::SkNoncopyable { public: AtlasEntry() : fAtlas(NULL) {} ~AtlasEntry() { SkDELETE(fAtlas); } - int compare(const AtlasHashKey& key) const { return fKey.compare(key); } AtlasHashKey fKey; GrTextureStripAtlas* fAtlas; }; @@ -178,4 +181,14 @@ private: SkTDArray<AtlasRow*> fKeyTable; }; +inline bool GrTextureStripAtlas::AtlasHashKey::Equals(const AtlasEntry& entry, + const AtlasHashKey& key) { + return entry.fKey == key; +} + +inline bool GrTextureStripAtlas::AtlasHashKey::LessThan(const AtlasEntry& entry, + const AtlasHashKey& key) { + return entry.fKey < key; +} + #endif diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 9cf39b6534..00d27b31ef 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -1276,6 +1276,7 @@ void GrGpuGL::onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) { return; } } + this->flushRenderTarget(rect); GrAutoTRestore<ScissorState> asr(&fScissorState); fScissorState.fEnabled = (NULL != rect); @@ -1522,10 +1523,16 @@ void GrGpuGL::flushRenderTarget(const SkIRect* bound) { if (fHWBoundRenderTarget != rt) { GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); #ifdef SK_DEBUG - GrGLenum status; - GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); - if (status != GR_GL_FRAMEBUFFER_COMPLETE) { - GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status); + // don't do this check in Chromium -- this is causing + // lots of repeated command buffer flushes when the compositor is + // rendering with Ganesh, which is really slow; even too slow for + // Debug mode. + if (!this->glContext().info().isChromium()) { + GrGLenum status; + GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { + GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status); + } } #endif fHWBoundRenderTarget = rt; diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp deleted file mode 100644 index ae9f67f28e..0000000000 --- a/src/gpu/gr_unittests.cpp +++ /dev/null @@ -1,80 +0,0 @@ - -/* - * Copyright 2010 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrBinHashKey.h" -#include "GrDrawTarget.h" -#include "SkMatrix.h" -#include "GrRedBlackTree.h" - -// FIXME: needs to be in a header -void gr_run_unittests(); - -// If we aren't inheriting these as #defines from elsewhere, -// clang demands they be declared before we #include the template -// that relies on them. -#ifdef SK_DEBUG -static bool LT(const int& elem, int value) { - return elem < value; -} -static bool EQ(const int& elem, int value) { - return elem == value; -} -#include "GrTBSearch.h" - -static void test_bsearch() { - const int array[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99 - }; - - for (int n = 0; n < static_cast<int>(GR_ARRAY_COUNT(array)); ++n) { - for (int i = 0; i < n; i++) { - int index = GrTBSearch<int, int>(array, n, array[i]); - SkASSERT(index == (int) i); - index = GrTBSearch<int, int>(array, n, -array[i]); - SkASSERT(index < 0); - } - } -} -#endif - -// bogus empty class for GrBinHashKey -class BogusEntry {}; - -static void test_binHashKey() -{ - const char* testStringA_ = "abcdABCD"; - const char* testStringB_ = "abcdBBCD"; - const uint32_t* testStringA = reinterpret_cast<const uint32_t*>(testStringA_); - const uint32_t* testStringB = reinterpret_cast<const uint32_t*>(testStringB_); - enum { - kDataLenUsedForKey = 8 - }; - - GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA; - keyA.setKeyData(testStringA); - // test copy constructor and comparison - GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA2(keyA); - SkASSERT(keyA.compare(keyA2) == 0); - SkASSERT(keyA.getHash() == keyA2.getHash()); - // test re-init - keyA2.setKeyData(testStringA); - SkASSERT(keyA.compare(keyA2) == 0); - SkASSERT(keyA.getHash() == keyA2.getHash()); - // test sorting - GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyB; - keyB.setKeyData(testStringB); - SkASSERT(keyA.compare(keyB) < 0); - SkASSERT(keyA.getHash() != keyB.getHash()); -} - - -void gr_run_unittests() { - SkDEBUGCODE(test_bsearch();) - test_binHashKey(); - GrRedBlackTree<int>::UnitTest(); -} diff --git a/src/opts/SkBlitMask_opts_arm.cpp b/src/opts/SkBlitMask_opts_arm.cpp index 0ad0919387..2bf760313c 100644 --- a/src/opts/SkBlitMask_opts_arm.cpp +++ b/src/opts/SkBlitMask_opts_arm.cpp @@ -1,14 +1,39 @@ +#include "SkColor.h" +#include "SkColorPriv.h" #include "SkBlitMask.h" +#include "SkUtilsArm.h" +#include "SkBlitMask_opts_arm_neon.h" SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig, SkMask::Format maskFormat, SkColor color) { +#if SK_ARM_NEON_IS_NONE + return NULL; +#else +#if SK_ARM_NEON_IS_DYNAMIC + if (!sk_cpu_arm_has_neon()) { + return NULL; + } +#endif + if ((SkBitmap::kARGB_8888_Config == dstConfig) && + (SkMask::kA8_Format == maskFormat)) { + return D32_A8_Factory_neon(color); + } +#endif + + // We don't need to handle the SkMask::kLCD16_Format case as the default + // LCD16 will call us through SkBlitMask::PlatformBlitRowProcs16() + return NULL; } SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) { - return NULL; + if (isOpaque) { + return SK_ARM_NEON_WRAP(SkBlitLCD16OpaqueRow); + } else { + return SK_ARM_NEON_WRAP(SkBlitLCD16Row); + } } SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig, diff --git a/src/opts/SkColor_opts_neon.h b/src/opts/SkColor_opts_neon.h index f81239712a..85752f5558 100644 --- a/src/opts/SkColor_opts_neon.h +++ b/src/opts/SkColor_opts_neon.h @@ -2,6 +2,7 @@ #define SkColor_opts_neon_DEFINED #include "SkTypes.h" +#include "SkColorPriv.h" #include <arm_neon.h> @@ -65,4 +66,20 @@ static inline uint16x8_t SkPixel32ToPixel16_neon8(uint8x8x4_t vsrc) { return ret; } +/* This function blends 8 pixels of the same channel in the exact same way as + * SkBlend32. + */ +static inline uint8x8_t SkBlend32_neon8(uint8x8_t src, uint8x8_t dst, uint16x8_t scale) { + int16x8_t src_wide, dst_wide; + + src_wide = vreinterpretq_s16_u16(vmovl_u8(src)); + dst_wide = vreinterpretq_s16_u16(vmovl_u8(dst)); + + src_wide = (src_wide - dst_wide) * vreinterpretq_s16_u16(scale); + + dst_wide += vshrq_n_s16(src_wide, 5); + + return vmovn_u16(vreinterpretq_u16_s16(dst_wide)); +} + #endif /* #ifndef SkColor_opts_neon_DEFINED */ diff --git a/src/pdf/SkPDFImage.cpp b/src/pdf/SkPDFImage.cpp index a99c9fe390..81adcc20d6 100644 --- a/src/pdf/SkPDFImage.cpp +++ b/src/pdf/SkPDFImage.cpp @@ -36,7 +36,6 @@ 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: @@ -166,48 +165,6 @@ 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, @@ -283,14 +240,6 @@ 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(); @@ -574,8 +523,7 @@ SkPDFImage::SkPDFImage(SkStream* stream, insertName("Type", "XObject"); insertName("Subtype", "Image"); - bool alphaOnly = (config == SkBitmap::kA1_Config || - config == SkBitmap::kA8_Config); + bool alphaOnly = (config == SkBitmap::kA8_Config); if (!isAlpha && alphaOnly) { // For alpha only images, we stretch a single pixel of black for @@ -601,8 +549,6 @@ 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 54ae0773fd..ebbd40018e 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", "A1", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888" + "None", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888" }; - SkASSERT(SkBitmap::kConfigCount == 7); + SkASSERT(SkBitmap::kConfigCount == SK_ARRAY_COUNT(gConfigStrings)); mBitmap->append(" Config: "); mBitmap->append(gConfigStrings[bitmap.config()]); |