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
diff --git a/src/pdf/SkPDFCatalog.cpp b/src/pdf/SkPDFCatalog.cpp
index 1349da1..7979b70 100644
--- a/src/pdf/SkPDFCatalog.cpp
+++ b/src/pdf/SkPDFCatalog.cpp
@@ -17,23 +17,35 @@
#include "SkPDFCatalog.h"
#include "SkPDFTypes.h"
#include "SkStream.h"
+#include "SkTypes.h"
SkPDFCatalog::SkPDFCatalog()
- : fNextObjNum(1),
- fStartedAssigningObjNums(false),
- fAssigningFirstPageObjNums(false) {
+ : fFirstPageCount(0),
+ fNextObjNum(1),
+ fNextFirstPageObjNum(0) {
}
SkPDFCatalog::~SkPDFCatalog() {}
void SkPDFCatalog::addObject(SkPDFObject* obj, bool onFirstPage) {
SkASSERT(findObjectIndex(obj) == -1);
- SkASSERT(!fStartedAssigningObjNums);
+ SkASSERT(fNextFirstPageObjNum == 0);
+ if (onFirstPage)
+ fFirstPageCount++;
struct Rec newEntry(obj, onFirstPage);
fCatalog.append(1, &newEntry);
}
+size_t SkPDFCatalog::setFileOffset(SkPDFObject* obj, size_t offset) {
+ int objIndex = assignObjNum(obj) - 1;
+ SkASSERT(fCatalog[objIndex].fObjNumAssigned);
+ SkASSERT(fCatalog[objIndex].fFileOffset == 0);
+ fCatalog[objIndex].fFileOffset = offset;
+
+ return obj->getOutputSize(this, true);
+}
+
void SkPDFCatalog::emitObjectNumber(SkWStream* stream, SkPDFObject* obj) {
stream->writeDecAsText(assignObjNum(obj));
stream->writeText(" 0"); // Generation number is always 0.
@@ -60,21 +72,54 @@
if (fCatalog[currentIndex].fObjNumAssigned)
return currentIndex + 1;
- fStartedAssigningObjNums = true;
+ // First assignment.
+ if (fNextFirstPageObjNum == 0)
+ fNextFirstPageObjNum = fCatalog.count() - fFirstPageCount + 1;
+
+ uint32_t objNum;
if (fCatalog[currentIndex].fOnFirstPage) {
- fAssigningFirstPageObjNums = true;
+ objNum = fNextFirstPageObjNum;
+ fNextFirstPageObjNum++;
} else {
- SkASSERT(!fAssigningFirstPageObjNums);
+ objNum = fNextObjNum;
+ fNextObjNum++;
}
// When we assign an object an object number, we put it in that array
// offset (minus 1 because object number 0 is reserved).
- if (fNextObjNum - 1 != currentIndex) {
- Rec other = fCatalog[fNextObjNum - 1];
- fCatalog[fNextObjNum - 1] = fCatalog[currentIndex];
- fCatalog[currentIndex] = other;
+ SkASSERT(!fCatalog[objNum - 1].fObjNumAssigned);
+ if (objNum - 1 != currentIndex)
+ SkTSwap(fCatalog[objNum - 1], fCatalog[currentIndex]);
+ fCatalog[objNum - 1].fObjNumAssigned = true;
+ return objNum;
+}
+
+int32_t SkPDFCatalog::emitXrefTable(SkWStream* stream, bool firstPage) {
+ int first = -1;
+ int last = fCatalog.count() - 1;
+ // TODO(vandebo) support linearized format.
+ //int last = fCatalog.count() - fFirstPageCount - 1;
+ //if (firstPage) {
+ // first = fCatalog.count() - fFirstPageCount;
+ // last = fCatalog.count() - 1;
+ //}
+
+ stream->writeText("xref\n");
+ stream->writeDecAsText(first + 1);
+ stream->writeText(" ");
+ stream->writeDecAsText(last - first + 1);
+ stream->writeText("\n");
+
+ if (first == -1) {
+ stream->writeText("0000000000 65535 f \n");
+ first++;
}
- fCatalog[fNextObjNum - 1].fObjNumAssigned = true;
- fNextObjNum++;
- return fNextObjNum - 1;
+ for (int i = first; i <= last; i++) {
+ SkASSERT(fCatalog[i].fFileOffset > 0);
+ SkASSERT(fCatalog[i].fFileOffset <= 9999999999LL);
+ stream->writeBigDecAsText(fCatalog[i].fFileOffset, 10);
+ stream->writeText(" 00000 n \n");
+ }
+
+ return fCatalog.count() + 1;
}