diff options
author | Android Chromium Automerger <chromium-automerger@android> | 2014-05-02 17:30:19 +0000 |
---|---|---|
committer | Android Chromium Automerger <chromium-automerger@android> | 2014-05-02 17:30:19 +0000 |
commit | f9ae730704cc91b8324622c2af3304ea106357ff (patch) | |
tree | d8b1b5022262f059c6b6ce52f1e010e631501768 | |
parent | 086c0a576a202296234038042382954beaea8d71 (diff) | |
parent | c54179f4375f836f4e53a9de6367e596e94d6e9d (diff) | |
download | src-f9ae730704cc91b8324622c2af3304ea106357ff.tar.gz |
Merge third_party/skia/src from https://chromium.googlesource.com/external/skia/src.git at c54179f4375f836f4e53a9de6367e596e94d6e9d
This commit was generated by merge_from_chromium.py.
Change-Id: Iaaa720438124aea9957ddb67f8e0f0685661b0a1
36 files changed, 729 insertions, 626 deletions
diff --git a/core/ARGB32_Clamp_Bilinear_BitmapShader.h b/core/ARGB32_Clamp_Bilinear_BitmapShader.h deleted file mode 100644 index 87121cfd..00000000 --- a/core/ARGB32_Clamp_Bilinear_BitmapShader.h +++ /dev/null @@ -1,177 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -class ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader { -public: - ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src) - : SkBitmapShader(src, true, - SkShader::kClamp_TileMode, SkShader::kClamp_TileMode) - {} - - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); -}; - -SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY, - const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table); -SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY, - const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table) -{ - int ix = fx >> 16; - int iy = fy >> 16; - - const SkPMColor *p00, *p01, *p10, *p11; - - p00 = p01 = ((const SkPMColor*)((const char*)srcPixels - + SkClampMax(iy, srcMaxY) * srcRB)) - + SkClampMax(ix, srcMaxX); - - if ((unsigned)ix < srcMaxX) - p01 += 1; - p10 = p00; - p11 = p01; - if ((unsigned)iy < srcMaxY) - { - p10 = (const SkPMColor*)((const char*)p10 + srcRB); - p11 = (const SkPMColor*)((const char*)p11 + srcRB); - } - - SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(proc_table, fx, fy); - return proc(p00, p01, p10, p11); -} - -static inline SkPMColor sample_bilerpx(SkFixed fx, unsigned srcMaxX, const SkPMColor* srcPixels, - int srcRB, const SkFilterPtrProc* proc_table) -{ - int ix = fx >> 16; - - const SkPMColor *p00, *p01, *p10, *p11; - - p00 = p01 = srcPixels + SkClampMax(ix, srcMaxX); - if ((unsigned)ix < srcMaxX) - p01 += 1; - - p10 = (const SkPMColor*)((const char*)p00 + srcRB); - p11 = (const SkPMColor*)((const char*)p01 + srcRB); - - SkFilterPtrProc proc = SkGetBilinearFilterPtrXProc(proc_table, fx); - return proc(p00, p01, p10, p11); -} - -void ARGB32_Clamp_Bilinear_BitmapShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) -{ - SkASSERT(count > 0); - - unsigned srcScale = SkAlpha255To256(this->getPaintAlpha()); - - const SkMatrix& inv = this->getTotalInverse(); - const SkBitmap& srcBitmap = this->getSrcBitmap(); - unsigned srcMaxX = srcBitmap.width() - 1; - unsigned srcMaxY = srcBitmap.height() - 1; - unsigned srcRB = srcBitmap.rowBytes(); - - const SkFilterPtrProc* proc_table = SkGetBilinearFilterPtrProcTable(); - const SkPMColor* srcPixels = (const SkPMColor*)srcBitmap.getPixels(); - - if (this->getInverseClass() == kPerspective_MatrixClass) - { - SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, count); - - if (256 == srcScale) - { - while ((count = iter.next()) != 0) - { - const SkFixed* srcXY = iter.getXY(); - while (--count >= 0) - { - SkFixed fx = *srcXY++ - SK_FixedHalf; - SkFixed fy = *srcXY++ - SK_FixedHalf; - *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); - } - } - } - else // scale by srcScale - { - while ((count = iter.next()) != 0) - { - const SkFixed* srcXY = iter.getXY(); - while (--count >= 0) - { - SkFixed fx = *srcXY++ - SK_FixedHalf; - SkFixed fy = *srcXY++ - SK_FixedHalf; - SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); - *dstC++ = SkAlphaMulQ(c, srcScale); - } - } - } - } - else // linear case - { - SkFixed fx, fy, dx, dy; - - // now init fx, fy, dx, dy - { - SkPoint srcPt; - this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, - &srcPt); - - fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf; - fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf; - - if (this->getInverseClass() == kFixedStepInX_MatrixClass) - (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); - else - { - dx = SkScalarToFixed(inv.getScaleX()); - dy = SkScalarToFixed(inv.getSkewY()); - } - } - - if (dy == 0 && (unsigned)(fy >> 16) < srcMaxY) - { - srcPixels = (const SkPMColor*)((const char*)srcPixels + (fy >> 16) * srcRB); - proc_table = SkGetBilinearFilterPtrProcYTable(proc_table, fy); - if (256 == srcScale) - { - do { - *dstC++ = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table); - fx += dx; - } while (--count != 0); - } - else - { - do { - SkPMColor c = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table); - *dstC++ = SkAlphaMulQ(c, srcScale); - fx += dx; - } while (--count != 0); - } - } - else // dy is != 0 - { - if (256 == srcScale) - { - do { - *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); - fx += dx; - fy += dy; - } while (--count != 0); - } - else - { - do { - SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); - *dstC++ = SkAlphaMulQ(c, srcScale); - fx += dx; - fy += dy; - } while (--count != 0); - } - } - } -} diff --git a/core/SkBitmapProcShader.cpp b/core/SkBitmapProcShader.cpp index 44bdc6d3..46cf7db1 100644 --- a/core/SkBitmapProcShader.cpp +++ b/core/SkBitmapProcShader.cpp @@ -97,10 +97,7 @@ static bool valid_for_drawing(const SkBitmap& bm) { return true; } -bool SkBitmapProcShader::validInternal(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse, +bool SkBitmapProcShader::validInternal(const ContextRec& rec, SkMatrix* totalInverse, SkBitmapProcState* state) const { if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) { return false; @@ -113,7 +110,7 @@ bool SkBitmapProcShader::validInternal(const SkBitmap& device, } // Do this first, so we know the matrix can be inverted. - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { + if (!this->INHERITED::validContext(rec, totalInverse)) { return false; } @@ -121,28 +118,23 @@ bool SkBitmapProcShader::validInternal(const SkBitmap& device, state->fTileModeX = fTileModeX; state->fTileModeY = fTileModeY; state->fOrigBitmap = fRawBitmap; - return state->chooseProcs(*totalInverse, paint); + return state->chooseProcs(*totalInverse, *rec.fPaint); } -bool SkBitmapProcShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { +bool SkBitmapProcShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { SkBitmapProcState state; - return this->validInternal(device, paint, matrix, totalInverse, &state); + return this->validInternal(rec, totalInverse, &state); } -SkShader::Context* SkBitmapProcShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { +SkShader::Context* SkBitmapProcShader::createContext(const ContextRec& rec, void* storage) const { void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState); - if (!this->validInternal(device, paint, matrix, NULL, state)) { + if (!this->validInternal(rec, NULL, state)) { state->~SkBitmapProcState(); return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, BitmapProcShaderContext, - (*this, device, paint, matrix, state)); + return SkNEW_PLACEMENT_ARGS(storage, BitmapProcShaderContext, (*this, rec, state)); } size_t SkBitmapProcShader::contextSize() const { @@ -152,9 +144,8 @@ size_t SkBitmapProcShader::contextSize() const { } SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext( - const SkBitmapProcShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, SkBitmapProcState* state) - : INHERITED(shader, device, paint, matrix) + const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state) + : INHERITED(shader, rec) , fState(state) { const SkBitmap& bitmap = *fState->fBitmap; @@ -182,7 +173,7 @@ SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext( break; } - if (paint.isDither() && bitmap.colorType() != kRGB_565_SkColorType) { + if (rec.fPaint->isDither() && bitmap.colorType() != kRGB_565_SkColorType) { // gradients can auto-dither in their 16bit sampler, but we don't so // we clear the flag here. flags &= ~kHasSpan16_Flag; diff --git a/core/SkBitmapProcShader.h b/core/SkBitmapProcShader.h index 78b46ce6..e32d35e2 100644 --- a/core/SkBitmapProcShader.h +++ b/core/SkBitmapProcShader.h @@ -23,12 +23,8 @@ public: virtual bool isOpaque() const SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE; - virtual bool validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, void* storage) const SK_OVERRIDE; + virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty); @@ -44,11 +40,7 @@ public: public: // The context takes ownership of the state. It will call its destructor // but will NOT free the memory. - BitmapProcShaderContext(const SkBitmapProcShader& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkBitmapProcState* state); + BitmapProcShaderContext(const SkBitmapProcShader&, const ContextRec&, SkBitmapProcState*); virtual ~BitmapProcShaderContext(); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; @@ -72,9 +64,7 @@ protected: uint8_t fTileModeX, fTileModeY; private: - bool validInternal(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse, - SkBitmapProcState* state) const; + bool validInternal(const ContextRec&, SkMatrix* totalInverse, SkBitmapProcState*) const; typedef SkShader INHERITED; }; diff --git a/core/SkBlitter.cpp b/core/SkBlitter.cpp index 41f37e65..74cd2982 100644 --- a/core/SkBlitter.cpp +++ b/core/SkBlitter.cpp @@ -591,51 +591,44 @@ public: return size; } - virtual bool validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse = NULL) const - SK_OVERRIDE - { - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { + virtual bool validContext(const ContextRec& rec, SkMatrix* totalInverse) const SK_OVERRIDE { + if (!this->INHERITED::validContext(rec, totalInverse)) { return false; } if (fProxy) { - return fProxy->validContext(device, paint, matrix); + return fProxy->validContext(rec); } return true; } - virtual SkShader::Context* createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const SK_OVERRIDE + virtual SkShader::Context* createContext(const ContextRec& rec, void* storage) const SK_OVERRIDE { - if (!this->validContext(device, paint, matrix)) { + if (!this->validContext(rec, NULL)) { return NULL; } SkShader::Context* proxyContext; if (fProxy) { char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext); - proxyContext = fProxy->createContext(device, paint, matrix, proxyContextStorage); + proxyContext = fProxy->createContext(rec, proxyContextStorage); SkASSERT(proxyContext); } else { proxyContext = NULL; } - return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, device, paint, matrix, - proxyContext)); + return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, rec, proxyContext)); } class Sk3DShaderContext : public SkShader::Context { public: // Calls proxyContext's destructor but will NOT free its memory. - Sk3DShaderContext(const Sk3DShader& shader, const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkShader::Context* proxyContext) - : INHERITED(shader, device, paint, matrix) + Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec, + SkShader::Context* proxyContext) + : INHERITED(shader, rec) , fMask(NULL) , fProxyContext(proxyContext) { if (!fProxyContext) { - fPMColor = SkPreMultiplyColor(paint.getColor()); + fPMColor = SkPreMultiplyColor(rec.fPaint->getColor()); } } @@ -954,9 +947,10 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, */ SkShader::Context* shaderContext; if (shader) { + SkShader::ContextRec rec(device, *paint, matrix); // Try to create the ShaderContext void* storage = allocator->reserveT<SkShader::Context>(shader->contextSize()); - shaderContext = shader->createContext(device, *paint, matrix, storage); + shaderContext = shader->createContext(rec, storage); if (!shaderContext) { allocator->freeLast(); blitter = allocator->createT<SkNullBlitter>(); @@ -1040,7 +1034,8 @@ SkShaderBlitter::~SkShaderBlitter() { bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { - if (!fShader->validContext(device, paint, matrix)) { + SkShader::ContextRec rec(device, paint, matrix); + if (!fShader->validContext(rec)) { return false; } @@ -1050,7 +1045,7 @@ bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& // The new context will be of the same size as the old one because we use the same // shader to create it. It is therefore safe to re-use the storage. fShaderContext->~Context(); - fShaderContext = fShader->createContext(device, paint, matrix, (void*)fShaderContext); + fShaderContext = fShader->createContext(rec, (void*)fShaderContext); SkASSERT(fShaderContext); return true; diff --git a/core/SkComposeShader.cpp b/core/SkComposeShader.cpp index 2c27c9e7..df8215c1 100644 --- a/core/SkComposeShader.cpp +++ b/core/SkComposeShader.cpp @@ -78,11 +78,8 @@ void SkComposeShader::flatten(SkWriteBuffer& buffer) const { really is translucent, then we apply that after the fact. */ -bool SkComposeShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { +bool SkComposeShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { + if (!this->INHERITED::validContext(rec, totalInverse)) { return false; } @@ -90,48 +87,49 @@ bool SkComposeShader::validContext(const SkBitmap& device, // before calling our sub-shaders SkMatrix tmpM; + tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix()); - tmpM.setConcat(matrix, this->getLocalMatrix()); + ContextRec newRec(rec); + newRec.fMatrix = &tmpM; - return fShaderA->validContext(device, paint, tmpM) && - fShaderB->validContext(device, paint, tmpM); + return fShaderA->validContext(newRec) && fShaderB->validContext(newRec); } -SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkComposeShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } + // TODO : must fix this to not "cheat" and modify fPaint + SkAutoAlphaRestore restore(const_cast<SkPaint*>(rec.fPaint), 0xFF); + + char* aStorage = (char*) storage + sizeof(ComposeShaderContext); + char* bStorage = aStorage + fShaderA->contextSize(); + // we preconcat our localMatrix (if any) with the device matrix // before calling our sub-shaders SkMatrix tmpM; + tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix()); - tmpM.setConcat(matrix, this->getLocalMatrix()); - - SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); - - char* aStorage = (char*) storage + sizeof(ComposeShaderContext); - char* bStorage = aStorage + fShaderA->contextSize(); + ContextRec newRec(rec); + newRec.fMatrix = &tmpM; - SkShader::Context* contextA = fShaderA->createContext(device, paint, tmpM, aStorage); - SkShader::Context* contextB = fShaderB->createContext(device, paint, tmpM, bStorage); + SkShader::Context* contextA = fShaderA->createContext(newRec, aStorage); + SkShader::Context* contextB = fShaderB->createContext(newRec, bStorage); // Both functions must succeed; otherwise validContext should have returned // false. SkASSERT(contextA); SkASSERT(contextB); - return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, - (*this, device, paint, matrix, contextA, contextB)); + return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, (*this, rec, contextA, contextB)); } SkComposeShader::ComposeShaderContext::ComposeShaderContext( - const SkComposeShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, + const SkComposeShader& shader, const ContextRec& rec, SkShader::Context* contextA, SkShader::Context* contextB) - : INHERITED(shader, device, paint, matrix) + : INHERITED(shader, rec) , fShaderContextA(contextA) , fShaderContextB(contextB) {} diff --git a/core/SkDraw.cpp b/core/SkDraw.cpp index f9e06e52..c4f5f74e 100644 --- a/core/SkDraw.cpp +++ b/core/SkDraw.cpp @@ -2353,14 +2353,12 @@ class SkTriColorShader : public SkShader { public: SkTriColorShader() {} - virtual SkShader::Context* createContext( - const SkBitmap&, const SkPaint&, const SkMatrix&, void*) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void*) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class TriColorShaderContext : public SkShader::Context { public: - TriColorShaderContext(const SkTriColorShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); + TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&); virtual ~TriColorShaderContext(); bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); @@ -2384,13 +2382,12 @@ private: typedef SkShader INHERITED; }; -SkShader::Context* SkTriColorShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkTriColorShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec)); } bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], @@ -2430,10 +2427,9 @@ static int ScalarTo256(SkScalar v) { } -SkTriColorShader::TriColorShaderContext::TriColorShaderContext( - const SkTriColorShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) {} +SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader, + const ContextRec& rec) + : INHERITED(shader, rec) {} SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} diff --git a/core/SkFilterShader.cpp b/core/SkFilterShader.cpp index 5c5e8f31..f1cc68d0 100644 --- a/core/SkFilterShader.cpp +++ b/core/SkFilterShader.cpp @@ -55,41 +55,30 @@ uint32_t SkFilterShader::FilterShaderContext::getFlags() const { return shaderF; } -SkShader::Context* SkFilterShader::createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkFilterShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec, NULL)) { return NULL; } char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext); - SkShader::Context* shaderContext = fShader->createContext(device, paint, matrix, - shaderContextStorage); + SkShader::Context* shaderContext = fShader->createContext(rec, shaderContextStorage); SkASSERT(shaderContext); - return SkNEW_PLACEMENT_ARGS(storage, FilterShaderContext, - (*this, shaderContext, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, FilterShaderContext, (*this, shaderContext, rec)); } size_t SkFilterShader::contextSize() const { return sizeof(FilterShaderContext) + fShader->contextSize(); } -bool SkFilterShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - return this->INHERITED::validContext(device, paint, matrix, totalInverse) && - fShader->validContext(device, paint, matrix); +bool SkFilterShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { + return this->INHERITED::validContext(rec, totalInverse) && fShader->validContext(rec); } SkFilterShader::FilterShaderContext::FilterShaderContext(const SkFilterShader& filterShader, SkShader::Context* shaderContext, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix) - : INHERITED(filterShader, device, paint, matrix) + const ContextRec& rec) + : INHERITED(filterShader, rec) , fShaderContext(shaderContext) {} SkFilterShader::FilterShaderContext::~FilterShaderContext() { diff --git a/core/SkFilterShader.h b/core/SkFilterShader.h index 4ef45772..629f3f8c 100644 --- a/core/SkFilterShader.h +++ b/core/SkFilterShader.h @@ -17,17 +17,14 @@ public: SkFilterShader(SkShader* shader, SkColorFilter* filter); virtual ~SkFilterShader(); - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, void* storage) const SK_OVERRIDE; + virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class FilterShaderContext : public SkShader::Context { public: // Takes ownership of shaderContext and calls its destructor. - FilterShaderContext(const SkFilterShader& filterShader, SkShader::Context* shaderContext, - const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); + FilterShaderContext(const SkFilterShader&, SkShader::Context*, const ContextRec&); virtual ~FilterShaderContext(); virtual uint32_t getFlags() const SK_OVERRIDE; diff --git a/core/SkPictureShader.cpp b/core/SkPictureShader.cpp index 466c5e12..27cbb00f 100644 --- a/core/SkPictureShader.cpp +++ b/core/SkPictureShader.cpp @@ -106,35 +106,31 @@ SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const { return fCachedBitmapShader; } -SkShader* SkPictureShader::validInternal(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const { - if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { +SkShader* SkPictureShader::validInternal(const ContextRec& rec, SkMatrix* totalInverse) const { + if (!this->INHERITED::validContext(rec, totalInverse)) { return NULL; } - SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(matrix)); - if (!bitmapShader || !bitmapShader->validContext(device, paint, matrix)) { + SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix)); + if (!bitmapShader || !bitmapShader->validContext(rec)) { return NULL; } return bitmapShader.detach(); } -bool SkPictureShader::validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const { - SkAutoTUnref<SkShader> shader(this->validInternal(device, paint, matrix, totalInverse)); +bool SkPictureShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { + SkAutoTUnref<SkShader> shader(this->validInternal(rec, totalInverse)); return shader != NULL; } -SkShader::Context* SkPictureShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - SkAutoTUnref<SkShader> bitmapShader(this->validInternal(device, paint, matrix, NULL)); +SkShader::Context* SkPictureShader::createContext(const ContextRec& rec, void* storage) const { + SkAutoTUnref<SkShader> bitmapShader(this->validInternal(rec, NULL)); if (!bitmapShader) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext, - (*this, device, paint, matrix, bitmapShader.detach())); + return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext, (*this, rec, bitmapShader.detach())); } size_t SkPictureShader::contextSize() const { @@ -142,15 +138,13 @@ size_t SkPictureShader::contextSize() const { } SkPictureShader::PictureShaderContext::PictureShaderContext( - const SkPictureShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, SkShader* bitmapShader) - : INHERITED(shader, device, paint, matrix) + const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader) + : INHERITED(shader, rec) , fBitmapShader(bitmapShader) { SkASSERT(fBitmapShader); fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize()); - fBitmapShaderContext = fBitmapShader->createContext( - device, paint, matrix, fBitmapShaderContextStorage); + fBitmapShaderContext = fBitmapShader->createContext(rec, fBitmapShaderContextStorage); SkASSERT(fBitmapShaderContext); } diff --git a/core/SkPictureShader.h b/core/SkPictureShader.h index d1be0591..510c9888 100644 --- a/core/SkPictureShader.h +++ b/core/SkPictureShader.h @@ -24,18 +24,13 @@ public: static SkPictureShader* Create(SkPicture*, TileMode, TileMode); virtual ~SkPictureShader(); - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const - SK_OVERRIDE; + virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class PictureShaderContext : public SkShader::Context { public: - PictureShaderContext(const SkPictureShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix, - SkShader* bitmapShader); + PictureShaderContext(const SkPictureShader&, const ContextRec&, SkShader* bitmapShader); virtual ~PictureShaderContext(); virtual uint32_t getFlags() const SK_OVERRIDE; @@ -66,9 +61,7 @@ protected: private: SkPictureShader(SkPicture*, TileMode, TileMode); - SkShader* validInternal(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const; - + SkShader* validInternal(const ContextRec&, SkMatrix* totalInverse) const; SkShader* refBitmapShader(const SkMatrix&) const; SkPicture* fPicture; diff --git a/core/SkShader.cpp b/core/SkShader.cpp index a449d0fd..0f6ba4ce 100644 --- a/core/SkShader.cpp +++ b/core/SkShader.cpp @@ -56,15 +56,11 @@ bool SkShader::computeTotalInverse(const SkMatrix& matrix, SkMatrix* totalInvers return m->invert(totalInverse); } -bool SkShader::validContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - SkMatrix* totalInverse) const { - return this->computeTotalInverse(matrix, totalInverse); +bool SkShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { + return this->computeTotalInverse(*rec.fMatrix, totalInverse); } -SkShader::Context* SkShader::createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const { +SkShader::Context* SkShader::createContext(const ContextRec&, void* storage) const { return NULL; } @@ -72,18 +68,17 @@ size_t SkShader::contextSize() const { return 0; } -SkShader::Context::Context(const SkShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) +SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) : fShader(shader) { - SkASSERT(fShader.validContext(device, paint, matrix)); + SkASSERT(fShader.validContext(rec)); // Because the context parameters must be valid at this point, we know that the matrix is // invertible. - SkAssertResult(fShader.computeTotalInverse(matrix, &fTotalInverse)); + SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, &fTotalInverse)); fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); - fPaintAlpha = paint.getAlpha(); + fPaintAlpha = rec.fPaint->getAlpha(); } SkShader::Context::~Context() {} @@ -250,23 +245,20 @@ uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { return SkGetPackedA32(fPMColor); } -SkShader::Context* SkColorShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkColorShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec)); } SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) + const ContextRec& rec) + : INHERITED(shader, rec) { SkColor color = shader.fColor; - unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha())); + unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); unsigned r = SkColorGetR(color); unsigned g = SkColorGetG(color); @@ -285,7 +277,7 @@ SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shade fFlags = kConstInY32_Flag; if (255 == a) { fFlags |= kOpaqueAlpha_Flag; - if (paint.isDither() == false) { + if (rec.fPaint->isDither() == false) { fFlags |= kHasSpan16_Flag; } } diff --git a/core/SkXfermode.cpp b/core/SkXfermode.cpp index 73d0b01e..182d3b71 100644 --- a/core/SkXfermode.cpp +++ b/core/SkXfermode.cpp @@ -774,118 +774,6 @@ void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, } } -/////////////////////////////////////////////////////////////////////////////// -#ifdef SK_SUPPORT_LEGACY_PROCXFERMODE - -void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - const SkAlpha* SK_RESTRICT aa) const { - SkASSERT(dst && src && count >= 0); - - SkXfermodeProc proc = fProc; - - if (NULL != proc) { - if (NULL == aa) { - for (int i = count - 1; i >= 0; --i) { - dst[i] = proc(src[i], dst[i]); - } - } else { - for (int i = count - 1; i >= 0; --i) { - unsigned a = aa[i]; - if (0 != a) { - SkPMColor dstC = dst[i]; - SkPMColor C = proc(src[i], dstC); - if (a != 0xFF) { - C = SkFourByteInterp(C, dstC, a); - } - dst[i] = C; - } - } - } - } -} - -void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - const SkAlpha* SK_RESTRICT aa) const { - SkASSERT(dst && src && count >= 0); - - SkXfermodeProc proc = fProc; - - if (NULL != proc) { - if (NULL == aa) { - for (int i = count - 1; i >= 0; --i) { - SkPMColor dstC = SkPixel16ToPixel32(dst[i]); - dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); - } - } else { - for (int i = count - 1; i >= 0; --i) { - unsigned a = aa[i]; - if (0 != a) { - SkPMColor dstC = SkPixel16ToPixel32(dst[i]); - SkPMColor C = proc(src[i], dstC); - if (0xFF != a) { - C = SkFourByteInterp(C, dstC, a); - } - dst[i] = SkPixel32ToPixel16_ToU16(C); - } - } - } - } -} - -void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - const SkAlpha* SK_RESTRICT aa) const { - SkASSERT(dst && src && count >= 0); - - SkXfermodeProc proc = fProc; - - if (NULL != proc) { - if (NULL == aa) { - for (int i = count - 1; i >= 0; --i) { - SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); - dst[i] = SkToU8(SkGetPackedA32(res)); - } - } else { - for (int i = count - 1; i >= 0; --i) { - unsigned a = aa[i]; - if (0 != a) { - SkAlpha dstA = dst[i]; - SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); - unsigned A = SkGetPackedA32(res); - if (0xFF != a) { - A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); - } - dst[i] = SkToU8(A); - } - } - } - } -} - -SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer) - : SkXfermode(buffer) { - fProc = NULL; - if (!buffer.isCrossProcess()) { - fProc = (SkXfermodeProc)buffer.readFunctionPtr(); - } -} - -void SkProcXfermode::flatten(SkWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - if (!buffer.isCrossProcess()) { - buffer.writeFunctionPtr((void*)fProc); - } -} - -#ifndef SK_IGNORE_TO_STRING -void SkProcXfermode::toString(SkString* str) const { - str->appendf("SkProcXfermode: %p", fProc); -} -#endif - -#endif ////////////////////////////////////////////////////////////////////////////// #if SK_SUPPORT_GPU diff --git a/effects/SkBlurMaskFilter.cpp b/effects/SkBlurMaskFilter.cpp index 5dffd6fd..2169a42c 100644 --- a/effects/SkBlurMaskFilter.cpp +++ b/effects/SkBlurMaskFilter.cpp @@ -28,6 +28,10 @@ #include "SkDraw.h" #endif +SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { + return SkBlurMask::ConvertRadiusToSigma(radius); +} + class SkBlurMaskFilterImpl : public SkMaskFilter { public: SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags); diff --git a/effects/SkMatrixConvolutionImageFilter.cpp b/effects/SkMatrixConvolutionImageFilter.cpp index 3c9fc877..be1dcb4c 100644 --- a/effects/SkMatrixConvolutionImageFilter.cpp +++ b/effects/SkMatrixConvolutionImageFilter.cpp @@ -153,6 +153,9 @@ void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect, const SkIRect& bounds) const { + if (rect.isEmpty()) { + return; + } for (int y = rect.fTop; y < rect.fBottom; ++y) { SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bounds.fTop); for (int x = rect.fLeft; x < rect.fRight; ++x) { diff --git a/effects/SkPerlinNoiseShader.cpp b/effects/SkPerlinNoiseShader.cpp index 5adb5825..a4944fb8 100644 --- a/effects/SkPerlinNoiseShader.cpp +++ b/effects/SkPerlinNoiseShader.cpp @@ -425,13 +425,12 @@ SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); } -SkShader::Context* SkPerlinNoiseShader::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkPerlinNoiseShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec)); } size_t SkPerlinNoiseShader::contextSize() const { @@ -439,11 +438,10 @@ size_t SkPerlinNoiseShader::contextSize() const { } SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( - const SkPerlinNoiseShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) + const SkPerlinNoiseShader& shader, const ContextRec& rec) + : INHERITED(shader, rec) { - SkMatrix newMatrix = matrix; + SkMatrix newMatrix = *rec.fMatrix; newMatrix.postConcat(shader.getLocalMatrix()); SkMatrix invMatrix; if (!newMatrix.invert(&invMatrix)) { diff --git a/effects/SkTransparentShader.cpp b/effects/SkTransparentShader.cpp index 0997e620..9a390ad6 100644 --- a/effects/SkTransparentShader.cpp +++ b/effects/SkTransparentShader.cpp @@ -11,15 +11,12 @@ #include "SkColorPriv.h" #include "SkString.h" -SkShader::Context* SkTransparentShader::createContext(const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix, - void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkTransparentShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec)); } size_t SkTransparentShader::contextSize() const { @@ -27,10 +24,9 @@ size_t SkTransparentShader::contextSize() const { } SkTransparentShader::TransparentShaderContext::TransparentShaderContext( - const SkTransparentShader& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) - , fDevice(&device) {} + const SkTransparentShader& shader, const ContextRec& rec) + : INHERITED(shader, rec) + , fDevice(rec.fDevice) {} SkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {} diff --git a/effects/gradients/SkGradientShader.cpp b/effects/gradients/SkGradientShader.cpp index 6d753a95..d376b222 100644 --- a/effects/gradients/SkGradientShader.cpp +++ b/effects/gradients/SkGradientShader.cpp @@ -253,9 +253,8 @@ bool SkGradientShaderBase::isOpaque() const { } SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( - const SkGradientShaderBase& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) + const SkGradientShaderBase& shader, const ContextRec& rec) + : INHERITED(shader, rec) , fCache(shader.refCache(getPaintAlpha())) { const SkMatrix& inverse = this->getTotalInverse(); diff --git a/effects/gradients/SkGradientShaderPriv.h b/effects/gradients/SkGradientShaderPriv.h index c1e253fd..a699c4ce 100644 --- a/effects/gradients/SkGradientShaderPriv.h +++ b/effects/gradients/SkGradientShaderPriv.h @@ -142,9 +142,7 @@ public: class GradientShaderBaseContext : public SkShader::Context { public: - GradientShaderBaseContext(const SkGradientShaderBase& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~GradientShaderBaseContext() {} + GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&); virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; } diff --git a/effects/gradients/SkLinearGradient.cpp b/effects/gradients/SkLinearGradient.cpp index 70bbbf3b..b9de651f 100644 --- a/effects/gradients/SkLinearGradient.cpp +++ b/effects/gradients/SkLinearGradient.cpp @@ -76,24 +76,22 @@ size_t SkLinearGradient::contextSize() const { return sizeof(LinearGradientContext); } -SkShader::Context* SkLinearGradient::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkLinearGradient::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, LinearGradientContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, LinearGradientContext, (*this, rec)); } SkLinearGradient::LinearGradientContext::LinearGradientContext( - const SkLinearGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) + const SkLinearGradient& shader, const ContextRec& rec) + : INHERITED(shader, rec) { unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; if ((fDstToIndex.getType() & ~mask) == 0) { // when we dither, we are (usually) not const-in-Y - if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) { + if ((fFlags & SkShader::kHasSpan16_Flag) && !rec.fPaint->isDither()) { // only claim this if we do have a 16bit mode (i.e. none of our // colors have alpha), and if we are not dithering (which obviously // is not const in Y). diff --git a/effects/gradients/SkLinearGradient.h b/effects/gradients/SkLinearGradient.h index 699d76ed..d9ffc77c 100644 --- a/effects/gradients/SkLinearGradient.h +++ b/effects/gradients/SkLinearGradient.h @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * @@ -15,14 +14,12 @@ class SkLinearGradient : public SkGradientShaderBase { public: SkLinearGradient(const SkPoint pts[2], const Descriptor&, const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class LinearGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { public: - LinearGradientContext(const SkLinearGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); + LinearGradientContext(const SkLinearGradient&, const ContextRec&); ~LinearGradientContext() {} virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; diff --git a/effects/gradients/SkRadialGradient.cpp b/effects/gradients/SkRadialGradient.cpp index f13d55c6..07ee680a 100644 --- a/effects/gradients/SkRadialGradient.cpp +++ b/effects/gradients/SkRadialGradient.cpp @@ -161,19 +161,17 @@ size_t SkRadialGradient::contextSize() const { return sizeof(RadialGradientContext); } -SkShader::Context* SkRadialGradient::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkRadialGradient::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, rec)); } SkRadialGradient::RadialGradientContext::RadialGradientContext( - const SkRadialGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) {} + const SkRadialGradient& shader, const ContextRec& rec) + : INHERITED(shader, rec) {} void SkRadialGradient::RadialGradientContext::shadeSpan16(int x, int y, uint16_t* dstCParam, int count) { diff --git a/effects/gradients/SkRadialGradient.h b/effects/gradients/SkRadialGradient.h index 7aafe2d1..87302473 100644 --- a/effects/gradients/SkRadialGradient.h +++ b/effects/gradients/SkRadialGradient.h @@ -16,15 +16,12 @@ public: SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&, const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class RadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { public: - RadialGradientContext(const SkRadialGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~RadialGradientContext() {} + RadialGradientContext(const SkRadialGradient&, const ContextRec&); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; diff --git a/effects/gradients/SkSweepGradient.cpp b/effects/gradients/SkSweepGradient.cpp index a65631c6..0baf5c71 100644 --- a/effects/gradients/SkSweepGradient.cpp +++ b/effects/gradients/SkSweepGradient.cpp @@ -56,19 +56,17 @@ size_t SkSweepGradient::contextSize() const { return sizeof(SweepGradientContext); } -SkShader::Context* SkSweepGradient::createContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkSweepGradient::createContext(const ContextRec& rec, void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, SweepGradientContext, (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, SweepGradientContext, (*this, rec)); } SkSweepGradient::SweepGradientContext::SweepGradientContext( - const SkSweepGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) {} + const SkSweepGradient& shader, const ContextRec& rec) + : INHERITED(shader, rec) {} // returns angle in a circle [0..2PI) -> [0..255] static unsigned SkATan2_255(float y, float x) { diff --git a/effects/gradients/SkSweepGradient.h b/effects/gradients/SkSweepGradient.h index 15c5b634..9ddd1e25 100644 --- a/effects/gradients/SkSweepGradient.h +++ b/effects/gradients/SkSweepGradient.h @@ -16,15 +16,12 @@ public: SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&, const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class SweepGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { public: - SweepGradientContext(const SkSweepGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix); - ~SweepGradientContext() {} + SweepGradientContext(const SkSweepGradient& shader, const ContextRec&); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; diff --git a/effects/gradients/SkTwoPointConicalGradient.cpp b/effects/gradients/SkTwoPointConicalGradient.cpp index 9d1f8f1a..e9c2efe3 100644 --- a/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/effects/gradients/SkTwoPointConicalGradient.cpp @@ -221,21 +221,18 @@ size_t SkTwoPointConicalGradient::contextSize() const { return sizeof(TwoPointConicalGradientContext); } -SkShader::Context* SkTwoPointConicalGradient::createContext( - const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkTwoPointConicalGradient::createContext(const ContextRec& rec, + void* storage) const { + if (!this->validContext(rec)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, - (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, (*this, rec)); } SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext( - const SkTwoPointConicalGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) + const SkTwoPointConicalGradient& shader, const ContextRec& rec) + : INHERITED(shader, rec) { // we don't have a span16 proc fFlags &= ~kHasSpan16_Flag; diff --git a/effects/gradients/SkTwoPointConicalGradient.h b/effects/gradients/SkTwoPointConicalGradient.h index 13ce3eaf..1c5e409a 100644 --- a/effects/gradients/SkTwoPointConicalGradient.h +++ b/effects/gradients/SkTwoPointConicalGradient.h @@ -48,16 +48,12 @@ public: const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class TwoPointConicalGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { public: - TwoPointConicalGradientContext(const SkTwoPointConicalGradient& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix); + TwoPointConicalGradientContext(const SkTwoPointConicalGradient&, const ContextRec&); ~TwoPointConicalGradientContext() {} virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; diff --git a/effects/gradients/SkTwoPointRadialGradient.cpp b/effects/gradients/SkTwoPointRadialGradient.cpp index 41e577fb..f691db29 100644 --- a/effects/gradients/SkTwoPointRadialGradient.cpp +++ b/effects/gradients/SkTwoPointRadialGradient.cpp @@ -224,31 +224,27 @@ size_t SkTwoPointRadialGradient::contextSize() const { return sizeof(TwoPointRadialGradientContext); } -bool SkTwoPointRadialGradient::validContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, SkMatrix* totalInverse) const { +bool SkTwoPointRadialGradient::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { // For now, we might have divided by zero, so detect that. if (0 == fDiffRadius) { return false; } - return this->INHERITED::validContext(device, paint, matrix, totalInverse); + return this->INHERITED::validContext(rec, totalInverse); } -SkShader::Context* SkTwoPointRadialGradient::createContext( - const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix, void* storage) const { - if (!this->validContext(device, paint, matrix)) { +SkShader::Context* SkTwoPointRadialGradient::createContext(const ContextRec& rec, + void* storage) const { + if (!this->validContext(rec, NULL)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, - (*this, device, paint, matrix)); + return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, (*this, rec)); } SkTwoPointRadialGradient::TwoPointRadialGradientContext::TwoPointRadialGradientContext( - const SkTwoPointRadialGradient& shader, const SkBitmap& device, - const SkPaint& paint, const SkMatrix& matrix) - : INHERITED(shader, device, paint, matrix) + const SkTwoPointRadialGradient& shader, const ContextRec& rec) + : INHERITED(shader, rec) { // we don't have a span16 proc fFlags &= ~kHasSpan16_Flag; diff --git a/effects/gradients/SkTwoPointRadialGradient.h b/effects/gradients/SkTwoPointRadialGradient.h index 1b387e68..de5b5434 100644 --- a/effects/gradients/SkTwoPointRadialGradient.h +++ b/effects/gradients/SkTwoPointRadialGradient.h @@ -23,20 +23,13 @@ public: virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE; virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE; - virtual size_t contextSize() const SK_OVERRIDE; - virtual bool validContext(const SkBitmap&, const SkPaint&, - const SkMatrix&, SkMatrix* totalInverse = NULL) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&, - void* storage) const SK_OVERRIDE; + virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; + virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; class TwoPointRadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { public: - TwoPointRadialGradientContext(const SkTwoPointRadialGradient& shader, - const SkBitmap& device, - const SkPaint& paint, - const SkMatrix& matrix); - ~TwoPointRadialGradientContext() {} + TwoPointRadialGradientContext(const SkTwoPointRadialGradient&, const ContextRec&); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; diff --git a/gpu/SkGpuDevice.cpp b/gpu/SkGpuDevice.cpp index 4af16109..60b4e7c4 100644 --- a/gpu/SkGpuDevice.cpp +++ b/gpu/SkGpuDevice.cpp @@ -1289,6 +1289,11 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, SkCanvas::DrawBitmapRectFlags flags, int tileSize, bool bicubic) { + // The following pixel lock is technically redundant, but it is desirable + // to lock outside of the tile loop to prevent redecoding the whole image + // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that + // is larger than the limit of the discardable memory pool. + SkAutoLockPixels alp(bitmap); SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect); int nx = bitmap.width() / tileSize; diff --git a/gpu/gl/GrGLInterface.cpp b/gpu/gl/GrGLInterface.cpp index 5bf0efb7..056a6018 100644 --- a/gpu/gl/GrGLInterface.cpp +++ b/gpu/gl/GrGLInterface.cpp @@ -116,9 +116,15 @@ GrGLInterface* GrGLInterface::NewClone(const GrGLInterface* interface) { return clone; } -#define RETURN_FALSE_INTERFACE \ - SkDEBUGFAIL("GrGLInterface::validate() failed."); \ - return false; \ +#ifdef SK_DEBUG + static int kIsDebug = 1; +#else + static int kIsDebug = 0; +#endif + +#define RETURN_FALSE_INTERFACE \ + if (kIsDebug) { SkDebugf("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); } \ + return false; bool GrGLInterface::validate() const { diff --git a/gpu/gl/GrGLUtil.cpp b/gpu/gl/GrGLUtil.cpp index ddfcfbf0..0fa2d2ce 100644 --- a/gpu/gl/GrGLUtil.cpp +++ b/gpu/gl/GrGLUtil.cpp @@ -99,7 +99,7 @@ bool get_gl_version_for_mesa(int mesaMajorVersion, int* major, int* minor) { GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) { if (NULL == versionString) { - SkDEBUGFAIL("NULL GL version string."); + SkDebugf("NULL GL version string."); return kNone_GrGLStandard; } @@ -139,7 +139,7 @@ bool GrGLIsChromiumFromRendererString(const char* rendererString) { GrGLVersion GrGLGetVersionFromString(const char* versionString) { if (NULL == versionString) { - SkDEBUGFAIL("NULL GL version string."); + SkDebugf("NULL GL version string."); return GR_GL_INVALID_VER; } @@ -178,7 +178,7 @@ GrGLVersion GrGLGetVersionFromString(const char* versionString) { GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) { if (NULL == versionString) { - SkDEBUGFAIL("NULL GLSL version string."); + SkDebugf("NULL GLSL version string."); return GR_GLSL_INVALID_VER; } diff --git a/ports/SkFontHost_win_dw.cpp b/ports/SkFontHost_win_dw.cpp index 36ed4d4f..cd32fdbf 100644 --- a/ports/SkFontHost_win_dw.cpp +++ b/ports/SkFontHost_win_dw.cpp @@ -22,7 +22,10 @@ #include "SkGlyph.h" #include "SkHRESULT.h" #include "SkMaskGamma.h" +#include "SkMatrix22.h" #include "SkOnce.h" +#include "SkOTTable_EBLC.h" +#include "SkOTTable_EBSC.h" #include "SkOTTable_head.h" #include "SkOTTable_hhea.h" #include "SkOTTable_OS_2.h" @@ -449,7 +452,22 @@ private: const void* drawDWMask(const SkGlyph& glyph); SkTDArray<uint8_t> fBits; + /** The total matrix without the text height scale. */ + SkMatrix fSkXform; + /** The total matrix without the text height scale. */ DWRITE_MATRIX fXform; + /** The non-rotational part of total matrix without the text height scale. + * This is used to find the magnitude of gdi compatible advances. + */ + DWRITE_MATRIX fGsA; + /** The inverse of the rotational part of the total matrix. + * This is used to find the direction of gdi compatible advances. + */ + SkMatrix fG_inv; + /** The text size to render with. */ + SkScalar fTextSizeRender; + /** The text size to measure with. */ + SkScalar fTextSizeMeasure; SkAutoTUnref<DWriteFontTypeface> fTypeface; int fGlyphCount; DWRITE_RENDERING_MODE fRenderingMode; @@ -570,32 +588,224 @@ static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; } +class AutoDWriteTable { +public: + AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) { + // Any errors are ignored, user must check fExists anyway. + fontFace->TryGetFontTable(beTag, + reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); + } + ~AutoDWriteTable() { + if (fExists) { + fFontFace->ReleaseFontTable(fLock); + } + } + + const uint8_t* fData; + UINT32 fSize; + BOOL fExists; +private: + // Borrowed reference, the user must ensure the fontFace stays alive. + IDWriteFontFace* fFontFace; + void* fLock; +}; +template<typename T> class AutoTDWriteTable : public AutoDWriteTable { +public: + static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3); + AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { } + + const T* get() const { return reinterpret_cast<const T*>(fData); } + const T* operator->() const { return reinterpret_cast<const T*>(fData); } +}; + +static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { + { + AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get()); + if (!eblc.fExists) { + return false; + } + if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { + return false; + } + if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { + return false; + } + + uint32_t numSizes = SkEndianSwap32(eblc->numSizes); + if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) + + sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes) + { + return false; + } + + const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable = + SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get()); + for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) { + if (sizeTable->ppemX == size && sizeTable->ppemY == size) { + // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable + // to determine the actual number of glyphs with bitmaps. + + // TODO: Ensure that the bitmaps actually cover a significant portion of the strike. + + //TODO: Endure that the bitmaps are bi-level. + if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) { + return true; + } + } + } + } + + { + AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get()); + if (!ebsc.fExists) { + return false; + } + if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) { + return false; + } + if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) { + return false; + } + + uint32_t numSizes = SkEndianSwap32(ebsc->numSizes); + if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) + + sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes) + { + return false; + } + + const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable = + SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get()); + for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) { + if (scaleTable->ppemX == size && scaleTable->ppemY == size) { + // EBSC tables are normally only found in bitmap only fonts. + return true; + } + } + } + + return false; +} + +static bool bothZero(SkScalar a, SkScalar b) { + return 0 == a && 0 == b; +} + +// returns false if there is any non-90-rotation or skew +static bool isAxisAligned(const SkScalerContext::Rec& rec) { + return 0 == rec.fPreSkewX && + (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || + bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); +} + SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, const SkDescriptor* desc) : SkScalerContext(typeface, desc) , fTypeface(SkRef(typeface)) , fGlyphCount(-1) { - fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]); - fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]); - fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]); - fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]); - fXform.dx = 0; - fXform.dy = 0; - - if (SkMask::kBW_Format == fRec.fMaskFormat) { + // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC + // except when bi-level rendering is requested or there are embedded + // bi-level bitmaps (and the embedded bitmap flag is set and no rotation). + // + // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do + // this. As a result, determine the actual size of the text and then see if + // there are any embedded bi-level bitmaps of that size. If there are, then + // force bitmaps by requesting bi-level rendering. + // + // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes + // square pixels and only uses ppemY. Therefore the transform must track any + // non-uniform x-scale. + // + // Also, rotated glyphs should have the same absolute advance widths as + // horizontal glyphs and the subpixel flag should not affect glyph shapes. + + // A is the total matrix. + SkMatrix A; + fRec.getSingleMatrix(&A); + + // h is where A maps the horizontal baseline. + SkPoint h = SkPoint::Make(SK_Scalar1, 0); + A.mapPoints(&h, 1); + + // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). + SkMatrix G; + SkComputeGivensRotation(h, &G); + + // GA is the matrix A with rotation removed. + SkMatrix GA(G); + GA.preConcat(A); + + // realTextSize is the actual device size we want (as opposed to the size the user requested). + // gdiTextSize is the size we request when GDI compatible. + // If the scale is negative, this means the matrix will do the flip anyway. + SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); + // Due to floating point math, the lower bits are suspect. Round carefully. + SkScalar roundedTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f; + SkScalar gdiTextSize = SkScalarFloorToScalar(roundedTextSize); + if (gdiTextSize == 0) { + gdiTextSize = SK_Scalar1; + } + + bool hasBitmap = fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag && + hasBitmapStrike(typeface, SkScalarTruncToInt(gdiTextSize)); + bool axisAligned = isAxisAligned(fRec); + bool isBiLevel = SkMask::kBW_Format == fRec.fMaskFormat || (hasBitmap && axisAligned); + + if (isBiLevel) { + fTextSizeRender = gdiTextSize; fRenderingMode = DWRITE_RENDERING_MODE_ALIASED; fTextureType = DWRITE_TEXTURE_ALIASED_1x1; + fTextSizeMeasure = gdiTextSize; + fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; + } else if (hasBitmap) { + // If rotated but the horizontal text would have used a bitmap, + // render high quality rotated glyphs using the bitmap metrics. + fTextSizeRender = gdiTextSize; + fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; + fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; + fTextSizeMeasure = gdiTextSize; fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; } else { + fTextSizeRender = realTextSize; fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; + fTextSizeMeasure = realTextSize; fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; } if (this->isSubpixel()) { + fTextSizeMeasure = realTextSize; fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; } + + // Remove the realTextSize, as that is the text height scale currently in A. + SkScalar scale = SkScalarInvert(realTextSize); + + // fSkXform is the total matrix A without the text height scale. + fSkXform = A; + fSkXform.preScale(scale, scale); //remove the text height scale. + + fXform.m11 = SkScalarToFloat(fSkXform.getScaleX()); + fXform.m12 = SkScalarToFloat(fSkXform.getSkewY()); + fXform.m21 = SkScalarToFloat(fSkXform.getSkewX()); + fXform.m22 = SkScalarToFloat(fSkXform.getScaleY()); + fXform.dx = 0; + fXform.dy = 0; + + // GsA is the non-rotational part of A without the text height scale. + SkMatrix GsA(GA); + GsA.preScale(scale, scale); //remove text height scale, G is rotational so reorders with scale. + + fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX)); + fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0. + fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX)); + fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY)); + + // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational. + fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX), + -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY), + G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2)); } SkScalerContext_DW::~SkScalerContext_DW() { @@ -631,9 +841,9 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) { HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( - fRec.fTextSize, + fTextSizeMeasure, 1.0f, // pixelsPerDip - &fXform, + &fGsA, DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode, &glyphId, 1, &gm), @@ -645,7 +855,7 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { DWRITE_FONT_METRICS dwfm; fTypeface->fDWriteFontFace->GetMetrics(&dwfm); - SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize, + SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, SkIntToScalar(gm.advanceWidth), SkIntToScalar(dwfm.designUnitsPerEm)); @@ -654,9 +864,13 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { } SkVector vecs[1] = { { advanceX, 0 } }; - SkMatrix mat; - fRec.getMatrixFrom2x2(&mat); - mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); + if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || + DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) + { + fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); + } else { + fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); + } glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); @@ -683,7 +897,7 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { run.glyphCount = 1; run.glyphAdvances = &advance; run.fontFace = fTypeface->fDWriteFontFace.get(); - run.fontEmSize = SkScalarToFloat(fRec.fTextSize); + run.fontEmSize = SkScalarToFloat(fTextSizeRender); run.bidiLevel = 0; run.glyphIndices = &glyphId; run.isSideways = FALSE; @@ -728,7 +942,7 @@ void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx, DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) { fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics( - fRec.fTextSize, + fTextSizeRender, 1.0f, // pixelsPerDip &fXform, &dwfm); @@ -738,28 +952,28 @@ void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx, SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm); if (mx) { - mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem; + mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; mx->fAscent = mx->fTop; - mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem; + mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; mx->fBottom = mx->fDescent; - mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem; - mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem; - mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem; - mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem); + mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; + mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; + mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem; + mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem); mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; } if (my) { - my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem; + my->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; my->fAscent = my->fTop; - my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem; + my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; my->fBottom = my->fDescent; - my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem; - my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem; - my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem; - my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem); + my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; + my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; + my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem; + my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem); my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; @@ -888,7 +1102,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) { run.glyphCount = 1; run.glyphAdvances = &advance; run.fontFace = fTypeface->fDWriteFontFace.get(); - run.fontEmSize = SkScalarToFloat(fRec.fTextSize); + run.fontEmSize = SkScalarToFloat(fTextSizeRender); run.bidiLevel = 0; run.glyphIndices = &index; run.isSideways = FALSE; @@ -966,7 +1180,7 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { uint16_t glyphId = glyph.getGlyphID(); //TODO: convert to<->from DIUs? This would make a difference if hinting. //It may not be needed, it appears that DirectWrite only hints at em size. - HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize), + HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender), &glyphId, NULL, //advances NULL, //offsets @@ -976,9 +1190,7 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { geometryToPath.get()), "Could not create glyph outline."); - SkMatrix mat; - fRec.getMatrixFrom2x2(&mat); - path->transform(mat); + path->transform(fSkXform); } void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, @@ -1146,28 +1358,6 @@ int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0; } -class AutoDWriteTable { -public: - AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) { - // Any errors are ignored, user must check fExists anyway. - fontFace->TryGetFontTable(beTag, - reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); - } - ~AutoDWriteTable() { - if (fExists) { - fFontFace->ReleaseFontTable(fLock); - } - } - - const uint8_t* fData; - UINT32 fSize; - BOOL fExists; -private: - // Borrowed reference, the user must ensure the fontFace stays alive. - IDWriteFontFace* fFontFace; - void* fLock; -}; - size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, size_t length, void* data) const { @@ -1260,7 +1450,6 @@ void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | SkScalerContext::kForceAutohinting_Flag | - SkScalerContext::kEmbeddedBitmapText_Flag | SkScalerContext::kEmbolden_Flag | SkScalerContext::kLCD_BGROrder_Flag | SkScalerContext::kLCD_Vertical_Flag; @@ -1362,14 +1551,6 @@ static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance return true; } -template<typename T> class AutoTDWriteTable : public AutoDWriteTable { -public: - static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3); - AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { } - - const T* operator->() const { return reinterpret_cast<const T*>(fData); } -}; - SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, const uint32_t* glyphIDs, diff --git a/sfnt/SkOTTable_EBDT.h b/sfnt/SkOTTable_EBDT.h new file mode 100644 index 00000000..89d7a3ab --- /dev/null +++ b/sfnt/SkOTTable_EBDT.h @@ -0,0 +1,109 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkOTTable_EBDT_DEFINED +#define SkOTTable_EBDT_DEFINED + +#include "SkEndian.h" +#include "SkOTTableTypes.h" +#include "SkOTTable_head.h" +#include "SkOTTable_loca.h" +#include "SkTypedEnum.h" + +#pragma pack(push, 1) + +struct SkOTTableEmbeddedBitmapData { + static const SK_OT_CHAR TAG0 = 'E'; + static const SK_OT_CHAR TAG1 = 'B'; + static const SK_OT_CHAR TAG2 = 'D'; + static const SK_OT_CHAR TAG3 = 'T'; + static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapData>::value; + + SK_OT_Fixed version; + static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000); + + struct BigGlyphMetrics { + SK_OT_BYTE height; + SK_OT_BYTE width; + SK_OT_CHAR horiBearingX; + SK_OT_CHAR horiBearingY; + SK_OT_BYTE horiAdvance; + SK_OT_CHAR vertBearingX; + SK_OT_CHAR vertBearingY; + SK_OT_BYTE vertAdvance; + }; + + struct SmallGlyphMetrics { + SK_OT_BYTE height; + SK_OT_BYTE width; + SK_OT_CHAR bearingX; + SK_OT_CHAR bearingY; + SK_OT_BYTE advance; + }; + + // Small metrics, byte-aligned data. + struct Format1 { + SmallGlyphMetrics smallGlyphMetrics; + //SK_OT_BYTE[] byteAlignedBitmap; + }; + + // Small metrics, bit-aligned data. + struct Format2 { + SmallGlyphMetrics smallGlyphMetrics; + //SK_OT_BYTE[] bitAlignedBitmap; + }; + + // Format 3 is not used. + + // EBLC metrics (IndexSubTable::header::indexFormat 2 or 5), compressed data. + // Only used on Mac. + struct Format4 { + SK_OT_ULONG whiteTreeOffset; + SK_OT_ULONG blackTreeOffset; + SK_OT_ULONG glyphDataOffset; + }; + + // EBLC metrics (IndexSubTable::header::indexFormat 2 or 5), bit-aligned data. + struct Format5 { + //SK_OT_BYTE[] bitAlignedBitmap; + }; + + // Big metrics, byte-aligned data. + struct Format6 { + BigGlyphMetrics bigGlyphMetrics; + //SK_OT_BYTE[] byteAlignedBitmap; + }; + + // Big metrics, bit-aligned data. + struct Format7 { + BigGlyphMetrics bigGlyphMetrics; + //SK_OT_BYTE[] bitAlignedBitmap; + }; + + struct EBDTComponent { + SK_OT_USHORT glyphCode; // Component glyph code + SK_OT_CHAR xOffset; // Position of component left + SK_OT_CHAR yOffset; // Position of component top + }; + + struct Format8 { + SmallGlyphMetrics smallMetrics; // Metrics information for the glyph + SK_OT_BYTE pad; // Pad to short boundary + SK_OT_USHORT numComponents; // Number of components + //EBDTComponent componentArray[numComponents]; // Glyph code, offset array + }; + + struct Format9 { + BigGlyphMetrics bigMetrics; // Metrics information for the glyph + SK_OT_USHORT numComponents; // Number of components + //EBDTComponent componentArray[numComponents]; // Glyph code, offset array + }; +}; + +#pragma pack(pop) + +#endif diff --git a/sfnt/SkOTTable_EBLC.h b/sfnt/SkOTTable_EBLC.h new file mode 100644 index 00000000..845418d3 --- /dev/null +++ b/sfnt/SkOTTable_EBLC.h @@ -0,0 +1,152 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkOTTable_EBLC_DEFINED +#define SkOTTable_EBLC_DEFINED + +#include "SkEndian.h" +#include "SkOTTable_EBDT.h" +#include "SkOTTableTypes.h" +#include "SkTypedEnum.h" + +#pragma pack(push, 1) + +struct SkOTTableEmbeddedBitmapLocation { + static const SK_OT_CHAR TAG0 = 'E'; + static const SK_OT_CHAR TAG1 = 'B'; + static const SK_OT_CHAR TAG2 = 'L'; + static const SK_OT_CHAR TAG3 = 'C'; + static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapLocation>::value; + + SK_OT_Fixed version; + static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000); + + SK_OT_ULONG numSizes; + + struct SbitLineMetrics { + SK_OT_CHAR ascender; + SK_OT_CHAR descender; + SK_OT_BYTE widthMax; + SK_OT_CHAR caretSlopeNumerator; + SK_OT_CHAR caretSlopeDenominator; + SK_OT_CHAR caretOffset; + SK_OT_CHAR minOriginSB; + SK_OT_CHAR minAdvanceSB; + SK_OT_CHAR maxBeforeBL; + SK_OT_CHAR minAfterBL; + SK_OT_CHAR pad1; + SK_OT_CHAR pad2; + }; + + struct BitmapSizeTable { + SK_OT_ULONG indexSubTableArrayOffset; //offset to indexSubtableArray from beginning of EBLC. + SK_OT_ULONG indexTablesSize; //number of bytes in corresponding index subtables and array + SK_OT_ULONG numberOfIndexSubTables; //an index subtable for each range or format change + SK_OT_ULONG colorRef; //not used; set to 0. + SbitLineMetrics hori; //line metrics for text rendered horizontally + SbitLineMetrics vert; //line metrics for text rendered vertically + SK_OT_USHORT startGlyphIndex; //lowest glyph index for this size + SK_OT_USHORT endGlyphIndex; //highest glyph index for this size + SK_OT_BYTE ppemX; //horizontal pixels per Em + SK_OT_BYTE ppemY; //vertical pixels per Em + struct BitDepth { + SK_TYPED_ENUM(Value, SK_OT_BYTE, + ((BW, 1)) + ((Gray4, 2)) + ((Gray16, 4)) + ((Gray256, 8)) + SK_SEQ_END, + SK_SEQ_END) + SK_OT_BYTE value; + } bitDepth; //the Microsoft rasterizer v.1.7 or greater supports + union Flags { + struct Field { + //0-7 + SK_OT_BYTE_BITFIELD( + Horizontal, // Horizontal small glyph metrics + Vertical, // Vertical small glyph metrics + Reserved02, + Reserved03, + Reserved04, + Reserved05, + Reserved06, + Reserved07) + } field; + struct Raw { + static const SK_OT_CHAR Horizontal = 1u << 0; + static const SK_OT_CHAR Vertical = 1u << 1; + SK_OT_CHAR value; + } raw; + } flags; + }; //bitmapSizeTable[numSizes]; + + struct IndexSubTableArray { + SK_OT_USHORT firstGlyphIndex; //first glyph code of this range + SK_OT_USHORT lastGlyphIndex; //last glyph code of this range (inclusive) + SK_OT_ULONG additionalOffsetToIndexSubtable; //add to BitmapSizeTable::indexSubTableArrayOffset to get offset from beginning of 'EBLC' + }; //indexSubTableArray[BitmapSizeTable::numberOfIndexSubTables]; + + struct IndexSubHeader { + SK_OT_USHORT indexFormat; //format of this indexSubTable + SK_OT_USHORT imageFormat; //format of 'EBDT' image data + SK_OT_ULONG imageDataOffset; //offset to image data in 'EBDT' table + }; + + // Variable metrics glyphs with 4 byte offsets + struct IndexSubTable1 { + IndexSubHeader header; + //SK_OT_ULONG offsetArray[lastGlyphIndex - firstGlyphIndex + 1 + 1]; //last element points to one past end of last glyph + //glyphData = offsetArray[glyphIndex - firstGlyphIndex] + imageDataOffset + }; + + // All Glyphs have identical metrics + struct IndexSubTable2 { + IndexSubHeader header; + SK_OT_ULONG imageSize; // all glyphs are of the same size + SkOTTableEmbeddedBitmapData::BigGlyphMetrics bigMetrics; // all glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned + }; + + // Variable metrics glyphs with 2 byte offsets + struct IndexSubTable3 { + IndexSubHeader header; + //SK_OT_USHORT offsetArray[lastGlyphIndex - firstGlyphIndex + 1 + 1]; //last element points to one past end of last glyph, may have extra element to force even number of elements + //glyphData = offsetArray[glyphIndex - firstGlyphIndex] + imageDataOffset + }; + + // Variable metrics glyphs with sparse glyph codes + struct IndexSubTable4 { + IndexSubHeader header; + SK_OT_ULONG numGlyphs; + struct CodeOffsetPair { + SK_OT_USHORT glyphCode; + SK_OT_USHORT offset; //location in EBDT + }; //glyphArray[numGlyphs+1] + }; + + // Constant metrics glyphs with sparse glyph codes + struct IndexSubTable5 { + IndexSubHeader header; + SK_OT_ULONG imageSize; //all glyphs have the same data size + SkOTTableEmbeddedBitmapData::BigGlyphMetrics bigMetrics; //all glyphs have the same metrics + SK_OT_ULONG numGlyphs; + //SK_OT_USHORT glyphCodeArray[numGlyphs] //must have even number of entries (set pad to 0) + }; + + union IndexSubTable { + IndexSubHeader header; + IndexSubTable1 format1; + IndexSubTable2 format2; + IndexSubTable3 format3; + IndexSubTable4 format4; + IndexSubTable5 format5; + }; + +}; + +#pragma pack(pop) + +#endif diff --git a/sfnt/SkOTTable_EBSC.h b/sfnt/SkOTTable_EBSC.h new file mode 100644 index 00000000..316c45d1 --- /dev/null +++ b/sfnt/SkOTTable_EBSC.h @@ -0,0 +1,41 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkOTTable_EBSC_DEFINED +#define SkOTTable_EBSC_DEFINED + +#include "SkEndian.h" +#include "SkOTTable_EBLC.h" +#include "SkOTTableTypes.h" + +#pragma pack(push, 1) + +struct SkOTTableEmbeddedBitmapScaling { + static const SK_OT_CHAR TAG0 = 'E'; + static const SK_OT_CHAR TAG1 = 'S'; + static const SK_OT_CHAR TAG2 = 'B'; + static const SK_OT_CHAR TAG3 = 'C'; + static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapScaling>::value; + + SK_OT_Fixed version; + static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000); + + SK_OT_ULONG numSizes; + + struct BitmapScaleTable { + SkOTTableEmbeddedBitmapLocation::SbitLineMetrics hori; + SkOTTableEmbeddedBitmapLocation::SbitLineMetrics vert; + SK_OT_BYTE ppemX; //target horizontal pixels per EM + SK_OT_BYTE ppemY; //target vertical pixels per EM + SK_OT_BYTE substitutePpemX; //use bitmaps of this size + SK_OT_BYTE substitutePpemY; //use bitmaps of this size + }; //bitmapScaleTable[numSizes]; +}; + +#pragma pack(pop) + +#endif diff --git a/utils/debugger/SkDebugCanvas.cpp b/utils/debugger/SkDebugCanvas.cpp index ec201789..14fbf888 100644 --- a/utils/debugger/SkDebugCanvas.cpp +++ b/utils/debugger/SkDebugCanvas.cpp @@ -125,8 +125,6 @@ public: #endif }; -// The OverdrawFilter modifies every paint to use an SkProcXfermode which -// in turn invokes OverdrawXferModeProc class SkOverdrawFilter : public SkDrawFilter { public: SkOverdrawFilter() { |