skia2/src/pdf/SkPDFResourceDict.h
halcanary bf799cd228 Simplify reference management in SkPDF
Prior to this change, SkPDFObject subclasses were required
to track their resources separately from the document
structure.  (An object has a resource if it depends, via an
indirect reference, on another object).  This led to a lot
of extra code to duplicate effort.  I replace the
getResources() function with the much simpler addResources()
function.  I only define a non-trivial addResources() method
on arrays, dictionaries, and indirect object references.
All other specialized classes simply rely on their parent
class's implementation.

SkPDFObject::addResources() works by recursively walking the
directed graph of object (direct and indirect) references
and adding resources to a set.  It doesn't matter that there
are closed loops in the graph, since we check the set before
walking down a branch.

-  Add SkPDFObject::addResources() virtual function, with
   four implementations
-  Remove SkPDFObject::getResources() virtual function and
   all implementations.
-  Remove SkPDFObject::GetResourcesHelper()
-  Remove SkPDFObject::AddResourceHelper()
-  In SkPDFCatalog::findObjectIndex(), add an object to the
   catalog if it doesn't exist yet.
-  SkPDFCatalog::setSubstitute() no longer sets up resources
-  SkPDFDocument.cpp no longer needs the Streamer object
-  SkPDFDocument.cpp calls fDocCatalog->addResources to build
   the resource list.
-  SkPDFFont::addResource() removed
-  All SkPDF-::fResource sets removed (they are redundant).
-  removed SkPDFImage::addSMask() function
-  SkPDFResourceDict::getReferencedResources() removed.

Motivation: this removes quite a bit of code and makes the
objects slightly slimmer in memory.  Most importantly, this
will lead the way towards removing SkPDFObject's inheritance
from SkRefCnt, which will greatly simplify everything.

Testing: I usually test changes to the PDF backend by
comparing checksums of PDF files rendered from GMs and SKPs
before and after the change.  This change both re-orders and
re-numbers the indirect PDF objects.  I used the qpdf
program to normalize the PDFs and then compared the
normalized outputs from before and after the change; they
matched.

Review URL: https://codereview.chromium.org/870333002
2015-02-10 13:32:09 -08:00

88 lines
3.0 KiB
C++

/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPDFResourceDict_DEFINED
#define SkPDFResourceDict_DEFINED
#include "SkPDFTypes.h"
#include "SkTDArray.h"
#include "SkTSet.h"
#include "SkTypes.h"
/** \class SkPDFResourceDict
A resource dictionary, which maintains the relevant sub-dicts and
allows generation of a list of referenced SkPDFObjects inserted with
insertResourceAsRef.
*/
class SkPDFResourceDict : public SkPDFDict {
public:
SK_DECLARE_INST_COUNT(SkPDFResourceDict)
enum SkPDFResourceType{
kExtGState_ResourceType,
kPattern_ResourceType,
kXObject_ResourceType,
kFont_ResourceType,
// These additional types are defined by the spec, but not
// currently used by Skia: ColorSpace, Shading, Properties
kResourceTypeCount
};
/** Create a PDF resource dictionary.
* The full set of ProcSet entries is automatically created for backwards
* compatibility, as recommended by the PDF spec.
*/
SkPDFResourceDict();
/** Add the value SkPDFObject as a reference to the resource dictionary
* with the give type and key.
* The relevant sub-dicts will be automatically generated, and the
* resource will be named by concatenating a type-specific prefix and
* the input key.
* This object will be part of the resource list when requested later.
* @param type The type of resource being entered, like
* kPattern_ResourceType or kExtGState_ResourceType.
* @param key The resource key, should be unique within its type.
* @param value The resource itself.
* @return The value argument is returned.
*/
SkPDFObject* insertResourceAsReference(SkPDFResourceType type, int key,
SkPDFObject* value);
/**
* Returns the name for the resource that will be generated by the resource
* dict.
*
* @param type The type of resource being entered, like
* kPattern_ResourceType or kExtGState_ResourceType.
* @param key The resource key, should be unique within its type.
*/
static SkString getResourceName(SkPDFResourceType type, int key);
private:
/** Add the value to the dictionary with the given key. Refs value.
* The relevant sub-dicts will be automatically generated, and the
* resource will be named by concatenating a type-specific prefix and
* the input key.
* The object will NOT be part of the resource list when requested later.
* @param type The type of resource being entered.
* @param key The resource key, should be unique within its type.
* @param value The resource itself.
* @return The value argument is returned.
*/
SkPDFObject* insertResource(SkPDFResourceType type, int key,
SkPDFObject* value);
SkTSet<SkPDFObject*> fResources;
SkTDArray<SkPDFDict*> fTypes;
typedef SkPDFDict INHERITED;
};
#endif