X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Fdocument.cpp;h=a4b20d08f091ecaa4585377343a9f97f7fccf9af;hp=892f77a084e97a16119834f104a5c8aa973af6d2;hb=46fa3e99a49b47c18836d44d806971192907c304;hpb=457682a07cf1346aecfec22798e5a49a16db3c1b diff --git a/src/document.cpp b/src/document.cpp index 892f77a..a4b20d0 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -3,6 +3,8 @@ #include #include +#include "stb_truetype.h" + using namespace IPDF; using namespace std; @@ -92,10 +94,11 @@ void Document::GenBaseQuadtree() { m_quadtree.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QTC_UNKNOWN, 0, ObjectCount()}); m_quadtree.root_id = 0; - GenQuadNode(0, QTC_TOP_LEFT); + GenQuadChild(0, QTC_TOP_LEFT); + GenQuadParent(0, QTC_BOTTOM_RIGHT); } -QuadTreeIndex Document::GenQuadNode(QuadTreeIndex parent, QuadTreeNodeChildren type) +QuadTreeIndex Document::GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren type) { QuadTreeIndex new_index = m_quadtree.nodes.size(); m_quadtree.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, parent, type, 0, 0}); @@ -132,6 +135,41 @@ QuadTreeIndex Document::GenQuadNode(QuadTreeIndex parent, QuadTreeNodeChildren t return new_index; } +// Reparent a quadtree node, making it the "type" child of a new node. +QuadTreeIndex Document::GenQuadParent(QuadTreeIndex child, QuadTreeNodeChildren type) +{ + 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}); + + m_quadtree.nodes[new_index].object_begin = m_objects.bounds.size(); + for (unsigned i = m_quadtree.nodes[child].object_begin; i < m_quadtree.nodes[child].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(); + switch (type) + { + case QTC_TOP_LEFT: + m_quadtree.nodes[new_index].top_left = child; + break; + case QTC_TOP_RIGHT: + m_quadtree.nodes[new_index].top_right = child; + break; + case QTC_BOTTOM_LEFT: + m_quadtree.nodes[new_index].bottom_left = child; + break; + case QTC_BOTTOM_RIGHT: + m_quadtree.nodes[new_index].bottom_right = child; + break; + default: + Fatal("Tried to add a QuadTree child of invalid type!"); + } + return new_index; +} + #endif void Document::Load(const string & filename) @@ -399,6 +437,11 @@ void Document::AddPathFromString(const string & d, const Rect & bounds) { x[3] = x[2]; y[3] = y[2]; + Real old_x1(x[1]), old_y1(y[1]); + x[1] = x[0] + Real(2) * (old_x1 - x[0])/ Real(3); + y[1] = y[0] + Real(2) * (old_y1 - y[0])/ Real(3); + x[2] = x[3] + Real(2) * (old_x1 - x[3])/ Real(3); + y[2] = y[3] + Real(2) * (old_y1 - y[3])/ Real(3); } unsigned index = AddBezierData(Bezier(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3])); @@ -420,8 +463,8 @@ void Document::AddPathFromString(const string & d, const Rect & bounds) assert(GetToken(d,token,i) == ","); Real dy = strtod(GetToken(d,token,i).c_str(),NULL) / bounds.h; - x[1] = (relative) ? x0 + dx : dx; - y[1] = (relative) ? y0 + dy : dy; + x[1] = (relative) ? x[0] + dx : dx; + y[1] = (relative) ? y[0] + dy : dy; x[2] = x[1]; y[2] = y[1]; @@ -472,3 +515,57 @@ void Document::AddPathFromString(const string & d, const Rect & bounds) prev_i = i; } } + +void Document::AddFontGlyphAtPoint(stbtt_fontinfo *font, int character, Real scale, Real x, Real y) +{ + int glyph_index = stbtt_FindGlyphIndex(font, character); + + // Check if there is actully a glyph to render. + if (stbtt_IsGlyphEmpty(font, glyph_index)) + { + return; + } + + stbtt_vertex *instructions; + int num_instructions = stbtt_GetGlyphShape(font, glyph_index, &instructions); + + Real current_x(0), current_y(0); + + for (int i = 0; i < num_instructions; ++i) + { + // TTF uses 16-bit signed ints for coordinates: + // with the y-axis inverted compared to us. + // Convert and scale any data. + Real inst_x = Real(instructions[i].x)*scale; + Real inst_y = Real(instructions[i].y)*-scale; + Real inst_cx = Real(instructions[i].cx)*scale; + Real inst_cy = Real(instructions[i].cy)*-scale; + Real old_x(current_x), old_y(current_y); + current_x = inst_x; + current_y = inst_y; + unsigned bezier_index; + switch(instructions[i].type) + { + // Move To + case STBTT_vmove: + break; + // Line To + case STBTT_vline: + bezier_index = AddBezierData(Bezier(old_x + x, old_y + y, old_x + x, old_y + y, current_x + x, current_y + y, current_x + x, current_y + y)); + Add(BEZIER,Rect(0,0,1,1),bezier_index); + break; + // Quadratic Bezier To: + case STBTT_vcurve: + // Quadratic -> Cubic: + // - Endpoints are the same. + // - cubic1 = quad0+(2/3)*(quad1-quad0) + // - cubic2 = quad2+(2/3)*(quad1-quad2) + bezier_index = AddBezierData(Bezier(old_x + x, old_y + y, old_x + Real(2)*(inst_cx-old_x)/Real(3) + x, old_y + Real(2)*(inst_cy-old_y)/Real(3) + y, + current_x + Real(2)*(inst_cx-current_x)/Real(3) + x, current_y + Real(2)*(inst_cy-current_y)/Real(3) + y, current_x + x, current_y + y)); + Add(BEZIER,Rect(0,0,1,1),bezier_index); + break; + } + } + + stbtt_FreeShape(font, instructions); +}