| 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 |