Define for Transformations on Path only, also fixed segfault due to GraphicsBuffer
authorSam Moore <matches@ucc.asn.au>
Sat, 27 Sep 2014 14:10:06 +0000 (22:10 +0800)
committerSam Moore <matches@ucc.asn.au>
Sat, 27 Sep 2014 14:10:06 +0000 (22:10 +0800)
The "invalidated" is used to recycle memory in the GraphicsBuffer,
but that can only be done if there is actually enough memory.

This was causing a segfault if the document was initially empty and had things added to it.
Can now remove the hack in main.cpp where documents started with a {0,0,0,0} RECT in them.

We can now (ab)use the Path for transformations.
The idea was that Arbitrary precision stuff might be faster if we only care about the bounds of the paths.

Unfortunately the way Real was used everywhere will make it a bit difficult to actually use this.
We need Beziers and their bounds to be stored with floats, but the Path bounds to be stored with GMPrat or some other arbitrary type.

It probably won't help that much, but evaluating those Beziers with GMPrat really slows down the CPU renderer.
It's also a giant hack because I still use BezierRenderer for GPU rendering but I now use PathRenderer for CPU rendering of Beziers.

Le sigh.

We can now store Bezier bounds relative to Path bounds and apply transformations only to the Path bounds.

20 files changed:
src/bezier.cpp
src/bezier.h
src/document.cpp
src/document.h
src/eye_of_the_rabbit.script
src/graphicsbuffer.cpp
src/main.cpp
src/main.h
src/objectrenderer.cpp
src/objectrenderer.h
src/paranoidnumber.cpp
src/paranoidnumber.h
src/path.cpp
src/path.h
src/rect.h
src/svg-tests/paths.svg
src/tests/muldiv.cpp
src/tests/realops.cpp
src/view.cpp
src/view.h

index cb92697..3c682a6 100644 (file)
@@ -54,11 +54,13 @@ static void CubicSolveSegment(vector<Real> & roots, const Real & a, const Real &
        Real l = a*tl*tl*tl + b*tl*tl + c*tl + d;
        Real u = a*tu*tu*tu + b*tu*tu + c*tu + d;
        if ((l < 0 && u < 0) || (l > 0 && u > 0))
-               Debug("Discarding segment (no roots) l = %f (%f), u = %f (%f)", Double(tl), Double(l), Double(tu), Double(u));
+       {
+               //Debug("Discarding segment (no roots) l = %f (%f), u = %f (%f)", Double(tl), Double(l), Double(tu), Double(u));
                //return;
+       }
        
        bool negative = (u < l); // lower point > 0, upper point < 0
-       Debug("%ft^3 + %ft^2 + %ft + %f is negative (%f < %f) %d", Double(a),Double(b),Double(c),Double(d),Double(u),Double(l), negative);
+       //Debug("%ft^3 + %ft^2 + %ft + %f is negative (%f < %f) %d", Double(a),Double(b),Double(c),Double(d),Double(u),Double(l), negative);
        while (tu - tl > delta)
        {
                Real t(tu+tl);
@@ -89,7 +91,7 @@ vector<Real> SolveCubic(const Real & a, const Real & b, const Real & c, const Re
        Real tu(max);
        Real tl(min);
        vector<Real> turns(SolveQuadratic(a*3, b*2, c));
-       Debug("%u turning points", turns.size());
+       //Debug("%u turning points", turns.size());
        for (unsigned i = 1; i < turns.size(); ++i)
        {
                tu = turns[i];
index 01da922..cedf8d4 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "real.h"
 #include "rect.h"
+
+
 namespace IPDF
 {
        extern int Factorial(int n);
index 9b94ba2..4be3ee0 100644 (file)
@@ -303,6 +303,7 @@ unsigned Document::AddPath(unsigned start_index, unsigned end_index, const Colou
        unsigned data_index = AddPathData(path);
        Rect bounds = path.SolveBounds(m_objects);
        unsigned result = Add(PATH, bounds,data_index);
+       m_objects.paths[data_index].m_index = result;
        //Debug("Added path %u -> %u (%u objects) colour {%u,%u,%u,%u}, stroke {%u,%u,%u,%u}", start_index, end_index, (end_index - start_index), fill.r, fill.g, fill.b, fill.a, stroke.r, stroke.g, stroke.b, stroke.a);
        return result;
 }
@@ -1052,19 +1053,25 @@ void Document::TransformObjectBounds(const SVGMatrix & transform)
        }
 }
 
-void Document::TranslateObjects(const Real & dx, const Real & dy)
+void Document::TranslateObjects(const Real & dx, const Real & dy, ObjectType type)
 {
        for (unsigned i = 0; i < m_count; ++i)
        {
-               m_objects.bounds[i].x += dx;
-               m_objects.bounds[i].y += dy;
+               if (type == NUMBER_OF_OBJECT_TYPES || m_objects.types[i] == type)
+               {
+                       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)
+void Document::ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real & scale_amount, ObjectType type)
 {
        for (unsigned i = 0; i < m_count; ++i)
        {
+               if (type != NUMBER_OF_OBJECT_TYPES && m_objects.types[i] != type)
+                       continue;
+               
                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;
@@ -1076,7 +1083,7 @@ void Document::ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real
                m_objects.bounds[i].y -= y;
                m_objects.bounds[i].y /= scale_amount;
                m_objects.bounds[i].y += y;
-
-       }       
-       
+       }
 }
+
+
index 0b095c3..57dbb9d 100644 (file)
@@ -83,8 +83,8 @@ namespace IPDF
                        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);
+                       void TranslateObjects(const Real & x, const Real & y, ObjectType type = NUMBER_OF_OBJECT_TYPES);
+                       void ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real & scale_amount, ObjectType type = NUMBER_OF_OBJECT_TYPES);
                        
 #ifndef QUADTREE_DISABLED
                        inline const QuadTree& GetQuadTree() { if (m_quadtree.root_id == QUADTREE_EMPTY) { GenBaseQuadtree(); } return m_quadtree; }
index 85d63a0..c94bccd 100644 (file)
@@ -1,5 +1,5 @@
 # Test how well document scales back to original...
-gpu
+cpu
 lazy
 label start
 debug Add rabbit 1
@@ -11,7 +11,9 @@ loop 200 pxzoom 508 305 1
 debug Add rabbit 3
 loadsvg svg-tests/rabbit_simple.svg
 loop 400 pxzoom 508 305 -1
-loop 400 pxzoom 508 305 1
+loop 200 pxzoom 508 305 1
+loop 1000 wait
+loop 200 pxzoom 508 305 1
 debug Repeat
-goto start
+#goto start
 wait
index 217fa9a..8075453 100644 (file)
@@ -224,7 +224,7 @@ void GraphicsBuffer::Upload(size_t length, const void* data)
        if (!RecreateBuffer(data))
        {
                Bind();
-               glBufferData(target, length, data, usage);
+               glBufferData(target, length+1, data, usage);
        }
        if (data != NULL)
                m_invalidated = false;
@@ -243,7 +243,7 @@ void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* dat
 
 void GraphicsBuffer::Resize(size_t length)
 {
-       if (m_invalidated)
+       if (m_invalidated && m_buffer_size > length)
        {
                m_buffer_size = length;
        }
index e20a7bf..e556fe4 100644 (file)
@@ -184,10 +184,7 @@ int main(int argc, char ** argv)
        {
                doc.AddText(input_text, bounds.h/Real(2), bounds.x, bounds.y+bounds.h/Real(2));
        }
-       else
-       {
-               doc.Add(RECT_OUTLINE, Rect(0,0,0,0),0); // hack to stop segfault if document is empty (:S)
-       }
+
 
 
        #ifndef CONTROLPANEL_DISABLED
index 5b9d263..b0c7a47 100644 (file)
@@ -156,6 +156,12 @@ inline void MainLoop(Document & doc, Screen & scr, View & view, int max_frames =
                        scr.DebugFontPrint("Doing coordinate transform on the CPU.\n");
                }
                #endif
+               
+               #ifdef TRANSFORM_BEZIERS_TO_PATH
+                       scr.DebugFontPrint("Beziers have been transformed to Path\n");
+               #endif
+
+               
                if (view.UsingGPURendering())
                {
                        scr.DebugFontPrint("Doing rendering using GPU.\n");
index cbceb3a..6a216bc 100644 (file)
@@ -228,11 +228,12 @@ ObjectRenderer::PixelPoint ObjectRenderer::CPUPointLocation(const Vec2 & point,
 }
        
        
-void BezierRenderer::RenderBezierOnCPU(unsigned i, Objects & objects, const View & view, const CPURenderTarget & target, const Colour & c)
+void BezierRenderer::RenderBezierOnCPU(const Bezier & relative, const Rect & bounds, const View & view, const CPURenderTarget & target, const Colour & c)
 {
-       const Rect & bounds = objects.bounds[i];
+       //const Rect & bounds = objects.bounds[i];
        PixelBounds pix_bounds(CPURenderBounds(bounds,view,target));
-       Bezier control(objects.beziers[objects.data_indices[i]].ToAbsolute(bounds),CPURenderBounds(Rect(0,0,1,1), view, target));
+       //Bezier control(objects.beziers[objects.data_indices[i]].ToAbsolute(bounds),CPURenderBounds(Rect(0,0,1,1), view, target));
+       Bezier control(relative.ToAbsolute(bounds), Rect(0,0,target.w, target.h)); 
 
        if (view.ShowingBezierBounds())
        {
@@ -242,20 +243,21 @@ void BezierRenderer::RenderBezierOnCPU(unsigned i, Objects & objects, const View
                ObjectRenderer::RenderLineOnCPU(pix_bounds.x+pix_bounds.w, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, Colour(0,255,0,0));
        }
        
-       unsigned blen = target.w;//min(max(2U, (unsigned)Int64(Real(target.w)/view.GetBounds().w)), 
+       unsigned blen = pix_bounds.w;//min(max(2U, (unsigned)Int64(Real(target.w)/view.GetBounds().w)), 
                        //min((unsigned)(pix_bounds.w+pix_bounds.h)/4 + 1, 100U));
                
                // DeCasteljau Divide the Bezier
+       #ifdef BEZIER_CPU_DECASTELJAU
        queue<Bezier> divisions;
        divisions.push(control);
        while(divisions.size() < blen)
        {
                Bezier & current = divisions.front();
-               if (current.GetType() == Bezier::LINE)
-               {
-                       --blen;
-                       continue;
-               }
+               //if (current.GetType() == Bezier::LINE)
+               //{
+               //      --blen;
+               //      continue;
+               //}
                divisions.push(current.DeCasteljauSubdivideRight(Real(1)/Real(2)));     
                divisions.push(current.DeCasteljauSubdivideLeft(Real(1)/Real(2)));
                divisions.pop();
@@ -266,6 +268,21 @@ void BezierRenderer::RenderBezierOnCPU(unsigned i, Objects & objects, const View
                RenderLineOnCPU(Int64(current.x0), Int64(current.y0), Int64(current.x3), Int64(current.y3), target, c);
                divisions.pop();
        }               
+       #else
+               Real invblen(1); invblen /= Real(blen);
+               
+               Real t(invblen);
+               Vec2 v0;
+               Vec2 v1;
+               control.Evaluate(v0.x, v0.y, 0);
+               for (int64_t j = 1; j <= blen; ++j)
+               {
+                       control.Evaluate(v1.x, v1.y, t);
+                       RenderLineOnCPU(v0.x, v0.y, v1.x, v1.y, target);
+                       t += invblen;
+                       v0 = v1;
+               }
+       #endif //BEZIER_CPU_DECASTELJAU
 }
 
 /**
@@ -274,6 +291,9 @@ void BezierRenderer::RenderBezierOnCPU(unsigned i, Objects & objects, const View
  */
 void BezierRenderer::RenderUsingCPU(Objects & objects, const View & view, const CPURenderTarget & target, unsigned first_obj_id, unsigned last_obj_id)
 {
+       #ifdef TRANSFORM_BEZIERS_TO_PATH
+               return;
+       #endif
        if (view.PerformingShading())
                return;
                
@@ -308,7 +328,9 @@ void BezierRenderer::RenderUsingCPU(Objects & objects, const View & view, const
                                        break;
                        }
                }
-               RenderBezierOnCPU(m_indexes[i], objects, view, target, c);
+               Rect & bounds = objects.bounds[m_indexes[i]];
+               Bezier & bez = objects.beziers[objects.data_indices[m_indexes[i]]];
+               RenderBezierOnCPU(bez, bounds, view, target, c);
        }
 }
 
@@ -319,11 +341,10 @@ void BezierRenderer::PrepareBezierGPUBuffer(Objects & objects)
        m_bezier_coeffs.Resize(objects.beziers.size()*sizeof(GPUBezierCoeffs));
        BufferBuilder<GPUBezierCoeffs> builder(m_bezier_coeffs.Map(false, true, true), m_bezier_coeffs.GetSize());
 
-
+       
        for (unsigned i = 0; i < objects.beziers.size(); ++i)
        {
                const Bezier & bez = objects.beziers[i];
-               
                GPUBezierCoeffs coeffs = {
                        Float(bez.x0), Float(bez.y0),
                        Float(bez.x1), Float(bez.y1),
@@ -332,6 +353,7 @@ void BezierRenderer::PrepareBezierGPUBuffer(Objects & objects)
                        };
                builder.Add(coeffs);
        }
+       
        m_bezier_coeffs.UnMap();
        glGenTextures(1, &m_bezier_buffer_texture);
        glBindTexture(GL_TEXTURE_BUFFER, m_bezier_buffer_texture);
@@ -350,6 +372,7 @@ void BezierRenderer::PrepareBezierGPUBuffer(Objects & objects)
 
 void BezierRenderer::RenderUsingGPU(unsigned first_obj_id, unsigned last_obj_id)
 {
+
        if (!m_shader_program.Valid())
                Warn("Shader is invalid (objects are of type %d)", m_type);
 
@@ -400,13 +423,41 @@ void PathRenderer::RenderUsingCPU(Objects & objects, const View & view, const CP
                        }
                }
                
+               #ifndef TRANSFORM_BEZIERS_TO_PATH
                if (!view.PerformingShading())
                        continue;
-               
                for (unsigned b = path.m_start; b <= path.m_end; ++b)
                {
-                       BezierRenderer::RenderBezierOnCPU(b,objects,view,target,path.m_stroke);
+                       Rect & bbounds = objects.bounds[b];
+                       Bezier & bez = objects.beziers[objects.data_indices[b]];
+                       BezierRenderer::RenderBezierOnCPU(bez,bbounds,view,target,path.m_stroke);
                }
+               #else
+               // Outlines still get drawn if using TRANSFORM_BEZIERS_TO_PATH
+               for (unsigned b = path.m_start; b <= path.m_end; ++b)
+               {
+                       Colour stroke = (view.PerformingShading()) ? path.m_stroke : Colour(0,0,0,255);
+                       // bezier's bounds are relative to this object's bounds, convert back to view bounds
+                       Rect bbounds = objects.bounds[b];
+                       bbounds.x *= objects.bounds[m_indexes[i]].w;
+                       bbounds.x += objects.bounds[m_indexes[i]].x;
+                       bbounds.y *= objects.bounds[m_indexes[i]].h;
+                       bbounds.y += objects.bounds[m_indexes[i]].y;
+                       bbounds.w *= objects.bounds[m_indexes[i]].w;
+                       bbounds.h *= objects.bounds[m_indexes[i]].h;
+                       bbounds = view.TransformToViewCoords(bbounds);
+                       //Debug("Bounds: %s", objects.bounds[m_indexes[i]].Str().c_str());
+                       //Debug("Relative Bez Bounds: %s", objects.bounds[b].Str().c_str());
+                       //Debug("Bez Bounds: %s", bbounds.Str().c_str());
+                       
+                       Bezier & bez = objects.beziers[objects.data_indices[b]];
+                       
+                       BezierRenderer::RenderBezierOnCPU(bez,bbounds,view,target, stroke);
+               }
+               if (!view.PerformingShading())
+                       continue;
+               #endif
+               
                
                if (pix_bounds.w*pix_bounds.h > 100)
                {
@@ -443,6 +494,9 @@ void PathRenderer::RenderUsingCPU(Objects & objects, const View & view, const CP
        }       
 }
 
+
+
+
 /**
  * For debug, save pixels to bitmap
  */
@@ -464,6 +518,9 @@ void ObjectRenderer::SaveBMP(const CPURenderTarget & target, const char * filena
        SDL_FreeSurface(surf);
 }
 
+
+
+
 /**
  * Bresenham's lines
  */
index 5a65363..9ea8a12 100644 (file)
@@ -11,6 +11,7 @@
 #include "shaderprogram.h"
 #include "bufferbuilder.h"
 
+#define BEZIER_CPU_DECASTELJAU
 
 namespace IPDF
 {
@@ -143,7 +144,7 @@ namespace IPDF
                        virtual void RenderUsingCPU(Objects & objects, const View & view, const CPURenderTarget & target, unsigned first_obj_id, unsigned last_obj_id);
                        void PrepareBezierGPUBuffer(Objects & objects);
                        
-                       static void RenderBezierOnCPU(unsigned index, Objects & objects, const View & view, const CPURenderTarget & target, const Colour & c=Colour(0,0,0,255));
+                       static void RenderBezierOnCPU(const Bezier & relative, const Rect & bounds, const View & view, const CPURenderTarget & target, const Colour & c=Colour(0,0,0,255));
                        
                private:
                        GraphicsBuffer m_bezier_coeffs;
@@ -165,11 +166,12 @@ namespace IPDF
        class PathRenderer : public ObjectRenderer
        {
                public:
-                       PathRenderer() : ObjectRenderer(PATH, "shaders/rect_vert.glsl", "shaders/rect_frag.glsl", "shaders/rect_outline_geom.glsl") {}
+                       PathRenderer() : ObjectRenderer(PATH, "shaders/rect_vert.glsl", "shaders/rect_frag.glsl", "shaders/bezier_texbug_geom.glsl") {}
                        virtual ~PathRenderer() {}
                        virtual void RenderUsingCPU(Objects & objects, const View & view, const CPURenderTarget & target, unsigned first_obj_id, unsigned last_obj_id);
                        // do nothing on GPU
                        virtual void RenderUsingGPU(unsigned first_obj_id, unsigned last_obj_id) {}
+
        };
 
        class FakeRenderer : public ObjectRenderer
index 6b602c0..60802eb 100644 (file)
@@ -32,7 +32,7 @@ ParanoidNumber::ParanoidNumber(const string & str) : m_value(0), m_next()
                m_size = 1;
        #endif
        #ifdef PARANOID_CACHE_RESULTS
-       m_cached_result = NAN;
+       m_cache_valid = false;
        #endif
        
        int dp = 0;
@@ -85,8 +85,9 @@ ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
        #endif
        
        m_value = a.m_value;
-       #ifdef PARANOID_CACHE_RESULT
+       #ifdef PARANOID_CACHE_RESULTS
        m_cached_result = a.m_cached_result;
+       m_cache_valid = a.m_cache_valid;
        #endif
        for (int i = 0; i < NOP; ++i)
        {
@@ -411,8 +412,9 @@ ParanoidNumber & ParanoidNumber::operator=(const digit_t & a)
                m_next[i].clear();
        }
        m_value = a;
-       #ifdef PARANOID_CACHE_RESULT
+       #ifdef PARANOID_CACHE_RESULTS
        m_cached_result = a;
+       m_cache_valid = true;
        #endif
 
        #ifdef PARANOID_COMPARE_EPSILON
@@ -427,7 +429,7 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa
 {
        ////assert(b->SanityCheck());
        #ifdef PARANOID_CACHE_RESULTS
-       m_cached_result = NAN;
+       m_cache_valid = false;
        #endif
        #ifdef PARANOID_SIZE_LIMIT
                if (m_size + b->m_size >= PARANOID_SIZE_LIMIT)
@@ -438,7 +440,10 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa
                        else
                                m_value -= b->Digit();
                        m_size = 1;
-                       //Debug("Cut off %p", this);
+                       #ifdef PARANOID_CACHE_RESULTS
+                               m_cached_result = m_value;
+                               m_cache_valid = true;
+                       #endif
                        return b;
                }
                //Debug("At size limit %d", m_size);
@@ -561,7 +566,7 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa
 ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
 {
        #ifdef PARANOID_CACHE_RESULTS
-       m_cached_result = NAN;
+       m_cache_valid = false;
        #endif
        #ifdef PARANOID_SIZE_LIMIT
                if (m_size + b->m_size >= PARANOID_SIZE_LIMIT)
@@ -572,7 +577,10 @@ ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op,
                        else
                                m_value /= b->Digit();
                        m_size = 1;
-                       
+                       #ifdef PARANOID_CACHE_RESULTS
+                               m_cached_result = m_value;
+                               m_cache_valid = true;
+                       #endif
                        //Debug("Cut off %p", this);
                        return b;
                        
@@ -838,10 +846,11 @@ ParanoidNumber::digit_t ParanoidNumber::Digit() const
 
        // Get around the absurd requirement that const correctness be observed.
        #ifdef PARANOID_CACHE_RESULTS
+       if (m_cache_valid) // le sigh ambiguous function compiler warnings
+               return m_cached_result;
+               
        digit_t & result = ((ParanoidNumber*)(this))->m_cached_result;
        
-       if (!isnan(float(result))) // le sigh ambiguous function compiler warnings
-               return result;
        #else
                digit_t result;
        #endif
@@ -858,6 +867,10 @@ ParanoidNumber::digit_t ParanoidNumber::Digit() const
                result += add->Digit();
        for (auto sub : m_next[SUBTRACT])
                result -= sub->Digit();
+               
+       #ifdef PARANOID_CACHE_RESULTS
+               ((ParanoidNumber*)(this))->m_cache_valid = true;
+       #endif
        return result;
                
 }
@@ -932,6 +945,9 @@ void ParanoidNumber::Negate()
 {
        swap(m_next[ADD], m_next[SUBTRACT]);
        m_value = -m_value;
+       #ifdef PARANOID_CACHE_RESULTS
+               m_cached_result = -m_cached_result;
+       #endif
 }
 
 #ifdef PARANOID_USE_ARENA
index 3a38286..a175ed5 100644 (file)
 //#define PARANOID_CACHE_RESULTS
 
 //#define PARANOID_USE_ARENA
-#define PARANOID_SIZE_LIMIT 10
+//#define PARANOID_SIZE_LIMIT 3
 
 
 // Define to compare all ops against double ops and check within epsilon
-//#define PARANOID_COMPARE_EPSILON 1e-
+//#define PARANOID_COMPARE_EPSILON 1e-6
 #ifdef PARANOID_COMPARE_EPSILON
 #define CompareForSanity(...) ParanoidNumber::CompareForSanityEx(__func__, __FILE__, __LINE__, __VA_ARGS__)
 #endif
@@ -93,6 +93,7 @@ namespace IPDF
                                #endif
                                #ifdef PARANOID_CACHE_RESULTS
                                        m_cached_result = value;
+                                       m_cache_valid = true;
                                #endif 
                        }
                        
@@ -104,6 +105,7 @@ namespace IPDF
                                #endif
                                #ifdef PARANOID_CACHE_RESULTS
                                        m_cached_result = cpy.m_cached_result;
+                                       m_cache_valid = cpy.m_cache_valid;
                                #endif 
                                for (int i = 0; i < NOP; ++i)
                                {
@@ -265,6 +267,7 @@ namespace IPDF
                        digit_t m_value;        
                        #ifdef PARANOID_CACHE_RESULTS
                                digit_t m_cached_result;
+                               bool m_cache_valid;
                        #endif
                        std::vector<ParanoidNumber*> m_next[4];
                        #ifdef PARANOID_SIZE_LIMIT
@@ -275,7 +278,7 @@ namespace IPDF
                        class Arena
                        {
                                public:
-                                       Arena(int64_t block_size = 10000000);
+                                       Arena(int64_t block_size = 10000);
                                        ~Arena();
                                        
                                        void * allocate(size_t bytes);
@@ -308,7 +311,7 @@ template <class T>
 T ParanoidNumber::Convert() const
 {
        #ifdef PARANOID_CACHE_RESULTS
-       if (!isnan((float(m_cached_result))))
+       if (m_cache_valid)
                return (T)m_cached_result;
        #endif
        T value(m_value);
index f12e2a7..04e537c 100644 (file)
@@ -5,7 +5,7 @@ using namespace std;
 namespace IPDF
 {
 
-Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour & fill, const Colour & stroke)
+Path::Path(Objects & objects, unsigned start, unsigned end, const Colour & fill, const Colour & stroke)
        : m_start(start), m_end(end), m_fill(fill), m_stroke(stroke)
 {
        Real xmin = 0; Real ymin = 0; 
@@ -53,6 +53,16 @@ Path::Path(const Objects & objects, unsigned start, unsigned end, const Colour &
        m_bottom = objects.beziers[objects.data_indices[bottom]].ToAbsolute(objects.bounds[bottom]).GetBottom();
        m_left = objects.beziers[objects.data_indices[left]].ToAbsolute(objects.bounds[left]).GetLeft();
        m_right = objects.beziers[objects.data_indices[right]].ToAbsolute(objects.bounds[right]).GetRight();    
+       
+       #ifdef TRANSFORM_BEZIERS_TO_PATH
+       Rect bounds = SolveBounds(objects);
+       for (unsigned i = m_start; i <= m_end; ++i)
+       {
+               //Debug("Transform %s -> %s", objects.bounds[i].Str().c_str(), bounds.Str().c_str());
+               objects.bounds[i] = TransformRectCoordinates(bounds, objects.bounds[i]);
+               //Debug("-> %s", objects.bounds[i].Str().c_str());
+       }
+       #endif
 }
 
 
@@ -183,7 +193,12 @@ vector<Vec2> & Path::FillPoints(const Objects & objects, const View & view)
 
 Rect Path::SolveBounds(const Objects & objects) const
 {
-               return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y);
+       return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y);
+}
+
+Rect & Path::GetBounds(Objects & objects) 
+{
+       return objects.bounds[m_index];
 }
 
 }
index fa63cb4..7eb8dee 100644 (file)
@@ -6,6 +6,13 @@
 #include "rect.h"
 #include "real.h"
 
+#ifdef QUADTREE_DISABLED
+
+#define TRANSFORM_BEZIERS_TO_PATH
+
+
+#endif
+
 namespace IPDF
 {
        
@@ -26,9 +33,10 @@ namespace IPDF
        
        struct Path
        {
-               Path(const Objects & objects, unsigned _start, unsigned _end, const Colour & _fill = Colour(128,128,128,255), const Colour & _stroke = Colour(0,0,0,0));
+               Path(Objects & objects, unsigned _start, unsigned _end, const Colour & _fill = Colour(128,128,128,255), const Colour & _stroke = Colour(0,0,0,0));
                
                Rect SolveBounds(const Objects & objects) const;
+               Rect & GetBounds(Objects & objects);
                std::vector<Vec2> & FillPoints(const Objects & objects, const View & view);
                
                // Is point inside shape?
index 5c600f3..b092fbe 100644 (file)
@@ -42,10 +42,10 @@ namespace IPDF
                Rect out;
                Real w = (view.w == Real(0))?Real(1):view.w;
                Real h = (view.h == Real(0))?Real(1):view.h;
-               out.x = (r.x - view.x) / w;
-               out.y = (r.y - view.y) / h;
-               out.w = r.w / w;
-               out.h = r.h / h;
+               out.x = (r.x - view.x) / w; //r.x = out.x *w + view.x
+               out.y = (r.y - view.y) / h; // r.y = out.y*h + view.y
+               out.w = r.w / w; // r.w = out.w * w
+               out.h = r.h / h; // r.h = out.h * h
                return out;
        }
 
index dd72201..2625fd9 100644 (file)
@@ -7,22 +7,22 @@
      width="400" height="400"
    >
        <g   transform="translate(-230,-250)">
-    <path
+    <!--<path
        style="fill:#ac9d93;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
        d="m 478.78564,339.0153 -16.66751,-1.01016 -36.11296,-47.7297 -12.6269,-33.0825 28.53681,17.17259 23.2335,24.4962 10.35407,21.97082 z"
        id="path4374"
-       inkscape:connector-curvature="0" />
-    <path
+       inkscape:connector-curvature="0" />-->
+    <!--<path
        style="fill:#ac9d93;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
        d="m 451.25899,350.37951 -51.26524,-30.55711 -27.52666,-37.12311 -0.25254,-6.81853 30.30458,4.29315 23.23351,11.11168 24.74873,26.5165 12.62691,21.71828 z"
        id="path4370"
-       inkscape:connector-curvature="0" />
+       inkscape:connector-curvature="0" />-->
        
-           <path
+           <!--<path
        style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
        d="M 25,158.21333 36.071428,144.28476 l 20,20 Z"
        id="path4498"
        inkscape:connector-curvature="0"
-       transform="translate(227.32245,266.11266)" />
+       transform="translate(227.32245,266.11266)" />-->
        </g>
  </svg>
index 19b1897..b89a5ad 100644 (file)
@@ -10,9 +10,9 @@ int main(int argc, char ** argv)
        DebugRealInfo();
        
        Debug("Repeated Multiplications and Divisions - Should give one");
-       first_clock = clock();
-       elapsed = 0;
-       for (int i = 1; i < 2; ++i)
+       clock_t first_clock = clock();
+       clock_t elapsed = 0;
+       for (int i = 1; i < 100; ++i)
        {
                for (int j = 1; j < 100; ++j)
                {
index 3c863a1..4669f59 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "main.h"
 #include "real.h"
+#include "progressbar.h"
 
 using namespace std;
 using namespace IPDF;
@@ -27,8 +28,10 @@ int main(int argc, char ** argv)
        unsigned failures = 0;
        Real acumulate(0);
        double dacumulate = 0;
+       
        for (unsigned i = 0; i < TEST_CASES; ++i)
        {
+               ProgressBar(i, TEST_CASES, 50);
                //Debug("Test %u of %u", i, TEST_CASES);
                double da = (double)(rand() + 1) / (double)(rand() + 1);
                double db = (double)(rand() + 1) / (double)(rand() + 1);
@@ -181,7 +184,6 @@ int main(int argc, char ** argv)
                                Debug("\tStrings are a = %s, b = %s, aa = %s, bb = %s", a.Str().c_str(), b.Str().c_str(), aa.Str().c_str(), bb.Str().c_str());
                        #endif
                }
-
        }
        Debug("Completed %u test cases with total of %u operations, %u failures", TEST_CASES, 18*TEST_CASES, failures);
        Debug("Total accumulated difference between Real and Double operations was %f", g_totalerror);
index c96fb0a..9ad633c 100644 (file)
@@ -7,6 +7,13 @@
        #include "controlpanel.h"
 #endif //CONTROLPANEL_DISABLED
 
+
+#ifdef TRANSFORM_BEZIERS_TO_PATH 
+       #ifndef TRANSFORM_OBJECTS_NOT_VIEW
+       //#error Cannot TRANSFORM_BEZIERS_TO_PATH _without_ TRANSFORM_OBJECTS_NOT_VIEW
+       #endif
+#endif
+
 using namespace IPDF;
 using namespace std;
 
@@ -83,7 +90,11 @@ void View::Translate(Real x, Real y)
                m_buffer_dirty = true;
        m_bounds_dirty = true;
        #ifdef TRANSFORM_OBJECTS_NOT_VIEW
-       m_document.TranslateObjects(-x, -y);
+       ObjectType type = NUMBER_OF_OBJECT_TYPES;
+               #ifdef TRANSFORM_BEZIERS_TO_PATH
+                       type = PATH;
+               #endif
+       m_document.TranslateObjects(-x, -y, type);
        #endif
        x *= m_bounds.w;
        y *= m_bounds.h;
@@ -126,7 +137,11 @@ void View::ScaleAroundPoint(Real x, Real y, Real scale_amount)
        
        
        #ifdef TRANSFORM_OBJECTS_NOT_VIEW
-       m_document.ScaleObjectsAboutPoint(x, y, scale_amount);
+       ObjectType type = NUMBER_OF_OBJECT_TYPES;
+       #ifdef TRANSFORM_BEZIERS_TO_PATH
+               type = PATH;
+       #endif
+       m_document.ScaleObjectsAboutPoint(x, y, scale_amount, type);
        #endif
        x *= m_bounds.w;
        y *= m_bounds.h;
@@ -159,12 +174,7 @@ 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;
-       out.w = inp.w / m_bounds.w;
-       out.h = inp.h / m_bounds.h;
-       return out;
+       return TransformRectCoordinates(m_bounds, inp);
 }
 
 /**
@@ -486,6 +496,7 @@ void View::UpdateObjBoundsVBO(unsigned first_obj, unsigned last_obj)
 
        BufferBuilder<GPUObjBounds> obj_bounds_builder(m_objbounds_vbo.MapRange(first_obj*sizeof(GPUObjBounds), (last_obj-first_obj)*sizeof(GPUObjBounds), false, true, true), m_objbounds_vbo.GetSize());
 
+       #ifndef TRANSFORM_BEZIERS_TO_PATH
        for (unsigned id = first_obj; id < last_obj; ++id)
        {
                Rect obj_bounds;
@@ -505,8 +516,46 @@ void View::UpdateObjBoundsVBO(unsigned first_obj, unsigned last_obj)
                };
 
                obj_bounds_builder.Add(gpu_bounds);
-
        }
+       #else
+       for (unsigned i = 0; i < m_document.m_objects.paths.size(); ++i)
+       {
+               Path & path = m_document.m_objects.paths[i];
+               Rect & pbounds = path.GetBounds(m_document.m_objects); // Not very efficient...
+               for (unsigned id = path.m_start; id <= path.m_end; ++id)
+               {
+                       if (id < first_obj || id >= last_obj)
+                               continue;
+                               
+                       Rect obj_bounds = m_document.m_objects.bounds[id];
+
+                       obj_bounds.x *= pbounds.w;
+                       obj_bounds.x += pbounds.x;
+                       obj_bounds.y *= pbounds.h;
+                       obj_bounds.y += pbounds.y;
+                       obj_bounds.w *= pbounds.w;
+                       obj_bounds.h *= pbounds.h;
+                       
+                       if (!m_use_gpu_transform)
+                               obj_bounds = TransformToViewCoords(obj_bounds);
+                       GPUObjBounds gpu_bounds = {
+                               Float(obj_bounds.x),
+                               Float(obj_bounds.y),
+                               Float(obj_bounds.x + obj_bounds.w),
+                               Float(obj_bounds.y + obj_bounds.h)
+                       };
+                       obj_bounds_builder.Add(gpu_bounds);
+                       //Debug("Path %d %s -> %s via %s", id, m_document.m_objects.bounds[id].Str().c_str(), obj_bounds.Str().c_str(), pbounds.Str().c_str()); 
+               }
+               GPUObjBounds p_gpu_bounds = {
+                               Float(pbounds.x),
+                               Float(pbounds.y),
+                               Float(pbounds.x + pbounds.w),
+                               Float(pbounds.y + pbounds.h)
+               };              
+               obj_bounds_builder.Add(p_gpu_bounds);
+       }
+       #endif
        m_objbounds_vbo.UnMap();
 }
 /**
@@ -554,7 +603,9 @@ void View::PrepareRender()
                m_object_renderers[i]->FinaliseBuffers();
        }
        if (UsingGPURendering())
+       {
                dynamic_cast<BezierRenderer*>(m_object_renderers[BEZIER])->PrepareBezierGPUBuffer(m_document.m_objects);
+       }
        m_render_dirty = false;
 }
 
index 5ea06a0..66ccee8 100644 (file)
@@ -12,7 +12,7 @@
 
 #ifdef QUADTREE_DISABLED
 
-#define TRANSFORM_OBJECTS_NOT_VIEW
+//#define TRANSFORM_OBJECTS_NOT_VIEW
 
 #endif
 

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