SkPDF: SkPDFGraphicState Lookup hashtabled
In Release, running `dm --src skp --config pdf`, I get a speedup of about 1.2%. SkPDFGraphicState class: - Holds the subset of SkPaint that maps to a PDF Graphics State - These fields are easily comparable, making hashtable comparisons easy. SkPDFCanon: - findGraphicState() takes a SkPDFGraphicState, not a SkPaint - fGraphicStateRecords is a SkHashSet, not a SkTDArray SkPDFGraphicState: - mode_for_pdf() replaces logic inside equivalent(), but is only called once per lookup. - emitObject() no longer modifies the SkPDFGraphicState to cache the SkPDFDict stucture. (Since it is de-duped, this get no speedup). - Static Functions that don't use the canon return a plain SkPDFDict now. No need for fPopulated. SkTHash.h - SkHashSet::forall added SkPDFDevice; SkPDFShader - Updated for new SkPDFGraphicState interface. BUG=skia:3585 Review URL: https://codereview.chromium.org/1046293002
This commit is contained in:
parent
03e5161bed
commit
be27a118c2
@ -237,6 +237,12 @@ public:
|
||||
// This pointer remains valid until the next call to add().
|
||||
const T* find(const T& item) const { return fTable.find(item); }
|
||||
|
||||
// Call fn on every item in the set. You may not mutate anything.
|
||||
template <typename Fn> // f(T), f(const T&)
|
||||
void foreach (Fn&& fn) const {
|
||||
fTable.foreach (fn);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Traits {
|
||||
static const T& GetKey(const T& item) { return item; }
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "SkPDFBitmap.h"
|
||||
#include "SkPDFCanon.h"
|
||||
#include "SkPDFFont.h"
|
||||
#include "SkPDFGraphicState.h"
|
||||
#include "SkPDFShader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -24,7 +23,7 @@ void SkPDFCanon::reset() {
|
||||
fAlphaShaderRecords.reset();
|
||||
fImageShaderRecords.unrefAll();
|
||||
fImageShaderRecords.reset();
|
||||
fGraphicStateRecords.unrefAll();
|
||||
fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); });
|
||||
fGraphicStateRecords.reset();
|
||||
fBitmapRecords.unrefAll();
|
||||
fBitmapRecords.reset();
|
||||
@ -107,12 +106,17 @@ void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkPDFGraphicState* SkPDFCanon::findGraphicState(const SkPaint& paint) const {
|
||||
return find_item(fGraphicStateRecords, paint);
|
||||
const SkPDFGraphicState* SkPDFCanon::findGraphicState(
|
||||
const SkPDFGraphicState& key) const {
|
||||
const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key));
|
||||
return ptr ? ptr->fPtr : NULL;
|
||||
}
|
||||
|
||||
void SkPDFCanon::addGraphicState(SkPDFGraphicState* state) {
|
||||
fGraphicStateRecords.push(SkRef(state));
|
||||
void SkPDFCanon::addGraphicState(const SkPDFGraphicState* state) {
|
||||
SkASSERT(state);
|
||||
WrapGS w(SkRef(state));
|
||||
SkASSERT(!fGraphicStateRecords.contains(w));
|
||||
fGraphicStateRecords.add(w);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -7,12 +7,13 @@
|
||||
#ifndef SkPDFCanon_DEFINED
|
||||
#define SkPDFCanon_DEFINED
|
||||
|
||||
#include "SkPDFGraphicState.h"
|
||||
#include "SkPDFShader.h"
|
||||
#include "SkTDArray.h"
|
||||
#include "SkTHash.h"
|
||||
|
||||
class SkBitmap;
|
||||
class SkPDFFont;
|
||||
class SkPDFGraphicState;
|
||||
class SkPDFBitmap;
|
||||
class SkPaint;
|
||||
|
||||
@ -56,8 +57,8 @@ public:
|
||||
SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
|
||||
void addImageShader(SkPDFImageShader*);
|
||||
|
||||
SkPDFGraphicState* findGraphicState(const SkPaint&) const;
|
||||
void addGraphicState(SkPDFGraphicState*);
|
||||
const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
|
||||
void addGraphicState(const SkPDFGraphicState*);
|
||||
|
||||
SkPDFBitmap* findBitmap(const SkBitmap&) const;
|
||||
void addBitmap(SkPDFBitmap*);
|
||||
@ -76,7 +77,20 @@ private:
|
||||
|
||||
SkTDArray<SkPDFImageShader*> fImageShaderRecords;
|
||||
|
||||
SkTDArray<SkPDFGraphicState*> fGraphicStateRecords;
|
||||
struct WrapGS {
|
||||
explicit WrapGS(const SkPDFGraphicState* ptr = NULL) : fPtr(ptr) {}
|
||||
const SkPDFGraphicState* fPtr;
|
||||
bool operator==(const WrapGS& rhs) const {
|
||||
SkASSERT(fPtr);
|
||||
SkASSERT(rhs.fPtr);
|
||||
return *fPtr == *rhs.fPtr;
|
||||
}
|
||||
static uint32_t Hash(const WrapGS& w) {
|
||||
SkASSERT(w.fPtr);
|
||||
return w.fPtr->hash();
|
||||
}
|
||||
};
|
||||
SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
|
||||
|
||||
SkTDArray<SkPDFBitmap*> fBitmapRecords;
|
||||
};
|
||||
|
@ -1569,8 +1569,7 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
|
||||
return;
|
||||
}
|
||||
|
||||
SkAutoTUnref<SkPDFGraphicState> sMaskGS(
|
||||
SkPDFGraphicState::GetSMaskGraphicState(
|
||||
SkAutoTUnref<SkPDFObject> sMaskGS(SkPDFGraphicState::GetSMaskGraphicState(
|
||||
mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode));
|
||||
|
||||
SkMatrix identity;
|
||||
@ -1941,7 +1940,7 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint(
|
||||
}
|
||||
}
|
||||
|
||||
int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) {
|
||||
int SkPDFDevice::addGraphicStateResource(SkPDFObject* gs) {
|
||||
// Assumes that gs has been canonicalized (so we can directly compare
|
||||
// pointers).
|
||||
int result = fGraphicStateResources.find(gs);
|
||||
|
@ -203,7 +203,7 @@ private:
|
||||
SkPDFArray* fAnnotations;
|
||||
SkTDArray<NamedDestination*> fNamedDestinations;
|
||||
|
||||
SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
|
||||
SkTDArray<SkPDFObject*> fGraphicStateResources;
|
||||
SkTDArray<SkPDFObject*> fXObjectResources;
|
||||
SkTDArray<SkPDFFont*> fFontResources;
|
||||
SkTDArray<SkPDFObject*> fShaderResources;
|
||||
@ -271,7 +271,7 @@ private:
|
||||
const SkPaint& paint,
|
||||
bool hasText,
|
||||
GraphicStateEntry* entry);
|
||||
int addGraphicStateResource(SkPDFGraphicState* gs);
|
||||
int addGraphicStateResource(SkPDFObject* gs);
|
||||
int addXObjectResource(SkPDFObject* xObject);
|
||||
|
||||
void updateFont(const SkPaint& paint, uint16_t glyphID,
|
||||
|
@ -70,66 +70,58 @@ static const char* as_blend_mode(SkXfermode::Mode mode) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool equivalent(const SkPaint& a, const SkPaint& b) {
|
||||
// We're only interested in some fields of the SkPaint, so we have
|
||||
// a custom equality function.
|
||||
if (SkColorGetA(a.getColor()) != SkColorGetA(b.getColor()) ||
|
||||
a.getStrokeCap() != b.getStrokeCap() ||
|
||||
a.getStrokeJoin() != b.getStrokeJoin() ||
|
||||
a.getStrokeWidth() != b.getStrokeWidth() ||
|
||||
a.getStrokeMiter() != b.getStrokeMiter()) {
|
||||
return false;
|
||||
// If a SkXfermode is unsupported in PDF, this function returns
|
||||
// SrcOver, otherwise, it returns that Xfermode as a Mode.
|
||||
static SkXfermode::Mode mode_for_pdf(const SkXfermode* xfermode) {
|
||||
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
|
||||
if (xfermode) {
|
||||
xfermode->asMode(&mode);
|
||||
}
|
||||
|
||||
SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode;
|
||||
SkXfermode* aXfermode = a.getXfermode();
|
||||
if (aXfermode) {
|
||||
aXfermode->asMode(&aXfermodeName);
|
||||
switch (mode) {
|
||||
case SkXfermode::kSrcOver_Mode:
|
||||
case SkXfermode::kMultiply_Mode:
|
||||
case SkXfermode::kScreen_Mode:
|
||||
case SkXfermode::kOverlay_Mode:
|
||||
case SkXfermode::kDarken_Mode:
|
||||
case SkXfermode::kLighten_Mode:
|
||||
case SkXfermode::kColorDodge_Mode:
|
||||
case SkXfermode::kColorBurn_Mode:
|
||||
case SkXfermode::kHardLight_Mode:
|
||||
case SkXfermode::kSoftLight_Mode:
|
||||
case SkXfermode::kDifference_Mode:
|
||||
case SkXfermode::kExclusion_Mode:
|
||||
case SkXfermode::kHue_Mode:
|
||||
case SkXfermode::kSaturation_Mode:
|
||||
case SkXfermode::kColor_Mode:
|
||||
case SkXfermode::kLuminosity_Mode:
|
||||
// Mode is suppported and handled by pdf graphics state.
|
||||
return mode;
|
||||
default:
|
||||
return SkXfermode::kSrcOver_Mode; // Default mode.
|
||||
}
|
||||
if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode ||
|
||||
as_blend_mode(aXfermodeName) == NULL) {
|
||||
aXfermodeName = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
const char* aXfermodeString = as_blend_mode(aXfermodeName);
|
||||
SkASSERT(aXfermodeString != NULL);
|
||||
|
||||
SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode;
|
||||
SkXfermode* bXfermode = b.getXfermode();
|
||||
if (bXfermode) {
|
||||
bXfermode->asMode(&bXfermodeName);
|
||||
}
|
||||
if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode ||
|
||||
as_blend_mode(bXfermodeName) == NULL) {
|
||||
bXfermodeName = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
const char* bXfermodeString = as_blend_mode(bXfermodeName);
|
||||
SkASSERT(bXfermodeString != NULL);
|
||||
|
||||
return strcmp(aXfermodeString, bXfermodeString) == 0;
|
||||
}
|
||||
|
||||
bool SkPDFGraphicState::equals(const SkPaint& paint) const {
|
||||
return equivalent(paint, fPaint);
|
||||
}
|
||||
|
||||
SkPDFGraphicState::~SkPDFGraphicState() {}
|
||||
|
||||
void SkPDFGraphicState::emitObject(SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) {
|
||||
populateDict();
|
||||
SkPDFDict::emitObject(stream, objNumMap, substitutes);
|
||||
}
|
||||
SkPDFGraphicState::SkPDFGraphicState(const SkPaint& p)
|
||||
: fStrokeWidth(p.getStrokeWidth())
|
||||
, fStrokeMiter(p.getStrokeMiter())
|
||||
, fAlpha(p.getAlpha())
|
||||
, fStrokeCap(SkToU8(p.getStrokeCap()))
|
||||
, fStrokeJoin(SkToU8(p.getStrokeJoin()))
|
||||
, fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {}
|
||||
|
||||
// static
|
||||
SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
|
||||
SkPDFCanon* canon, const SkPaint& paint) {
|
||||
SkASSERT(canon);
|
||||
SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(paint);
|
||||
if (pdfGraphicState) {
|
||||
return SkRef(pdfGraphicState);
|
||||
SkPDFGraphicState key(paint);
|
||||
if (const SkPDFGraphicState* canonGS = canon->findGraphicState(key)) {
|
||||
// The returned SkPDFGraphicState must be made non-const,
|
||||
// since the emitObject() interface is non-const. But We
|
||||
// promise that there is no way to mutate this object from
|
||||
// here on out.
|
||||
return SkRef(const_cast<SkPDFGraphicState*>(canonGS));
|
||||
}
|
||||
pdfGraphicState = new SkPDFGraphicState(paint);
|
||||
SkPDFGraphicState* pdfGraphicState = new SkPDFGraphicState(paint);
|
||||
canon->addGraphicState(pdfGraphicState);
|
||||
return pdfGraphicState;
|
||||
}
|
||||
@ -159,12 +151,15 @@ SkPDFObject* create_invert_function() {
|
||||
template <typename T> void unref(T* ptr) { ptr->unref(); }
|
||||
} // namespace
|
||||
|
||||
SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, invertFunction,
|
||||
create_invert_function, unref<SkPDFObject>);
|
||||
SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject,
|
||||
invertFunction,
|
||||
create_invert_function,
|
||||
unref<SkPDFObject>);
|
||||
|
||||
// static
|
||||
SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
|
||||
SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) {
|
||||
SkPDFDict* SkPDFGraphicState::GetSMaskGraphicState(SkPDFFormXObject* sMask,
|
||||
bool invert,
|
||||
SkPDFSMaskMode sMaskMode) {
|
||||
// The practical chances of using the same mask more than once are unlikely
|
||||
// enough that it's not worth canonicalizing.
|
||||
SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask"));
|
||||
@ -174,81 +169,64 @@ SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
|
||||
sMaskDict->insertName("S", "Luminosity");
|
||||
}
|
||||
sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref();
|
||||
|
||||
SkPDFGraphicState* result = new SkPDFGraphicState;
|
||||
result->fPopulated = true;
|
||||
result->insertName("Type", "ExtGState");
|
||||
result->insert("SMask", sMaskDict.get());
|
||||
|
||||
if (invert) {
|
||||
sMaskDict->insert("TR", new SkPDFObjRef(invertFunction.get()))->unref();
|
||||
}
|
||||
|
||||
SkPDFDict* result = new SkPDFDict("ExtGState");
|
||||
result->insert("SMask", sMaskDict.get());
|
||||
return result;
|
||||
}
|
||||
|
||||
SkPDFGraphicState* SkPDFGraphicState::CreateNoSMaskGraphicState() {
|
||||
SkPDFGraphicState* noSMaskGS = SkNEW(SkPDFGraphicState);
|
||||
noSMaskGS->fPopulated = true;
|
||||
noSMaskGS->insertName("Type", "ExtGState");
|
||||
namespace {
|
||||
SkPDFDict* create_no_smask_graphic_state() {
|
||||
SkPDFDict* noSMaskGS = new SkPDFDict("ExtGState");
|
||||
noSMaskGS->insertName("SMask", "None");
|
||||
return noSMaskGS;
|
||||
}
|
||||
|
||||
SK_DECLARE_STATIC_LAZY_PTR(
|
||||
SkPDFGraphicState, noSMaskGraphicState,
|
||||
SkPDFGraphicState::CreateNoSMaskGraphicState, unref<SkPDFGraphicState>);
|
||||
} // namespace
|
||||
SK_DECLARE_STATIC_LAZY_PTR(SkPDFDict,
|
||||
noSMaskGraphicState,
|
||||
create_no_smask_graphic_state,
|
||||
unref<SkPDFDict>);
|
||||
|
||||
// static
|
||||
SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
|
||||
SkPDFDict* SkPDFGraphicState::GetNoSMaskGraphicState() {
|
||||
return SkRef(noSMaskGraphicState.get());
|
||||
}
|
||||
|
||||
SkPDFGraphicState::SkPDFGraphicState()
|
||||
: fPopulated(false) {}
|
||||
void SkPDFGraphicState::emitObject(SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) {
|
||||
SkAutoTUnref<SkPDFDict> dict(SkNEW_ARGS(SkPDFDict, ("ExtGState")));
|
||||
dict->insertName("Type", "ExtGState");
|
||||
|
||||
SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint)
|
||||
: fPaint(paint), fPopulated(false) {}
|
||||
SkAutoTUnref<SkPDFScalar> alpha(new SkPDFScalar(SkScalarDiv(fAlpha, 0xFF)));
|
||||
dict->insert("CA", alpha.get());
|
||||
dict->insert("ca", alpha.get());
|
||||
|
||||
// populateDict and operator== have to stay in sync with each other.
|
||||
void SkPDFGraphicState::populateDict() {
|
||||
if (!fPopulated) {
|
||||
fPopulated = true;
|
||||
insertName("Type", "ExtGState");
|
||||
SkPaint::Cap strokeCap = (SkPaint::Cap)fStrokeCap;
|
||||
SkPaint::Join strokeJoin = (SkPaint::Join)fStrokeJoin;
|
||||
SkXfermode::Mode xferMode = (SkXfermode::Mode)fMode;
|
||||
|
||||
SkAutoTUnref<SkPDFScalar> alpha(
|
||||
new SkPDFScalar(SkScalarDiv(fPaint.getAlpha(), 0xFF)));
|
||||
insert("CA", alpha.get());
|
||||
insert("ca", alpha.get());
|
||||
SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch);
|
||||
SkASSERT(strokeCap >= 0 && strokeCap <= 2);
|
||||
dict->insertInt("LC", strokeCap);
|
||||
|
||||
SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch);
|
||||
SkASSERT(fPaint.getStrokeCap() >= 0 && fPaint.getStrokeCap() <= 2);
|
||||
insertInt("LC", fPaint.getStrokeCap());
|
||||
SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch);
|
||||
SkASSERT(strokeJoin >= 0 && strokeJoin <= 2);
|
||||
dict->insertInt("LJ", strokeJoin);
|
||||
|
||||
SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch);
|
||||
SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch);
|
||||
SkASSERT(fPaint.getStrokeJoin() >= 0 && fPaint.getStrokeJoin() <= 2);
|
||||
insertInt("LJ", fPaint.getStrokeJoin());
|
||||
|
||||
insertScalar("LW", fPaint.getStrokeWidth());
|
||||
insertScalar("ML", fPaint.getStrokeMiter());
|
||||
insert("SA", new SkPDFBool(true))->unref(); // Auto stroke adjustment.
|
||||
|
||||
SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
|
||||
// If asMode fails, default to kSrcOver_Mode.
|
||||
if (fPaint.getXfermode())
|
||||
fPaint.getXfermode()->asMode(&xfermode);
|
||||
// If we don't support the mode, just use kSrcOver_Mode.
|
||||
if (xfermode < 0 || xfermode > SkXfermode::kLastMode ||
|
||||
as_blend_mode(xfermode) == NULL) {
|
||||
xfermode = SkXfermode::kSrcOver_Mode;
|
||||
NOT_IMPLEMENTED("unsupported xfermode", false);
|
||||
}
|
||||
insertName("BM", as_blend_mode(xfermode));
|
||||
}
|
||||
dict->insertScalar("LW", fStrokeWidth);
|
||||
dict->insertScalar("ML", fStrokeMiter);
|
||||
// SA = Auto stroke adjustment.
|
||||
dict->insert("SA", new SkPDFBool(true))->unref();
|
||||
dict->insertName("BM", as_blend_mode(xferMode));
|
||||
dict->emitObject(stream, objNumMap, substitutes);
|
||||
}
|
||||
|
@ -13,19 +13,17 @@
|
||||
#include "SkPaint.h"
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkChecksum.h"
|
||||
|
||||
class SkPDFCanon;
|
||||
class SkPDFFormXObject;
|
||||
|
||||
/** \class SkPDFGraphicState
|
||||
SkPaint objects roughly correspond to graphic state dictionaries that can
|
||||
be installed. So that a given dictionary is only output to the pdf file
|
||||
once, we want to canonicalize them. Static methods in this class manage
|
||||
a weakly referenced set of SkPDFGraphicState objects: when the last
|
||||
reference to a SkPDFGraphicState is removed, it removes itself from the
|
||||
static set of objects.
|
||||
|
||||
once, we want to canonicalize them.
|
||||
*/
|
||||
class SkPDFGraphicState : public SkPDFDict {
|
||||
class SkPDFGraphicState : public SkPDFObject {
|
||||
SK_DECLARE_INST_COUNT(SkPDFGraphicState)
|
||||
public:
|
||||
enum SkPDFSMaskMode {
|
||||
@ -33,8 +31,6 @@ public:
|
||||
kLuminosity_SMaskMode
|
||||
};
|
||||
|
||||
virtual ~SkPDFGraphicState();
|
||||
|
||||
// Override emitObject so that we can populate the dictionary on
|
||||
// demand.
|
||||
virtual void emitObject(SkWStream* stream,
|
||||
@ -57,32 +53,37 @@ public:
|
||||
* @param sMask The form xobject to use as a soft mask.
|
||||
* @param invert Indicates if the alpha of the sMask should be inverted.
|
||||
* @param sMaskMode Whether to use alpha or luminosity for the sMask.
|
||||
*
|
||||
* These are not de-duped.
|
||||
*/
|
||||
static SkPDFGraphicState* GetSMaskGraphicState(SkPDFFormXObject* sMask,
|
||||
bool invert,
|
||||
SkPDFSMaskMode sMaskMode);
|
||||
static SkPDFDict* GetSMaskGraphicState(SkPDFFormXObject* sMask,
|
||||
bool invert,
|
||||
SkPDFSMaskMode sMaskMode);
|
||||
|
||||
/** Get a graphic state that only unsets the soft mask. The reference
|
||||
* count of the object is incremented and it is the caller's responsibility
|
||||
* to unreference it when done. This is needed to accommodate the weak
|
||||
* reference pattern used when the returned object is new and has no
|
||||
* other references.
|
||||
*
|
||||
* The returned object is a singleton.
|
||||
*/
|
||||
static SkPDFGraphicState* GetNoSMaskGraphicState();
|
||||
static SkPDFDict* GetNoSMaskGraphicState();
|
||||
|
||||
bool equals(const SkPaint&) const;
|
||||
|
||||
// Only public for SK_DECLARE_STATIC_LAZY_PTR
|
||||
static SkPDFGraphicState* CreateNoSMaskGraphicState();
|
||||
bool operator==(const SkPDFGraphicState& rhs) const {
|
||||
return 0 == memcmp(&fStrokeWidth, &rhs.fStrokeWidth, 12);
|
||||
}
|
||||
uint32_t hash() const { return SkChecksum::Murmur3(&fStrokeWidth, 12); }
|
||||
|
||||
private:
|
||||
const SkPaint fPaint;
|
||||
bool fPopulated;
|
||||
const SkScalar fStrokeWidth;
|
||||
const SkScalar fStrokeMiter;
|
||||
const uint8_t fAlpha;
|
||||
const uint8_t fStrokeCap; // SkPaint::Cap
|
||||
const uint8_t fStrokeJoin; // SkPaint::Join
|
||||
const uint8_t fMode; // SkXfermode::Mode
|
||||
|
||||
SkPDFGraphicState();
|
||||
SkPDFGraphicState(const SkPaint& paint);
|
||||
|
||||
void populateDict();
|
||||
SkPDFGraphicState(const SkPaint&);
|
||||
|
||||
typedef SkPDFDict INHERITED;
|
||||
};
|
||||
|
@ -635,7 +635,7 @@ static SkStream* create_pattern_fill_content(int gsIndex, SkRect& bounds) {
|
||||
* Creates a ExtGState with the SMask set to the luminosityShader in
|
||||
* luminosity mode. The shader pattern extends to the bbox.
|
||||
*/
|
||||
static SkPDFGraphicState* create_smask_graphic_state(
|
||||
static SkPDFObject* create_smask_graphic_state(
|
||||
SkPDFCanon* canon, SkScalar dpi, const SkPDFShader::State& state) {
|
||||
SkRect bbox;
|
||||
bbox.set(state.fBBox);
|
||||
@ -676,7 +676,7 @@ SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create(
|
||||
|
||||
// Create resource dict with alpha graphics state as G0 and
|
||||
// pattern shader as P0, then write content stream.
|
||||
SkAutoTUnref<SkPDFGraphicState> alphaGs(
|
||||
SkAutoTUnref<SkPDFObject> alphaGs(
|
||||
create_smask_graphic_state(canon, dpi, state));
|
||||
|
||||
SkPDFAlphaFunctionShader* alphaFunctionShader =
|
||||
|
Loading…
Reference in New Issue
Block a user