Index: src/pdf/SkPDFShader.cpp |
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp |
index 885b7e6049bd2a991b80187fb4573153eb6d297a..f7aef6304a7b5969e4e1689a38423326a1a074ab 100644 |
--- a/src/pdf/SkPDFShader.cpp |
+++ b/src/pdf/SkPDFShader.cpp |
@@ -523,112 +523,65 @@ static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri |
canvas->drawBitmap(bm, 0, 0); |
} |
-class SkPDFShader::State { |
-public: |
- SkShader::GradientType fType; |
- SkShader::GradientInfo fInfo; |
- SkAutoFree fColorData; // This provides storage for arrays in fInfo. |
- SkMatrix fCanvasTransform; |
- SkMatrix fShaderTransform; |
- SkIRect fBBox; |
- |
- SkBitmap fImage; |
- SkBitmapKey fBitmapKey; |
- SkShader::TileMode fImageTileModes[2]; |
- |
- State(SkShader* shader, const SkMatrix& canvasTransform, |
- const SkIRect& bbox, SkScalar rasterScale); |
- |
- bool operator==(const State& b) const; |
- |
- SkPDFShader::State* CreateAlphaToLuminosityState() const; |
- SkPDFShader::State* CreateOpaqueState() const; |
- |
- bool GradientHasAlpha() const; |
- |
-private: |
- State(const State& other); |
- State operator=(const State& rhs); |
- void AllocateGradientInfoStorage(); |
-}; |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
- : SkPDFDict("Pattern"), fShaderState(state) { |
- state->fImage.reset(); |
-} |
- |
-SkPDFFunctionShader::~SkPDFFunctionShader() {} |
- |
-bool SkPDFFunctionShader::equals(const SkPDFShader::State& state) const { |
- return state == *fShaderState; |
-} |
- |
//////////////////////////////////////////////////////////////////////////////// |
-SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) |
- : fShaderState(state) { |
- state->fImage.reset(); |
-} |
- |
-bool SkPDFAlphaFunctionShader::equals(const SkPDFShader::State& state) const { |
- return state == *fShaderState; |
-} |
+static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, |
+ SkScalar dpi, |
+ const SkPDFShader::State& state); |
+static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, |
+ const SkPDFShader::State& state); |
-SkPDFAlphaFunctionShader::~SkPDFAlphaFunctionShader() {} |
+static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, |
+ SkScalar dpi, |
+ const SkPDFShader::State& state, |
+ SkBitmap image); |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) |
- : fShaderState(state) { |
- state->fImage.reset(); |
-} |
- |
-bool SkPDFImageShader::equals(const SkPDFShader::State& state) const { |
- return state == *fShaderState; |
-} |
- |
-SkPDFImageShader::~SkPDFImageShader() {} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-static SkPDFObject* get_pdf_shader_by_state( |
+static sk_sp<SkPDFObject> get_pdf_shader_by_state( |
SkPDFDocument* doc, |
SkScalar dpi, |
- std::unique_ptr<SkPDFShader::State>* autoState) { |
- const SkPDFShader::State& state = **autoState; |
+ SkPDFShader::State state, |
+ SkBitmap image) { |
SkPDFCanon* canon = doc->canon(); |
- if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) { |
+ if (state.fType == SkShader::kNone_GradientType && image.isNull()) { |
// TODO(vandebo) This drops SKComposeShader on the floor. We could |
// handle compose shader by pulling things up to a layer, drawing with |
// the first shader, applying the xfer mode and drawing again with the |
// second shader, then applying the layer to the original drawing. |
return nullptr; |
} else if (state.fType == SkShader::kNone_GradientType) { |
- SkPDFObject* shader = canon->findImageShader(state); |
- return shader ? SkRef(shader) |
- : SkPDFImageShader::Create(doc, dpi, autoState); |
+ sk_sp<SkPDFObject> shader = canon->findImageShader(state); |
+ if (!shader) { |
+ shader = make_image_shader(doc, dpi, state, std::move(image)); |
+ canon->addImageShader(shader, std::move(state)); |
+ } |
+ return shader; |
} else if (state.GradientHasAlpha()) { |
- SkPDFObject* shader = canon->findAlphaShader(state); |
- return shader ? SkRef(shader) |
- : SkPDFAlphaFunctionShader::Create(doc, dpi, autoState); |
+ sk_sp<SkPDFObject> shader = canon->findAlphaShader(state); |
+ if (!shader) { |
+ shader = make_alpha_function_shader(doc, dpi, state); |
+ canon->addAlphaShader(shader, std::move(state)); |
+ } |
+ return shader; |
} else { |
- SkPDFObject* shader = canon->findFunctionShader(state); |
- return shader ? SkRef(shader) |
- : SkPDFFunctionShader::Create(canon, autoState); |
+ sk_sp<SkPDFObject> shader = canon->findFunctionShader(state); |
+ if (!shader) { |
+ shader = make_function_shader(canon, state); |
+ canon->addFunctionShader(shader, std::move(state)); |
+ } |
+ return shader; |
} |
} |
-// static |
-SkPDFObject* SkPDFShader::GetPDFShader(SkPDFDocument* doc, |
- SkScalar dpi, |
- SkShader* shader, |
- const SkMatrix& matrix, |
- const SkIRect& surfaceBBox, |
- SkScalar rasterScale) { |
- std::unique_ptr<SkPDFShader::State> state(new State(shader, matrix, surfaceBBox, rasterScale)); |
- return get_pdf_shader_by_state(doc, dpi, &state); |
+sk_sp<SkPDFObject> SkPDFShader::GetPDFShader(SkPDFDocument* doc, |
+ SkScalar dpi, |
+ SkShader* shader, |
+ const SkMatrix& matrix, |
+ const SkIRect& surfaceBBox, |
+ SkScalar rasterScale) { |
+ SkBitmap image; |
+ State state(shader, matrix, surfaceBBox, rasterScale, &image); |
+ return get_pdf_shader_by_state( |
+ doc, dpi, std::move(state), std::move(image)); |
} |
static sk_sp<SkPDFDict> get_gradient_resource_dict( |
@@ -647,7 +600,7 @@ static sk_sp<SkPDFDict> get_gradient_resource_dict( |
static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
SkRect& bbox, |
- SkPDFDict* resources, |
+ sk_sp<SkPDFDict> resources, |
const SkMatrix& matrix) { |
const int kTiling_PatternType = 1; |
const int kColoredTilingPattern_PaintType = 1; |
@@ -660,7 +613,7 @@ static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
pattern->insertObject("BBox", SkPDFUtils::RectToArray(bbox)); |
pattern->insertScalar("XStep", bbox.width()); |
pattern->insertScalar("YStep", bbox.height()); |
- pattern->insertObject("Resources", sk_ref_sp(resources)); |
+ pattern->insertObject("Resources", std::move(resources)); |
if (!matrix.isIdentity()) { |
pattern->insertObject("Matrix", SkPDFUtils::MatrixToArray(matrix)); |
} |
@@ -671,7 +624,8 @@ static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
* @param gsIndex A graphics state resource index to apply, or <0 if no |
* graphics state to apply. |
*/ |
-static SkStreamAsset* create_pattern_fill_content(int gsIndex, SkRect& bounds) { |
+static std::unique_ptr<SkStreamAsset> create_pattern_fill_content( |
+ int gsIndex, SkRect& bounds) { |
SkDynamicMemoryWStream content; |
if (gsIndex >= 0) { |
SkPDFUtils::ApplyGraphicState(gsIndex, &content); |
@@ -681,7 +635,7 @@ static SkStreamAsset* create_pattern_fill_content(int gsIndex, SkRect& bounds) { |
SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, |
&content); |
- return content.detachAsStream(); |
+ return std::unique_ptr<SkStreamAsset>(content.detachAsStream()); |
} |
/** |
@@ -693,10 +647,9 @@ static sk_sp<SkPDFObject> create_smask_graphic_state( |
SkRect bbox; |
bbox.set(state.fBBox); |
- std::unique_ptr<SkPDFShader::State> alphaToLuminosityState( |
- state.CreateAlphaToLuminosityState()); |
sk_sp<SkPDFObject> luminosityShader( |
- get_pdf_shader_by_state(doc, dpi, &alphaToLuminosityState)); |
+ get_pdf_shader_by_state(doc, dpi, state.MakeAlphaToLuminosityState(), |
+ SkBitmap())); |
std::unique_ptr<SkStreamAsset> alphaStream(create_pattern_fill_content(-1, bbox)); |
@@ -709,22 +662,20 @@ static sk_sp<SkPDFObject> create_smask_graphic_state( |
SkMatrix::I(), |
"DeviceRGB"); |
return SkPDFGraphicState::GetSMaskGraphicState( |
- alphaMask.get(), false, |
+ std::move(alphaMask), false, |
SkPDFGraphicState::kLuminosity_SMaskMode, doc->canon()); |
} |
-SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( |
- SkPDFDocument* doc, |
- SkScalar dpi, |
- std::unique_ptr<SkPDFShader::State>* autoState) { |
- const SkPDFShader::State& state = **autoState; |
+static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, |
+ SkScalar dpi, |
+ const SkPDFShader::State& state) { |
SkRect bbox; |
bbox.set(state.fBBox); |
- std::unique_ptr<SkPDFShader::State> opaqueState(state.CreateOpaqueState()); |
+ SkPDFShader::State opaqueState(state.MakeOpaqueState()); |
sk_sp<SkPDFObject> colorShader( |
- get_pdf_shader_by_state(doc, dpi, &opaqueState)); |
+ get_pdf_shader_by_state(doc, dpi, std::move(opaqueState), SkBitmap())); |
if (!colorShader) { |
return nullptr; |
} |
@@ -733,20 +684,15 @@ SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( |
// pattern shader as P0, then write content stream. |
auto alphaGs = create_smask_graphic_state(doc, dpi, state); |
- SkPDFAlphaFunctionShader* alphaFunctionShader = |
- new SkPDFAlphaFunctionShader(autoState->release()); |
- |
auto resourceDict = |
get_gradient_resource_dict(colorShader.get(), alphaGs.get()); |
std::unique_ptr<SkStreamAsset> colorStream( |
create_pattern_fill_content(0, bbox)); |
- alphaFunctionShader->setData(std::move(colorStream)); |
+ auto alphaFunctionShader = sk_make_sp<SkPDFStream>(std::move(colorStream)); |
- populate_tiling_pattern_dict( |
- alphaFunctionShader->dict(), bbox, resourceDict.get(), |
- SkMatrix::I()); |
- doc->canon()->addAlphaShader(alphaFunctionShader); |
+ populate_tiling_pattern_dict(alphaFunctionShader->dict(), bbox, |
+ std::move(resourceDict), SkMatrix::I()); |
return alphaFunctionShader; |
} |
@@ -802,11 +748,11 @@ sk_sp<SkPDFArray> SkPDFShader::MakeRangeObject() { |
static sk_sp<SkPDFStream> make_ps_function( |
std::unique_ptr<SkStreamAsset> psCode, |
- SkPDFArray* domain, |
+ sk_sp<SkPDFArray> domain, |
sk_sp<SkPDFObject> range) { |
auto result = sk_make_sp<SkPDFStream>(std::move(psCode)); |
result->dict()->insertInt("FunctionType", 4); |
- result->dict()->insertObject("Domain", sk_ref_sp(domain)); |
+ result->dict()->insertObject("Domain", std::move(domain)); |
result->dict()->insertObject("Range", std::move(range)); |
return result; |
} |
@@ -826,10 +772,8 @@ static void FixUpRadius(const SkPoint& p1, SkScalar& r1, const SkPoint& p2, SkSc |
} |
} |
-SkPDFFunctionShader* SkPDFFunctionShader::Create( |
- SkPDFCanon* canon, std::unique_ptr<SkPDFShader::State>* autoState) { |
- const SkPDFShader::State& state = **autoState; |
- |
+static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, |
+ const SkPDFShader::State& state) { |
void (*codeFunction)(const SkShader::GradientInfo& info, |
const SkMatrix& perspectiveRemover, |
SkDynamicMemoryWStream* function) = nullptr; |
@@ -839,10 +783,10 @@ SkPDFFunctionShader* SkPDFFunctionShader::Create( |
finalMatrix.preConcat(state.fShaderTransform); |
bool doStitchFunctions = (state.fType == SkShader::kLinear_GradientType || |
- state.fType == SkShader::kRadial_GradientType || |
- state.fType == SkShader::kConical_GradientType) && |
- info->fTileMode == SkShader::kClamp_TileMode && |
- !finalMatrix.hasPerspective(); |
+ state.fType == SkShader::kRadial_GradientType || |
+ state.fType == SkShader::kConical_GradientType) && |
+ info->fTileMode == SkShader::kClamp_TileMode && |
+ !finalMatrix.hasPerspective(); |
auto domain = sk_make_sp<SkPDFArray>(); |
@@ -984,39 +928,37 @@ SkPDFFunctionShader* SkPDFFunctionShader::Create( |
codeFunction(*info, perspectiveInverseOnly, &functionCode); |
} |
- pdfShader->insertObject("Domain", sk_ref_sp(domain.get())); |
+ pdfShader->insertObject("Domain", domain); |
// Call canon->makeRangeObject() instead of |
// SkPDFShader::MakeRangeObject() so that the canon can |
// deduplicate. |
std::unique_ptr<SkStreamAsset> functionStream( |
functionCode.detachAsStream()); |
- auto function = make_ps_function(std::move(functionStream), domain.get(), |
- canon->makeRangeObject()); |
+ sk_sp<SkPDFStream> function = make_ps_function(std::move(functionStream), |
+ std::move(domain), |
+ canon->makeRangeObject()); |
pdfShader->insertObjRef("Function", std::move(function)); |
} |
pdfShader->insertInt("ShadingType", shadingType); |
pdfShader->insertName("ColorSpace", "DeviceRGB"); |
- sk_sp<SkPDFFunctionShader> pdfFunctionShader( |
- new SkPDFFunctionShader(autoState->release())); |
+ auto pdfFunctionShader = sk_make_sp<SkPDFDict>("Pattern"); |
pdfFunctionShader->insertInt("PatternType", 2); |
pdfFunctionShader->insertObject("Matrix", |
SkPDFUtils::MatrixToArray(finalMatrix)); |
pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); |
- canon->addFunctionShader(pdfFunctionShader.get()); |
- return pdfFunctionShader.release(); |
+ return pdfFunctionShader; |
} |
-SkPDFImageShader* SkPDFImageShader::Create( |
- SkPDFDocument* doc, |
- SkScalar dpi, |
- std::unique_ptr<SkPDFShader::State>* autoState) { |
- const SkPDFShader::State& state = **autoState; |
- |
- state.fImage.lockPixels(); |
+static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, |
+ SkScalar dpi, |
+ const SkPDFShader::State& state, |
+ SkBitmap image) { |
+ SkASSERT(state.fBitmapKey == SkBitmapKey(image)); |
+ SkAutoLockPixels SkAutoLockPixels(image); |
// 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 |
@@ -1032,9 +974,8 @@ SkPDFImageShader* SkPDFImageShader::Create( |
return nullptr; |
} |
- const SkBitmap* image = &state.fImage; |
SkRect bitmapBounds; |
- image->getBounds(&bitmapBounds); |
+ image.getBounds(&bitmapBounds); |
// For tiling modes, the bounds should be extended to include the bitmap, |
// otherwise the bitmap gets clipped out and the shader is empty and awful. |
@@ -1055,7 +996,7 @@ SkPDFImageShader* SkPDFImageShader::Create( |
SkCanvas canvas(patternDevice.get()); |
SkRect patternBBox; |
- image->getBounds(&patternBBox); |
+ image.getBounds(&patternBBox); |
// Translate the canvas so that the bitmap origin is at (0, 0). |
canvas.translate(-deviceBounds.left(), -deviceBounds.top()); |
@@ -1066,24 +1007,24 @@ SkPDFImageShader* SkPDFImageShader::Create( |
// If the bitmap is out of bounds (i.e. clamp mode where we only see the |
// stretched sides), canvas will clip this out and the extraneous data |
// won't be saved to the PDF. |
- canvas.drawBitmap(*image, 0, 0); |
+ canvas.drawBitmap(image, 0, 0); |
- SkScalar width = SkIntToScalar(image->width()); |
- SkScalar height = SkIntToScalar(image->height()); |
+ SkScalar width = SkIntToScalar(image.width()); |
+ SkScalar height = SkIntToScalar(image.height()); |
// Tiling is implied. First we handle mirroring. |
if (tileModes[0] == SkShader::kMirror_TileMode) { |
SkMatrix xMirror; |
xMirror.setScale(-1, 1); |
xMirror.postTranslate(2 * width, 0); |
- drawBitmapMatrix(&canvas, *image, xMirror); |
+ drawBitmapMatrix(&canvas, image, xMirror); |
patternBBox.fRight += width; |
} |
if (tileModes[1] == SkShader::kMirror_TileMode) { |
SkMatrix yMirror; |
yMirror.setScale(SK_Scalar1, -SK_Scalar1); |
yMirror.postTranslate(0, 2 * height); |
- drawBitmapMatrix(&canvas, *image, yMirror); |
+ drawBitmapMatrix(&canvas, image, yMirror); |
patternBBox.fBottom += height; |
} |
if (tileModes[0] == SkShader::kMirror_TileMode && |
@@ -1091,7 +1032,7 @@ SkPDFImageShader* SkPDFImageShader::Create( |
SkMatrix mirror; |
mirror.setScale(-1, -1); |
mirror.postTranslate(2 * width, 2 * height); |
- drawBitmapMatrix(&canvas, *image, mirror); |
+ drawBitmapMatrix(&canvas, image, mirror); |
} |
// Then handle Clamping, which requires expanding the pattern canvas to |
@@ -1105,39 +1046,39 @@ SkPDFImageShader* SkPDFImageShader::Create( |
SkRect rect; |
rect = SkRect::MakeLTRB(deviceBounds.left(), deviceBounds.top(), 0, 0); |
if (!rect.isEmpty()) { |
- paint.setColor(image->getColor(0, 0)); |
+ paint.setColor(image.getColor(0, 0)); |
canvas.drawRect(rect, paint); |
} |
rect = SkRect::MakeLTRB(width, deviceBounds.top(), |
deviceBounds.right(), 0); |
if (!rect.isEmpty()) { |
- paint.setColor(image->getColor(image->width() - 1, 0)); |
+ paint.setColor(image.getColor(image.width() - 1, 0)); |
canvas.drawRect(rect, paint); |
} |
rect = SkRect::MakeLTRB(width, height, |
deviceBounds.right(), deviceBounds.bottom()); |
if (!rect.isEmpty()) { |
- paint.setColor(image->getColor(image->width() - 1, |
- image->height() - 1)); |
+ paint.setColor(image.getColor(image.width() - 1, |
+ image.height() - 1)); |
canvas.drawRect(rect, paint); |
} |
rect = SkRect::MakeLTRB(deviceBounds.left(), height, |
0, deviceBounds.bottom()); |
if (!rect.isEmpty()) { |
- paint.setColor(image->getColor(0, image->height() - 1)); |
+ paint.setColor(image.getColor(0, image.height() - 1)); |
canvas.drawRect(rect, paint); |
} |
} |
// Then expand the left, right, top, then bottom. |
if (tileModes[0] == SkShader::kClamp_TileMode) { |
- SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, image->height()); |
+ SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, image.height()); |
if (deviceBounds.left() < 0) { |
SkBitmap left; |
- SkAssertResult(image->extractSubset(&left, subset)); |
+ SkAssertResult(image.extractSubset(&left, subset)); |
SkMatrix leftMatrix; |
leftMatrix.setScale(-deviceBounds.left(), 1); |
@@ -1154,8 +1095,8 @@ SkPDFImageShader* SkPDFImageShader::Create( |
if (deviceBounds.right() > width) { |
SkBitmap right; |
- subset.offset(image->width() - 1, 0); |
- SkAssertResult(image->extractSubset(&right, subset)); |
+ subset.offset(image.width() - 1, 0); |
+ SkAssertResult(image.extractSubset(&right, subset)); |
SkMatrix rightMatrix; |
rightMatrix.setScale(deviceBounds.right() - width, 1); |
@@ -1172,10 +1113,10 @@ SkPDFImageShader* SkPDFImageShader::Create( |
} |
if (tileModes[1] == SkShader::kClamp_TileMode) { |
- SkIRect subset = SkIRect::MakeXYWH(0, 0, image->width(), 1); |
+ SkIRect subset = SkIRect::MakeXYWH(0, 0, image.width(), 1); |
if (deviceBounds.top() < 0) { |
SkBitmap top; |
- SkAssertResult(image->extractSubset(&top, subset)); |
+ SkAssertResult(image.extractSubset(&top, subset)); |
SkMatrix topMatrix; |
topMatrix.setScale(SK_Scalar1, -deviceBounds.top()); |
@@ -1192,8 +1133,8 @@ SkPDFImageShader* SkPDFImageShader::Create( |
if (deviceBounds.bottom() > height) { |
SkBitmap bottom; |
- subset.offset(0, image->height() - 1); |
- SkAssertResult(image->extractSubset(&bottom, subset)); |
+ subset.offset(0, image.height() - 1); |
+ SkAssertResult(image.extractSubset(&bottom, subset)); |
SkMatrix bottomMatrix; |
bottomMatrix.setScale(SK_Scalar1, deviceBounds.bottom() - height); |
@@ -1209,17 +1150,9 @@ SkPDFImageShader* SkPDFImageShader::Create( |
} |
} |
- // Put the canvas into the pattern stream (fContent). |
- SkPDFImageShader* imageShader = new SkPDFImageShader(autoState->release()); |
- imageShader->setData(patternDevice->content()); |
- |
- auto resourceDict = patternDevice->makeResourceDict(); |
+ auto imageShader = sk_make_sp<SkPDFStream>(patternDevice->content()); |
populate_tiling_pattern_dict(imageShader->dict(), patternBBox, |
- resourceDict.get(), finalMatrix); |
- |
- imageShader->fShaderState->fImage.unlockPixels(); |
- |
- doc->canon()->addImageShader(imageShader); |
+ patternDevice->makeResourceDict(), finalMatrix); |
return imageShader; |
} |
@@ -1277,9 +1210,11 @@ bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { |
} |
SkPDFShader::State::State(SkShader* shader, const SkMatrix& canvasTransform, |
- const SkIRect& bbox, SkScalar rasterScale) |
+ const SkIRect& bbox, SkScalar rasterScale, |
+ SkBitmap* imageDst) |
: fCanvasTransform(canvasTransform), |
fBBox(bbox) { |
+ SkASSERT(imageDst); |
fInfo.fColorCount = 0; |
fInfo.fColors = nullptr; |
fInfo.fColorOffsets = nullptr; |
@@ -1289,18 +1224,19 @@ SkPDFShader::State::State(SkShader* shader, const SkMatrix& canvasTransform, |
fType = shader->asAGradient(&fInfo); |
if (fType == SkShader::kNone_GradientType) { |
- if (!shader->isABitmap(&fImage, nullptr, fImageTileModes)) { |
+ if (!shader->isABitmap(imageDst, nullptr, fImageTileModes)) { |
// Generic fallback for unsupported shaders: |
// * allocate a bbox-sized bitmap |
// * shade the whole area |
// * use the result as a bitmap shader |
- // bbox is in device space. While that's exactly what we want for sizing our bitmap, |
- // we need to map it into shader space for adjustments (to match |
- // SkPDFImageShader::Create's behavior). |
+ // bbox is in device space. While that's exactly what we |
+ // want for sizing our bitmap, we need to map it into |
+ // shader space for adjustments (to match |
+ // MakeImageShader's behavior). |
SkRect shaderRect = SkRect::Make(bbox); |
if (!inverse_transform_bbox(canvasTransform, &shaderRect)) { |
- fImage.reset(); |
+ imageDst->reset(); |
return; |
} |
@@ -1316,13 +1252,13 @@ SkPDFShader::State::State(SkShader* shader, const SkMatrix& canvasTransform, |
SkSize scale = SkSize::Make(SkIntToScalar(size.width()) / shaderRect.width(), |
SkIntToScalar(size.height()) / shaderRect.height()); |
- fImage.allocN32Pixels(size.width(), size.height()); |
- fImage.eraseColor(SK_ColorTRANSPARENT); |
+ imageDst->allocN32Pixels(size.width(), size.height()); |
+ imageDst->eraseColor(SK_ColorTRANSPARENT); |
SkPaint p; |
p.setShader(sk_ref_sp(shader)); |
- SkCanvas canvas(fImage); |
+ SkCanvas canvas(*imageDst); |
canvas.scale(scale.width(), scale.height()); |
canvas.translate(-shaderRect.x(), -shaderRect.y()); |
canvas.drawPaint(p); |
@@ -1330,9 +1266,9 @@ SkPDFShader::State::State(SkShader* shader, const SkMatrix& canvasTransform, |
fShaderTransform.setTranslate(shaderRect.x(), shaderRect.y()); |
fShaderTransform.preScale(1 / scale.width(), 1 / scale.height()); |
} |
- fBitmapKey = SkBitmapKey(fImage); |
+ fBitmapKey = SkBitmapKey(*imageDst); |
} else { |
- AllocateGradientInfoStorage(); |
+ this->allocateGradientInfoStorage(); |
shader->asAGradient(&fInfo); |
} |
} |
@@ -1350,7 +1286,7 @@ SkPDFShader::State::State(const SkPDFShader::State& other) |
if (fType != SkShader::kNone_GradientType) { |
fInfo = other.fInfo; |
- AllocateGradientInfoStorage(); |
+ this->allocateGradientInfoStorage(); |
for (int i = 0; i < fInfo.fColorCount; i++) { |
fInfo.fColors[i] = other.fInfo.fColors[i]; |
fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; |
@@ -1362,14 +1298,15 @@ 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 { |
+SkPDFShader::State SkPDFShader::State::MakeAlphaToLuminosityState() const { |
+ SkASSERT(fBitmapKey == SkBitmapKey()); |
SkASSERT(fType != SkShader::kNone_GradientType); |
- SkPDFShader::State* newState = new SkPDFShader::State(*this); |
+ SkPDFShader::State newState(*this); |
for (int i = 0; i < fInfo.fColorCount; i++) { |
SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
- newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); |
+ newState.fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); |
} |
return newState; |
@@ -1379,12 +1316,13 @@ 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 { |
+SkPDFShader::State SkPDFShader::State::MakeOpaqueState() const { |
+ SkASSERT(fBitmapKey == SkBitmapKey()); |
SkASSERT(fType != SkShader::kNone_GradientType); |
- SkPDFShader::State* newState = new SkPDFShader::State(*this); |
+ SkPDFShader::State newState(*this); |
for (int i = 0; i < fInfo.fColorCount; i++) { |
- newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], |
+ newState.fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], |
SK_AlphaOPAQUE); |
} |
@@ -1408,10 +1346,9 @@ bool SkPDFShader::State::GradientHasAlpha() const { |
return false; |
} |
-void SkPDFShader::State::AllocateGradientInfoStorage() { |
- fColorData.set(sk_malloc_throw( |
- fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
- fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
- fInfo.fColorOffsets = |
- reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
+void SkPDFShader::State::allocateGradientInfoStorage() { |
+ fColors.reset(new SkColor[fInfo.fColorCount]); |
+ fStops.reset(new SkScalar[fInfo.fColorCount]); |
+ fInfo.fColors = fColors.get(); |
+ fInfo.fColorOffsets = fStops.get(); |
} |