Index: src/pdf/SkPDFShader.cpp |
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp |
index 40f7d93f8907b30ab5c9ae191c449c60fa292879..ec92742b6ea76e253f4e87ea7f1223cc4631aded 100644 |
--- a/src/pdf/SkPDFShader.cpp |
+++ b/src/pdf/SkPDFShader.cpp |
@@ -10,6 +10,7 @@ |
#include "SkPDFShader.h" |
#include "SkData.h" |
+#include "SkPDFCanon.h" |
#include "SkPDFCatalog.h" |
#include "SkPDFDevice.h" |
#include "SkPDFFormXObject.h" |
@@ -475,7 +476,7 @@ static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri |
canvas->drawBitmap(bm, 0, 0); |
} |
-class SkPDFShader::State { |
+class SkPDFShaderState { |
public: |
SkShader::GradientType fType; |
SkShader::GradientInfo fInfo; |
@@ -488,35 +489,41 @@ public: |
uint32_t fPixelGeneration; |
SkShader::TileMode fImageTileModes[2]; |
- State(const SkShader& shader, const SkMatrix& canvasTransform, |
- const SkIRect& bbox); |
+ SkPDFShaderState(const SkShader& shader, |
+ const SkMatrix& canvasTransform, |
+ const SkIRect& bbox); |
- bool operator==(const State& b) const; |
+ bool operator==(const SkPDFShaderState& b) const; |
- SkPDFShader::State* CreateAlphaToLuminosityState() const; |
- SkPDFShader::State* CreateOpaqueState() const; |
+ SkPDFShaderState* CreateAlphaToLuminosityState() const; |
+ SkPDFShaderState* CreateOpaqueState() const; |
bool GradientHasAlpha() const; |
private: |
- State(const State& other); |
- State operator=(const State& rhs); |
+ SkPDFShaderState(const SkPDFShaderState& other); |
+ SkPDFShaderState operator=(const SkPDFShaderState& rhs); |
void AllocateGradientInfoStorage(); |
}; |
class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { |
SK_DECLARE_INST_COUNT(SkPDFFunctionShader) |
public: |
- explicit SkPDFFunctionShader(SkPDFShader::State* state); |
+ explicit SkPDFFunctionShader(SkPDFShaderState* state); |
virtual ~SkPDFFunctionShader() { |
if (isValid()) { |
- RemoveShader(this); |
+ SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
+ SkPDFCanon::GetCanon().removeShader(this); |
} |
fResources.unrefAll(); |
} |
bool isValid() SK_OVERRIDE { return fResources.count() > 0; } |
+ virtual SkPDFObject* toPDFObject() SK_OVERRIDE { |
+ return this; |
+ } |
+ |
void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
GetResourcesHelper(&fResources, |
@@ -528,7 +535,6 @@ private: |
static SkPDFObject* RangeObject(); |
SkTDArray<SkPDFObject*> fResources; |
- SkAutoTDelete<const SkPDFShader::State> fState; |
SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); |
typedef SkPDFDict INHERITED; |
@@ -541,10 +547,11 @@ private: |
*/ |
class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { |
public: |
- explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); |
+ explicit SkPDFAlphaFunctionShader(SkPDFShaderState* state); |
virtual ~SkPDFAlphaFunctionShader() { |
if (isValid()) { |
- RemoveShader(this); |
+ SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
+ SkPDFCanon::GetCanon().removeShader(this); |
} |
} |
@@ -552,9 +559,11 @@ public: |
return fColorShader.get() != NULL; |
} |
-private: |
- SkAutoTDelete<const SkPDFShader::State> fState; |
+ virtual SkPDFObject* toPDFObject() SK_OVERRIDE { |
+ return this; |
+ } |
+private: |
SkPDFGraphicState* CreateSMaskGraphicState(); |
void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
@@ -570,16 +579,21 @@ private: |
class SkPDFImageShader : public SkPDFStream, public SkPDFShader { |
public: |
- explicit SkPDFImageShader(SkPDFShader::State* state); |
+ explicit SkPDFImageShader(SkPDFShaderState* state); |
virtual ~SkPDFImageShader() { |
if (isValid()) { |
- RemoveShader(this); |
+ SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
+ SkPDFCanon::GetCanon().removeShader(this); |
} |
fResources.unrefAll(); |
} |
bool isValid() SK_OVERRIDE { return size() > 0; } |
+ virtual SkPDFObject* toPDFObject() SK_OVERRIDE { |
+ return this; |
+ } |
+ |
void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
GetResourcesHelper(&fResources.toArray(), |
@@ -589,16 +603,26 @@ public: |
private: |
SkTSet<SkPDFObject*> fResources; |
- SkAutoTDelete<const SkPDFShader::State> fState; |
}; |
-SkPDFShader::SkPDFShader() {} |
+SkPDFShader::SkPDFShader(const SkPDFShaderState* state) |
+ : fPDFShaderState(state) { |
+} |
-// static |
-SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { |
- SkPDFObject* result; |
+SkPDFShader::~SkPDFShader() { |
+} |
+ |
+bool SkPDFShader::equals(const SkPDFShaderState& state) const { |
+ return state == this->pdfShaderState(); |
+} |
+ |
+const SkPDFShaderState& SkPDFShader::pdfShaderState() const { |
+ return *fPDFShaderState; |
+} |
- SkAutoTDelete<State> shaderState(inState); |
+// static |
+SkPDFObject* SkPDFShader::GetPDFShaderByState(SkPDFShaderState* inState) { |
+ SkAutoTDelete<SkPDFShaderState> shaderState(inState); |
if (shaderState.get()->fType == SkShader::kNone_GradientType && |
shaderState.get()->fImage.isNull()) { |
// TODO(vandebo) This drops SKComposeShader on the floor. We could |
@@ -608,77 +632,57 @@ SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { |
return NULL; |
} |
- ShaderCanonicalEntry entry(NULL, shaderState.get()); |
- int index = CanonicalShaders().find(entry); |
- if (index >= 0) { |
- result = CanonicalShaders()[index].fPDFShader; |
- result->ref(); |
- return result; |
+ SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*shaderState); |
+ if (pdfShader) { |
+ return SkRef(pdfShader->toPDFObject()); |
} |
- bool valid = false; |
// The PDFShader takes ownership of the shaderSate. |
- if (shaderState.get()->fType == SkShader::kNone_GradientType) { |
+ if (shaderState->fType == SkShader::kNone_GradientType) { |
SkPDFImageShader* imageShader = |
new SkPDFImageShader(shaderState.detach()); |
- valid = imageShader->isValid(); |
- result = imageShader; |
- } else { |
- if (shaderState.get()->GradientHasAlpha()) { |
- SkPDFAlphaFunctionShader* gradientShader = |
+ if (imageShader->isValid()) { |
mtklein
2015/01/20 21:59:52
Might want to extract this if-else block as add_to
hal.canary
2015/01/21 17:07:51
GREAT idea
|
+ SkPDFCanon::GetCanon().addShader(imageShader); |
+ return imageShader->toPDFObject(); |
+ } else { |
+ SkDELETE(imageShader); |
+ return NULL; |
+ } |
+ } else if (shaderState->GradientHasAlpha()) { |
+ SkPDFAlphaFunctionShader* gradientShader = |
SkNEW_ARGS(SkPDFAlphaFunctionShader, (shaderState.detach())); |
- valid = gradientShader->isValid(); |
- result = gradientShader; |
+ if (gradientShader->isValid()) { |
+ SkPDFCanon::GetCanon().addShader(gradientShader); |
+ return gradientShader->toPDFObject(); |
} else { |
- SkPDFFunctionShader* functionShader = |
+ SkDELETE(gradientShader); |
+ return NULL; |
+ } |
+ } else { |
+ SkPDFFunctionShader* functionShader = |
SkNEW_ARGS(SkPDFFunctionShader, (shaderState.detach())); |
- valid = functionShader->isValid(); |
- result = functionShader; |
+ if (functionShader->isValid()) { |
+ SkPDFCanon::GetCanon().addShader(functionShader); |
+ return functionShader->toPDFObject(); |
+ } else { |
+ SkDELETE(functionShader); |
+ return NULL; |
} |
} |
- if (!valid) { |
- delete result; |
- return NULL; |
- } |
- entry.fPDFShader = result; |
- CanonicalShaders().push(entry); |
- return result; // return the reference that came from new. |
-} |
- |
-// static |
-void SkPDFShader::RemoveShader(SkPDFObject* shader) { |
- SkAutoMutexAcquire lock(CanonicalShadersMutex()); |
- ShaderCanonicalEntry entry(shader, NULL); |
- int index = CanonicalShaders().find(entry); |
- SkASSERT(index >= 0); |
- CanonicalShaders().removeShuffle(index); |
} |
// static |
SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, |
const SkMatrix& matrix, |
const SkIRect& surfaceBBox) { |
- SkAutoMutexAcquire lock(CanonicalShadersMutex()); |
+ SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
return GetPDFShaderByState( |
- SkNEW_ARGS(State, (shader, matrix, surfaceBBox))); |
-} |
- |
-// static |
-SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { |
- SkPDFShader::CanonicalShadersMutex().assertHeld(); |
- static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; |
- return gCanonicalShaders; |
-} |
- |
-SK_DECLARE_STATIC_MUTEX(gCanonicalShadersMutex); |
-// static |
-SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { |
- return gCanonicalShadersMutex; |
+ SkNEW_ARGS(SkPDFShaderState, (shader, matrix, surfaceBBox))); |
} |
// static |
SkPDFObject* SkPDFFunctionShader::RangeObject() { |
- SkPDFShader::CanonicalShadersMutex().assertHeld(); |
+ SkPDFCanon::GetShaderMutex().assertHeld(); |
static SkPDFArray* range = NULL; |
// This method is only used with CanonicalShadersMutex, so it's safe to |
// populate domain. |
@@ -756,11 +760,10 @@ static SkStream* create_pattern_fill_content(int gsIndex, SkRect& bounds) { |
*/ |
SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { |
SkRect bbox; |
- bbox.set(fState.get()->fBBox); |
+ bbox.set(this->pdfShaderState().fBBox); |
- SkAutoTUnref<SkPDFObject> luminosityShader( |
- SkPDFShader::GetPDFShaderByState( |
- fState->CreateAlphaToLuminosityState())); |
+ SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState( |
+ this->pdfShaderState().CreateAlphaToLuminosityState())); |
SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); |
@@ -775,10 +778,10 @@ SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { |
SkPDFGraphicState::kLuminosity_SMaskMode); |
} |
-SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) |
- : fState(state) { |
+SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShaderState* state) |
+ : SkPDFShader(state) { |
SkRect bbox; |
- bbox.set(fState.get()->fBBox); |
+ bbox.set(this->pdfShaderState().fBBox); |
fColorShader.reset( |
SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); |
@@ -835,19 +838,18 @@ static bool split_perspective(const SkMatrix in, SkMatrix* affine, |
return true; |
} |
-SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
- : SkPDFDict("Pattern"), |
- fState(state) { |
+SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShaderState* state) |
+ : SkPDFDict("Pattern"), SkPDFShader(state) { |
SkString (*codeFunction)(const SkShader::GradientInfo& info, |
const SkMatrix& perspectiveRemover) = NULL; |
SkPoint transformPoints[2]; |
// Depending on the type of the gradient, we want to transform the |
// coordinate space in different ways. |
- const SkShader::GradientInfo* info = &fState.get()->fInfo; |
+ const SkShader::GradientInfo* info = &this->pdfShaderState().fInfo; |
mtklein
2015/01/20 21:59:52
Why don't we just write "this->pdfShaderState()" a
hal.canary
2015/01/21 17:07:51
Done.
|
transformPoints[0] = info->fPoint[0]; |
transformPoints[1] = info->fPoint[1]; |
- switch (fState.get()->fType) { |
+ switch (this->pdfShaderState().fType) { |
case SkShader::kLinear_GradientType: |
codeFunction = &linearCode; |
break; |
@@ -892,8 +894,8 @@ SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
SkMatrix mapperMatrix; |
unitToPointsMatrix(transformPoints, &mapperMatrix); |
- SkMatrix finalMatrix = fState.get()->fCanvasTransform; |
- finalMatrix.preConcat(fState.get()->fShaderTransform); |
+ SkMatrix finalMatrix = this->pdfShaderState().fCanvasTransform; |
+ finalMatrix.preConcat(this->pdfShaderState().fShaderTransform); |
finalMatrix.preConcat(mapperMatrix); |
// Preserves as much as posible in the final matrix, and only removes |
@@ -910,7 +912,7 @@ SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
} |
SkRect bbox; |
- bbox.set(fState.get()->fBBox); |
+ bbox.set(this->pdfShaderState().fBBox); |
if (!inverseTransformBBox(finalMatrix, &bbox)) { |
return; |
} |
@@ -923,10 +925,11 @@ SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
domain->appendScalar(bbox.fBottom); |
SkString functionCode; |
- // The two point radial gradient further references fState.get()->fInfo |
+ // The two point radial gradient further references |
+ // this->pdfShaderState().fInfo |
// in translating from x, y coordinates to the t parameter. So, we have |
// to transform the points and radii according to the calculated matrix. |
- if (fState.get()->fType == SkShader::kRadial2_GradientType) { |
+ if (this->pdfShaderState().fType == SkShader::kRadial2_GradientType) { |
SkShader::GradientInfo twoPointRadialInfo = *info; |
SkMatrix inverseMapperMatrix; |
if (!mapperMatrix.invert(&inverseMapperMatrix)) { |
@@ -956,8 +959,9 @@ SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
insert("Shading", pdfShader.get()); |
} |
-SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { |
- fState.get()->fImage.lockPixels(); |
+SkPDFImageShader::SkPDFImageShader(SkPDFShaderState* state) |
+ : SkPDFShader(state) { |
+ this->pdfShaderState().fImage.lockPixels(); |
// The image shader pattern cell will be drawn into a separate device |
// in pattern cell space (no scaling on the bitmap, though there may be |
@@ -965,15 +969,15 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { |
// Map clip bounds to shader space to ensure the device is large enough |
// to handle fake clamping. |
- SkMatrix finalMatrix = fState.get()->fCanvasTransform; |
- finalMatrix.preConcat(fState.get()->fShaderTransform); |
+ SkMatrix finalMatrix = this->pdfShaderState().fCanvasTransform; |
+ finalMatrix.preConcat(this->pdfShaderState().fShaderTransform); |
SkRect deviceBounds; |
- deviceBounds.set(fState.get()->fBBox); |
+ deviceBounds.set(this->pdfShaderState().fBBox); |
if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { |
return; |
} |
- const SkBitmap* image = &fState.get()->fImage; |
+ const SkBitmap* image = &this->pdfShaderState().fImage; |
SkRect bitmapBounds; |
image->getBounds(&bitmapBounds); |
@@ -982,8 +986,8 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { |
// For clamp modes, we're only interested in the clip region, whether |
// or not the main bitmap is in it. |
SkShader::TileMode tileModes[2]; |
- tileModes[0] = fState.get()->fImageTileModes[0]; |
- tileModes[1] = fState.get()->fImageTileModes[1]; |
+ tileModes[0] = this->pdfShaderState().fImageTileModes[0]; |
+ tileModes[1] = this->pdfShaderState().fImageTileModes[1]; |
if (tileModes[0] != SkShader::kClamp_TileMode || |
tileModes[1] != SkShader::kClamp_TileMode) { |
deviceBounds.join(bitmapBounds); |
@@ -1163,7 +1167,7 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { |
populate_tiling_pattern_dict(this, patternBBox, |
pattern.getResourceDict(), finalMatrix); |
- fState.get()->fImage.unlockPixels(); |
+ this->pdfShaderState().fImage.unlockPixels(); |
} |
SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFArray* domain) { |
@@ -1175,17 +1179,7 @@ SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr |
return result; |
} |
-SkPDFShader::ShaderCanonicalEntry::ShaderCanonicalEntry(SkPDFObject* pdfShader, const State* state) |
- : fPDFShader(pdfShader) |
- , fState(state) |
-{} |
- |
-bool SkPDFShader::ShaderCanonicalEntry::operator==(const ShaderCanonicalEntry& b) const { |
- return fPDFShader == b.fPDFShader || |
- (fState != NULL && b.fState != NULL && *fState == *b.fState); |
-} |
- |
-bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { |
+bool SkPDFShaderState::operator==(const SkPDFShaderState& b) const { |
if (fType != b.fType || |
fCanvasTransform != b.fCanvasTransform || |
fShaderTransform != b.fShaderTransform || |
@@ -1239,11 +1233,10 @@ bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { |
return true; |
} |
-SkPDFShader::State::State(const SkShader& shader, |
- const SkMatrix& canvasTransform, const SkIRect& bbox) |
- : fCanvasTransform(canvasTransform), |
- fBBox(bbox), |
- fPixelGeneration(0) { |
+SkPDFShaderState::SkPDFShaderState(const SkShader& shader, |
+ const SkMatrix& canvasTransform, |
+ const SkIRect& bbox) |
+ : fCanvasTransform(canvasTransform), fBBox(bbox), fPixelGeneration(0) { |
fInfo.fColorCount = 0; |
fInfo.fColors = NULL; |
fInfo.fColorOffsets = NULL; |
@@ -1268,12 +1261,11 @@ SkPDFShader::State::State(const SkShader& shader, |
} |
} |
-SkPDFShader::State::State(const SkPDFShader::State& other) |
- : fType(other.fType), |
- fCanvasTransform(other.fCanvasTransform), |
- fShaderTransform(other.fShaderTransform), |
- fBBox(other.fBBox) |
-{ |
+SkPDFShaderState::SkPDFShaderState(const SkPDFShaderState& other) |
+ : fType(other.fType) |
+ , fCanvasTransform(other.fCanvasTransform) |
+ , fShaderTransform(other.fShaderTransform) |
+ , fBBox(other.fBBox) { |
// Only gradients supported for now, since that is all that is used. |
// If needed, image state copy constructor can be added here later. |
SkASSERT(fType != SkShader::kNone_GradientType); |
@@ -1293,10 +1285,10 @@ SkPDFShader::State::State(const SkPDFShader::State& other) |
* Create a copy of this gradient state with alpha assigned to RGB luminousity. |
* Only valid for gradient states. |
*/ |
-SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { |
+SkPDFShaderState* SkPDFShaderState::CreateAlphaToLuminosityState() const { |
SkASSERT(fType != SkShader::kNone_GradientType); |
- SkPDFShader::State* newState = new SkPDFShader::State(*this); |
+ SkPDFShaderState* newState = new SkPDFShaderState(*this); |
for (int i = 0; i < fInfo.fColorCount; i++) { |
SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
@@ -1310,10 +1302,10 @@ SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { |
* Create a copy of this gradient state with alpha set to fully opaque |
* Only valid for gradient states. |
*/ |
-SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { |
+SkPDFShaderState* SkPDFShaderState::CreateOpaqueState() const { |
SkASSERT(fType != SkShader::kNone_GradientType); |
- SkPDFShader::State* newState = new SkPDFShader::State(*this); |
+ SkPDFShaderState* newState = new SkPDFShaderState(*this); |
for (int i = 0; i < fInfo.fColorCount; i++) { |
newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], |
SK_AlphaOPAQUE); |
@@ -1325,7 +1317,7 @@ SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { |
/** |
* Returns true if state is a gradient and the gradient has alpha. |
*/ |
-bool SkPDFShader::State::GradientHasAlpha() const { |
+bool SkPDFShaderState::GradientHasAlpha() const { |
if (fType == SkShader::kNone_GradientType) { |
return false; |
} |
@@ -1339,7 +1331,7 @@ bool SkPDFShader::State::GradientHasAlpha() const { |
return false; |
} |
-void SkPDFShader::State::AllocateGradientInfoStorage() { |
+void SkPDFShaderState::AllocateGradientInfoStorage() { |
fColorData.set(sk_malloc_throw( |
fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |