OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkDocument.h" | 8 #include "SkDocument.h" |
9 #include "SkPDFCanon.h" | 9 #include "SkPDFCanon.h" |
10 #include "SkPDFDevice.h" | 10 #include "SkPDFDevice.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 SkPDFDict** rootNode) { | 87 SkPDFDict** rootNode) { |
88 // PDF wants a tree describing all the pages in the document. We arbitrary | 88 // PDF wants a tree describing all the pages in the document. We arbitrary |
89 // choose 8 (kNodeSize) as the number of allowed children. The internal | 89 // choose 8 (kNodeSize) as the number of allowed children. The internal |
90 // nodes have type "Pages" with an array of children, a parent pointer, and | 90 // nodes have type "Pages" with an array of children, a parent pointer, and |
91 // the number of leaves below the node as "Count." The leaves are passed | 91 // the number of leaves below the node as "Count." The leaves are passed |
92 // into the method, have type "Page" and need a parent pointer. This method | 92 // into the method, have type "Page" and need a parent pointer. This method |
93 // builds the tree bottom up, skipping internal nodes that would have only | 93 // builds the tree bottom up, skipping internal nodes that would have only |
94 // one child. | 94 // one child. |
95 static const int kNodeSize = 8; | 95 static const int kNodeSize = 8; |
96 | 96 |
97 SkAutoTUnref<SkPDFName> kidsName(new SkPDFName("Kids")); | |
98 SkAutoTUnref<SkPDFName> countName(new SkPDFName("Count")); | |
99 SkAutoTUnref<SkPDFName> parentName(new SkPDFName("Parent")); | |
100 | |
101 // curNodes takes a reference to its items, which it passes to pageTree. | 97 // curNodes takes a reference to its items, which it passes to pageTree. |
102 SkTDArray<SkPDFDict*> curNodes; | 98 SkTDArray<SkPDFDict*> curNodes; |
103 curNodes.setReserve(pages.count()); | 99 curNodes.setReserve(pages.count()); |
104 for (int i = 0; i < pages.count(); i++) { | 100 for (int i = 0; i < pages.count(); i++) { |
105 SkSafeRef(pages[i]); | 101 SkSafeRef(pages[i]); |
106 curNodes.push(pages[i]); | 102 curNodes.push(pages[i]); |
107 } | 103 } |
108 | 104 |
109 // nextRoundNodes passes its references to nodes on to curNodes. | 105 // nextRoundNodes passes its references to nodes on to curNodes. |
110 SkTDArray<SkPDFDict*> nextRoundNodes; | 106 SkTDArray<SkPDFDict*> nextRoundNodes; |
111 nextRoundNodes.setReserve((pages.count() + kNodeSize - 1)/kNodeSize); | 107 nextRoundNodes.setReserve((pages.count() + kNodeSize - 1)/kNodeSize); |
112 | 108 |
113 int treeCapacity = kNodeSize; | 109 int treeCapacity = kNodeSize; |
114 do { | 110 do { |
115 for (int i = 0; i < curNodes.count(); ) { | 111 for (int i = 0; i < curNodes.count(); ) { |
116 if (i > 0 && i + 1 == curNodes.count()) { | 112 if (i > 0 && i + 1 == curNodes.count()) { |
117 nextRoundNodes.push(curNodes[i]); | 113 nextRoundNodes.push(curNodes[i]); |
118 break; | 114 break; |
119 } | 115 } |
120 | 116 |
121 SkPDFDict* newNode = new SkPDFDict("Pages"); | 117 SkPDFDict* newNode = new SkPDFDict("Pages"); |
122 SkAutoTUnref<SkPDFObjRef> newNodeRef(new SkPDFObjRef(newNode)); | 118 SkAutoTUnref<SkPDFObjRef> newNodeRef(new SkPDFObjRef(newNode)); |
123 | 119 |
124 SkAutoTUnref<SkPDFArray> kids(new SkPDFArray); | 120 SkAutoTUnref<SkPDFArray> kids(new SkPDFArray); |
125 kids->reserve(kNodeSize); | 121 kids->reserve(kNodeSize); |
126 | 122 |
127 int count = 0; | 123 int count = 0; |
128 for (; i < curNodes.count() && count < kNodeSize; i++, count++) { | 124 for (; i < curNodes.count() && count < kNodeSize; i++, count++) { |
129 curNodes[i]->insert(parentName.get(), newNodeRef.get()); | 125 curNodes[i]->insert("Parent", newNodeRef.get()); |
130 kids->append(new SkPDFObjRef(curNodes[i]))->unref(); | 126 kids->append(new SkPDFObjRef(curNodes[i]))->unref(); |
131 | 127 |
132 // TODO(vandebo): put the objects in strict access order. | 128 // TODO(vandebo): put the objects in strict access order. |
133 // Probably doesn't matter because they are so small. | 129 // Probably doesn't matter because they are so small. |
134 if (curNodes[i] != pages[0]) { | 130 if (curNodes[i] != pages[0]) { |
135 pageTree->push(curNodes[i]); // Transfer reference. | 131 pageTree->push(curNodes[i]); // Transfer reference. |
136 } else { | 132 } else { |
137 SkSafeUnref(curNodes[i]); | 133 SkSafeUnref(curNodes[i]); |
138 } | 134 } |
139 } | 135 } |
140 | 136 |
141 // treeCapacity is the number of leaf nodes possible for the | 137 // treeCapacity is the number of leaf nodes possible for the |
142 // current set of subtrees being generated. (i.e. 8, 64, 512, ...). | 138 // current set of subtrees being generated. (i.e. 8, 64, 512, ...). |
143 // It is hard to count the number of leaf nodes in the current | 139 // It is hard to count the number of leaf nodes in the current |
144 // subtree. However, by construction, we know that unless it's the | 140 // subtree. However, by construction, we know that unless it's the |
145 // last subtree for the current depth, the leaf count will be | 141 // last subtree for the current depth, the leaf count will be |
146 // treeCapacity, otherwise it's what ever is left over after | 142 // treeCapacity, otherwise it's what ever is left over after |
147 // consuming treeCapacity chunks. | 143 // consuming treeCapacity chunks. |
148 int pageCount = treeCapacity; | 144 int pageCount = treeCapacity; |
149 if (i == curNodes.count()) { | 145 if (i == curNodes.count()) { |
150 pageCount = ((pages.count() - 1) % treeCapacity) + 1; | 146 pageCount = ((pages.count() - 1) % treeCapacity) + 1; |
151 } | 147 } |
152 newNode->insert(countName.get(), new SkPDFInt(pageCount))->unref(); | 148 newNode->insert("Count", new SkPDFInt(pageCount))->unref(); |
153 newNode->insert(kidsName.get(), kids.get()); | 149 newNode->insert("Kids", kids.get()); |
154 nextRoundNodes.push(newNode); // Transfer reference. | 150 nextRoundNodes.push(newNode); // Transfer reference. |
155 } | 151 } |
156 | 152 |
157 curNodes = nextRoundNodes; | 153 curNodes = nextRoundNodes; |
158 nextRoundNodes.rewind(); | 154 nextRoundNodes.rewind(); |
159 treeCapacity *= kNodeSize; | 155 treeCapacity *= kNodeSize; |
160 } while (curNodes.count() > 1); | 156 } while (curNodes.count() > 1); |
161 | 157 |
162 pageTree->push(curNodes[0]); // Transfer reference. | 158 pageTree->push(curNodes[0]); // Transfer reference. |
163 if (rootNode) { | 159 if (rootNode) { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 | 355 |
360 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { | 356 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { |
361 SkFILEWStream* stream = SkNEW_ARGS(SkFILEWStream, (path)); | 357 SkFILEWStream* stream = SkNEW_ARGS(SkFILEWStream, (path)); |
362 if (!stream->isValid()) { | 358 if (!stream->isValid()) { |
363 SkDELETE(stream); | 359 SkDELETE(stream); |
364 return NULL; | 360 return NULL; |
365 } | 361 } |
366 auto delete_wstream = [](SkWStream* stream, bool) { SkDELETE(stream); }; | 362 auto delete_wstream = [](SkWStream* stream, bool) { SkDELETE(stream); }; |
367 return SkNEW_ARGS(SkDocument_PDF, (stream, delete_wstream, dpi)); | 363 return SkNEW_ARGS(SkDocument_PDF, (stream, delete_wstream, dpi)); |
368 } | 364 } |
OLD | NEW |