Beispiel #1
0
// 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;
                }
            }
        }
    }
}