aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar halcanary <halcanary@google.com>2016-08-03 11:16:56 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-03 11:16:57 -0700
commitdabd4f0b799318cb6e90b69ae1ec0ed0b6d32f60 (patch)
tree440e9e2677dbbf17b2b8e2ce10a7131b99641eb7
parent62e1a1a4ba9926c9b515eb603173ea4202ac28ae (diff)
SkPDF: PDFShader code modernized.
Motivation: reduce code complexity. SkCanon stores SkPDFShader::State next to SkDFObject, not inside. many places use sk_sp<T> rather than T* to represent ownership. SkPDFShader::State no longer holds bitmap. SkPDFShader::State gets move constructor, no longer heap-allocated. Classes removed: SkPDFFunctionShader SkPDFAlphaFunctionShader SkPDFImageShader BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2193973002 Review-Url: https://codereview.chromium.org/2193973002
-rw-r--r--src/pdf/SkPDFCanon.cpp64
-rw-r--r--src/pdf/SkPDFCanon.h26
-rw-r--r--src/pdf/SkPDFDevice.cpp55
-rw-r--r--src/pdf/SkPDFDevice.h6
-rw-r--r--src/pdf/SkPDFGraphicState.cpp4
-rw-r--r--src/pdf/SkPDFGraphicState.h2
-rw-r--r--src/pdf/SkPDFShader.cpp319
-rw-r--r--src/pdf/SkPDFShader.h90
-rw-r--r--src/pdf/SkPDFTypes.h2
-rw-r--r--tests/CPlusPlusEleven.cpp20
10 files changed, 268 insertions, 320 deletions
diff --git a/src/pdf/SkPDFCanon.cpp b/src/pdf/SkPDFCanon.cpp
index 11bfb892d1..3dcf4e9f0f 100644
--- a/src/pdf/SkPDFCanon.cpp
+++ b/src/pdf/SkPDFCanon.cpp
@@ -17,12 +17,13 @@ void SkPDFCanon::reset() {
fFontRecords[i].fFont->unref();
}
fFontRecords.reset();
- fFunctionShaderRecords.unrefAll();
+
fFunctionShaderRecords.reset();
- fAlphaShaderRecords.unrefAll();
fAlphaShaderRecords.reset();
- fImageShaderRecords.unrefAll();
fImageShaderRecords.reset();
+
+ // TODO(halcanary): make SkTHashSet work nicely with sk_sp<>,
+ // or use std::unordered_set<>
fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); });
fGraphicStateRecords.reset();
@@ -32,21 +33,6 @@ void SkPDFCanon::reset() {
////////////////////////////////////////////////////////////////////////////////
-template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; }
-
-// requires `bool T::equals(const U&) const`
-template <typename T, typename U>
-T* find_item(const SkTDArray<T*>& ptrArray, const U& object) {
- for (int i = 0; i < ptrArray.count(); ++i) {
- if (ptrArray[i]->equals(object)) {
- return ptrArray[i];
- }
- }
- return nullptr;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
SkPDFFont* SkPDFCanon::findFont(uint32_t fontID,
uint16_t glyphID,
SkPDFFont** relatedFontPtr) const {
@@ -76,33 +62,43 @@ void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) {
////////////////////////////////////////////////////////////////////////////////
-SkPDFFunctionShader* SkPDFCanon::findFunctionShader(
+template <typename T>
+sk_sp<SkPDFObject> find_shader(const SkTArray<T>& records,
+ const SkPDFShader::State& state) {
+ for (const T& record : records) {
+ if (record.fShaderState == state) {
+ return record.fShaderObject;
+ }
+ }
+ return nullptr;
+}
+
+sk_sp<SkPDFObject> SkPDFCanon::findFunctionShader(
const SkPDFShader::State& state) const {
- return find_item(fFunctionShaderRecords, state);
+ return find_shader(fFunctionShaderRecords, state);
}
-void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) {
- fFunctionShaderRecords.push(SkRef(pdfShader));
+void SkPDFCanon::addFunctionShader(sk_sp<SkPDFObject> pdfShader,
+ SkPDFShader::State state) {
+ fFunctionShaderRecords.emplace_back(std::move(state), std::move(pdfShader));
}
-////////////////////////////////////////////////////////////////////////////////
-
-SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader(
+sk_sp<SkPDFObject> SkPDFCanon::findAlphaShader(
const SkPDFShader::State& state) const {
- return find_item(fAlphaShaderRecords, state);
+ return find_shader(fAlphaShaderRecords, state);
}
-void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
- fAlphaShaderRecords.push(SkRef(pdfShader));
+void SkPDFCanon::addAlphaShader(sk_sp<SkPDFObject> pdfShader,
+ SkPDFShader::State state) {
+ fAlphaShaderRecords.emplace_back(std::move(state), std::move(pdfShader));
}
-////////////////////////////////////////////////////////////////////////////////
-
-SkPDFImageShader* SkPDFCanon::findImageShader(
+sk_sp<SkPDFObject> SkPDFCanon::findImageShader(
const SkPDFShader::State& state) const {
- return find_item(fImageShaderRecords, state);
+ return find_shader(fImageShaderRecords, state);
}
-void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
- fImageShaderRecords.push(SkRef(pdfShader));
+void SkPDFCanon::addImageShader(sk_sp<SkPDFObject> pdfShader,
+ SkPDFShader::State state) {
+ fImageShaderRecords.emplace_back(std::move(state), std::move(pdfShader));
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h
index cae93c97c9..a0241e308f 100644
--- a/src/pdf/SkPDFCanon.h
+++ b/src/pdf/SkPDFCanon.h
@@ -48,14 +48,14 @@ public:
SkPDFFont** relatedFont) const;
void addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
- SkPDFFunctionShader* findFunctionShader(const SkPDFShader::State&) const;
- void addFunctionShader(SkPDFFunctionShader*);
+ sk_sp<SkPDFObject> findFunctionShader(const SkPDFShader::State&) const;
+ void addFunctionShader(sk_sp<SkPDFObject>, SkPDFShader::State);
- SkPDFAlphaFunctionShader* findAlphaShader(const SkPDFShader::State&) const;
- void addAlphaShader(SkPDFAlphaFunctionShader*);
+ sk_sp<SkPDFObject> findAlphaShader(const SkPDFShader::State&) const;
+ void addAlphaShader(sk_sp<SkPDFObject>, SkPDFShader::State);
- SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
- void addImageShader(SkPDFImageShader*);
+ sk_sp<SkPDFObject> findImageShader(const SkPDFShader::State&) const;
+ void addImageShader(sk_sp<SkPDFObject>, SkPDFShader::State);
const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
void addGraphicState(const SkPDFGraphicState*);
@@ -82,11 +82,15 @@ private:
};
SkTDArray<FontRec> fFontRecords;
- SkTDArray<SkPDFFunctionShader*> fFunctionShaderRecords;
-
- SkTDArray<SkPDFAlphaFunctionShader*> fAlphaShaderRecords;
-
- SkTDArray<SkPDFImageShader*> fImageShaderRecords;
+ struct ShaderRec {
+ SkPDFShader::State fShaderState;
+ sk_sp<SkPDFObject> fShaderObject;
+ ShaderRec(SkPDFShader::State s, sk_sp<SkPDFObject> o)
+ : fShaderState(std::move(s)), fShaderObject(std::move(o)) {}
+ };
+ SkTArray<ShaderRec> fFunctionShaderRecords;
+ SkTArray<ShaderRec> fAlphaShaderRecords;
+ SkTArray<ShaderRec> fImageShaderRecords;
struct WrapGS {
explicit WrapGS(const SkPDFGraphicState* ptr = nullptr) : fPtr(ptr) {}
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 211ce50b3d..7d025780a6 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -564,9 +564,8 @@ public:
if (shape->isEmpty()) {
shape = nullptr;
}
- fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape);
+ fDevice->finishContentEntry(fXfermode, std::move(fDstFormXObject), shape);
}
- SkSafeUnref(fDstFormXObject);
}
SkPDFDevice::ContentEntry* entry() { return fContentEntry; }
@@ -609,7 +608,7 @@ private:
SkPDFDevice* fDevice;
SkPDFDevice::ContentEntry* fContentEntry;
SkXfermode::Mode fXfermode;
- SkPDFObject* fDstFormXObject;
+ sk_sp<SkPDFObject> fDstFormXObject;
SkPath fShape;
void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
@@ -1606,7 +1605,7 @@ sk_sp<SkPDFObject> SkPDFDevice::makeFormXObjectFromDevice() {
}
void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
- SkPDFObject* mask,
+ sk_sp<SkPDFObject> mask,
const SkClipStack* clipStack,
const SkRegion& clipRegion,
SkXfermode::Mode mode,
@@ -1616,7 +1615,8 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
}
sk_sp<SkPDFDict> sMaskGS = SkPDFGraphicState::GetSMaskGraphicState(
- mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode, fDocument->canon());
+ std::move(mask), invertClip,
+ SkPDFGraphicState::kAlpha_SMaskMode, fDocument->canon());
SkMatrix identity;
identity.reset();
@@ -1643,7 +1643,7 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli
const SkMatrix& matrix,
const SkPaint& paint,
bool hasText,
- SkPDFObject** dst) {
+ sk_sp<SkPDFObject>* dst) {
*dst = nullptr;
if (clipRegion.isEmpty()) {
return nullptr;
@@ -1684,8 +1684,7 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli
xfermode == SkXfermode::kDstATop_Mode ||
xfermode == SkXfermode::kModulate_Mode) {
if (!isContentEmpty()) {
- // TODO(halcanary): make this safer.
- *dst = this->makeFormXObjectFromDevice().release();
+ *dst = this->makeFormXObjectFromDevice();
SkASSERT(isContentEmpty());
} else if (xfermode != SkXfermode::kSrc_Mode &&
xfermode != SkXfermode::kSrcOut_Mode) {
@@ -1716,7 +1715,7 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli
}
void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
- SkPDFObject* dst,
+ sk_sp<SkPDFObject> dst,
SkPath* shape) {
if (xfermode != SkXfermode::kClear_Mode &&
xfermode != SkXfermode::kSrc_Mode &&
@@ -1773,7 +1772,8 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
ScopedContentEntry content(this, &fExistingClipStack,
fExistingClipRegion, identity,
stockPaint);
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
+ // TODO: addXObjectResource take sk_sp
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()),
&content.entry()->fContent);
return;
} else {
@@ -1795,8 +1795,6 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
&fExistingClipStack, fExistingClipRegion,
SkXfermode::kSrcOver_Mode, true);
} else {
- sk_sp<SkPDFObject> dstMaskStorage;
- SkPDFObject* dstMask = srcFormXObject.get();
if (shape != nullptr) {
// Draw shape into a form-xobject.
SkRasterClip rc(clipRegion);
@@ -1808,13 +1806,16 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
filledPaint.setColor(SK_ColorBLACK);
filledPaint.setStyle(SkPaint::kFill_Style);
this->drawPath(d, *shape, filledPaint, nullptr, true);
+ drawFormXObjectWithMask(addXObjectResource(dst.get()),
+ this->makeFormXObjectFromDevice(),
+ &fExistingClipStack, fExistingClipRegion,
+ SkXfermode::kSrcOver_Mode, true);
- dstMaskStorage = this->makeFormXObjectFromDevice();
- dstMask = dstMaskStorage.get();
+ } else {
+ drawFormXObjectWithMask(addXObjectResource(dst.get()), srcFormXObject,
+ &fExistingClipStack, fExistingClipRegion,
+ SkXfermode::kSrcOver_Mode, true);
}
- drawFormXObjectWithMask(addXObjectResource(dst), dstMask,
- &fExistingClipStack, fExistingClipRegion,
- SkXfermode::kSrcOver_Mode, true);
}
if (xfermode == SkXfermode::kClear_Mode) {
@@ -1835,7 +1836,7 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
ScopedContentEntry content(this, &fExistingClipStack,
fExistingClipRegion, identity, stockPaint);
if (content.entry()) {
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()),
&content.entry()->fContent);
}
}
@@ -1851,22 +1852,26 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
if (xfermode == SkXfermode::kSrcIn_Mode ||
xfermode == SkXfermode::kSrcOut_Mode ||
xfermode == SkXfermode::kSrcATop_Mode) {
- drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
+ drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
+ std::move(dst),
&fExistingClipStack, fExistingClipRegion,
SkXfermode::kSrcOver_Mode,
xfermode == SkXfermode::kSrcOut_Mode);
+ return;
} else {
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
+ int resourceID = addXObjectResource(dst.get());
if (xfermode == SkXfermode::kModulate_Mode) {
drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
- dst, &fExistingClipStack,
+ std::move(dst), &fExistingClipStack,
fExistingClipRegion,
SkXfermode::kSrcOver_Mode, false);
mode = SkXfermode::kMultiply_Mode;
}
- drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(),
+ drawFormXObjectWithMask(resourceID, std::move(srcFormXObject),
&fExistingClipStack, fExistingClipRegion, mode,
xfermode == SkXfermode::kDstOut_Mode);
+ return;
}
}
@@ -1918,8 +1923,8 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint(
SkScalar rasterScale =
SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE;
- pdfShader.reset(SkPDFShader::GetPDFShader(
- fDocument, fRasterDpi, shader, transform, bounds, rasterScale));
+ pdfShader = SkPDFShader::GetPDFShader(
+ fDocument, fRasterDpi, shader, transform, bounds, rasterScale);
if (pdfShader.get()) {
// pdfShader has been canonicalized so we can directly compare
@@ -1981,13 +1986,13 @@ int SkPDFDevice::addGraphicStateResource(SkPDFObject* gs) {
}
int SkPDFDevice::addXObjectResource(SkPDFObject* xObject) {
+ // TODO(halcanary): make this take a sk_sp<SkPDFObject>
// Assumes that xobject has been canonicalized (so we can directly compare
// pointers).
int result = fXObjectResources.find(xObject);
if (result < 0) {
result = fXObjectResources.count();
- fXObjectResources.push(xObject);
- xObject->ref();
+ fXObjectResources.push(SkRef(xObject));
}
return result;
}
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index d5d52f98e3..5fedd0eb4c 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -271,7 +271,7 @@ private:
sk_sp<SkPDFObject> makeFormXObjectFromDevice();
void drawFormXObjectWithMask(int xObjectIndex,
- SkPDFObject* mask,
+ sk_sp<SkPDFObject> mask,
const SkClipStack* clipStack,
const SkRegion& clipRegion,
SkXfermode::Mode mode,
@@ -286,9 +286,9 @@ private:
const SkMatrix& matrix,
const SkPaint& paint,
bool hasText,
- SkPDFObject** dst);
+ sk_sp<SkPDFObject>* dst);
void finishContentEntry(SkXfermode::Mode xfermode,
- SkPDFObject* dst,
+ sk_sp<SkPDFObject> dst,
SkPath* shape);
bool isContentEmpty();
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp
index 7b793e6ea8..5a603ce8da 100644
--- a/src/pdf/SkPDFGraphicState.cpp
+++ b/src/pdf/SkPDFGraphicState.cpp
@@ -144,7 +144,7 @@ sk_sp<SkPDFStream> SkPDFGraphicState::MakeInvertFunction() {
}
sk_sp<SkPDFDict> SkPDFGraphicState::GetSMaskGraphicState(
- SkPDFObject* sMask,
+ sk_sp<SkPDFObject> sMask,
bool invert,
SkPDFSMaskMode sMaskMode,
SkPDFCanon* canon) {
@@ -156,7 +156,7 @@ sk_sp<SkPDFDict> SkPDFGraphicState::GetSMaskGraphicState(
} else if (sMaskMode == kLuminosity_SMaskMode) {
sMaskDict->insertName("S", "Luminosity");
}
- sMaskDict->insertObjRef("G", sk_ref_sp(sMask));
+ sMaskDict->insertObjRef("G", std::move(sMask));
if (invert) {
// Instead of calling SkPDFGraphicState::MakeInvertFunction,
// let the canon deduplicate this object.
diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h
index 6b3f7cccf0..84491ba0d3 100644
--- a/src/pdf/SkPDFGraphicState.h
+++ b/src/pdf/SkPDFGraphicState.h
@@ -51,7 +51,7 @@ public:
*
* These are not de-duped.
*/
- static sk_sp<SkPDFDict> GetSMaskGraphicState(SkPDFObject* sMask,
+ static sk_sp<SkPDFDict> GetSMaskGraphicState(sk_sp<SkPDFObject> sMask,
bool invert,
SkPDFSMaskMode sMaskMode,
SkPDFCanon* canon);
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp
index 885b7e6049..f7aef6304a 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();
}
diff --git a/src/pdf/SkPDFShader.h b/src/pdf/SkPDFShader.h
index a6d36b6f02..db13cd50b3 100644
--- a/src/pdf/SkPDFShader.h
+++ b/src/pdf/SkPDFShader.h
@@ -9,12 +9,13 @@
#ifndef SkPDFShader_DEFINED
#define SkPDFShader_DEFINED
+#include "SkBitmapKey.h"
#include "SkPDFTypes.h"
+#include "SkShader.h"
class SkPDFCanon;
class SkPDFDocument;
class SkMatrix;
-class SkShader;
struct SkIRect;
/** \class SkPDFShader
@@ -25,8 +26,6 @@ struct SkIRect;
class SkPDFShader {
public:
- class State;
-
/** Get the PDF shader for the passed SkShader. If the SkShader is
* invalid in some way, returns nullptr. The reference count of
* the object is incremented and it is the caller's responsibility to
@@ -41,60 +40,47 @@ public:
* @param rasterScale Additional scale to be applied for early
* rasterization.
*/
- static SkPDFObject* GetPDFShader(SkPDFDocument* doc,
- SkScalar dpi,
- SkShader* shader,
- const SkMatrix& matrix,
- const SkIRect& surfaceBBox,
- SkScalar rasterScale);
+ static sk_sp<SkPDFObject> GetPDFShader(SkPDFDocument* doc,
+ SkScalar dpi,
+ SkShader* shader,
+ const SkMatrix& matrix,
+ const SkIRect& surfaceBBox,
+ SkScalar rasterScale);
static sk_sp<SkPDFArray> MakeRangeObject();
-};
-class SkPDFFunctionShader final : public SkPDFDict {
-public:
- static SkPDFFunctionShader* Create(SkPDFCanon*,
- std::unique_ptr<SkPDFShader::State>*);
- virtual ~SkPDFFunctionShader();
- bool equals(const SkPDFShader::State&) const;
-
-private:
- std::unique_ptr<const SkPDFShader::State> fShaderState;
- SkPDFFunctionShader(SkPDFShader::State*);
- typedef SkPDFDict INHERITED;
-};
+ class State {
+ public:
+ SkShader::GradientType fType;
+ SkShader::GradientInfo fInfo;
+ std::unique_ptr<SkColor[]> fColors;
+ std::unique_ptr<SkScalar[]> fStops;
+ SkMatrix fCanvasTransform;
+ SkMatrix fShaderTransform;
+ SkIRect fBBox;
-/**
- * A shader for PDF gradients. This encapsulates the function shader
- * inside a tiling pattern while providing a common pattern interface.
- * The encapsulation allows the use of a SMask for transparency gradients.
- */
-class SkPDFAlphaFunctionShader final : public SkPDFStream {
-public:
- static SkPDFAlphaFunctionShader* Create(SkPDFDocument*,
- SkScalar dpi,
- std::unique_ptr<SkPDFShader::State>*);
- virtual ~SkPDFAlphaFunctionShader();
- bool equals(const SkPDFShader::State&) const;
-
-private:
- std::unique_ptr<const SkPDFShader::State> fShaderState;
- SkPDFAlphaFunctionShader(SkPDFShader::State*);
- typedef SkPDFStream INHERITED;
-};
+ SkBitmapKey fBitmapKey;
+ SkShader::TileMode fImageTileModes[2];
-class SkPDFImageShader final : public SkPDFStream {
-public:
- static SkPDFImageShader* Create(SkPDFDocument*,
- SkScalar dpi,
- std::unique_ptr<SkPDFShader::State>*);
- virtual ~SkPDFImageShader();
- bool equals(const SkPDFShader::State&) const;
-
-private:
- std::unique_ptr<const SkPDFShader::State> fShaderState;
- SkPDFImageShader(SkPDFShader::State*);
- typedef SkPDFStream INHERITED;
+ State(SkShader* shader, const SkMatrix& canvasTransform,
+ const SkIRect& bbox, SkScalar rasterScale,
+ SkBitmap* dstImage);
+
+ bool operator==(const State& b) const;
+
+ State MakeAlphaToLuminosityState() const;
+ State MakeOpaqueState() const;
+
+ bool GradientHasAlpha() const;
+
+ State(State&&) = default;
+ State& operator=(State&&) = default;
+
+ private:
+ State(const State& other);
+ State& operator=(const State& rhs);
+ void allocateGradientInfoStorage();
+ };
};
#endif
diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h
index 6ee9162139..52ce221725 100644
--- a/src/pdf/SkPDFTypes.h
+++ b/src/pdf/SkPDFTypes.h
@@ -331,7 +331,7 @@ private:
memory.
*/
-class SkPDFStream : public SkPDFObject {
+class SkPDFStream final : public SkPDFObject {
public:
/** Create a PDF stream. A Length entry is automatically added to the
diff --git a/tests/CPlusPlusEleven.cpp b/tests/CPlusPlusEleven.cpp
index b5a34b2264..3130e6f95b 100644
--- a/tests/CPlusPlusEleven.cpp
+++ b/tests/CPlusPlusEleven.cpp
@@ -35,3 +35,23 @@ DEF_TEST(CPlusPlusEleven_constexpr, r) {
static constexpr int y = SkTPin<int>(100, 0, 10);
REPORTER_ASSERT(r, y == 10);
}
+
+namespace {
+struct MoveableCopyable {
+ bool fCopied;
+ MoveableCopyable() : fCopied(false) {}
+ MoveableCopyable(const MoveableCopyable &o) : fCopied(true) {}
+ MoveableCopyable(MoveableCopyable &&o) : fCopied(o.fCopied) {}
+};
+struct TestClass {
+ MoveableCopyable fFoo;
+};
+} // namespace
+
+DEF_TEST(CPlusPlusEleven_default_move, r) {
+ TestClass a;
+ TestClass b(a);
+ TestClass c(std::move(a));
+ REPORTER_ASSERT(r, b.fFoo.fCopied);
+ REPORTER_ASSERT(r, !c.fFoo.fCopied);
+}