From: Sam Moore Date: Sat, 27 Sep 2014 16:08:19 +0000 (+0800) Subject: Use Gmprat for Path bounds with TRANSFORM_BEZIERS_TO_PATH X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=58a6719da2337b3e6e20b581885f170bbe5fc480;p=ipdf%2Fcode.git Use Gmprat for Path bounds with TRANSFORM_BEZIERS_TO_PATH So, the bounds of Paths are stored with Gmprat The Bezier's are all stored relative to the Path, as floats The transformations are only applied to the Path Gmprat bounds. This seems to work rather well. In other news, the DeCasteljau algorithm in the CPU renderer had no upper limit, which is why it was slowing down so much. The CPU renderer tends to suffer from SIGFPE-itis when using floats, because when you do a cast there is a SIGFPE if the resultant type can't represent the operand. This occurs in a few places that don't actually affect the rendering... --- diff --git a/src/Makefile b/src/Makefile index 31ea736..805964e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,8 +9,8 @@ QT_INCLUDE := -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCor QT_DEF := -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB QT_LIB := -L/usr/lib/x86_64-linux-gnu -lQtGui -lQtCore -lpthread -LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL -LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL +LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL -lgmp +LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL -lgmp LIB_i686 = $(LIB_i386) MAINRPATH_x86_64 = -Wl,-rpath,'$$ORIGIN/../contrib/lib' diff --git a/src/bezier.cpp b/src/bezier.cpp index 3c682a6..daa0736 100644 --- a/src/bezier.cpp +++ b/src/bezier.cpp @@ -4,6 +4,8 @@ #include #include + + using namespace std; namespace IPDF @@ -424,3 +426,4 @@ Rect Bezier::SolveBounds() const } } // end namespace + diff --git a/src/bezier.h b/src/bezier.h index cedf8d4..fbfbb61 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -8,6 +8,7 @@ #include "rect.h" + namespace IPDF { extern int Factorial(int n); @@ -356,4 +357,6 @@ namespace IPDF } +#undef Real + #endif //_BEZIER_H diff --git a/src/document.cpp b/src/document.cpp index 4be3ee0..1e768bd 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1055,6 +1055,16 @@ void Document::TransformObjectBounds(const SVGMatrix & transform) void Document::TranslateObjects(const Real & dx, const Real & dy, ObjectType type) { + #ifdef TRANSFORM_BEZIERS_TO_PATH + for (unsigned i = 0; i < m_objects.paths.size(); ++i) + { + Path & p = m_objects.paths[i]; + p.x += dx; + p.y += dy; + } + return; + #endif + for (unsigned i = 0; i < m_count; ++i) { if (type == NUMBER_OF_OBJECT_TYPES || m_objects.types[i] == type) @@ -1067,6 +1077,22 @@ void Document::TranslateObjects(const Real & dx, const Real & dy, ObjectType typ void Document::ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real & scale_amount, ObjectType type) { + #ifdef TRANSFORM_BEZIERS_TO_PATH + for (unsigned i = 0; i < m_objects.paths.size(); ++i) + { + Path & p = m_objects.paths[i]; + p.w /= scale_amount; + p.h /= scale_amount; + p.x -= x; + p.x /= scale_amount; + p.x += x; + p.y -= y; + p.y /= scale_amount; + p.y += y; + } + return; + #endif + for (unsigned i = 0; i < m_count; ++i) { if (type != NUMBER_OF_OBJECT_TYPES && m_objects.types[i] != type) @@ -1084,6 +1110,7 @@ void Document::ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real m_objects.bounds[i].y /= scale_amount; m_objects.bounds[i].y += y; } + } diff --git a/src/eye_of_the_rabbit.script b/src/eye_of_the_rabbit.script index c94bccd..a96efa6 100644 --- a/src/eye_of_the_rabbit.script +++ b/src/eye_of_the_rabbit.script @@ -1,19 +1,19 @@ # Test how well document scales back to original... -cpu +gpu lazy label start debug Add rabbit 1 loadsvg svg-tests/rabbit_simple.svg -loop 200 pxzoom 508 305 1 +loop 250 pxzoom 508 305 1 debug Add rabbit 2 loadsvg svg-tests/rabbit_simple.svg -loop 200 pxzoom 508 305 1 +loop 250 pxzoom 508 305 1 debug Add rabbit 3 loadsvg svg-tests/rabbit_simple.svg -loop 400 pxzoom 508 305 -1 -loop 200 pxzoom 508 305 1 +loop 500 pxzoom 508 305 -1 +loop 250 pxzoom 508 305 1 loop 1000 wait -loop 200 pxzoom 508 305 1 +loop 250 pxzoom 508 305 1 debug Repeat #goto start wait diff --git a/src/gmprat.h b/src/gmprat.h index de0e80b..5df43ef 100644 --- a/src/gmprat.h +++ b/src/gmprat.h @@ -32,6 +32,7 @@ class Gmprat } Gmprat & operator=(const Gmprat & equ) {mpq_set(m_op, equ.m_op); return *this;} + Gmprat & operator=(const double & equ) {mpq_set_d(m_op, equ); return *this;} Gmprat & operator+=(const Gmprat & add) {mpq_add(m_op, m_op, add.m_op); return *this;} Gmprat & operator-=(const Gmprat & sub) {mpq_sub(m_op, m_op, sub.m_op); return *this;} Gmprat & operator*=(const Gmprat & mul) {mpq_mul(m_op, m_op, mul.m_op); return *this;} diff --git a/src/objectrenderer.cpp b/src/objectrenderer.cpp index 6a216bc..21c9648 100644 --- a/src/objectrenderer.cpp +++ b/src/objectrenderer.cpp @@ -243,14 +243,14 @@ void BezierRenderer::RenderBezierOnCPU(const Bezier & relative, const Rect & bou 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 = pix_bounds.w;//min(max(2U, (unsigned)Int64(Real(target.w)/view.GetBounds().w)), + int64_t blen = min(50L,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 divisions; divisions.push(control); - while(divisions.size() < blen) + while(divisions.size() < (uint64_t)(blen)) { Bezier & current = divisions.front(); //if (current.GetType() == Bezier::LINE) @@ -328,7 +328,7 @@ void BezierRenderer::RenderUsingCPU(Objects & objects, const View & view, const break; } } - Rect & bounds = objects.bounds[m_indexes[i]]; + Rect bounds = view.TransformToViewCoords(objects.bounds[m_indexes[i]]); Bezier & bez = objects.beziers[objects.data_indices[m_indexes[i]]]; RenderBezierOnCPU(bez, bounds, view, target, c); } @@ -408,9 +408,10 @@ void PathRenderer::RenderUsingCPU(Objects & objects, const View & view, const CP if (m_indexes[i] >= last_obj_id) continue; - Rect bounds(CPURenderBounds(objects.bounds[m_indexes[i]], view, target)); - PixelBounds pix_bounds(bounds); + Path & path = objects.paths[objects.data_indices[m_indexes[i]]]; + Rect bounds(CPURenderBounds(path.GetBounds(objects), view, target)); + PixelBounds pix_bounds(bounds); if (view.ShowingFillPoints()) { @@ -640,4 +641,12 @@ void ObjectRenderer::FloodFillOnCPU(int64_t x, int64_t y, const PixelBounds & bo } } +ObjectRenderer::PixelBounds::PixelBounds(const Rect & bounds) +{ + x = Int64(Double(bounds.x)); + y = Int64(Double(bounds.y)); + w = Int64(Double(bounds.w)); + h = Int64(Double(bounds.h)); +} + } diff --git a/src/objectrenderer.h b/src/objectrenderer.h index 9ea8a12..85a413b 100644 --- a/src/objectrenderer.h +++ b/src/objectrenderer.h @@ -10,6 +10,7 @@ #include "graphicsbuffer.h" #include "shaderprogram.h" #include "bufferbuilder.h" +#include #define BEZIER_CPU_DECASTELJAU @@ -76,7 +77,7 @@ namespace IPDF struct PixelBounds { int64_t x; int64_t y; int64_t w; int64_t h; - PixelBounds(const Rect & bounds) : x(Double(bounds.x)), y(Double(bounds.y)), w(Double(bounds.w)), h(Double(bounds.h)) {} + PixelBounds(const Rect & bounds); }; typedef std::pair PixelPoint; diff --git a/src/path.cpp b/src/path.cpp index 04e537c..251de1e 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -55,6 +55,11 @@ Path::Path(Objects & objects, unsigned start, unsigned end, const Colour & fill, m_right = objects.beziers[objects.data_indices[right]].ToAbsolute(objects.bounds[right]).GetRight(); #ifdef TRANSFORM_BEZIERS_TO_PATH + x = m_left.x; + y = m_top.y; + w = m_right.x - m_left.x; + h = m_bottom.y - m_top.y; + Rect bounds = SolveBounds(objects); for (unsigned i = m_start; i <= m_end; ++i) { @@ -191,13 +196,20 @@ vector & Path::FillPoints(const Objects & objects, const View & view) return m_fill_points; } -Rect Path::SolveBounds(const Objects & objects) const +Rect Path::SolveBounds(const Objects & objects) { - return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y); + #ifdef TRANSFORM_BEZIERS_TO_PATH + return Rect(Real(x.ToDouble()), Real(y.ToDouble()), Real(w.ToDouble()), Real(h.ToDouble())); + #else + return Rect(m_left.x, m_top.y, m_right.x-m_left.x, m_bottom.y-m_top.y); + #endif } Rect & Path::GetBounds(Objects & objects) { + #ifdef TRANSFORM_BEZIERS_TO_PATH + objects.bounds[m_index] = Rect(Real(x.ToDouble()), Real(y.ToDouble()), Real(w.ToDouble()), Real(h.ToDouble())); + #endif return objects.bounds[m_index]; } diff --git a/src/path.h b/src/path.h index 7eb8dee..eb2b7b7 100644 --- a/src/path.h +++ b/src/path.h @@ -9,7 +9,9 @@ #ifdef QUADTREE_DISABLED #define TRANSFORM_BEZIERS_TO_PATH - +#ifdef TRANSFORM_BEZIERS_TO_PATH +#include "gmprat.h" +#endif #endif @@ -35,7 +37,7 @@ namespace IPDF { 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 SolveBounds(const Objects & objects); Rect & GetBounds(Objects & objects); std::vector & FillPoints(const Objects & objects, const View & view); @@ -53,6 +55,13 @@ namespace IPDF std::vector m_fill_points; + #ifdef TRANSFORM_BEZIERS_TO_PATH + Gmprat x; + Gmprat y; + Gmprat w; + Gmprat h; + #endif + Colour m_fill; // colour to fill with Colour m_stroke; // colour to outline with }; diff --git a/src/real.h b/src/real.h index e35d952..7f29ca8 100644 --- a/src/real.h +++ b/src/real.h @@ -128,7 +128,14 @@ namespace IPDF inline double Double(long double f) {return (double)(f);} inline double Sqrt(double f) {return sqrt(f);} inline double Abs(double a) {return fabs(a);} - inline int64_t Int64(double a){return (int64_t)a;} + inline int64_t Int64(double a) + { + if (a < INT64_MIN) + return INT64_MIN; + if (a > INT64_MAX) + return INT64_MAX; + return (int64_t)(a); + } inline Real Power(const Real & a, int n) { diff --git a/src/view.h b/src/view.h index 66ccee8..5ea06a0 100644 --- a/src/view.h +++ b/src/view.h @@ -12,7 +12,7 @@ #ifdef QUADTREE_DISABLED -//#define TRANSFORM_OBJECTS_NOT_VIEW +#define TRANSFORM_OBJECTS_NOT_VIEW #endif