• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "SkPDFCatalog.h"
18 #include "SkPDFTypes.h"
19 #include "SkStream.h"
20 #include "SkTypes.h"
21 
SkPDFCatalog()22 SkPDFCatalog::SkPDFCatalog()
23     : fFirstPageCount(0),
24       fNextObjNum(1),
25       fNextFirstPageObjNum(0) {
26 }
27 
~SkPDFCatalog()28 SkPDFCatalog::~SkPDFCatalog() {}
29 
addObject(SkPDFObject * obj,bool onFirstPage)30 SkPDFObject* SkPDFCatalog::addObject(SkPDFObject* obj, bool onFirstPage) {
31     SkASSERT(findObjectIndex(obj) == -1);
32     SkASSERT(fNextFirstPageObjNum == 0);
33     if (onFirstPage)
34         fFirstPageCount++;
35 
36     struct Rec newEntry(obj, onFirstPage);
37     fCatalog.append(1, &newEntry);
38     return obj;
39 }
40 
setFileOffset(SkPDFObject * obj,size_t offset)41 size_t SkPDFCatalog::setFileOffset(SkPDFObject* obj, size_t offset) {
42     int objIndex = assignObjNum(obj) - 1;
43     SkASSERT(fCatalog[objIndex].fObjNumAssigned);
44     SkASSERT(fCatalog[objIndex].fFileOffset == 0);
45     fCatalog[objIndex].fFileOffset = offset;
46 
47     return obj->getOutputSize(this, true);
48 }
49 
emitObjectNumber(SkWStream * stream,SkPDFObject * obj)50 void SkPDFCatalog::emitObjectNumber(SkWStream* stream, SkPDFObject* obj) {
51     stream->writeDecAsText(assignObjNum(obj));
52     stream->writeText(" 0");  // Generation number is always 0.
53 }
54 
getObjectNumberSize(SkPDFObject * obj)55 size_t SkPDFCatalog::getObjectNumberSize(SkPDFObject* obj) {
56     SkDynamicMemoryWStream buffer;
57     emitObjectNumber(&buffer, obj);
58     return buffer.getOffset();
59 }
60 
findObjectIndex(SkPDFObject * obj) const61 int SkPDFCatalog::findObjectIndex(SkPDFObject* obj) const {
62     for (int i = 0; i < fCatalog.count(); i++) {
63         if (fCatalog[i].fObject == obj)
64             return i;
65     }
66     return -1;
67 }
68 
assignObjNum(SkPDFObject * obj)69 int SkPDFCatalog::assignObjNum(SkPDFObject* obj) {
70     int pos = findObjectIndex(obj);
71     // If this assert fails, it means you probably forgot to add an object
72     // to the resource list.
73     SkASSERT(pos >= 0);
74     uint32_t currentIndex = pos;
75     if (fCatalog[currentIndex].fObjNumAssigned)
76         return currentIndex + 1;
77 
78     // First assignment.
79     if (fNextFirstPageObjNum == 0)
80         fNextFirstPageObjNum = fCatalog.count() - fFirstPageCount + 1;
81 
82     uint32_t objNum;
83     if (fCatalog[currentIndex].fOnFirstPage) {
84         objNum = fNextFirstPageObjNum;
85         fNextFirstPageObjNum++;
86     } else {
87         objNum = fNextObjNum;
88         fNextObjNum++;
89     }
90 
91     // When we assign an object an object number, we put it in that array
92     // offset (minus 1 because object number 0 is reserved).
93     SkASSERT(!fCatalog[objNum - 1].fObjNumAssigned);
94     if (objNum - 1 != currentIndex)
95         SkTSwap(fCatalog[objNum - 1], fCatalog[currentIndex]);
96     fCatalog[objNum - 1].fObjNumAssigned = true;
97     return objNum;
98 }
99 
emitXrefTable(SkWStream * stream,bool firstPage)100 int32_t SkPDFCatalog::emitXrefTable(SkWStream* stream, bool firstPage) {
101     int first = -1;
102     int last = fCatalog.count() - 1;
103     // TODO(vandebo) support linearized format.
104     //int last = fCatalog.count() - fFirstPageCount - 1;
105     //if (firstPage) {
106     //    first = fCatalog.count() - fFirstPageCount;
107     //    last = fCatalog.count() - 1;
108     //}
109 
110     stream->writeText("xref\n");
111     stream->writeDecAsText(first + 1);
112     stream->writeText(" ");
113     stream->writeDecAsText(last - first + 1);
114     stream->writeText("\n");
115 
116     if (first == -1) {
117         stream->writeText("0000000000 65535 f \n");
118         first++;
119     }
120     for (int i = first; i <= last; i++) {
121         SkASSERT(fCatalog[i].fFileOffset > 0);
122         SkASSERT(fCatalog[i].fFileOffset <= 9999999999LL);
123         stream->writeBigDecAsText(fCatalog[i].fFileOffset, 10);
124         stream->writeText(" 00000 n \n");
125     }
126 
127     return fCatalog.count() + 1;
128 }
129