diff options
author | 2010-10-12 23:08:13 +0000 | |
---|---|---|
committer | 2010-10-12 23:08:13 +0000 | |
commit | d877fdbb6e64692285c3e6532d88b9458f65b3cd (patch) | |
tree | c346892a4d2d014c95acc6729174c779d0bfcd02 /include | |
parent | f66025d59ab4c8c4439fabf6ad89ddf35a19d1fd (diff) |
High level pdf classes and pdf specific interface.
The guts of the implementation will be in SkPDFDevice and below. This is a first implementation of everything above that point.
Review URL: http://codereview.appspot.com/2342043
git-svn-id: http://skia.googlecode.com/svn/trunk@602 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include')
-rw-r--r-- | include/core/SkStream.h | 2 | ||||
-rw-r--r-- | include/core/SkString.h | 6 | ||||
-rw-r--r-- | include/pdf/SkPDFCatalog.h | 33 | ||||
-rw-r--r-- | include/pdf/SkPDFDocument.h | 80 | ||||
-rw-r--r-- | include/pdf/SkPDFPage.h | 98 | ||||
-rw-r--r-- | include/pdf/SkPDFStream.h | 10 | ||||
-rw-r--r-- | include/pdf/SkPDFTypes.h | 21 |
7 files changed, 237 insertions, 13 deletions
diff --git a/include/core/SkStream.h b/include/core/SkStream.h index 3a82991eba..487c7d68c4 100644 --- a/include/core/SkStream.h +++ b/include/core/SkStream.h @@ -91,6 +91,7 @@ public: bool writeText(const char text[]); bool writeDecAsText(int32_t); + bool writeBigDecAsText(int64_t, int minDigits = 0); bool writeHexAsText(uint32_t, int minDigits = 0); bool writeScalarAsText(SkScalar); @@ -308,4 +309,3 @@ public: typedef SkFILEStream SkURLStream; #endif - diff --git a/include/core/SkString.h b/include/core/SkString.h index 5ecfb1e108..4498bba768 100644 --- a/include/core/SkString.h +++ b/include/core/SkString.h @@ -28,6 +28,8 @@ int SkStrStartsWithOneOf(const char string[], const char prefixes[]); #define SkStrAppendS32_MaxSize 11 char* SkStrAppendS32(char buffer[], int32_t); +#define SkStrAppendS64_MaxSize 20 +char* SkStrAppendS64(char buffer[], int64_t, int minDigits); #define SkStrAppendScalar_MaxSize 11 char* SkStrAppendScalar(char buffer[], SkScalar); @@ -93,6 +95,7 @@ public: void insert(size_t offset, const char text[], size_t len); void insertUnichar(size_t offset, SkUnichar); void insertS32(size_t offset, int32_t value); + void insertS64(size_t offset, int64_t value, int minDigits = 0); void insertHex(size_t offset, uint32_t value, int minDigits = 0); void insertScalar(size_t offset, SkScalar); @@ -101,6 +104,7 @@ public: void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); } void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); } void appendS32(int32_t value) { this->insertS32((size_t)-1, value); } + void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); } void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); } void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } @@ -109,6 +113,7 @@ public: void prepend(const char text[], size_t len) { this->insert(0, text, len); } void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); } void prependS32(int32_t value) { this->insertS32(0, value); } + void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); } void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); } void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } @@ -165,4 +170,3 @@ private: }; #endif - diff --git a/include/pdf/SkPDFCatalog.h b/include/pdf/SkPDFCatalog.h index 932f1c895b..6e530db33b 100644 --- a/include/pdf/SkPDFCatalog.h +++ b/include/pdf/SkPDFCatalog.h @@ -34,23 +34,39 @@ public: ~SkPDFCatalog(); /** Add the passed object to the catalog. - * @param obj The object to add. - * @param onFirstPage Is the object on the first page. + * @param obj The object to add. + * @param onFirstPage Is the object on the first page. */ void addObject(SkPDFObject* obj, bool onFirstPage); + /** Inform the catalog of the object's position in the final stream. + * The object should already have been added to the catalog. Returns + * the object's size. + * @param obj The object to add. + * @param offset The byte offset in the output stream of this object. + */ + size_t setFileOffset(SkPDFObject* obj, size_t offset); + /** Output the object number for the passed object. - * @param obj The object of interest. - * @param stream The writable output stream to send the output to. + * @param obj The object of interest. + * @param stream The writable output stream to send the output to. */ void emitObjectNumber(SkWStream* stream, SkPDFObject* obj); /** Return the number of bytes that would be emitted for the passed * object's object number. - * @param obj The object of interest + * @param obj The object of interest */ size_t getObjectNumberSize(SkPDFObject* obj); + /** Output the cross reference table for objects in the catalog. + * Returns the total number of objects. + * @param stream The writable output stream to send the output to. + * @param firstPage If true, include first page objects only, otherwise + * include all objects not on the first page. + */ + int32_t emitXrefTable(SkWStream* stream, bool firstPage); + private: struct Rec { Rec(SkPDFObject* object, bool onFirstPage) @@ -68,9 +84,12 @@ private: // TODO(vandebo) Make this a hash if it's a performance problem. SkTDArray<struct Rec> fCatalog; + // Number of objects on the first page. + uint32_t fFirstPageCount; + // Next object number to assign (on page > 1). uint32_t fNextObjNum; - bool fStartedAssigningObjNums; - bool fAssigningFirstPageObjNums; + // Next object number to assign on the first page. + uint32_t fNextFirstPageObjNum; int findObjectIndex(SkPDFObject* obj) const; diff --git a/include/pdf/SkPDFDocument.h b/include/pdf/SkPDFDocument.h new file mode 100644 index 0000000000..91dd379214 --- /dev/null +++ b/include/pdf/SkPDFDocument.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFDocument_DEFINED +#define SkPDFDocument_DEFINED + +#include "SkPDFCatalog.h" +#include "SkPDFTypes.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" + +class SkPDFDevice; +class SkPDFPage; +class SkWSteam; + +/** \class SkPDFDocument + + A SkPDFDocument assembles pages together and generates the final PDF file. +*/ +class SkPDFDocument { +public: + /** Create a PDF document. + */ + SkPDFDocument(); + ~SkPDFDocument(); + + /** Output the PDF to the passed stream. + * @param stream The writable output stream to send the PDF to. + */ + bool emitPDF(SkWStream* stream); + + /** Append the passed pdf device to the document as a new page. Returns + * true if successful. Will fail if the document has already been emitted. + * + * @param pdfDevice The page to add to this document. + */ + bool appendPage(const SkRefPtr<SkPDFDevice>& pdfDevice); + +private: + SkPDFCatalog fCatalog; + int64_t fXRefFileOffset; + + SkTDArray<SkPDFPage*> fPages; + SkTDArray<SkPDFDict*> fPageTree; + SkRefPtr<SkPDFDict> fDocCatalog; + SkTDArray<SkPDFObject*> fPageResources; + int fSecondPageFirstResouceIndex; + + SkRefPtr<SkPDFDict> fTrailerDict; + + /** Output the PDF header to the passed stream. + * @param stream The writable output stream to send the header to. + */ + void emitHeader(SkWStream* stream); + + /** Get the size of the header. + */ + size_t headerSize(); + + /** Output the PDF footer to the passed stream. + * @param stream The writable output stream to send the footer to. + * @param objCount The number of objects in the PDF. + */ + void emitFooter(SkWStream* stream, int64_t objCount); +}; + +#endif diff --git a/include/pdf/SkPDFPage.h b/include/pdf/SkPDFPage.h new file mode 100644 index 0000000000..7e96212bbf --- /dev/null +++ b/include/pdf/SkPDFPage.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPDFPage_DEFINED +#define SkPDFPage_DEFINED + +#include "SkPDFTypes.h" +#include "SkPDFStream.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" + +class SkPDFCatalog; +class SkPDFDevice; +class SkWStream; + +/** \class SkPDFPage + + A SkPDFPage contains meta information about a page, is used in the page + tree and points to the content of the page. +*/ +class SkPDFPage : public SkPDFDict { +public: + /** Create a PDF page with the passed PDF device. The device need not + * have content on it yet. + * @param content The page content. + */ + explicit SkPDFPage(const SkRefPtr<SkPDFDevice>& content); + ~SkPDFPage(); + + /** Before a page and its contents can be sized and emitted, it must + * be finalized. No changes to the PDFDevice will be honored after + * finalizePage has been called. This function adds the page content + * to the passed catalog, so it must be called for each document + * that the page is part of. + * @param catalog The catalog to add page content objects to. + * @param firstPage Indicate if this is the first page of a document. + * @param resouceObjects The resource objects used on the page are added + * to this array. This gives the caller a chance + * to deduplicate resources across pages. + */ + void finalizePage(SkPDFCatalog* catalog, bool firstPage, + SkTDArray<SkPDFObject*>* resourceObjects); + + /** Determine the size of the page content and store to the catalog + * the offsets of all nonresource-indirect objects that make up the page + * content. This must be called before emitPage(), but after finalizePage. + * @param catalog The catalog to add the object offsets to. + * @param fileOffset The file offset where the page content will be + * emitted. + */ + off_t getPageSize(SkPDFCatalog* catalog, off_t fileOffset); + + /** Output the page content to the passed stream. + * @param stream The writable output stream to send the content to. + * @param catalog The active object catalog. + */ + void emitPage(SkWStream* stream, SkPDFCatalog* catalog); + + /** Generate a page tree for the passed vector of pages. New objects are + * added to the catalog. The pageTree vector is populated with all of + * the 'Pages' dictionaries as well as the 'Page' objects. Page trees + * have both parent and children links, creating reference cycles, so + * it must be torn down explicitly. The first page is not added to + * the pageTree dictionary array so the caller can handle it specially. + * @param pages The ordered vector of page objects. + * @param catalog The catalog to add new objects into. + * @param pageTree An output vector with all of the internal and leaf + * nodes of the pageTree. + * @param rootNode An output parameter set to the root node. + */ + static void generatePageTree(const SkTDArray<SkPDFPage*>& pages, + SkPDFCatalog* catalog, + SkTDArray<SkPDFDict*>* pageTree, + SkPDFDict** rootNode); + +private: + // Multiple pages may reference the content. + SkRefPtr<SkPDFDevice> fDevice; + + SkString fContent; + // Once the content is finalized, put it into a stream for output. + SkRefPtr<SkPDFStream> fContentStream; +}; + +#endif diff --git a/include/pdf/SkPDFStream.h b/include/pdf/SkPDFStream.h index b83aa591f6..24a96422be 100644 --- a/include/pdf/SkPDFStream.h +++ b/include/pdf/SkPDFStream.h @@ -44,11 +44,17 @@ public: virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); /** Add the value to the stream dictionary with the given key. - * @param index The index into the array to set. - * @param value The value to add to the array. + * @param key The key for this dictionary entry. + * @param value The value for this dictionary entry. */ void insert(SkPDFName* key, SkPDFObject* value); + /** Add the value to the stream dictionary with the given key. + * @param key The text of the key for this dictionary entry. + * @param value The value for this dictionary entry. + */ + void insert(const char key[], SkPDFObject* value); + private: SkPDFDict fDict; SkRefPtr<SkStream> fData; diff --git a/include/pdf/SkPDFTypes.h b/include/pdf/SkPDFTypes.h index 9324595339..e0b1041b92 100644 --- a/include/pdf/SkPDFTypes.h +++ b/include/pdf/SkPDFTypes.h @@ -147,7 +147,7 @@ public: virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); private: - static const uint32_t kMaxLen = 65535; + static const size_t kMaxLen = 65535; const SkString fValue; @@ -173,7 +173,7 @@ public: virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); private: - static const uint32_t kMaxLen = 127; + static const size_t kMaxLen = 127; const SkString fValue; @@ -235,6 +235,12 @@ public: /** 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. @@ -252,6 +258,17 @@ public: */ void insert(SkPDFName* key, SkPDFObject* value); + /** Add the value to the dictionary with the given key. 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. + */ + void insert(const char key[], SkPDFObject* value); + + /** Remove all entries from the dictionary. + */ + void clear(); + private: static const int kMaxLen = 4095; |