Merge branch 'master' of git.ucc.asn.au:ipdf/code
authorDavid Gow <[email protected]>
Wed, 24 Sep 2014 13:05:49 +0000 (21:05 +0800)
committerDavid Gow <[email protected]>
Wed, 24 Sep 2014 13:05:49 +0000 (21:05 +0800)
1  2 
src/bezier.h
src/document.cpp
src/document.h
src/view.cpp

diff --combined src/bezier.h
@@@ -15,7 -15,7 +15,7 @@@ namespace IPD
        
        extern std::vector<Real> SolveQuadratic(const Real & a, const Real & b, const Real & c, const Real & min = 0, const Real & max = 1);
  
 -      extern std::vector<Real> SolveCubic(const Real & a, const Real & b, const Real & c, const Real & d, const Real & min = 0, const Real & max = 1, const Real & delta = 1e-4);
 +      extern std::vector<Real> SolveCubic(const Real & a, const Real & b, const Real & c, const Real & d, const Real & min = 0, const Real & max = 1, const Real & delta = 1e-9);
  
        /** A _cubic_ bezier. **/
        struct Bezier
@@@ -28,8 -28,8 +28,8 @@@
                typedef enum {UNKNOWN, LINE, QUADRATIC, CUSP, LOOP, SERPENTINE} Type;
                Type type;
                
-               Bezier() = default; // Needed so we can fread/fwrite this struct... for now.
-               Bezier(Real _x0, Real _y0, Real _x1, Real _y1, Real _x2, Real _y2, Real _x3, Real _y3) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x3), y3(_y3), type(UNKNOWN)
+               //Bezier() = default; // Needed so we can fread/fwrite this struct... for now.
+               Bezier(Real _x0=0, Real _y0=0, Real _x1=0, Real _y1=0, Real _x2=0, Real _y2=0, Real _x3=0, Real _y3=0) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x3), y3(_y3), type(UNKNOWN)
                {
  
                }
                                return type;
                        // From Loop-Blinn 2005, with w0 == w1 == w2 == w3 = 1
                        // Transformed control points: (a0 = x0, b0 = y0)
-                       Real a1 = (x1-x0)*3;
-                       Real a2 = (x0- x1*2 +x2)*3;
-                       Real a3 = (x3 - x0 + (x1 - x2)*3);
+                       Real a1 = (x1-x0)*Real(3);
+                       Real a2 = (x0- x1*Real(2) +x2)*Real(3);
+                       Real a3 = (x3 - x0 + (x1 - x2)*Real(3));
                        
-                       Real b1 = (y1-y0)*3;
-                       Real b2 = (y0- y1*2 +y2)*3;
-                       Real b3 = (y3 - y0 + (y1 - y2)*3);
+                       Real b1 = (y1-y0)*Real(3);
+                       Real b2 = (y0- y1*Real(2) +y2)*Real(3);
+                       Real b3 = (y3 - y0 + (y1 - y2)*Real(3));
                        
                        // d vector (d0 = 0 since all w = 1)
                        Real d1 = a2*b3 - a3*b2;
                        Real d2 = a3*b1 - a1*b3;
                        Real d3 = a1*b2 - a2*b1;
                        
-                       if (Abs(d1+d2+d3) < 1e-6)
+                       if (Abs(d1+d2+d3) < Real(1e-6))
                        {
                                type = LINE;
                                //Debug("LINE %s", Str().c_str());
@@@ -63,7 -63,7 +63,7 @@@
                        Real delta1 = -(d1*d1);
                        Real delta2 = d1*d2;
                        Real delta3 = d1*d3 -(d2*d2);
-                       if (Abs(delta1+delta2+delta3) < 1e-6)
+                       if (Abs(delta1+delta2+delta3) < Real(1e-6))
                        {
                                type = QUADRATIC;
                                
                                return type;
                        }
                        
-                       Real discriminant = d1*d3*4 -d2*d2;
-                       if (Abs(discriminant) < 1e-6)
+                       Real discriminant = d1*d3*Real(4) -d2*d2;
+                       if (Abs(discriminant) < Real(1e-6))
                        {
                                type = CUSP;
                                //Debug("CUSP %s", Str().c_str());
                        }
-                       else if (discriminant > 0)
+                       else if (discriminant > Real(0))
                        {
                                type = SERPENTINE;
                                //Debug("SERPENTINE %s", Str().c_str());
                        // (So can't just use the Copy constructor on the inverse of bounds)
                        // Rect inverse = {-bounds.x/bounds.w, -bounds.y/bounds.h, Real(1)/bounds.w, Real(1)/bounds.h};
                        Bezier result;
-                       if (bounds.w == 0)
+                       if (bounds.w == Real(0))
                        {
                                result.x0 = 0;
                                result.x1 = 0;
                                result.x3 = (x3 - bounds.x)/bounds.w;
                        }
  
-                       if (bounds.h == 0)
+                       if (bounds.h == Real(0))
                        {
                                result.y0 = 0;
                                result.y1 = 0;
  
                        // Find its roots.
                        std::vector<Real> x_intersection = SolveXParam(r.x);
 +                      Debug("Found %d intersections on left edge", x_intersection.size());
  
                        // And for the other side.
  
                        std::vector<Real> x_intersection_pt2 = SolveXParam(r.x + r.w);
                        x_intersection.insert(x_intersection.end(), x_intersection_pt2.begin(), x_intersection_pt2.end());
 +                      Debug("Found %d intersections on right edge (total x: %d)", x_intersection_pt2.size(), x_intersection.size());
  
                        // Find its roots.
                        std::vector<Real> y_intersection = SolveYParam(r.y);
 +                      Debug("Found %d intersections on top edge", y_intersection.size());
  
                        std::vector<Real> y_intersection_pt2 = SolveYParam(r.y+r.h);
                        y_intersection.insert(y_intersection.end(), y_intersection_pt2.begin(), y_intersection_pt2.end());
 +                      Debug("Found %d intersections on bottom edge (total y: %d)", y_intersection_pt2.size(), y_intersection.size());
  
                        // Merge and sort.
                        x_intersection.insert(x_intersection.end(), y_intersection.begin(), y_intersection.end());
                        {
                                Real t1 = *it;
                                if (t1 == t0) continue;
-                               Debug(" -- t0: %f to t1: %f: %f", Double(t0), Double(t1), (t1 + t0)/Real(2));
+                               Debug(" -- t0: %f to t1: %f: %f", Double(t0), Double(t1), Double((t1 + t0)/Real(2)));
                                Real ptx, pty;
                                Evaluate(ptx, pty, ((t1 + t0) / Real(2)));
                                if (r.PointIn(ptx, pty))
diff --combined src/document.cpp
@@@ -94,8 -94,9 +94,8 @@@ void Document::Save(const string & file
  
  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.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QTC_UNKNOWN, 0, ObjectCount(), -1});
        m_quadtree.root_id = 0;
 -      GenQuadChild(0, QTC_TOP_LEFT);
  }
  
  int Document::ClipObjectToQuadChild(int object_id, 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});
 +      Debug("-------------- Generating Quadtree Node %d (parent %d) ----------------------", new_index, parent);
 +      m_quadtree.nodes.push_back(QuadTreeNode{QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, QUADTREE_EMPTY, parent, type, 0, 0, -1});
  
        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)
  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.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();
        for (unsigned i = m_quadtree.nodes[child].object_begin; i < m_quadtree.nodes[child].object_end; ++i)
@@@ -316,7 -316,7 +316,7 @@@ unsigned Document::AddBezier(const Bezi
        Bezier data = bezier.ToRelative(bounds); // Relative
        if (data.ToAbsolute(bounds) != bezier)
        {
-               Warn("%s != %s", data.ToAbsolute(Rect(0,0,1,1)).Str().c_str(),
+               Warn("%s != %s", data.ToAbsolute(bounds).Str().c_str(),
                        bezier.Str().c_str());
                Warn("ToAbsolute on ToRelative does not give original Bezier");
        }
        return Add(BEZIER, bounds, index);
  }
  
 -unsigned Document::Add(ObjectType type, const Rect & bounds, unsigned data_index)
 +unsigned Document::Add(ObjectType type, const Rect & bounds, unsigned data_index, QuadTreeIndex qti)
  {
        m_objects.types.push_back(type);
        m_objects.bounds.push_back(bounds);
        m_objects.data_indices.push_back(data_index);
 +#ifndef QUADTREE_DISABLED
 +      if (qti != -1)
 +      {
 +              if (m_count == m_quadtree.nodes[qti].object_end+1)
 +              {
 +                      m_quadtree.nodes[qti].object_end++;
 +              }
 +              else
 +              {
 +                      QuadTreeIndex overlay = m_quadtree.nodes.size();
 +                      m_quadtree.nodes.push_back(m_quadtree.nodes[qti]);
 +                      m_quadtree.nodes[overlay].object_begin = m_count;
 +                      m_quadtree.nodes[overlay].object_end = m_count+1;
 +                      m_quadtree.nodes[qti].next_overlay = overlay;
 +              }
 +      }
 +#endif
        return (m_count++); // Why can't we just use the size of types or something?
  }
  
@@@ -409,12 -392,12 +409,12 @@@ static void GetXYPair(const string & d
  {
        string token("");
        while (GetToken(d, token, i, delims) == ",");
-       x = strtod(token.c_str(),NULL);
+       x = RealFromStr(token);
        if (GetToken(d, token, i, delims) != ",")
        {
                Fatal("Expected \",\" seperating x,y pair");
        }
-       y = strtod(GetToken(d, token, i, delims).c_str(),NULL);
+       y = RealFromStr(GetToken(d,token,i,delims));
  }
  
  static bool GetKeyValuePair(const string & d, string & key, string & value, unsigned & i, const string & delims = "()[],{}<>;:=")
@@@ -477,11 -460,11 +477,11 @@@ void Document::ParseSVGTransform(const 
                }
                else if (command == "scale")
                {
-                       delta.a = (strtod(GetToken(s,token,i).c_str(), NULL));
+                       delta.a = RealFromStr(GetToken(s,token,i));
                        GetToken(s, token, i);
                        if (token == ",")
                        {
-                               delta.d = (strtod(GetToken(s,token,i).c_str(), NULL));
+                               delta.d = RealFromStr(GetToken(s,token,i));
                                assert(GetToken(s, token, i) == ")");
                        }
                        else
@@@ -527,7 -510,7 +527,7 @@@ inline Colour ParseColourString(const s
                c = {255,255,255,255};
        else if (colour_str.size() == 7 && colour_str[0] == '#')
        {
-               Debug("Parse colour string: \"%s\"", colour_str.c_str());
+               //Debug("Parse colour string: \"%s\"", colour_str.c_str());
                char comp[3] = {colour_str[1], colour_str[2], '\0'};
                c.r = strtoul(comp, NULL, 16);
                comp[0] = colour_str[3]; comp[1] = colour_str[4];
                comp[0] = colour_str[5]; comp[1] = colour_str[6];
                c.b = strtoul(comp, NULL, 16);
                c.a = 255;
-               Debug("Colour is: %u, %u, %u, %u", c.r, c.g, c.b, c.a);
+               //Debug("Colour is: %u, %u, %u, %u", c.r, c.g, c.b, c.a);
        }
        return c;
  }
@@@ -544,7 -527,16 +544,16 @@@ void Document::ParseSVGNode(pugi::xml_n
  {
        //Debug("Parse node <%s>", root.name());
  
-               
+       
+       // Centre the SVGs
+       if (strcmp(root.name(),"svg") == 0)
+       {
+               Real ww = RealFromStr(root.attribute("width").as_string());
+               Real hh = RealFromStr(root.attribute("height").as_string());
+               parent_transform.e -= parent_transform.a * ww/Real(2);
+               parent_transform.f -= parent_transform.d * hh/Real(2);
+       }
+       
        for (pugi::xml_node child = root.first_child(); child; child = child.next_sibling())
        {
                SVGMatrix transform(parent_transform);  
                        //Debug("Path data attribute is \"%s\"", d.c_str());
                        bool closed = false;
                        pair<unsigned, unsigned> range = ParseSVGPathData(d, transform, closed);
-                       if (true)//(closed)
+                       if (true && range.first < m_count && range.second < m_count)//(closed)
                        {
                                
                                string colour_str("");
@@@ -726,7 -718,7 +735,7 @@@ void Document::LoadSVG(const string & f
        
        input.close();
                                                // a c e, b d f
-       SVGMatrix transform = {bounds.w, 0,bounds.x, 0,bounds.h,bounds.y};
+       SVGMatrix transform = {bounds.w,,bounds.x, 0,bounds.h,bounds.y};
        ParseSVGNode(doc_xml, transform);
  }
  
@@@ -772,9 -764,9 +781,9 @@@ pair<unsigned, unsigned> Document::Pars
                if (command == "m" || command == "M")
                {
                        //Debug("Construct moveto command");
-                       Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       Real dx = RealFromStr(GetToken(d,token,i,delims));
                        assert(GetToken(d,token,i,delims) == ",");
-                       Real dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       Real dy = RealFromStr(GetToken(d,token,i,delims));
                        
                        x[0] = (relative) ? x[0] + dx : dx;
                        y[0] = (relative) ? y[0] + dy : dy;
                else if (command == "c" || command == "C" || command == "q" || command == "Q")
                {
                        //Debug("Construct curveto command");
-                       Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       Real dx = RealFromStr(GetToken(d,token,i,delims));
                        assert(GetToken(d,token,i,delims) == ",");
-                       Real dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       Real dy = RealFromStr(GetToken(d,token,i,delims));
                        
                        x[1] = (relative) ? x[0] + dx : dx;
                        y[1] = (relative) ? y[0] + dy : dy;
                        
-                       dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       dx = RealFromStr(GetToken(d,token,i,delims));
                        assert(GetToken(d,token,i,delims) == ",");
-                       dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                       dy = RealFromStr(GetToken(d,token,i,delims));
                        
                        x[2] = (relative) ? x[0] + dx : dx;
                        y[2] = (relative) ? y[0] + dy : dy;
                        
                        if (command != "q" && command != "Q")
                        {
-                               dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                               dx = RealFromStr(GetToken(d,token,i,delims));
                                assert(GetToken(d,token,i,delims) == ",");
-                               dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                               dy = RealFromStr(GetToken(d,token,i,delims));
                                x[3] = (relative) ? x[0] + dx : dx;
                                y[3] = (relative) ? y[0] + dy : dy;
                        }
                {
                        //Debug("Construct lineto command, relative %d", relative);
                
-                       Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
-                       Real dy;
+                       Real dx = RealFromStr(GetToken(d,token,i,delims));
+                       Real dy = 0;
                        if (command == "l" || command == "L")
                        {
                                assert(GetToken(d,token,i,delims) == ",");
-                               dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+                               dy = RealFromStr(GetToken(d,token,i,delims));
                        }
                        else if (command == "v" || command == "V")
                        {
@@@ -1032,3 -1024,42 +1041,42 @@@ void Document::AddFontGlyphAtPoint(stbt
  
        stbtt_FreeShape(font, instructions);
  }
+ void Document::TransformObjectBounds(const SVGMatrix & transform)
+ {
+       for (unsigned i = 0; i < m_count; ++i)
+       {
+               TransformXYPair(m_objects.bounds[i].x, m_objects.bounds[i].y, transform);
+               m_objects.bounds[i].w *= transform.a;
+               m_objects.bounds[i].h *= transform.d;
+       }
+ }
+ void Document::TranslateObjects(const Real & dx, const Real & dy)
+ {
+       for (unsigned i = 0; i < m_count; ++i)
+       {
+               m_objects.bounds[i].x += dx;
+               m_objects.bounds[i].y += dy;
+       }
+ }
+ void Document::ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real & scale_amount)
+ {
+       for (unsigned i = 0; i < m_count; ++i)
+       {
+               m_objects.bounds[i].w /= scale_amount;
+               m_objects.bounds[i].h /= scale_amount;
+               //m_objects.bounds[i].x = x + (m_objects.bounds[i].x-x)/scale_amount;
+               //m_objects.bounds[i].y = y + (m_objects.bounds[i].y-x)/scale_amount;
+               m_objects.bounds[i].x -= x;
+               m_objects.bounds[i].x /= scale_amount;
+               m_objects.bounds[i].x += x;
+               
+               m_objects.bounds[i].y -= y;
+               m_objects.bounds[i].y /= scale_amount;
+               m_objects.bounds[i].y += y;
+       }       
+       
+ }
diff --combined src/document.h
@@@ -54,7 -54,7 +54,7 @@@ namespace IPD
  
                        unsigned AddPath(unsigned start_index, unsigned end_index, const Colour & shading=Colour(0.6,0.6,0.6,1), const Colour & stroke=Colour(0,0,0,0));
                        unsigned AddBezier(const Bezier & bezier);
 -                      unsigned Add(ObjectType type, const Rect & bounds, unsigned data_index = 0);
 +                      unsigned Add(ObjectType type, const Rect & bounds, unsigned data_index = 0, QuadTreeIndex qtnode = 0);
                        unsigned AddBezierData(const Bezier & bezier);
                        unsigned AddPathData(const Path & path);
  
                        void AddText(const std::string & text, Real scale, Real x, Real y);
                        
                        void AddFontGlyphAtPoint(stbtt_fontinfo *font, int character, Real scale, Real x, Real y);
+                       
+                       void TransformObjectBounds(const SVGMatrix & transform);
+                       void TranslateObjects(const Real & x, const Real & y);
+                       void ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real & scale_amount);
+                       
  #ifndef QUADTREE_DISABLED
                        inline const QuadTree& GetQuadTree() { if (m_quadtree.root_id == QUADTREE_EMPTY) { GenBaseQuadtree(); } return m_quadtree; }
                        QuadTreeIndex GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren type);
diff --combined src/view.cpp
@@@ -22,19 -22,29 +22,29 @@@ View::View(Document & document, Screen 
                m_render_dirty(true), m_document(document), m_screen(screen), m_cached_display(), m_bounds(bounds), m_colour(colour), m_bounds_ubo(), 
                m_objbounds_vbo(), m_object_renderers(NUMBER_OF_OBJECT_TYPES), m_cpu_rendering_pixels(NULL),
                m_perform_shading(USE_SHADING), m_show_bezier_bounds(false), m_show_bezier_type(false),
-               m_show_fill_points(false), m_show_fill_bounds(false)
+               m_show_fill_points(false), m_show_fill_bounds(false), m_lazy_rendering(true)
  {
        Debug("View Created - Bounds => {%s}", m_bounds.Str().c_str());
  
        screen.SetView(this); // oh dear...
  
+       
        // Create ObjectRenderers - new's match delete's in View::~View
        //TODO: Don't forget to put new renderers here or things will be segfaultastic
-       m_object_renderers[RECT_FILLED] = new RectFilledRenderer();
-       m_object_renderers[RECT_OUTLINE] = new RectOutlineRenderer();
-       m_object_renderers[CIRCLE_FILLED] = new CircleFilledRenderer();
-       m_object_renderers[BEZIER] = new BezierRenderer();
-       m_object_renderers[PATH] = new PathRenderer();
+       if (screen.Valid())
+       {
+               m_object_renderers[RECT_FILLED] = new RectFilledRenderer();
+               m_object_renderers[RECT_OUTLINE] = new RectOutlineRenderer();
+               m_object_renderers[CIRCLE_FILLED] = new CircleFilledRenderer();
+               m_object_renderers[BEZIER] = new BezierRenderer();
+               m_object_renderers[PATH] = new PathRenderer();
+       }
+       else
+       {
+               for (int i = RECT_FILLED; i <= PATH; ++i)
+                       m_object_renderers[i] = new FakeRenderer();
+       }
  
        // To add rendering for a new type of object;
        // 1. Add enum to ObjectType in ipdf.h
@@@ -69,14 -79,19 +79,19 @@@ View::~View(
   */
  void View::Translate(Real x, Real y)
  {
+       if (!m_use_gpu_transform)
+               m_buffer_dirty = true;
+       m_bounds_dirty = true;
+       #ifdef TRANSFORM_OBJECTS_NOT_VIEW
+       m_document.TranslateObjects(-x, -y);
+       #endif
        x *= m_bounds.w;
        y *= m_bounds.h;
        m_bounds.x += x;
        m_bounds.y += y;
        //Debug("View Bounds => %s", m_bounds.Str().c_str());
-       if (!m_use_gpu_transform)
-               m_buffer_dirty = true;
-       m_bounds_dirty = true;
+       
  }
  
  /**
@@@ -101,8 -116,18 +116,18 @@@ void View::SetBounds(const Rect & bound
   */
  void View::ScaleAroundPoint(Real x, Real y, Real scale_amount)
  {
+       
+       // (x0, y0, w, h) -> (x*w - (x*w - x0)*s, y*h - (y*h - y0)*s, w*s, h*s)
        // x and y are coordinates in the window
        // Convert to local coords.
+       if (!m_use_gpu_transform)
+               m_buffer_dirty = true;
+       m_bounds_dirty = true;
+       
+       
+       #ifdef TRANSFORM_OBJECTS_NOT_VIEW
+       m_document.ScaleObjectsAboutPoint(x, y, scale_amount);
+       #endif
        x *= m_bounds.w;
        y *= m_bounds.h;
        x += m_bounds.x;
        m_bounds.w *= scale_amount;
        m_bounds.h *= scale_amount;
        //Debug("Scale at {%s, %s} by %s View Bounds => %s", x.Str().c_str(), y.Str().c_str(), scale_amount.Str().c_str(), m_bounds.Str().c_str());
-       if (!m_use_gpu_transform)
-               m_buffer_dirty = true;
-       m_bounds_dirty = true;
+       
+       
  }
  
  /**
   */
  Rect View::TransformToViewCoords(const Rect& inp) const
  {
+       #ifdef TRANSFORM_OBJECTS_NOT_VIEW
+               return inp;
+       #endif
        Rect out;
        out.x = (inp.x - m_bounds.x) / m_bounds.w;
        out.y = (inp.y - m_bounds.y) / m_bounds.h;
   */
  void View::Render(int width, int height)
  {
+       if (!m_screen.Valid()) return;
        glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION,42,-1, "Beginning View::Render()");
        // View dimensions have changed (ie: Window was resized)
        int prev_width = m_cached_display.GetWidth();
        }
  
        // View bounds have not changed; blit the FrameBuffer as it is
-       if (!m_bounds_dirty)
+       if (!m_bounds_dirty && m_lazy_rendering)
        {
                m_cached_display.UnBind();
                m_cached_display.Blit();
        m_cached_display.Clear();
  
  #ifndef QUADTREE_DISABLED
-       if (m_bounds_dirty)
+       if (m_bounds_dirty || !m_lazy_rendering)
        {
 -              if ( false &&  (m_bounds.x > 1.0 || m_bounds.x < 0.0 || m_bounds.y > 1.0 || m_bounds.y < 0.0 || m_bounds.w > 1.0 || m_bounds.h > 1.0))
 +              if ( (m_bounds.x > 1.0 || m_bounds.x < 0.0 || m_bounds.y > 1.0 || m_bounds.y < 0.0 || m_bounds.w > 1.0 || m_bounds.h > 1.0))
                {
                        //TODO: Generate a new parent node.
                        if (m_document.GetQuadTree().nodes[m_current_quadtree_node].parent != QUADTREE_EMPTY)
                        m_current_quadtree_node = m_document.GetQuadTree().nodes[m_current_quadtree_node].bottom_right;
                }
        }
 -      m_screen.DebugFontPrintF("Current View QuadTree Node: %d (objs: %d -> %d)\n", m_current_quadtree_node, m_document.GetQuadTree().nodes[m_current_quadtree_node].object_begin,
 -                              m_document.GetQuadTree().nodes[m_current_quadtree_node].object_end);
 +
 +      m_screen.DebugFontPrintF("Current View QuadTree");
 +      QuadTreeIndex overlay = m_current_quadtree_node;
 +      while (overlay != -1)
 +      {
 +              m_screen.DebugFontPrintF(" Node: %d (objs: %d -> %d)", overlay, m_document.GetQuadTree().nodes[overlay].object_begin,
 +                                      m_document.GetQuadTree().nodes[overlay].object_end);
 +              overlay = m_document.GetQuadTree().nodes[overlay].next_overlay;
 +      }
 +      m_screen.DebugFontPrintF("\n");
  
        Rect view_top_bounds = m_bounds;
        QuadTreeIndex tmp = m_current_quadtree_node;
@@@ -293,12 -313,7 +321,12 @@@ void View::RenderQuadtreeNode(int width
        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;
 -      RenderRange(width, height, m_document.GetQuadTree().nodes[node].object_begin, m_document.GetQuadTree().nodes[node].object_end);
 +      QuadTreeIndex overlay = node;
 +      while(overlay != -1)
 +      {
 +              RenderRange(width, height, m_document.GetQuadTree().nodes[overlay].object_begin, m_document.GetQuadTree().nodes[overlay].object_end);
 +              overlay = m_document.GetQuadTree().nodes[overlay].next_overlay;
 +      }
  
        if (m_bounds.Intersects(Rect(-1,-1,1,1)))
        {
@@@ -376,13 -391,21 +404,21 @@@ void View::RenderRange(int width, int h
        if (m_render_dirty) // document has changed
                PrepareRender();
  
-       if (m_buffer_dirty || m_bounds_dirty) // object bounds have changed
-               UpdateObjBoundsVBO(first_obj, last_obj);
+       if (m_buffer_dirty || m_bounds_dirty || !m_lazy_rendering) // object bounds have changed
+       {
+               if (m_use_gpu_rendering)
+                       UpdateObjBoundsVBO(first_obj, last_obj);
+       }
  
        if (m_use_gpu_transform)
        {
+               #ifdef TRANSFORM_OBJECTS_NOT_VIEW
+                               GLfloat glbounds[] = {0.0f, 0.0f, 1.0f, 1.0f,
+                                       0.0f, 0.0f, float(width), float(height)};
+               #else
                GLfloat glbounds[] = {static_cast<GLfloat>(Float(m_bounds.x)), static_cast<GLfloat>(Float(m_bounds.y)), static_cast<GLfloat>(Float(m_bounds.w)), static_cast<GLfloat>(Float(m_bounds.h)),
                                        0.0, 0.0, static_cast<GLfloat>(width), static_cast<GLfloat>(height)};
+               #endif
                m_bounds_ubo.Upload(sizeof(float)*8, glbounds);
        }
        else
@@@ -477,10 -500,13 +513,13 @@@ void View::PrepareRender(
  {
        Debug("Recreate buffers with %u objects", m_document.ObjectCount());
        // Prepare bounds vbo
-       m_bounds_ubo.Invalidate();
-       m_bounds_ubo.SetType(GraphicsBuffer::BufferTypeUniform);
-       m_bounds_ubo.SetUsage(GraphicsBuffer::BufferUsageStreamDraw);
-       m_bounds_ubo.SetName("m_bounds_ubo: Screen bounds.");
+       if (UsingGPURendering())
+       {
+               m_bounds_ubo.Invalidate();
+               m_bounds_ubo.SetType(GraphicsBuffer::BufferTypeUniform);
+               m_bounds_ubo.SetUsage(GraphicsBuffer::BufferUsageStreamDraw);
+               m_bounds_ubo.SetName("m_bounds_ubo: Screen bounds.");
+       }
        
        // Instead of having each ObjectRenderer go through the whole document
        //  we initialise them, go through the document once adding to the appropriate Renderers
                //Debug("Object of type %d", type);
        }
  
        // Finish the buffers
        for (unsigned i = 0; i < m_object_renderers.size(); ++i)
        {
                m_object_renderers[i]->FinaliseBuffers();
        }
-       dynamic_cast<BezierRenderer*>(m_object_renderers[BEZIER])->PrepareBezierGPUBuffer(m_document.m_objects);
+       if (UsingGPURendering())
+               dynamic_cast<BezierRenderer*>(m_object_renderers[BEZIER])->PrepareBezierGPUBuffer(m_document.m_objects);
        m_render_dirty = false;
  }
+ void View::SaveCPUBMP(const char * filename)
+ {
+       bool prev = UsingGPURendering();
+       SetGPURendering(false);
+       Render(800, 600);
+       ObjectRenderer::SaveBMP({m_cpu_rendering_pixels, 800, 600}, filename);
+       SetGPURendering(prev);
+ }
+ void View::SaveGPUBMP(const char * filename)
+ {
+       bool prev = UsingGPURendering();
+       SetGPURendering(true);
+       Render(800,600);
+       m_screen.ScreenShot(filename);
+       SetGPURendering(prev);  
+ }

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