/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPDFCanon_DEFINED
#define SkPDFCanon_DEFINED
#include "SkPDFGraphicState.h"
#include "SkPDFShader.h"
#include "SkPixelSerializer.h"
#include "SkTDArray.h"
#include "SkTHash.h"
#include "SkBitmapKey.h"
class SkAdvancedTypefaceMetrics;
class SkPDFFont;
/**
* The SkPDFCanon canonicalizes objects across PDF pages
* (SkPDFDevices) and across draw calls.
*
* The PDF backend works correctly if:
* - There is no more than one SkPDFCanon for each thread.
* - Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
* - All SkPDFDevices in a document share the same SkPDFCanon.
* The SkPDFDocument class makes this happen by owning a single
* SkPDFCanon.
*
* The addFoo() methods will ref the Foo; the canon's destructor will
* call foo->unref() on all of these objects.
*
* The findFoo() methods do not change the ref count of the Foo
* objects.
*/
class SkPDFCanon : SkNoncopyable {
public:
~SkPDFCanon();
// reset to original setting, unrefs all objects.
void reset();
sk_sp<SkPDFObject> findFunctionShader(const SkPDFShader::State&) const;
void addFunctionShader(sk_sp<SkPDFObject>, SkPDFShader::State);
sk_sp<SkPDFObject> findAlphaShader(const SkPDFShader::State&) const;
void addAlphaShader(sk_sp<SkPDFObject>, SkPDFShader::State);
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*);
sk_sp<SkPDFObject> findPDFBitmap(SkBitmapKey key) const;
void addPDFBitmap(SkBitmapKey key, sk_sp<SkPDFObject>);
SkTHashMap<uint32_t, SkAdvancedTypefaceMetrics*> fTypefaceMetrics;
SkTHashMap<uint32_t, SkPDFDict*> fFontDescriptors;
SkTHashMap<uint64_t, SkPDFFont*> fFontMap;
SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer.get(); }
void setPixelSerializer(sk_sp<SkPixelSerializer> ps) {
fPixelSerializer = std::move(ps);
}
sk_sp<SkPDFStream> makeInvertFunction();
sk_sp<SkPDFDict> makeNoSmaskGraphicState();
sk_sp<SkPDFArray> makeRangeObject();
private:
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) {}
const SkPDFGraphicState* fPtr;
bool operator==(const WrapGS& rhs) const {
SkASSERT(fPtr);
SkASSERT(rhs.fPtr);
return *fPtr == *rhs.fPtr;
}
struct Hash {
uint32_t operator()(const WrapGS& w) const {
SkASSERT(w.fPtr);
return w.fPtr->hash();
}
};
};
SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
// TODO(halcanary): make SkTHashMap<K, sk_sp<V>> work correctly.
SkTHashMap<SkBitmapKey, SkPDFObject*> fPDFBitmapMap;
sk_sp<SkPixelSerializer> fPixelSerializer;
sk_sp<SkPDFStream> fInvertFunction;
sk_sp<SkPDFDict> fNoSmaskGraphicState;
sk_sp<SkPDFArray> fRangeObject;
};
#endif // SkPDFCanon_DEFINED