PDF: Now threadsafe!

The PDF canvas is now just as threadsafe as any other Skia canvas.

DM updated to thread PDF tests.

SkDocument_PDF now owns SkPDFCanon, and pointers to that canon are
passed around to all classes that need access to the canon.

BUG=skia:2683

Review URL: https://codereview.chromium.org/944643002
This commit is contained in:
halcanary 2015-02-20 07:21:05 -08:00 committed by Commit bot
parent d08ea5fdae
commit 792c80f5a7
16 changed files with 203 additions and 217 deletions

View File

@ -42,8 +42,8 @@ struct Sink {
virtual const char* fileExtension() const = 0;
};
enum { kAnyThread_Enclave, kGPU_Enclave, kPDFSink_Enclave };
static const int kNumEnclaves = kPDFSink_Enclave + 1;
enum { kAnyThread_Enclave, kGPU_Enclave };
static const int kNumEnclaves = kGPU_Enclave + 1;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@ -115,7 +115,7 @@ public:
PDFSink();
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const SK_OVERRIDE;
int enclave() const SK_OVERRIDE { return kPDFSink_Enclave; }
int enclave() const SK_OVERRIDE { return kAnyThread_Enclave; }
const char* fileExtension() const SK_OVERRIDE { return "pdf"; }
};

View File

@ -13,7 +13,7 @@
class SkDocument_PDF : public SkDocument {
public:
SkDocument_PDF(SkWStream* stream,
void (*doneProc)(SkWStream*,bool),
void (*doneProc)(SkWStream*, bool),
SkScalar rasterDpi)
: SkDocument(stream, doneProc)
, fDoc(SkNEW(SkPDFDocument))

View File

@ -247,13 +247,12 @@ void SkPDFBitmap::emitDict(SkWStream* stream,
pdfDict.emitObject(stream, catalog);
}
SkPDFBitmap::SkPDFBitmap(const SkBitmap& bm, SkPDFObject* smask)
: fBitmap(bm), fSMask(smask) {}
SkPDFBitmap::SkPDFBitmap(SkPDFCanon* canon,
const SkBitmap& bm,
SkPDFObject* smask)
: fCanon(canon), fBitmap(bm), fSMask(smask) {}
SkPDFBitmap::~SkPDFBitmap() {
SkAutoMutexAcquire autoMutexAcquire(SkPDFCanon::GetBitmapMutex());
SkPDFCanon::GetCanon().removeBitmap(this);
}
SkPDFBitmap::~SkPDFBitmap() { fCanon->removeBitmap(this); }
////////////////////////////////////////////////////////////////////////////////
static bool is_transparent(const SkBitmap& bm) {
@ -275,9 +274,10 @@ static bool is_transparent(const SkBitmap& bm) {
return true;
}
// TODO(halcanary): SkPDFBitmap::Create should take a SkPDFCanon* parameter.
SkPDFBitmap* SkPDFBitmap::Create(const SkBitmap& bitmap,
SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon,
const SkBitmap& bitmap,
const SkIRect& subset) {
SkASSERT(canon);
if (kN32_SkColorType != bitmap.colorType()) {
// TODO(halcanary): support other colortypes.
return NULL;
@ -299,9 +299,7 @@ SkPDFBitmap* SkPDFBitmap::Create(const SkBitmap& bitmap,
bm = copy;
}
SkAutoMutexAcquire autoMutexAcquire(SkPDFCanon::GetBitmapMutex());
SkPDFCanon& canon = SkPDFCanon::GetCanon();
SkPDFBitmap* pdfBitmap = canon.findBitmap(bm);
SkPDFBitmap* pdfBitmap = canon->findBitmap(bm);
if (pdfBitmap) {
return SkRef(pdfBitmap);
}
@ -314,7 +312,7 @@ SkPDFBitmap* SkPDFBitmap::Create(const SkBitmap& bitmap,
// are refed by the SkPDFBitmap).
smask = SkNEW_ARGS(PDFAlphaBitmap, (bm));
}
pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (bm, smask));
canon.addBitmap(pdfBitmap);
pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (canon, bm, smask));
canon->addBitmap(pdfBitmap);
return pdfBitmap;
}

View File

@ -10,6 +10,8 @@
#include "SkPDFTypes.h"
#include "SkBitmap.h"
class SkPDFCanon;
/**
* SkPDFBitmap wraps a SkBitmap and serializes it as an image Xobject.
* It is designed to use a minimal amout of memory, aside from refing
@ -24,7 +26,9 @@ public:
// Returns NULL on unsupported bitmap;
// TODO(halcanary): support other bitmap colortypes and replace
// SkPDFImage.
static SkPDFBitmap* Create(const SkBitmap&, const SkIRect& subset);
static SkPDFBitmap* Create(SkPDFCanon*,
const SkBitmap&,
const SkIRect& subset);
~SkPDFBitmap();
void emitObject(SkWStream*, SkPDFCatalog*) SK_OVERRIDE;
void addResources(SkTSet<SkPDFObject*>* resourceSet,
@ -36,9 +40,10 @@ public:
}
private:
SkPDFCanon* const fCanon;
const SkBitmap fBitmap;
const SkAutoTUnref<SkPDFObject> fSMask;
SkPDFBitmap(const SkBitmap&, SkPDFObject*);
SkPDFBitmap(SkPDFCanon*, const SkBitmap&, SkPDFObject*);
void emitDict(SkWStream*, SkPDFCatalog*, size_t, bool) const;
};

View File

@ -5,7 +5,6 @@
* found in the LICENSE file.
*/
#include "SkLazyPtr.h"
#include "SkPDFBitmap.h"
#include "SkPDFCanon.h"
#include "SkPDFFont.h"
@ -14,32 +13,12 @@
////////////////////////////////////////////////////////////////////////////////
SK_DECLARE_STATIC_MUTEX(gSkPDFCanonFontMutex);
SK_DECLARE_STATIC_MUTEX(gSkPDFCanonShaderMutex);
SK_DECLARE_STATIC_MUTEX(gSkPDFCanonPaintMutex);
SK_DECLARE_STATIC_MUTEX(gSkPDFCanonBitmapMutex);
SkBaseMutex& SkPDFCanon::GetFontMutex() { return gSkPDFCanonFontMutex; }
SkBaseMutex& SkPDFCanon::GetShaderMutex() { return gSkPDFCanonShaderMutex; }
SkBaseMutex& SkPDFCanon::GetPaintMutex() { return gSkPDFCanonPaintMutex; }
SkBaseMutex& SkPDFCanon::GetBitmapMutex() { return gSkPDFCanonBitmapMutex; }
SkPDFCanon::SkPDFCanon() {}
SkPDFCanon::~SkPDFCanon() {}
SK_DECLARE_STATIC_LAZY_PTR(SkPDFCanon, singleton);
SkPDFCanon& SkPDFCanon::GetCanon() { return *singleton.get(); }
////////////////////////////////////////////////////////////////////////////////
static void assert_mutex_held(const SkPDFCanon* canon, SkBaseMutex& mutex) {
if (canon == singleton.get()) {
mutex.assertHeld();
}
}
template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; }
template <typename T>
@ -68,7 +47,6 @@ T* find_item(const SkTDArray<T*>& ptrArray, const U& object) {
SkPDFFont* SkPDFCanon::findFont(uint32_t fontID,
uint16_t glyphID,
SkPDFFont** relatedFontPtr) const {
assert_mutex_held(this, gSkPDFCanonFontMutex);
SkASSERT(relatedFontPtr);
SkPDFFont* relatedFont = NULL;
@ -87,7 +65,6 @@ SkPDFFont* SkPDFCanon::findFont(uint32_t fontID,
}
void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) {
assert_mutex_held(this, gSkPDFCanonFontMutex);
SkPDFCanon::FontRec* rec = fFontRecords.push();
rec->fFont = font;
rec->fFontID = fontID;
@ -95,7 +72,6 @@ void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) {
}
void SkPDFCanon::removeFont(SkPDFFont* pdfFont) {
assert_mutex_held(this, gSkPDFCanonFontMutex);
for (int i = 0; i < fFontRecords.count(); i++) {
if (fFontRecords[i].fFont == pdfFont) {
fFontRecords.removeShuffle(i);
@ -109,15 +85,12 @@ void SkPDFCanon::removeFont(SkPDFFont* pdfFont) {
SkPDFFunctionShader* SkPDFCanon::findFunctionShader(
const SkPDFShader::State& state) const {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
return find_item(fFunctionShaderRecords, state);
}
void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
fFunctionShaderRecords.push(assert_ptr(pdfShader));
}
void SkPDFCanon::removeFunctionShader(SkPDFFunctionShader* pdfShader) {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
SkAssertResult(remove_item(&fFunctionShaderRecords, pdfShader));
}
@ -125,15 +98,12 @@ void SkPDFCanon::removeFunctionShader(SkPDFFunctionShader* pdfShader) {
SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader(
const SkPDFShader::State& state) const {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
return find_item(fAlphaShaderRecords, state);
}
void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
fAlphaShaderRecords.push(assert_ptr(pdfShader));
}
void SkPDFCanon::removeAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
SkAssertResult(remove_item(&fAlphaShaderRecords, pdfShader));
}
@ -141,50 +111,41 @@ void SkPDFCanon::removeAlphaShader(SkPDFAlphaFunctionShader* pdfShader) {
SkPDFImageShader* SkPDFCanon::findImageShader(
const SkPDFShader::State& state) const {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
return find_item(fImageShaderRecords, state);
}
void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
fImageShaderRecords.push(assert_ptr(pdfShader));
}
void SkPDFCanon::removeImageShader(SkPDFImageShader* pdfShader) {
assert_mutex_held(this, gSkPDFCanonShaderMutex);
SkAssertResult(remove_item(&fImageShaderRecords, pdfShader));
}
////////////////////////////////////////////////////////////////////////////////
SkPDFGraphicState* SkPDFCanon::findGraphicState(const SkPaint& paint) const {
assert_mutex_held(this, gSkPDFCanonPaintMutex);
return find_item(fGraphicStateRecords, paint);
}
void SkPDFCanon::addGraphicState(SkPDFGraphicState* state) {
assert_mutex_held(this, gSkPDFCanonPaintMutex);
fGraphicStateRecords.push(assert_ptr(state));
}
void SkPDFCanon::removeGraphicState(SkPDFGraphicState* pdfGraphicState) {
assert_mutex_held(this, gSkPDFCanonPaintMutex);
SkAssertResult(remove_item(&fGraphicStateRecords, pdfGraphicState));
}
////////////////////////////////////////////////////////////////////////////////
SkPDFBitmap* SkPDFCanon::findBitmap(const SkBitmap& bm) const {
assert_mutex_held(this, gSkPDFCanonBitmapMutex);
return find_item(fBitmapRecords, bm);
}
void SkPDFCanon::addBitmap(SkPDFBitmap* pdfBitmap) {
assert_mutex_held(this, gSkPDFCanonBitmapMutex);
fBitmapRecords.push(assert_ptr(pdfBitmap));
}
void SkPDFCanon::removeBitmap(SkPDFBitmap* pdfBitmap) {
assert_mutex_held(this, gSkPDFCanonBitmapMutex);
SkAssertResult(remove_item(&fBitmapRecords, pdfBitmap));
}

View File

@ -8,42 +8,33 @@
#define SkPDFCanon_DEFINED
#include "SkPDFShader.h"
#include "SkThread.h"
#include "SkTDArray.h"
struct SkIRect;
class SkBitmap;
class SkMatrix;
class SkPDFFont;
class SkPDFGraphicState;
class SkPDFBitmap;
class SkPaint;
// This class's fields and methods will eventually become part of
// SkPDFDocument/SkDocument_PDF. For now, it exists as a singleton to
// preflight that transition. This replaces three global arrays in
// SkPDFFont, SkPDFShader, and SkPDFGraphicsContext.
//
// IF YOU ARE LOOKING AT THIS API PLEASE DO NOT WRITE THE CHANGE
// YOU ARE ABOUT TO WRITE WITHOUT TALKING TO HALCANARY@.
//
// Note that this class does not create, delete, reference or
// dereference the SkPDFObject objects that it indexes. It is up to
// the caller to manage the lifetime of these objects.
/**
* The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
*
* 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 SkDocument_PDF class makes this happen by owning a single
* SkPDFCanon.
*
* Note that this class does not create, delete, reference or
* dereference the SkPDFObject objects that it indexes. It is up to
* the caller to manage the lifetime of these objects.
*/
class SkPDFCanon : SkNoncopyable {
public:
SkPDFCanon();
~SkPDFCanon();
static SkPDFCanon& GetCanon();
// This mutexes will be removed once this class is subsumed into
// SkPDFDocument.
static SkBaseMutex& GetFontMutex();
static SkBaseMutex& GetShaderMutex();
static SkBaseMutex& GetPaintMutex();
static SkBaseMutex& GetBitmapMutex();
// Returns exact match if there is one. If not, it returns NULL.
// If there is no exact match, but there is a related font, we
// still return NULL, but also set *relatedFont.

View File

@ -737,7 +737,7 @@ void SkPDFDevice::init() {
fLastMarginContentEntry = NULL;
fDrawingArea = kContent_DrawingArea;
if (fFontGlyphUsage.get() == NULL) {
fFontGlyphUsage.reset(new SkPDFGlyphSetMap());
fFontGlyphUsage.reset(SkNEW(SkPDFGlyphSetMap));
}
}
@ -1896,8 +1896,10 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint(
fInitialTransform.mapRect(&boundsTemp);
boundsTemp.roundOut(&bounds);
pdfShader.reset(SkPDFShader::GetPDFShader(*shader, transform, bounds,
SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE));
SkScalar rasterScale =
SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE;
pdfShader.reset(SkPDFShader::GetPDFShader(
fCanon, fRasterDpi, *shader, transform, bounds, rasterScale));
if (pdfShader.get()) {
// pdfShader has been canonicalized so we can directly compare
@ -1928,12 +1930,12 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint(
SkAutoTUnref<SkPDFGraphicState> newGraphicState;
if (color == paint.getColor()) {
newGraphicState.reset(
SkPDFGraphicState::GetGraphicStateForPaint(paint));
SkPDFGraphicState::GetGraphicStateForPaint(fCanon, paint));
} else {
SkPaint newPaint = paint;
newPaint.setColor(color);
newGraphicState.reset(
SkPDFGraphicState::GetGraphicStateForPaint(newPaint));
SkPDFGraphicState::GetGraphicStateForPaint(fCanon, newPaint));
}
int resourceIndex = addGraphicStateResource(newGraphicState.get());
entry->fGraphicStateIndex = resourceIndex;
@ -1989,8 +1991,8 @@ void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
}
int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface,
glyphID));
SkAutoTUnref<SkPDFFont> newFont(
SkPDFFont::GetFontResource(fCanon, typeface, glyphID));
int resourceIndex = fFontResources.find(newFont.get());
if (resourceIndex < 0) {
resourceIndex = fFontResources.count();
@ -2133,7 +2135,7 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
}
SkAutoTUnref<SkPDFObject> image(
SkPDFCreateImageObject(*bitmap, subset));
SkPDFCreateImageObject(fCanon, *bitmap, subset));
if (!image) {
return;
}
@ -2141,4 +2143,3 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
&content.entry()->fContent);
}

View File

@ -747,12 +747,7 @@ SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) {
* from each page and combine it and ask for a resource with that subset.
*/
SkPDFFont::~SkPDFFont() {
{
SkAutoMutexAcquire lock(SkPDFCanon::GetFontMutex());
SkPDFCanon::GetCanon().removeFont(this);
}
}
SkPDFFont::~SkPDFFont() { fCanon->removeFont(this); }
SkTypeface* SkPDFFont::typeface() {
return fTypeface.get();
@ -804,16 +799,16 @@ int SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, int numGlyphs) {
}
// static
SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) {
SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
SkTypeface* typeface,
uint16_t glyphID) {
SkASSERT(canon);
SkAutoResolveDefaultTypeface autoResolve(typeface);
typeface = autoResolve.get();
const uint32_t fontID = typeface->uniqueID();
SkAutoMutexAcquire lock(SkPDFCanon::GetFontMutex());
SkPDFFont* relatedFont;
SkPDFFont* pdfFont =
SkPDFCanon::GetCanon().findFont(fontID, glyphID, &relatedFont);
if (pdfFont) {
if (SkPDFFont* pdfFont = canon->findFont(fontID, glyphID, &relatedFont)) {
return SkRef(pdfFont);
}
@ -857,25 +852,27 @@ SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) {
#endif
}
SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID,
relatedFontDescriptor);
SkPDFCanon::GetCanon().addFont(font, fontID, font->fFirstGlyphID);
return font; // Return the reference new SkPDFFont() created.
SkPDFFont* font = SkPDFFont::Create(canon, fontMetrics.get(), typeface,
glyphID, relatedFontDescriptor);
canon->addFont(font, fontID, font->fFirstGlyphID);
return font;
}
SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet*) {
return NULL; // Default: no support.
}
SkPDFFont::SkPDFFont(const SkAdvancedTypefaceMetrics* info,
SkPDFFont::SkPDFFont(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
SkPDFDict* relatedFontDescriptor)
: SkPDFDict("Font"),
fTypeface(ref_or_default(typeface)),
fFirstGlyphID(1),
fLastGlyphID(info ? info->fLastGlyphID : 0),
fFontInfo(SkSafeRef(info)),
fDescriptor(SkSafeRef(relatedFontDescriptor)) {
: SkPDFDict("Font")
, fCanon(canon)
, fTypeface(ref_or_default(typeface))
, fFirstGlyphID(1)
, fLastGlyphID(info ? info->fLastGlyphID : 0)
, fFontInfo(SkSafeRef(info))
, fDescriptor(SkSafeRef(relatedFontDescriptor)) {
if (info == NULL ||
info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) {
fFontType = SkAdvancedTypefaceMetrics::kOther_Font;
@ -885,8 +882,10 @@ SkPDFFont::SkPDFFont(const SkAdvancedTypefaceMetrics* info,
}
// static
SkPDFFont* SkPDFFont::Create(const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface, uint16_t glyphID,
SkPDFFont* SkPDFFont::Create(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
uint16_t glyphID,
SkPDFDict* relatedFontDescriptor) {
SkAdvancedTypefaceMetrics::FontType type =
info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font;
@ -894,26 +893,22 @@ SkPDFFont* SkPDFFont::Create(const SkAdvancedTypefaceMetrics* info,
if (info &&
(info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) {
NOT_IMPLEMENTED(true, true);
return new SkPDFType3Font(info,
typeface,
glyphID);
return new SkPDFType3Font(canon, info, typeface, glyphID);
}
if (type == SkAdvancedTypefaceMetrics::kType1CID_Font ||
type == SkAdvancedTypefaceMetrics::kTrueType_Font) {
SkASSERT(relatedFontDescriptor == NULL);
return new SkPDFType0Font(info, typeface);
return new SkPDFType0Font(canon, info, typeface);
}
if (type == SkAdvancedTypefaceMetrics::kType1_Font) {
return new SkPDFType1Font(info,
typeface,
glyphID,
return new SkPDFType1Font(canon, info, typeface, glyphID,
relatedFontDescriptor);
}
SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font ||
type == SkAdvancedTypefaceMetrics::kOther_Font);
return new SkPDFType3Font(info, typeface, glyphID);
return new SkPDFType3Font(canon, info, typeface, glyphID);
}
const SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() {
@ -1001,9 +996,10 @@ void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) {
// class SkPDFType0Font
///////////////////////////////////////////////////////////////////////////////
SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics* info,
SkPDFType0Font::SkPDFType0Font(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface)
: SkPDFFont(info, typeface, NULL) {
: SkPDFFont(canon, info, typeface, NULL) {
SkDEBUGCODE(fPopulated = false);
if (!canSubset()) {
populate(NULL);
@ -1016,7 +1012,8 @@ SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) {
if (!canSubset()) {
return NULL;
}
SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface());
SkPDFType0Font* newSubset =
new SkPDFType0Font(fCanon, fontInfo(), typeface());
newSubset->populate(subset);
return newSubset;
}
@ -1034,7 +1031,7 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) {
insertName("Encoding", "Identity-H");
SkAutoTUnref<SkPDFCIDFont> newCIDFont(
new SkPDFCIDFont(fontInfo(), typeface(), subset));
new SkPDFCIDFont(fCanon, fontInfo(), typeface(), subset));
SkAutoTUnref<SkPDFArray> descendantFonts(new SkPDFArray());
descendantFonts->append(new SkPDFObjRef(newCIDFont.get()))->unref();
insert("DescendantFonts", descendantFonts.get());
@ -1049,9 +1046,11 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) {
// class SkPDFCIDFont
///////////////////////////////////////////////////////////////////////////////
SkPDFCIDFont::SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface, const SkPDFGlyphSet* subset)
: SkPDFFont(info, typeface, NULL) {
SkPDFCIDFont::SkPDFCIDFont(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
const SkPDFGlyphSet* subset)
: SkPDFFont(canon, info, typeface, NULL) {
populate(subset);
}
@ -1202,11 +1201,12 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
// class SkPDFType1Font
///////////////////////////////////////////////////////////////////////////////
SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics* info,
SkPDFType1Font::SkPDFType1Font(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
uint16_t glyphID,
SkPDFDict* relatedFontDescriptor)
: SkPDFFont(info, typeface, relatedFontDescriptor) {
: SkPDFFont(canon, info, typeface, relatedFontDescriptor) {
populate(glyphID);
}
@ -1329,10 +1329,11 @@ void SkPDFType1Font::addWidthInfoFromRange(
// class SkPDFType3Font
///////////////////////////////////////////////////////////////////////////////
SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
SkPDFType3Font::SkPDFType3Font(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
uint16_t glyphID)
: SkPDFFont(info, typeface, NULL) {
: SkPDFFont(canon, info, typeface, NULL) {
populate(glyphID);
}

View File

@ -18,6 +18,7 @@
#include "SkTypeface.h"
class SkPaint;
class SkPDFCanon;
class SkPDFCatalog;
class SkPDFFont;
@ -126,7 +127,9 @@ public:
* @param typeface The typeface to find.
* @param glyphID Specify which section of a large font is of interest.
*/
static SkPDFFont* GetFontResource(SkTypeface* typeface, uint16_t glyphID);
static SkPDFFont* GetFontResource(SkPDFCanon* canon,
SkTypeface* typeface,
uint16_t glyphID);
/** Subset the font based on usage set. Returns a SkPDFFont instance with
* subset.
@ -148,8 +151,12 @@ public:
uint16_t searchGlyphID);
protected:
SkPDFCanon* const fCanon;
// Common constructor to handle common members.
SkPDFFont(const SkAdvancedTypefaceMetrics* fontInfo, SkTypeface* typeface,
SkPDFFont(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* fontInfo,
SkTypeface* typeface,
SkPDFDict* relatedFontDescriptor);
// Accessors for subclass.
@ -176,8 +183,10 @@ protected:
void populateToUnicodeTable(const SkPDFGlyphSet* subset);
// Create instances of derived types based on fontInfo.
static SkPDFFont* Create(const SkAdvancedTypefaceMetrics* fontInfo,
SkTypeface* typeface, uint16_t glyphID,
static SkPDFFont* Create(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* fontInfo,
SkTypeface* typeface,
uint16_t glyphID,
SkPDFDict* relatedFontDescriptor);
static bool Find(uint32_t fontID, uint16_t glyphID, int* index);

View File

@ -28,7 +28,9 @@ private:
typedef SkPDFDict INHERITED;
#endif
SkPDFType0Font(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface);
SkPDFType0Font(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface);
bool populate(const SkPDFGlyphSet* subset);
};
@ -41,7 +43,9 @@ public:
private:
friend class SkPDFType0Font; // to access the constructor
SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface,
SkPDFCIDFont(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
const SkPDFGlyphSet* subset);
bool populate(const SkPDFGlyphSet* subset);
@ -57,8 +61,11 @@ public:
private:
friend class SkPDFFont; // to access the constructor
SkPDFType1Font(const SkAdvancedTypefaceMetrics* info, SkTypeface* typeface,
uint16_t glyphID, SkPDFDict* relatedFontDescriptor);
SkPDFType1Font(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
uint16_t glyphID,
SkPDFDict* relatedFontDescriptor);
bool populate(int16_t glyphID);
bool addFontDescriptor(int16_t defaultWidth);
@ -74,8 +81,10 @@ public:
private:
friend class SkPDFFont; // to access the constructor
SkPDFType3Font(const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface, uint16_t glyphID);
SkPDFType3Font(SkPDFCanon* canon,
const SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface,
uint16_t glyphID);
bool populate(uint16_t glyphID);
};

View File

@ -113,9 +113,8 @@ bool SkPDFGraphicState::equals(const SkPaint& paint) const {
}
SkPDFGraphicState::~SkPDFGraphicState() {
SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
if (!fSMask) {
SkPDFCanon::GetCanon().removeGraphicState(this);
if (fCanon) {
fCanon->removeGraphicState(this);
}
}
@ -126,15 +125,14 @@ void SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
// static
SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
const SkPaint& paint) {
SkAutoMutexAcquire lock(SkPDFCanon::GetPaintMutex());
SkPDFGraphicState* pdfGraphicState =
SkPDFCanon::GetCanon().findGraphicState(paint);
SkPDFCanon* canon, const SkPaint& paint) {
SkASSERT(canon);
SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(paint);
if (pdfGraphicState) {
return SkRef(pdfGraphicState);
}
pdfGraphicState = new SkPDFGraphicState(paint);
SkPDFCanon::GetCanon().addGraphicState(pdfGraphicState);
pdfGraphicState = new SkPDFGraphicState(canon, paint);
canon->addGraphicState(pdfGraphicState);
return pdfGraphicState;
}
@ -181,7 +179,6 @@ SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
SkPDFGraphicState* result = new SkPDFGraphicState;
result->fPopulated = true;
result->fSMask = true;
result->insertName("Type", "ExtGState");
result->insert("SMask", sMaskDict.get());
@ -195,7 +192,6 @@ SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
SkPDFGraphicState* SkPDFGraphicState::CreateNoSMaskGraphicState() {
SkPDFGraphicState* noSMaskGS = SkNEW(SkPDFGraphicState);
noSMaskGS->fPopulated = true;
noSMaskGS->fSMask = true;
noSMaskGS->insertName("Type", "ExtGState");
noSMaskGS->insertName("SMask", "None");
return noSMaskGS;
@ -211,15 +207,10 @@ SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
}
SkPDFGraphicState::SkPDFGraphicState()
: fPopulated(false),
fSMask(false) {
}
: fCanon(NULL), fPopulated(false) {}
SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint)
: fPaint(paint),
fPopulated(false),
fSMask(false) {
}
SkPDFGraphicState::SkPDFGraphicState(SkPDFCanon* canon, const SkPaint& paint)
: fCanon(canon), fPaint(paint), fPopulated(false) {}
// populateDict and operator== have to stay in sync with each other.
void SkPDFGraphicState::populateDict() {

View File

@ -47,7 +47,8 @@ public:
* other references.
* @param paint The SkPaint to emulate.
*/
static SkPDFGraphicState* GetGraphicStateForPaint(const SkPaint& paint);
static SkPDFGraphicState* GetGraphicStateForPaint(SkPDFCanon* canon,
const SkPaint& paint);
/** Make a graphic state that only sets the passed soft mask. The
* reference count of the object is incremented and it is the caller's
@ -74,12 +75,12 @@ public:
static SkPDFGraphicState* CreateNoSMaskGraphicState();
private:
SkPDFCanon* const fCanon;
const SkPaint fPaint;
bool fPopulated;
bool fSMask;
SkPDFGraphicState();
explicit SkPDFGraphicState(const SkPaint& paint);
SkPDFGraphicState(SkPDFCanon* canon, const SkPaint& paint);
void populateDict();

View File

@ -687,10 +687,10 @@ static bool is_jfif_jpeg(SkData* data) {
} // namespace
#endif
SkPDFObject* SkPDFCreateImageObject(
const SkBitmap& bitmap,
const SkIRect& subset) {
if (SkPDFObject* pdfBitmap = SkPDFBitmap::Create(bitmap, subset)) {
SkPDFObject* SkPDFCreateImageObject(SkPDFCanon* canon,
const SkBitmap& bitmap,
const SkIRect& subset) {
if (SkPDFObject* pdfBitmap = SkPDFBitmap::Create(canon, bitmap, subset)) {
return pdfBitmap;
}
#if 0 // reenable when we can figure out the JPEG colorspace

View File

@ -24,7 +24,9 @@ struct SkIRect;
/**
* Return the mose efficient availible encoding of the given bitmap.
*/
SkPDFObject* SkPDFCreateImageObject(const SkBitmap&, const SkIRect& subset);
SkPDFObject* SkPDFCreateImageObject(SkPDFCanon* canon,
const SkBitmap&,
const SkIRect& subset);
/** \class SkPDFImage

View File

@ -507,13 +507,12 @@ private:
////////////////////////////////////////////////////////////////////////////////
SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state)
: SkPDFDict("Pattern"), fShaderState(state) {}
SkPDFFunctionShader::SkPDFFunctionShader(SkPDFCanon* canon,
SkPDFShader::State* state)
: SkPDFDict("Pattern"), fCanon(canon), fShaderState(state) {}
SkPDFFunctionShader::~SkPDFFunctionShader() {
SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
SkPDFCanon::GetCanon().removeFunctionShader(this);
lock.release();
fCanon->removeFunctionShader(this);
fResources.unrefAll();
}
@ -523,37 +522,37 @@ bool SkPDFFunctionShader::equals(const SkPDFShader::State& state) const {
////////////////////////////////////////////////////////////////////////////////
SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state)
: fShaderState(state) {}
SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFCanon* canon,
SkPDFShader::State* state)
: fCanon(canon), fShaderState(state) {}
bool SkPDFAlphaFunctionShader::equals(const SkPDFShader::State& state) const {
return state == *fShaderState;
}
SkPDFAlphaFunctionShader::~SkPDFAlphaFunctionShader() {
SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
SkPDFCanon::GetCanon().removeAlphaShader(this);
fCanon->removeAlphaShader(this);
}
////////////////////////////////////////////////////////////////////////////////
SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state)
: fShaderState(state) {}
SkPDFImageShader::SkPDFImageShader(SkPDFCanon* canon, SkPDFShader::State* state)
: fCanon(canon), fShaderState(state) {}
bool SkPDFImageShader::equals(const SkPDFShader::State& state) const {
return state == *fShaderState;
}
SkPDFImageShader::~SkPDFImageShader() {
SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
SkPDFCanon::GetCanon().removeImageShader(this);
lock.release();
fCanon->removeImageShader(this);
fResources.unrefAll();
}
////////////////////////////////////////////////////////////////////////////////
static SkPDFObject* get_pdf_shader_by_state(
SkPDFCanon* canon,
SkScalar dpi,
SkAutoTDelete<SkPDFShader::State>* autoState) {
const SkPDFShader::State& state = **autoState;
if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) {
@ -563,28 +562,31 @@ static SkPDFObject* get_pdf_shader_by_state(
// second shader, then applying the layer to the original drawing.
return NULL;
} else if (state.fType == SkShader::kNone_GradientType) {
SkPDFObject* shader = SkPDFCanon::GetCanon().findImageShader(state);
return shader ? SkRef(shader) : SkPDFImageShader::Create(autoState);
} else if (state.GradientHasAlpha()) {
SkPDFObject* shader = SkPDFCanon::GetCanon().findAlphaShader(state);
SkPDFObject* shader = canon->findImageShader(state);
return shader ? SkRef(shader)
: SkPDFAlphaFunctionShader::Create(autoState);
: SkPDFImageShader::Create(canon, dpi, autoState);
} else if (state.GradientHasAlpha()) {
SkPDFObject* shader = canon->findAlphaShader(state);
return shader ? SkRef(shader)
: SkPDFAlphaFunctionShader::Create(canon, dpi, autoState);
} else {
SkPDFObject* shader = SkPDFCanon::GetCanon().findFunctionShader(state);
return shader ? SkRef(shader) : SkPDFFunctionShader::Create(autoState);
SkPDFObject* shader = canon->findFunctionShader(state);
return shader ? SkRef(shader)
: SkPDFFunctionShader::Create(canon, autoState);
}
}
// static
SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
SkPDFObject* SkPDFShader::GetPDFShader(SkPDFCanon* canon,
SkScalar dpi,
const SkShader& shader,
const SkMatrix& matrix,
const SkIRect& surfaceBBox,
SkScalar rasterScale) {
// There is only one mutex becasue we don't know which one we'll need.
SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
SkAutoTDelete<SkPDFShader::State> state(
SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale)));
return get_pdf_shader_by_state(&state);
return get_pdf_shader_by_state(canon, dpi, &state);
}
static SkPDFResourceDict* get_gradient_resource_dict(
@ -647,14 +649,14 @@ static SkStream* create_pattern_fill_content(int gsIndex, SkRect& bounds) {
* luminosity mode. The shader pattern extends to the bbox.
*/
static SkPDFGraphicState* create_smask_graphic_state(
const SkPDFShader::State& state) {
SkPDFCanon* canon, SkScalar dpi, const SkPDFShader::State& state) {
SkRect bbox;
bbox.set(state.fBBox);
SkAutoTDelete<SkPDFShader::State> alphaToLuminosityState(
state.CreateAlphaToLuminosityState());
SkAutoTUnref<SkPDFObject> luminosityShader(
get_pdf_shader_by_state(&alphaToLuminosityState));
get_pdf_shader_by_state(canon, dpi, &alphaToLuminosityState));
SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox));
@ -670,6 +672,8 @@ static SkPDFGraphicState* create_smask_graphic_state(
}
SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create(
SkPDFCanon* canon,
SkScalar dpi,
SkAutoTDelete<SkPDFShader::State>* autoState) {
const SkPDFShader::State& state = **autoState;
SkRect bbox;
@ -677,17 +681,19 @@ SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create(
SkAutoTDelete<SkPDFShader::State> opaqueState(state.CreateOpaqueState());
SkPDFObject* colorShader = get_pdf_shader_by_state(&opaqueState);
SkPDFObject* colorShader =
get_pdf_shader_by_state(canon, dpi, &opaqueState);
if (!colorShader) {
return NULL;
}
// Create resource dict with alpha graphics state as G0 and
// pattern shader as P0, then write content stream.
SkAutoTUnref<SkPDFGraphicState> alphaGs(create_smask_graphic_state(state));
SkAutoTUnref<SkPDFGraphicState> alphaGs(
create_smask_graphic_state(canon, dpi, state));
SkPDFAlphaFunctionShader* alphaFunctionShader =
SkNEW_ARGS(SkPDFAlphaFunctionShader, (autoState->detach()));
SkNEW_ARGS(SkPDFAlphaFunctionShader, (canon, autoState->detach()));
alphaFunctionShader->fColorShader.reset(colorShader);
@ -701,7 +707,7 @@ SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create(
populate_tiling_pattern_dict(alphaFunctionShader, bbox,
alphaFunctionShader->fResourceDict.get(),
SkMatrix::I());
SkPDFCanon::GetCanon().addAlphaShader(alphaFunctionShader);
canon->addAlphaShader(alphaFunctionShader);
return alphaFunctionShader;
}
@ -774,7 +780,7 @@ static SkPDFStream* make_ps_function(const SkString& psCode,
}
SkPDFFunctionShader* SkPDFFunctionShader::Create(
SkAutoTDelete<SkPDFShader::State>* autoState) {
SkPDFCanon* canon, SkAutoTDelete<SkPDFShader::State>* autoState) {
const SkPDFShader::State& state = **autoState;
SkString (*codeFunction)(const SkShader::GradientInfo& info,
@ -893,7 +899,7 @@ SkPDFFunctionShader* SkPDFFunctionShader::Create(
SkPDFUtils::MatrixToArray(finalMatrix));
SkPDFFunctionShader* pdfFunctionShader =
SkNEW_ARGS(SkPDFFunctionShader, (autoState->detach()));
SkNEW_ARGS(SkPDFFunctionShader, (canon, autoState->detach()));
pdfFunctionShader->fResources.push(function);
// Pass ownership to resource list.
@ -902,11 +908,13 @@ SkPDFFunctionShader* SkPDFFunctionShader::Create(
pdfFunctionShader->insert("Matrix", matrixArray.get());
pdfFunctionShader->insert("Shading", pdfShader.get());
SkPDFCanon::GetCanon().addFunctionShader(pdfFunctionShader);
canon->addFunctionShader(pdfFunctionShader);
return pdfFunctionShader;
}
SkPDFImageShader* SkPDFImageShader::Create(
SkPDFCanon* canon,
SkScalar dpi,
SkAutoTDelete<SkPDFShader::State>* autoState) {
const SkPDFShader::State& state = **autoState;
@ -945,7 +953,7 @@ SkPDFImageShader* SkPDFImageShader::Create(
SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
SkScalarRoundToInt(deviceBounds.height()));
SkAutoTUnref<SkPDFDevice> patternDevice(
SkPDFDevice::CreateUnflipped(size, 72.0f, NULL));
SkPDFDevice::CreateUnflipped(size, dpi, canon));
SkCanvas canvas(patternDevice.get());
SkRect patternBBox;
@ -1107,17 +1115,15 @@ SkPDFImageShader* SkPDFImageShader::Create(
SkAutoTDelete<SkStream> content(patternDevice->content());
SkPDFImageShader* imageShader =
SkNEW_ARGS(SkPDFImageShader, (autoState->detach()));
SkNEW_ARGS(SkPDFImageShader, (canon, autoState->detach()));
imageShader->setData(content.get());
populate_tiling_pattern_dict(imageShader,
patternBBox,
patternDevice->getResourceDict(),
finalMatrix);
populate_tiling_pattern_dict(imageShader, patternBBox,
patternDevice->getResourceDict(), finalMatrix);
imageShader->fShaderState->fImage.unlockPixels();
SkPDFCanon::GetCanon().addImageShader(imageShader);
canon->addImageShader(imageShader);
return imageShader;
}

View File

@ -14,6 +14,7 @@
#include "SkPDFStream.h"
#include "SkPDFTypes.h"
class SkPDFCanon;
class SkMatrix;
class SkShader;
struct SkIRect;
@ -42,7 +43,9 @@ public:
* @param rasterScale Additional scale to be applied for early
* rasterization.
*/
static SkPDFObject* GetPDFShader(const SkShader& shader,
static SkPDFObject* GetPDFShader(SkPDFCanon* canon,
SkScalar dpi,
const SkShader& shader,
const SkMatrix& matrix,
const SkIRect& surfaceBBox,
SkScalar rasterScale);
@ -52,14 +55,16 @@ class SkPDFFunctionShader : public SkPDFDict {
SK_DECLARE_INST_COUNT(SkPDFFunctionShader);
public:
static SkPDFFunctionShader* Create(SkAutoTDelete<SkPDFShader::State>*);
static SkPDFFunctionShader* Create(SkPDFCanon*,
SkAutoTDelete<SkPDFShader::State>*);
virtual ~SkPDFFunctionShader();
bool equals(const SkPDFShader::State&) const;
private:
SkPDFCanon* fCanon;
SkAutoTDelete<const SkPDFShader::State> fShaderState;
SkTDArray<SkPDFObject*> fResources;
explicit SkPDFFunctionShader(SkPDFShader::State* state);
SkPDFFunctionShader(SkPDFCanon*, SkPDFShader::State*);
typedef SkPDFDict INHERITED;
};
@ -70,27 +75,33 @@ private:
*/
class SkPDFAlphaFunctionShader : public SkPDFStream {
public:
static SkPDFAlphaFunctionShader* Create(SkAutoTDelete<SkPDFShader::State>*);
static SkPDFAlphaFunctionShader* Create(SkPDFCanon*,
SkScalar dpi,
SkAutoTDelete<SkPDFShader::State>*);
virtual ~SkPDFAlphaFunctionShader();
bool equals(const SkPDFShader::State&) const;
private:
SkPDFCanon* fCanon;
SkAutoTDelete<const SkPDFShader::State> fShaderState;
SkAutoTUnref<SkPDFObject> fColorShader;
SkAutoTUnref<SkPDFResourceDict> fResourceDict;
explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state);
SkPDFAlphaFunctionShader(SkPDFCanon*, SkPDFShader::State*);
};
class SkPDFImageShader : public SkPDFStream {
public:
static SkPDFImageShader* Create(SkAutoTDelete<SkPDFShader::State>*);
static SkPDFImageShader* Create(SkPDFCanon*,
SkScalar dpi,
SkAutoTDelete<SkPDFShader::State>*);
virtual ~SkPDFImageShader();
bool equals(const SkPDFShader::State&) const;
private:
SkPDFCanon* fCanon;
SkAutoTDelete<const SkPDFShader::State> fShaderState;
SkTSet<SkPDFObject*> fResources;
explicit SkPDFImageShader(SkPDFShader::State* state);
SkPDFImageShader(SkPDFCanon*, SkPDFShader::State*);
};
#endif