From f28146cf72fc68c8d3690814b1f89d47b8c4e7b9 Mon Sep 17 00:00:00 2001 From: David Gow Date: Thu, 16 Oct 2014 19:49:25 +0800 Subject: [PATCH] Bugfixes, performance fixes, tears. --- src/bezier.h | 2 +- src/document.cpp | 55 +++++++++++++++++++++++++++-- src/document.h | 2 ++ src/quadtree.cpp | 9 +++++ src/quadtree.h | 1 + src/turtles_all_the_way_down.script | 1 + src/view.cpp | 6 +++- 7 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/bezier.h b/src/bezier.h index d3c0e2d..0fcf167 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -20,7 +20,7 @@ namespace IPDF extern std::vector SolveQuadratic(const BReal & a, const BReal & b, const BReal & c, const BReal & min = 0, const BReal & max = 1); - extern std::vector SolveCubic(const BReal & a, const BReal & b, const BReal & c, const BReal & d, const BReal & min = 0, const BReal & max = 1, const BReal & delta = 1e-9); + extern std::vector SolveCubic(const BReal & a, const BReal & b, const BReal & c, const BReal & d, const BReal & min = 0, const BReal & max = 1, const BReal & delta = 1e-5); /** A _cubic_ bezier. **/ struct Bezier diff --git a/src/document.cpp b/src/document.cpp index a7fb524..256950b 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -206,6 +206,7 @@ QuadTreeIndex Document::GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren default: Fatal("Tried to add a QuadTree child of invalid type!"); } + m_document_dirty = true; return new_index; } @@ -264,6 +265,44 @@ void Document::OverlayQuadChildren(QuadTreeIndex orig_parent, QuadTreeIndex pare m_quadtree.nodes[new_index].object_dirty = m_quadtree.nodes[new_index].object_end; m_quadtree.nodes[new_index].next_overlay = -1; + m_document_dirty = true; +} + +void Document::OverlayQuadParent(QuadTreeIndex orig_child, QuadTreeIndex child, QuadTreeNodeChildren type) +{ + PROFILE_SCOPE("Document::OverlayQuadParent()"); + QuadTreeIndex new_index = m_quadtree.nodes.size(); + m_quadtree.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, -1, QTC_UNKNOWN, 0, 0, -1}); + + m_quadtree.nodes[new_index].object_begin = m_objects.bounds.size(); + m_quadtree.nodes[new_index].object_dirty = m_objects.bounds.size(); + for (QuadTreeIndex overlay = child; overlay != -1; overlay = m_quadtree.nodes[overlay].next_overlay) + { + for (unsigned i = m_quadtree.nodes[overlay].object_begin; i < m_quadtree.nodes[overlay].object_end; ++i) + { + m_objects.bounds.push_back(TransformFromQuadChild(m_objects.bounds[i], type)); + m_objects.types.push_back(m_objects.types[i]); + m_objects.data_indices.push_back(m_objects.data_indices[i]); + m_count++; + } + } + m_quadtree.nodes[new_index].object_end = m_objects.bounds.size(); + QuadTreeIndex orig_node = m_quadtree.nodes[orig_child].parent; + if (orig_node == -1) + Fatal("Tried to overlay a QuadTree child that didn't exist!"); + + // Add us to the node's overlay linked list. + QuadTreeIndex prev_overlay = orig_node; + while (m_quadtree.nodes[prev_overlay].next_overlay != -1) prev_overlay = m_quadtree.nodes[prev_overlay].next_overlay; + m_quadtree.nodes[prev_overlay].next_overlay = new_index; + + // Recurse into any extant parent. + if (m_quadtree.nodes[orig_node].parent != -1) + OverlayQuadParent(orig_node, new_index, m_quadtree.nodes[orig_node].child_type); + + m_quadtree.nodes[new_index].object_dirty = m_quadtree.nodes[new_index].object_end; + m_quadtree.nodes[new_index].next_overlay = -1; + m_document_dirty = true; } void Document::PropagateQuadChanges(QuadTreeIndex node) @@ -272,6 +311,9 @@ void Document::PropagateQuadChanges(QuadTreeIndex node) { // We don't care about clean overlays. if (m_quadtree.nodes[overlay].object_dirty == m_quadtree.nodes[overlay].object_end) continue; + // Recurse into our parent, should we have any. + if (m_quadtree.nodes[node].parent != -1) + OverlayQuadParent(node, overlay, m_quadtree.nodes[overlay].child_type); // Recurse into any extant children. if (m_quadtree.nodes[node].top_left != -1) OverlayQuadChildren(node, overlay, QTC_TOP_LEFT); @@ -323,6 +365,7 @@ QuadTreeIndex Document::GenQuadParent(QuadTreeIndex child, QuadTreeNodeChildren Fatal("Tried to add a QuadTree child of invalid type!"); } return new_index; + m_document_dirty = true; } #endif @@ -418,11 +461,19 @@ unsigned Document::AddBezier(const Bezier & bezier) unsigned Document::Add(ObjectType type, const Rect & bounds, unsigned data_index, QuadTreeIndex qti) { PROFILE_SCOPE("Document::Add"); + Rect new_bounds = bounds; +#ifndef QUADTREE_DISABLED + if (qti == -1) qti = m_current_insert_node; + if (qti != -1) + { + // I am ashamed, yes. + m_quadtree.GetCanonicalCoords(qti, new_bounds.x, new_bounds.y, this); + } +#endif m_objects.types.push_back(type); - m_objects.bounds.push_back(bounds); + m_objects.bounds.push_back(new_bounds); m_objects.data_indices.push_back(data_index); #ifndef QUADTREE_DISABLED - if (qti == -1) qti = m_current_insert_node; if (qti != -1) { QuadTreeIndex new_qti = qti; diff --git a/src/document.h b/src/document.h index 59beee6..fd6e574 100644 --- a/src/document.h +++ b/src/document.h @@ -91,6 +91,7 @@ namespace IPDF QuadTreeIndex GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren type); QuadTreeIndex GenQuadParent(QuadTreeIndex child, QuadTreeNodeChildren mytype); void OverlayQuadChildren(QuadTreeIndex orig_parent, QuadTreeIndex parent, QuadTreeNodeChildren type); + void OverlayQuadParent(QuadTreeIndex orig_child, QuadTreeIndex child, QuadTreeNodeChildren type); void PropagateQuadChanges(QuadTreeIndex node); // Returns the number of objects the current object formed when clipped, the objects in question are added to the end of the document. int ClipObjectToQuadChild(int object_id, QuadTreeNodeChildren type); @@ -114,6 +115,7 @@ namespace IPDF QuadTreeIndex m_current_insert_node; #endif + bool m_document_dirty; unsigned m_count; unsigned char * m_font_data; stbtt_fontinfo m_font; diff --git a/src/quadtree.cpp b/src/quadtree.cpp index b84bb78..623bd38 100644 --- a/src/quadtree.cpp +++ b/src/quadtree.cpp @@ -297,6 +297,15 @@ QuadTreeIndex QuadTree::GetNeighbour(QuadTreeIndex start, int xdir, int ydir, Do return -1; } +void QuadTree::GetCanonicalCoords(QuadTreeIndex& start, Real& x, Real& y, Document *doc) +{ + int _x = (int)x; + int _y = (int)y; + start = GetNeighbour(start, _x, _y, doc); + x -= _x; + y -= _y; +} + } #endif diff --git a/src/quadtree.h b/src/quadtree.h index 15fd8a9..4fd4b2d 100644 --- a/src/quadtree.h +++ b/src/quadtree.h @@ -53,6 +53,7 @@ namespace IPDF std::vector nodes; QuadTreeIndex GetNeighbour(QuadTreeIndex start, int xdir, int ydir, Document *doc) const; + void GetCanonicalCoords(QuadTreeIndex& start, Real& x, Real& y, Document *doc); }; diff --git a/src/turtles_all_the_way_down.script b/src/turtles_all_the_way_down.script index fcddfe7..45fb1e5 100644 --- a/src/turtles_all_the_way_down.script +++ b/src/turtles_all_the_way_down.script @@ -1,6 +1,7 @@ # BECAUSE I CAN gpu lazy +profileon #debugfont off diff --git a/src/view.cpp b/src/view.cpp index b489e08..1ed36e7 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -406,7 +406,11 @@ void View::RenderQuadtreeNode(int width, int height, QuadTreeIndex node, int rem if (!remaining_depth) return; //Debug("Rendering QT node %d, (objs: %d -- %d)\n", node, m_document.GetQuadTree().nodes[node].object_begin, m_document.GetQuadTree().nodes[node].object_end); m_bounds_dirty = true; - m_render_dirty = m_buffer_dirty = true; + if (m_document.m_document_dirty) + { + m_render_dirty = m_buffer_dirty = true; + m_document.m_document_dirty = false; + } QuadTreeIndex overlay = node; while(overlay != -1) { -- 2.20.1