blob: b92c872a41d32eb6721c4e1421a18bad404ec2fd [file] [log] [blame]
/*
* 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 SkPdfNativeDoc_DEFINED
#define SkPdfNativeDoc_DEFINED
#include "SkRect.h"
#include "SkTDArray.h"
class SkCanvas;
class SkPdfAllocator;
class SkPdfMapper;
class SkPdfNativeObject;
class SkPdfReal;
class SkPdfInteger;
class SkPdfString;
class SkPdfResourceDictionary;
class SkPdfCatalogDictionary;
class SkPdfPageObjectDictionary;
class SkPdfPageTreeNodeDictionary;
class SkPdfNativeTokenizer;
class SkStream;
// TODO(edisonn): Implement a smart stream that can seek, and that can also fall back to reading
// the bytes in order. For example, we can try to read the stream optimistically, but if there
// are issues in the pdf, we must read the pdf from the beginning, and fix whatever errors we can.
// This would be useful to show quickly page 100 in a pdf (www.example.com/foo.pdf#page100)
// But if the pdf is missing the xref, then we will have to read most of pdf to be able to render
// page 100.
/** \class SkPdfNativeDoc
*
* The SkPdfNativeDoc class is used to load a PDF in memory and it represents a PDF Document.
*
*/
class SkPdfNativeDoc {
private:
// Information about public objects in pdf that can be referenced with ID GEN R
struct PublicObjectEntry {
// Offset in the file where the object starts.
long fOffset;
// Offset in file where the object ends. Could be used to quickly fail if there is a
// problem in pdf structure.
// long endOffset; // TODO(edisonn): determine the end of the object,
// to be used when the doc is corrupted, for fast failure.
// Refered object.
SkPdfNativeObject* fObj;
// If refered object is a reference, we resolve recursively the reference until we find
// the real object.
SkPdfNativeObject* fResolvedReference;
// Used to break a recursive reference to itself.
bool fIsReferenceResolved;
};
public:
// TODO(edisonn) should be deprecated
SkPdfNativeDoc(const char* path);
// TODO(edisonn) should be deprecated
// FIXME: Untested.
SkPdfNativeDoc(SkStream* stream);
~SkPdfNativeDoc();
// returns the number of pages in the pdf
int pages() const;
// returns the page resources
SkPdfResourceDictionary* pageResources(int page);
// returns the page's mediabox i points - the page physical boundaries.
SkRect MediaBox(int page);
//returns objects that are references and can be queried.
size_t objects() const;
// returns an object.
// TODO(edisonn): pdf updates are not supported yet.
// add generation parameter to support page updates.
SkPdfNativeObject* object(int id /*, int generation*/ );
// returns the object that holds all the page informnation
// TODO(edisonn): pdf updates are not supported yet.
// add generation parameter to support page updates.
SkPdfPageObjectDictionary* page(int page/*, int generation*/);
// TODO(edisonn): deprecate the mapper - was used when we supported multiple
// parsers (podofo)
// The mapper maps allows an object to be mapped to a different dictionary type
// and it could verify the integrity of the object.
const SkPdfMapper* mapper() const;
// Allocator of the pdf - this holds all objects that are publicly referenced
// and all the objects that they refer
SkPdfAllocator* allocator() const;
// Allows a renderer to create values to be dumped on the stack for operators to process them.
SkPdfReal* createReal(double value) const;
SkPdfInteger* createInteger(int value) const;
// the string does not own the char*
SkPdfString* createString(const unsigned char* sz, size_t len) const;
// Resolve a reference object. Will recursively resolve the reference
// until a real object is found
SkPdfNativeObject* resolveReference(SkPdfNativeObject* ref);
// Reports an approximation of all the memory usage.
size_t bytesUsed() const;
private:
// Takes ownership of bytes.
void init(const void* bytes, size_t length);
// loads a pdf that has missing xref
void loadWithoutXRef();
const unsigned char* readCrossReferenceSection(const unsigned char* xrefStart,
const unsigned char* trailerEnd);
const unsigned char* readTrailer(const unsigned char* trailerStart,
const unsigned char* trailerEnd,
bool storeCatalog, long* prev, bool skipKeyword);
// TODO(edisonn): pdfs with updates not supported right now, generation ignored.
void addCrossSectionInfo(int id, int generation, int offset, bool isFreed);
static void reset(PublicObjectEntry* obj) {
obj->fObj = NULL;
obj->fResolvedReference = NULL;
obj->fOffset = -1;
obj->fIsReferenceResolved = false;
}
SkPdfNativeObject* readObject(int id/*, int generation*/);
void fillPages(SkPdfPageTreeNodeDictionary* tree);
SkPdfAllocator* fAllocator;
SkPdfMapper* fMapper;
const unsigned char* fFileContent;
size_t fContentLength;
SkPdfNativeObject* fRootCatalogRef;
SkPdfCatalogDictionary* fRootCatalog;
mutable SkTDArray<PublicObjectEntry> fObjects;
SkTDArray<SkPdfPageObjectDictionary*> fPages;
};
#endif // SkPdfNativeDoc_DEFINED