#ifndef SEEN_OBJECT_TEST_H #define SEEN_OBJECT_TEST_H #include #include #include #include #include #include "document.h" #include "sp-item-group.h" #include "sp-object.h" #include "sp-path.h" #include "sp-root.h" #include "xml/document.h" #include "xml/node.h" class ObjectTest : public CxxTest::TestSuite { public: virtual ~ObjectTest() {} static ObjectTest *createSuite() { return new ObjectTest(); } static void destroySuite(ObjectTest *suite) { delete suite; } void testObjects() { clock_t begin, end; // Sample document // svg:svg // svg:defs // svg:path // svg:linearGradient // svg:stop // svg:filter // svg:feGaussianBlur (feel free to implement for other filters) // svg:clipPath // svg:rect // svg:g // svg:use // svg:circle // svg:ellipse // svg:text // svg:polygon // svg:polyline // svg:image // svg:line char const *docString = "\n" "\n" "SVG test\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" "\n" " \n" " \n" " \n" " TEST\n" " \n" " \n" " \n" " \n" "\n" "\n"; begin = clock(); SPDocument *doc = SPDocument::createNewDocFromMem(docString, strlen(docString), false); end = clock(); assert(doc != NULL); // cannot continue if doc is null, abort! assert(doc->getRoot() != NULL); SPRoot *root = doc->getRoot(); assert(root->getRepr() != NULL); assert(root->hasChildren()); std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to construct the test document\n"; SPPath *path = dynamic_cast(doc->getObjectById("P")); testClones(path); SPGroup *group = dynamic_cast(doc->getObjectById("G")); testGrouping(group); // Test parent behavior SPObject *child = root->firstChild(); assert(child != NULL); TS_ASSERT(child->parent == root); TS_ASSERT(child->document == doc); TS_ASSERT(root->isAncestorOf(child)); // Test list behavior SPObject *next = child->getNext(); SPObject *prev = next; TS_ASSERT(next->getPrev() == child); prev = next; next = next->getNext(); while (next != NULL) { // Walk the list TS_ASSERT(next->getPrev() == prev); prev = next; next = next->getNext(); } TS_ASSERT(child->lastChild() == next); // Test hrefcount TS_ASSERT(path->isReferenced()); } void testClones(SPPath *path) { clock_t begin, end; assert(path != NULL); // Since we don't yet have any clean way to do this (FIXME), we'll abuse the XML tree a bit. Inkscape::XML::Node *node = path->getRepr(); assert(node != NULL); Inkscape::XML::Document *xml_doc = node->document(); Inkscape::XML::Node *parent = node->parent(); assert(parent != NULL); TS_TRACE("Benchmarking clones..."); const size_t num_clones = 10000; std::string href(std::string("#") + std::string(path->getId())); std::vector clones(num_clones, NULL); begin = clock(); // Create num_clones clones of this path and stick them in the document for (size_t i = 0; i < num_clones; ++i) { Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); Inkscape::GC::release(clone); clone->setAttribute("xlink:href", href.c_str()); parent->addChild(clone, node); clones[i] = clone; } end = clock(); std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to write " << num_clones << " clones of a path\n"; begin = clock(); // Remove those clones for (size_t i = num_clones - 1; i >= 1; --i) { parent->removeChild(clones[i]); } end = clock(); std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to remove " << num_clones << " clones of a path\n"; } void testGrouping(SPGroup *group) { clock_t begin, end; assert(group != NULL); // Since we don't yet have any clean way to do this (FIXME), we'll abuse the XML tree a bit. Inkscape::XML::Node *node = group->getRepr(); assert(node != NULL); Inkscape::XML::Document *xml_doc = node->document(); TS_TRACE("Benchmarking groups..."); const size_t num_elements = 10000; Inkscape::XML::Node *new_group = xml_doc->createElement("svg:g"); Inkscape::GC::release(new_group); node->addChild(new_group, NULL); std::vector elements(num_elements, NULL); begin = clock(); for (size_t i = 0; i < num_elements; ++i) { Inkscape::XML::Node *circle = xml_doc->createElement("svg:circle"); Inkscape::GC::release(circle); circle->setAttribute("cx", "2048"); circle->setAttribute("cy", "1024"); circle->setAttribute("r", "1.5"); new_group->addChild(circle, NULL); elements[i] = circle; } end = clock(); std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to write " << num_elements << " elements into a group\n"; SPGroup *n_group = dynamic_cast(group->get_child_by_repr(new_group)); assert(n_group != NULL); begin = clock(); sp_item_group_ungroup(n_group, NULL, false); end = clock(); std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to ungroup a with " << num_elements << " elements\n"; begin = clock(); // Remove those elements for (size_t i = num_elements - 1; i >= 1; --i) { elements[i]->parent()->removeChild(elements[i]); } end = clock(); std::cout << "Took " << double(end - begin) / double(CLOCKS_PER_SEC) << " seconds to remove " << num_elements << " elements\n"; } }; #endif // SEEN_OBJECT_TEST_H /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :