aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/animator/SkDrawBitmap.cpp9
-rw-r--r--src/core/SkBitmap.cpp68
-rw-r--r--src/core/SkBlitter.cpp5
-rw-r--r--src/core/SkBlitter_A1.cpp50
-rw-r--r--src/core/SkCoreBlitters.h16
-rw-r--r--src/core/SkGlyphCache.cpp4
-rw-r--r--src/core/SkGlyphCache.h2
-rw-r--r--src/core/SkPaint.cpp12
-rw-r--r--src/core/SkPicture.cpp13
-rw-r--r--src/core/SkScaledImageCache.cpp47
-rw-r--r--src/core/SkScaledImageCache.h4
-rw-r--r--src/core/SkScalerContext.cpp109
-rw-r--r--src/core/SkScalerContext.h57
-rw-r--r--src/core/SkString.cpp12
-rw-r--r--src/core/SkValidatingReadBuffer.cpp2
-rw-r--r--src/effects/SkDropShadowImageFilter.cpp37
-rw-r--r--src/effects/SkTransparentShader.cpp3
-rw-r--r--src/fonts/SkGScalerContext.cpp2
-rw-r--r--src/gpu/GrBinHashKey.h74
-rw-r--r--src/gpu/GrResourceCache.h67
-rw-r--r--src/gpu/GrTHashTable.h24
-rw-r--r--src/gpu/GrTextStrike_impl.h8
-rw-r--r--src/gpu/SkGrFontScaler.cpp2
-rw-r--r--src/gpu/effects/GrTextureStripAtlas.h17
-rw-r--r--src/gpu/gl/GrGpuGL.cpp15
-rw-r--r--src/gpu/gr_unittests.cpp80
-rw-r--r--src/opts/SkBlitMask_opts_arm.cpp27
-rw-r--r--src/opts/SkColor_opts_neon.h17
-rw-r--r--src/pdf/SkPDFImage.cpp56
-rw-r--r--src/utils/debugger/SkObjectParser.cpp4
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()]);