// return root node. static sk_sp<SkPDFDict> generate_page_tree(SkTArray<sk_sp<SkPDFDict>>* pages) { // PDF wants a tree describing all the pages in the document. We arbitrary // choose 8 (kNodeSize) as the number of allowed children. The internal // nodes have type "Pages" with an array of children, a parent pointer, and // the number of leaves below the node as "Count." The leaves are passed // into the method, have type "Page" and need a parent pointer. This method // builds the tree bottom up, skipping internal nodes that would have only // one child. static const int kNodeSize = 8; // curNodes takes a reference to its items, which it passes to pageTree. int totalPageCount = pages->count(); SkTArray<sk_sp<SkPDFDict>> curNodes; curNodes.swap(pages); // nextRoundNodes passes its references to nodes on to curNodes. int treeCapacity = kNodeSize; do { SkTArray<sk_sp<SkPDFDict>> nextRoundNodes; for (int i = 0; i < curNodes.count(); ) { if (i > 0 && i + 1 == curNodes.count()) { SkASSERT(curNodes[i]); nextRoundNodes.emplace_back(std::move(curNodes[i])); break; } auto newNode = sk_make_sp<SkPDFDict>("Pages"); auto kids = sk_make_sp<SkPDFArray>(); kids->reserve(kNodeSize); int count = 0; for (; i < curNodes.count() && count < kNodeSize; i++, count++) { SkASSERT(curNodes[i]); curNodes[i]->insertObjRef("Parent", newNode); kids->appendObjRef(std::move(curNodes[i])); } // treeCapacity is the number of leaf nodes possible for the // current set of subtrees being generated. (i.e. 8, 64, 512, ...). // It is hard to count the number of leaf nodes in the current // subtree. However, by construction, we know that unless it's the // last subtree for the current depth, the leaf count will be // treeCapacity, otherwise it's what ever is left over after // consuming treeCapacity chunks. int pageCount = treeCapacity; if (i == curNodes.count()) { pageCount = ((totalPageCount - 1) % treeCapacity) + 1; } newNode->insertInt("Count", pageCount); newNode->insertObject("Kids", std::move(kids)); nextRoundNodes.emplace_back(std::move(newNode)); } SkDEBUGCODE( for (const auto& n : curNodes) { SkASSERT(!n); } ); curNodes.swap(&nextRoundNodes); nextRoundNodes.reset(); treeCapacity *= kNodeSize; } while (curNodes.count() > 1);
static void test_swap(skiatest::Reporter* reporter) { typedef SkTArray<int>* (*ArrayMaker)(); ArrayMaker arrayMakers[] = {make, make_s<5>, make_s<10>, make_s<20>}; static int kSizes[] = {0, 1, 5, 10, 15, 20, 25}; for (size_t arrayA = 0; arrayA < SK_ARRAY_COUNT(arrayMakers); ++arrayA) { for (size_t arrayB = arrayA; arrayB < SK_ARRAY_COUNT(arrayMakers); ++arrayB) { for (size_t dataSizeA = 0; dataSizeA < SK_ARRAY_COUNT(kSizes); ++dataSizeA) { for (size_t dataSizeB = 0; dataSizeB < SK_ARRAY_COUNT(kSizes); ++dataSizeB) { int curr = 0; SkTArray<int>* a = arrayMakers[arrayA](); SkTArray<int>* b = arrayMakers[arrayB](); for (int i = 0; i < kSizes[dataSizeA]; ++i) { a->push_back(curr++); } for (int i = 0; i < kSizes[dataSizeB]; ++i) { b->push_back(curr++); } a->swap(b); REPORTER_ASSERT(reporter, kSizes[dataSizeA] == b->count()); REPORTER_ASSERT(reporter, kSizes[dataSizeB] == a->count()); curr = 0; for (int i = 0; i < kSizes[dataSizeA]; ++i) { REPORTER_ASSERT(reporter, curr++ == (*b)[i]); } for (int i = 0; i < kSizes[dataSizeB]; ++i) { REPORTER_ASSERT(reporter, curr++ == (*a)[i]); } delete b; a->swap(a); curr = kSizes[dataSizeA]; for (int i = 0; i < kSizes[dataSizeB]; ++i) { REPORTER_ASSERT(reporter, curr++ == (*a)[i]); } delete a; } } } } }