blob: ce1ca86e6e370fa212a4b8a690b47bcf3cfb86c5 [file] [log] [blame]
/*
* Copyright 2010 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPDFTypes_DEFINED
#define SkPDFTypes_DEFINED
#include "SkRefCnt.h"
#include "SkScalar.h"
#include "SkString.h"
#include "SkTDArray.h"
#include "SkTSet.h"
#include "SkTypes.h"
class SkPDFCatalog;
class SkWStream;
/** \class SkPDFObject
A PDF Object is the base class for primitive elements in a PDF file. A
common subtype is used to ease the use of indirect object references,
which are common in the PDF format.
*/
class SkPDFObject : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkPDFObject)
/** Return the size (number of bytes) of this object in the final output
* file. Only used for testing.
* @param catalog The object catalog to use.
* @param indirect If true, output an object identifier with the object.
*/
size_t getOutputSize(SkPDFCatalog* catalog, bool indirect);
/** For non-primitive objects (i.e. objects defined outside this file),
* this method will add to newResourceObjects any objects that this method
* depends on, but not already in knownResourceObjects. This operates
* recursively so if this object depends on another object and that object
* depends on two more, all three objects will be added.
*
* @param knownResourceObjects The set of resources to be ignored.
* @param newResourceObjects The set to append dependant resources to.
*/
virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects);
/** Emit this object unless the catalog has a substitute object, in which
* case emit that.
* @see emitObject
*/
void emit(SkWStream* stream, SkPDFCatalog* catalog, bool indirect);
/** Helper function to output an indirect object.
* @param catalog The object catalog to use.
* @param stream The writable output stream to send the output to.
*/
void emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog);
/** Helper function to find the size of an indirect object.
* @param catalog The object catalog to use.
*/
size_t getIndirectOutputSize(SkPDFCatalog* catalog);
/** Static helper function to add a resource to a list. The list takes
* a reference.
* @param resource The resource to add.
* @param list The list to add the resource to.
*/
static void AddResourceHelper(SkPDFObject* resource,
SkTDArray<SkPDFObject*>* list);
/** Static helper function to copy and reference the resources (and all
* their subresources) into a new list.
* @param resources The resource list.
* @param newResourceObjects All the resource objects (recursively) used on
* the page are added to this array. This gives
* the caller a chance to deduplicate resources
* across pages.
* @param knownResourceObjects The set of resources to be ignored.
*/
static void GetResourcesHelper(
const SkTDArray<SkPDFObject*>* resources,
const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects);
protected:
/** Subclasses must implement this method to print the object to the
* PDF file.
* @param catalog The object catalog to use.
* @param stream The writable output stream to send the output to.
*/
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) = 0;
typedef SkRefCnt INHERITED;
};
/** \class SkPDFObjRef
An indirect reference to a PDF object.
*/
class SkPDFObjRef : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFObjRef)
/** Create a reference to an existing SkPDFObject.
* @param obj The object to reference.
*/
explicit SkPDFObjRef(SkPDFObject* obj);
virtual ~SkPDFObjRef();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
private:
SkAutoTUnref<SkPDFObject> fObj;
typedef SkPDFObject INHERITED;
};
/** \class SkPDFInt
An integer object in a PDF.
*/
class SkPDFInt : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFInt)
/** Create a PDF integer (usually for indirect reference purposes).
* @param value An integer value between 2^31 - 1 and -2^31.
*/
explicit SkPDFInt(int32_t value);
virtual ~SkPDFInt();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
private:
int32_t fValue;
typedef SkPDFObject INHERITED;
};
/** \class SkPDFBool
An boolean value in a PDF.
*/
class SkPDFBool : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFBool)
/** Create a PDF boolean.
* @param value true or false.
*/
explicit SkPDFBool(bool value);
virtual ~SkPDFBool();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
private:
bool fValue;
typedef SkPDFObject INHERITED;
};
/** \class SkPDFScalar
A real number object in a PDF.
*/
class SkPDFScalar : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFScalar)
/** Create a PDF real number.
* @param value A real value.
*/
explicit SkPDFScalar(SkScalar value);
virtual ~SkPDFScalar();
static void Append(SkScalar value, SkWStream* stream);
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
private:
SkScalar fValue;
typedef SkPDFObject INHERITED;
};
/** \class SkPDFString
A string object in a PDF.
*/
class SkPDFString : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFString)
/** Create a PDF string. Maximum length (in bytes) is 65,535.
* @param value A string value.
*/
explicit SkPDFString(const char value[]);
explicit SkPDFString(const SkString& value);
/** Create a PDF string. Maximum length (in bytes) is 65,535.
* @param value A string value.
* @param len The length of value.
* @param wideChars Indicates if the top byte in value is significant and
* should be encoded (true) or not (false).
*/
SkPDFString(const uint16_t* value, size_t len, bool wideChars);
virtual ~SkPDFString();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
static SkString FormatString(const char* input, size_t len);
static SkString FormatString(const uint16_t* input, size_t len,
bool wideChars);
private:
static const size_t kMaxLen = 65535;
const SkString fValue;
static SkString DoFormatString(const void* input, size_t len,
bool wideInput, bool wideOutput);
typedef SkPDFObject INHERITED;
};
/** \class SkPDFName
A name object in a PDF.
*/
class SkPDFName : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFName)
/** Create a PDF name object. Maximum length is 127 bytes.
* @param value The name.
*/
explicit SkPDFName(const char name[]);
explicit SkPDFName(const SkString& name);
virtual ~SkPDFName();
bool operator==(const SkPDFName& b) const;
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
private:
static const size_t kMaxLen = 127;
const SkString fValue;
static SkString FormatName(const SkString& input);
typedef SkPDFObject INHERITED;
};
/** \class SkPDFArray
An array object in a PDF.
*/
class SkPDFArray : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFArray)
/** Create a PDF array. Maximum length is 8191.
*/
SkPDFArray();
virtual ~SkPDFArray();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
/** The size of the array.
*/
int size() { return fValue.count(); }
/** Preallocate space for the given number of entries.
* @param length The number of array slots to preallocate.
*/
void reserve(int length);
/** Returns the object at the given offset in the array.
* @param index The index into the array to retrieve.
*/
SkPDFObject* getAt(int index) { return fValue[index]; }
/** Set the object at the given offset in the array. Ref's value.
* @param index The index into the array to set.
* @param value The value to add to the array.
* @return The value argument is returned.
*/
SkPDFObject* setAt(int index, SkPDFObject* value);
/** Append the object to the end of the array and increments its ref count.
* @param value The value to add to the array.
* @return The value argument is returned.
*/
SkPDFObject* append(SkPDFObject* value);
/** Creates a SkPDFInt object and appends it to the array.
* @param value The value to add to the array.
*/
void appendInt(int32_t value);
/** Creates a SkPDFScalar object and appends it to the array.
* @param value The value to add to the array.
*/
void appendScalar(SkScalar value);
/** Creates a SkPDFName object and appends it to the array.
* @param value The value to add to the array.
*/
void appendName(const char name[]);
private:
static const int kMaxLen = 8191;
SkTDArray<SkPDFObject*> fValue;
typedef SkPDFObject INHERITED;
};
/** \class SkPDFDict
A dictionary object in a PDF.
*/
class SkPDFDict : public SkPDFObject {
public:
SK_DECLARE_INST_COUNT(SkPDFDict)
/** Create a PDF dictionary. Maximum number of entries is 4095.
*/
SkPDFDict();
/** Create a PDF dictionary with a Type entry.
* @param type The value of the Type entry.
*/
explicit SkPDFDict(const char type[]);
virtual ~SkPDFDict();
// The SkPDFObject interface.
virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog) SK_OVERRIDE;
/** The size of the dictionary.
*/
int size() const;
/** Add the value to the dictionary with the given key. Refs value.
* @param key The key for this dictionary entry.
* @param value The value for this dictionary entry.
* @return The value argument is returned.
*/
SkPDFObject* insert(SkPDFName* key, SkPDFObject* value);
/** Add the value to the dictionary with the given key. Refs value. The
* method will create the SkPDFName object.
* @param key The text of the key for this dictionary entry.
* @param value The value for this dictionary entry.
* @return The value argument is returned.
*/
SkPDFObject* insert(const char key[], SkPDFObject* value);
/** Add the int to the dictionary with the given key.
* @param key The text of the key for this dictionary entry.
* @param value The int value for this dictionary entry.
*/
void insertInt(const char key[], int32_t value);
/**
* Calls insertInt() but asserts in debug builds that the value can be represented
* by an int32_t.
*/
void insertInt(const char key[], size_t value) {
this->insertInt(key, SkToS32(value));
}
/** Add the scalar to the dictionary with the given key.
* @param key The text of the key for this dictionary entry.
* @param value The scalar value for this dictionary entry.
*/
void insertScalar(const char key[], SkScalar value);
/** Add the name to the dictionary with the given key.
* @param key The text of the key for this dictionary entry.
* @param name The name for this dictionary entry.
*/
void insertName(const char key[], const char name[]);
/** Add the name to the dictionary with the given key.
* @param key The text of the key for this dictionary entry.
* @param name The name for this dictionary entry.
*/
void insertName(const char key[], const SkString& name) {
this->insertName(key, name.c_str());
}
/** Remove all entries from the dictionary.
*/
void clear();
protected:
/** Use to remove a single key from the dictionary.
*/
void remove(const char key[]);
/** Insert references to all of the key-value pairs from the other
* dictionary into this one.
*/
void mergeFrom(const SkPDFDict& other);
private:
struct Rec {
SkPDFName* key;
SkPDFObject* value;
Rec(SkPDFName* k, SkPDFObject* v) : key(k), value(v) {}
};
static const int kMaxLen = 4095;
mutable SkMutex fMutex; // protects modifications to fValue
SkTDArray<struct Rec> fValue;
SkPDFObject* append(SkPDFName* key, SkPDFObject* value);
typedef SkPDFObject INHERITED;
};
#endif