Support some more SVG stuff.
[ipdf/code.git] / src / document.cpp
index 9d9011e..dab0868 100644 (file)
@@ -99,6 +99,46 @@ void Document::GenBaseQuadtree()
        GenQuadChild(0, QTC_TOP_LEFT);
 }
 
+int Document::ClipObjectToQuadChild(int object_id, QuadTreeNodeChildren type)
+{
+       switch (m_objects.types[object_id])
+       {
+       case RECT_FILLED:
+       case RECT_OUTLINE:
+               {
+               Rect obj_bounds = TransformToQuadChild(m_objects.bounds[object_id], type);
+               if (obj_bounds.x < 0)
+               {
+                       obj_bounds.w += obj_bounds.x;
+                       obj_bounds.x = 0;
+               }
+               if (obj_bounds.y < 0)
+               {
+                       obj_bounds.h += obj_bounds.y;
+                       obj_bounds.y = 0;
+               }
+               if (obj_bounds.x + obj_bounds.w > 1)
+               {
+                       obj_bounds.w += (1 - (obj_bounds.x + obj_bounds.w));
+               }
+               if (obj_bounds.y + obj_bounds.h > 1)
+               {
+                       obj_bounds.h += (1 - (obj_bounds.y + obj_bounds.h));
+               }
+               m_objects.bounds.push_back(obj_bounds);
+               m_objects.types.push_back(m_objects.types[object_id]);
+               m_objects.data_indices.push_back(m_objects.data_indices[object_id]);
+               return 1;
+               }
+       default:
+               Debug("Adding %s -> %s", m_objects.bounds[object_id].Str().c_str(), TransformToQuadChild(m_objects.bounds[object_id], type).Str().c_str());
+               m_objects.bounds.push_back(TransformToQuadChild(m_objects.bounds[object_id], type));
+               m_objects.types.push_back(m_objects.types[object_id]);
+               m_objects.data_indices.push_back(m_objects.data_indices[object_id]);
+               return 1;
+       }
+       return 0;
+}
 QuadTreeIndex Document::GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren type)
 {
        QuadTreeIndex new_index = m_quadtree.nodes.size();
@@ -107,12 +147,9 @@ QuadTreeIndex Document::GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren
        m_quadtree.nodes[new_index].object_begin = m_objects.bounds.size();
        for (unsigned i = m_quadtree.nodes[parent].object_begin; i < m_quadtree.nodes[parent].object_end; ++i)
        {
-               if (ContainedInQuadChild(m_objects.bounds[i], type))
+               if (IntersectsQuadChild(m_objects.bounds[i], type))
                {
-                       m_objects.bounds.push_back(TransformToQuadChild(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_count += ClipObjectToQuadChild(i, type);
                }
        }
        m_quadtree.nodes[new_index].object_end = m_objects.bounds.size();
@@ -503,9 +540,9 @@ void Document::ParseSVGPathData(const string & d, const SVGMatrix & transform)
        
        bool start = false;
        
-       static string delims("()[],{}<>;:=LlmMqQzZcC");
+       static string delims("()[],{}<>;:=LlHhVvmMqQzZcC");
        
-       while (i < d.size() && GetToken(d, token, i).size() > 0)
+       while (i < d.size() && GetToken(d, token, i, delims).size() > 0)
        {
                if (isalpha(token[0]))
                        command = token;
@@ -583,16 +620,32 @@ void Document::ParseSVGPathData(const string & d, const SVGMatrix & transform)
 
                        
                }
-               else if (command == "l" || command == "L")
+               else if (command == "l" || command == "L" || command == "h" || command == "H" || command == "v" || command == "V")
                {
                        Debug("Construct lineto command, relative %d", relative);
                
                        Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
-                       assert(GetToken(d,token,i,delims) == ",");
-                       Real dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       Real dy;
+                       if (command == "l" || command == "L")
+                       {
+                               assert(GetToken(d,token,i,delims) == ",");
+                               dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       }
+                       else if (command == "v" || command == "V")
+                       {
+                               swap(dx,dy);
+                       }
                        
                        x[1] = (relative) ? x[0] + dx : dx;
                        y[1] = (relative) ? y[0] + dy : dy;
+                       if (command == "v" || command == "V")
+                       {
+                               x[1] = x[0];
+                       }
+                       else if (command == "h" || command == "H")
+                       {
+                               y[1] = y[0];
+                       }
                        
                        Real x1(x[1]);
                        Real y1(y[1]);
@@ -682,18 +735,28 @@ void Document::AddText(const string & text, Real scale, Real x, Real y)
        float font_scale = stbtt_ScaleForPixelHeight(&m_font, scale);
        Real x0(x);
        //Real y0(y);
+       int ascent = 0, descent = 0, line_gap = 0;
+       stbtt_GetFontVMetrics(&m_font, &ascent, &descent, &line_gap);
+       Real y_advance = Real(font_scale) * Real(ascent - descent + line_gap);
        for (unsigned i = 0; i < text.size(); ++i)
        {
                if (text[i] == '\n')
                {
-                       y += 0.5*scale;
+                       y += y_advance;
                        x = x0;
                }
                if (!isprint(text[i]))
                        continue;
                        
+               int advance_width = 0, left_side_bearing = 0, kerning = 0;
+               stbtt_GetCodepointHMetrics(&m_font, text[i], &advance_width, &left_side_bearing);
+               if (i > 1)
+               {
+                       kerning = stbtt_GetCodepointKernAdvance(&m_font, text[i-1], text[i]);
+               }
+               x += Real(font_scale) * Real(left_side_bearing + kerning);
                AddFontGlyphAtPoint(&m_font, text[i], font_scale, x, y);
-               x += 0.5*scale;
+               x += Real(font_scale) * Real(advance_width);
        }
 }
 

UCC git Repository :: git.ucc.asn.au