From 326f04a375ce3120f7e8957e3d7cd5f296f513e3 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Thu, 2 Oct 2014 18:40:19 +0800 Subject: [PATCH] Totally FITH everything I'm trying to get it so that Path and View can use a different number representation to Bezier. It's not going well. --- src/Makefile | 10 +- src/bezier.cpp | 162 +++++++++++++++--------------- src/bezier.h | 184 +++++++++++++++++------------------ src/debugscript.cpp | 56 +++++++++++ src/debugscript.h | 18 ++++ src/document.cpp | 21 ++-- src/document.h | 7 ++ src/eye_of_the_rabbit.script | 9 +- src/gmprat.h | 8 ++ src/ipdf.h | 9 ++ src/main.h | 2 +- src/path.cpp | 19 +--- src/path.h | 22 ++--- src/real.h | 11 ++- src/rect.h | 37 ++++--- src/transformationtype.h | 9 ++ src/view.cpp | 12 +-- src/view.h | 25 +++-- 18 files changed, 374 insertions(+), 247 deletions(-) create mode 100644 src/transformationtype.h diff --git a/src/Makefile b/src/Makefile index 805964e..fd0b81b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,9 +1,9 @@ #Makefile ARCH := $(shell uname -m) # TODO: stb_truetype doesn't compile with some of these warnings. -CXX = g++ -std=c++11 -g -Wall -Werror -Wshadow -pedantic -rdynamic +CXX = g++ -std=c++0x -g -Wall -Werror -Wshadow -pedantic -rdynamic MAIN = main.o -OBJ = log.o real.o bezier.o document.o objectrenderer.o view.o screen.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o path.o paranoidnumber.o quadtree.o debugscript.o +OBJ = log.o real.o bezier.o objectrenderer.o view.o screen.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o path.o document.o debugscript.o QT_INCLUDE := -I/usr/share/qt4/mkspecs/linux-g++-64 -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -Itests -I. QT_DEF := -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB @@ -41,7 +41,7 @@ DEF = -DREALTYPE=$(REALTYPE) ## Only link with things we care about ifeq ($(QUADTREE),enabled) - OBJ := $(OBJ) + OBJ := $(OBJ) quadtree.o else DEF := $(DEF) -DQUADTREE_DISABLED endif @@ -73,7 +73,9 @@ ifeq ($(REALTYPE),7) CFLAGS := $(CFLAGS) -I../contrib/iRRAM/include endif - +ifeq ($(REALTYPE),8) + OBJ := $(OBJ) paranoidnumber.o +endif ifeq ($(REALTYPE),9) LIB := $(LIB) -lgmp diff --git a/src/bezier.cpp b/src/bezier.cpp index daa0736..19d89af 100644 --- a/src/bezier.cpp +++ b/src/bezier.cpp @@ -11,32 +11,32 @@ using namespace std; namespace IPDF { -vector SolveQuadratic(const Real & a, const Real & b, const Real & c, const Real & min, const Real & max) +vector SolveQuadratic(const BReal & a, const BReal & b, const BReal & c, const BReal & min, const BReal & max) { - vector roots; roots.reserve(2); + vector roots; roots.reserve(2); if (a == 0 && b != 0) { roots.push_back(-c/b); return roots; } - Real disc(b*b - Real(4)*a*c); + BReal disc(b*b - BReal(4)*a*c); if (disc < 0) { return roots; } else if (disc == 0) { - Real x(-b/Real(2)*a); + BReal x(-b/BReal(2)*a); if (x >= min && x <= max) roots.push_back(x); return roots; } - Real x0((-b - Sqrt(b*b - Real(4)*a*c))/(Real(2)*a)); - Real x1((-b + Sqrt(b*b - Real(4)*a*c))/(Real(2)*a)); + BReal x0((-b - Sqrt(b*b - BReal(4)*a*c))/(BReal(2)*a)); + BReal x1((-b + Sqrt(b*b - BReal(4)*a*c))/(BReal(2)*a)); if (x0 > x1) { - Real tmp(x0); + BReal tmp(x0); x0 = x1; x1 = tmp; } @@ -51,10 +51,10 @@ vector SolveQuadratic(const Real & a, const Real & b, const Real & c, cons * Finds the root (if it exists) in a monotonicly in(de)creasing segment of a Cubic */ -static void CubicSolveSegment(vector & roots, const Real & a, const Real & b, const Real & c, const Real & d, Real & tl, Real & tu, const Real & delta) +static void CubicSolveSegment(vector & roots, const BReal & a, const BReal & b, const BReal & c, const BReal & d, BReal & tl, BReal & tu, const BReal & delta) { - Real l = a*tl*tl*tl + b*tl*tl + c*tl + d; - Real u = a*tu*tu*tu + b*tu*tu + c*tu + d; + BReal l = a*tl*tl*tl + b*tl*tl + c*tl + d; + BReal 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)); @@ -65,9 +65,9 @@ static void CubicSolveSegment(vector & roots, const Real & a, const Real & //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); + BReal t(tu+tl); t /= 2; - Real m = a*t*t*t + b*t*t + c*t + d; + BReal m = a*t*t*t + b*t*t + c*t + d; if (m > 0) { if (negative) @@ -87,12 +87,12 @@ static void CubicSolveSegment(vector & roots, const Real & a, const Real & } roots.push_back(tl); } -vector SolveCubic(const Real & a, const Real & b, const Real & c, const Real & d, const Real & min, const Real & max, const Real & delta) +vector SolveCubic(const BReal & a, const BReal & b, const BReal & c, const BReal & d, const BReal & min, const BReal & max, const BReal & delta) { - vector roots; roots.reserve(3); - Real tu(max); - Real tl(min); - vector turns(SolveQuadratic(a*3, b*2, c)); + vector roots; roots.reserve(3); + BReal tu(max); + BReal tl(min); + vector turns(SolveQuadratic(a*3, b*2, c)); //Debug("%u turning points", turns.size()); for (unsigned i = 1; i < turns.size(); ++i) { @@ -137,9 +137,9 @@ int BinomialCoeff(int n, int k) /** * Bernstein Basis Polynomial */ -Real Bernstein(int k, int n, const Real & u) +BReal Bernstein(int k, int n, const BReal & u) { - return Real(BinomialCoeff(n, k)) * Power(u, k) * Power(Real(1.0) - u, n-k); + return BReal(BinomialCoeff(n, k)) * Power(u, k) * Power(BReal(1.0) - u, n-k); } @@ -148,42 +148,42 @@ Real Bernstein(int k, int n, const Real & u) * In one coordinate direction */ -pair BezierTurningPoints(const Real & p0, const Real & p1, const Real & p2, const Real & p3) +pair BezierTurningPoints(const BReal & p0, const BReal & p1, const BReal & p2, const BReal & p3) { // straight line if (p1 == p2 && p2 == p3) { - return pair(0, 1); + return pair(0, 1); } - Real a = ((p1-p2)*3 + p3 - p0); - Real b = (p2 - p1*2 + p0)*2; - Real c = (p1-p0); + BReal a = ((p1-p2)*3 + p3 - p0); + BReal b = (p2 - p1*2 + p0)*2; + BReal c = (p1-p0); if (a == 0) { if (b == 0) - return pair(0,1); - Real t = -c/b; + return pair(0,1); + BReal t = -c/b; if (t > 1) t = 1; if (t < 0) t = 0; - return pair(t, t); + return pair(t, t); } //Debug("a, b, c are %f, %f, %f", Float(a), Float(b), Float(c)); if (b*b - a*c*4 < 0) { //Debug("No real roots"); - return pair(0,1); + return pair(0,1); } - vector tsols = SolveQuadratic(a, b, c); + vector tsols = SolveQuadratic(a, b, c); if (tsols.size() == 1) - return pair(tsols[0], tsols[0]); + return pair(tsols[0], tsols[0]); else if (tsols.size() == 0) - return pair(0,1); + return pair(0,1); - return pair(tsols[0], tsols[1]); + return pair(tsols[0], tsols[1]); } -inline bool CompRealByPtr(const Real * a, const Real * b) +inline bool CompBRealByPtr(const BReal * a, const BReal * b) { return (*a) < (*b); } @@ -191,20 +191,20 @@ inline bool CompRealByPtr(const Real * a, const Real * b) /** * Get top most *point* on Bezier curve */ -pair Bezier::GetTop() const +pair Bezier::GetTop() const { - pair tsols = BezierTurningPoints(y0,y1,y2,y3); - Real tx0; Real ty0; - Real tx1; Real ty1; + pair tsols = BezierTurningPoints(y0,y1,y2,y3); + BReal tx0; BReal ty0; + BReal tx1; BReal ty1; Evaluate(tx0, ty0, tsols.first); Evaluate(tx1, ty1, tsols.second); - vector v(4); + vector v(4); v[0] = &y0; v[1] = &y3; v[2] = &ty0; v[3] = &ty1; - sort(v.begin(), v.end(), CompRealByPtr); - pair result; + sort(v.begin(), v.end(), CompBRealByPtr); + pair result; result.second = *v[0]; if (v[0] == &y0) { @@ -228,20 +228,20 @@ pair Bezier::GetTop() const /** * Get bottom most *point* on Bezier curve */ -pair Bezier::GetBottom() const +pair Bezier::GetBottom() const { - pair tsols = BezierTurningPoints(y0,y1,y2,y3); - Real tx0; Real ty0; - Real tx1; Real ty1; + pair tsols = BezierTurningPoints(y0,y1,y2,y3); + BReal tx0; BReal ty0; + BReal tx1; BReal ty1; Evaluate(tx0, ty0, tsols.first); Evaluate(tx1, ty1, tsols.second); - vector v(4); + vector v(4); v[0] = &y0; v[1] = &y3; v[2] = &ty0; v[3] = &ty1; - sort(v.begin(), v.end(), CompRealByPtr); - pair result; + sort(v.begin(), v.end(), CompBRealByPtr); + pair result; result.second = *v[3]; if (v[3] == &y0) { @@ -265,20 +265,20 @@ pair Bezier::GetBottom() const /** * Get left most *point* on Bezier curve */ -pair Bezier::GetLeft() const +pair Bezier::GetLeft() const { - pair tsols = BezierTurningPoints(x0,x1,x2,x3); - Real tx0; Real ty0; - Real tx1; Real ty1; + pair tsols = BezierTurningPoints(x0,x1,x2,x3); + BReal tx0; BReal ty0; + BReal tx1; BReal ty1; Evaluate(tx0, ty0, tsols.first); Evaluate(tx1, ty1, tsols.second); - vector v(4); + vector v(4); v[0] = &x0; v[1] = &x3; v[2] = &tx0; v[3] = &tx1; - sort(v.begin(), v.end(), CompRealByPtr); - pair result; + sort(v.begin(), v.end(), CompBRealByPtr); + pair result; result.first = *v[0]; if (v[0] == &x0) { @@ -303,20 +303,20 @@ pair Bezier::GetLeft() const /** * Get left most *point* on Bezier curve */ -pair Bezier::GetRight() const +pair Bezier::GetRight() const { - pair tsols = BezierTurningPoints(x0,x1,x2,x3); - Real tx0; Real ty0; - Real tx1; Real ty1; + pair tsols = BezierTurningPoints(x0,x1,x2,x3); + BReal tx0; BReal ty0; + BReal tx1; BReal ty1; Evaluate(tx0, ty0, tsols.first); Evaluate(tx1, ty1, tsols.second); - vector v(4); + vector v(4); v[0] = &x0; v[1] = &x3; v[2] = &tx0; v[3] = &tx1; - sort(v.begin(), v.end(), CompRealByPtr); - pair result; + sort(v.begin(), v.end(), CompBRealByPtr); + pair result; result.first = *v[3]; if (v[3] == &x0) { @@ -337,13 +337,13 @@ pair Bezier::GetRight() const return result; } -vector Bezier::SolveXParam(const Real & x) const +vector Bezier::SolveXParam(const BReal & x) const { - Real d(x0 - x); - Real c((x1 - x0)*Real(3)); - Real b((x2 - x1)*Real(3) - c); - Real a(x3 -x0 - c - b); - vector results(SolveCubic(a, b, c, d)); + BReal d(x0 - x); + BReal c((x1 - x0)*BReal(3)); + BReal b((x2 - x1)*BReal(3) - c); + BReal a(x3 -x0 - c - b); + vector results(SolveCubic(a, b, c, d)); for (unsigned i = 0; i < results.size(); ++i) { Vec2 p; @@ -353,13 +353,13 @@ vector Bezier::SolveXParam(const Real & x) const } -vector Bezier::SolveYParam(const Real & y) const +vector Bezier::SolveYParam(const BReal & y) const { - Real d(y0 - y); - Real c((y1 - y0)*Real(3)); - Real b((y2 - y1)*Real(3) - c); - Real a(y3 -y0 - c - b); - vector results(SolveCubic(a, b, c, d)); + BReal d(y0 - y); + BReal c((y1 - y0)*BReal(3)); + BReal b((y2 - y1)*BReal(3) - c); + BReal a(y3 -y0 - c - b); + vector results(SolveCubic(a, b, c, d)); for (unsigned i = 0; i < results.size(); ++i) { Vec2 p; @@ -368,7 +368,7 @@ vector Bezier::SolveYParam(const Real & y) const return results; } -vector Bezier::Evaluate(const vector & u) const +vector Bezier::Evaluate(const vector & u) const { vector result(u.size()); for (unsigned i = 0; i < u.size(); ++i) @@ -381,25 +381,25 @@ vector Bezier::Evaluate(const vector & u) const /** * Get Bounds Rectangle of Bezier */ -Rect Bezier::SolveBounds() const +BRect Bezier::SolveBounds() const { - Rect result; - pair tsols = BezierTurningPoints(x0, x1, x2, x3); + BRect result; + pair tsols = BezierTurningPoints(x0, x1, x2, x3); - Real tp0; Real tp1; Real o; + BReal tp0; BReal tp1; BReal o; Evaluate(tp0, o, tsols.first); Evaluate(tp1, o, tsols.second); //Debug("x: tp0 is %f tp1 is %f", Float(tp0), Float(tp1)); - vector v(4); + vector v(4); v[0] = &x0; v[1] = &x3; v[2] = &tp0; v[3] = &tp1; // Not using a lambda to keep this compiling on cabellera - sort(v.begin(), v.end(), CompRealByPtr); + sort(v.begin(), v.end(), CompBRealByPtr); result.x = *(v[0]); result.w = *(v[3]) - result.x; @@ -416,7 +416,7 @@ Rect Bezier::SolveBounds() const v[1] = &y3; v[2] = &tp0; v[3] = &tp1; - sort(v.begin(), v.end(), CompRealByPtr); + sort(v.begin(), v.end(), CompBRealByPtr); result.y = *(v[0]); result.h = *(v[3]) - result.y; diff --git a/src/bezier.h b/src/bezier.h index c0e1e34..3f47555 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -3,36 +3,38 @@ #include #include - -#include "real.h" #include "rect.h" +#include "real.h" namespace IPDF { + typedef Real BReal; + typedef TRect BRect; + extern int Factorial(int n); extern int BinomialCoeff(int n, int k); - extern Real Bernstein(int k, int n, const Real & u); - extern std::pair BezierTurningPoints(const Real & p0, const Real & p1, const Real & p2, const Real & p3); + extern BReal Bernstein(int k, int n, const BReal & u); + extern std::pair BezierTurningPoints(const BReal & p0, const BReal & p1, const BReal & p2, const BReal & p3); - extern std::vector SolveQuadratic(const Real & a, const Real & b, const Real & c, const Real & min = 0, const Real & max = 1); + extern std::vector SolveQuadratic(const BReal & a, const BReal & b, const BReal & c, const BReal & min = 0, const BReal & max = 1); - extern std::vector 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); + extern std::vector SolveCubic(const BReal & a, const BReal & b, const BReal & c, const BReal & d, const BReal & min = 0, const BReal & max = 1, const BReal & delta = 1e-9); /** A _cubic_ bezier. **/ struct Bezier { - Real x0; Real y0; - Real x1; Real y1; - Real x2; Real y2; - Real x3; Real y3; + BReal x0; BReal y0; + BReal x1; BReal y1; + BReal x2; BReal y2; + BReal x3; BReal y3; 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=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) + Bezier(BReal _x0=0, BReal _y0=0, BReal _x1=0, BReal _y1=0, BReal _x2=0, BReal _y2=0, BReal _x3=0, BReal _y3=0) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x3), y3(_y3), type(UNKNOWN) { } @@ -43,30 +45,30 @@ namespace IPDF return type; // From Loop-Blinn 2005, with w0 == w1 == w2 == w3 = 1 // Transformed control points: (a0 = x0, b0 = y0) - Real a1 = (x1-x0)*Real(3); - Real a2 = (x0- x1*Real(2) +x2)*Real(3); - Real a3 = (x3 - x0 + (x1 - x2)*Real(3)); + BReal a1 = (x1-x0)*BReal(3); + BReal a2 = (x0- x1*BReal(2) +x2)*BReal(3); + BReal a3 = (x3 - x0 + (x1 - x2)*BReal(3)); - Real b1 = (y1-y0)*Real(3); - Real b2 = (y0- y1*Real(2) +y2)*Real(3); - Real b3 = (y3 - y0 + (y1 - y2)*Real(3)); + BReal b1 = (y1-y0)*BReal(3); + BReal b2 = (y0- y1*BReal(2) +y2)*BReal(3); + BReal b3 = (y3 - y0 + (y1 - y2)*BReal(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; + BReal d1 = a2*b3 - a3*b2; + BReal d2 = a3*b1 - a1*b3; + BReal d3 = a1*b2 - a2*b1; - if (Abs(d1+d2+d3) < Real(1e-6)) + if (Abs(d1+d2+d3) < BReal(1e-6)) { type = LINE; //Debug("LINE %s", Str().c_str()); return type; } - Real delta1 = -(d1*d1); - Real delta2 = d1*d2; - Real delta3 = d1*d3 -(d2*d2); - if (Abs(delta1+delta2+delta3) < Real(1e-6)) + BReal delta1 = -(d1*d1); + BReal delta2 = d1*d2; + BReal delta3 = d1*d3 -(d2*d2); + if (Abs(delta1+delta2+delta3) < BReal(1e-6)) { type = QUADRATIC; @@ -74,13 +76,13 @@ namespace IPDF return type; } - Real discriminant = d1*d3*Real(4) -d2*d2; - if (Abs(discriminant) < Real(1e-6)) + BReal discriminant = d1*d3*BReal(4) -d2*d2; + if (Abs(discriminant) < BReal(1e-6)) { type = CUSP; //Debug("CUSP %s", Str().c_str()); } - else if (discriminant > Real(0)) + else if (discriminant > BReal(0)) { type = SERPENTINE; //Debug("SERPENTINE %s", Str().c_str()); @@ -106,7 +108,7 @@ namespace IPDF * Construct absolute control points using relative control points to a bounding rectangle * ie: If cpy is relative to bounds rectangle, this will be absolute */ - Bezier(const Bezier & cpy, const Rect & t = Rect(0,0,1,1)) : x0(cpy.x0), y0(cpy.y0), x1(cpy.x1), y1(cpy.y1), x2(cpy.x2),y2(cpy.y2), x3(cpy.x3), y3(cpy.y3), type(cpy.type) + Bezier(const Bezier & cpy, const BRect & t = BRect(0,0,1,1)) : x0(cpy.x0), y0(cpy.y0), x1(cpy.x1), y1(cpy.y1), x2(cpy.x2),y2(cpy.y2), x3(cpy.x3), y3(cpy.y3), type(cpy.type) { x0 *= t.w; y0 *= t.h; @@ -126,14 +128,14 @@ namespace IPDF y3 += t.y; } - Rect SolveBounds() const; + BRect SolveBounds() const; - std::pair GetTop() const; - std::pair GetBottom() const; - std::pair GetLeft() const; - std::pair GetRight() const; + std::pair GetTop() const; + std::pair GetBottom() const; + std::pair GetLeft() const; + std::pair GetRight() const; - Bezier ToAbsolute(const Rect & bounds) const + Bezier ToAbsolute(const BRect & bounds) const { return Bezier(*this, bounds); } @@ -142,14 +144,14 @@ namespace IPDF * (This basically does the opposite of the Copy constructor) * ie: If this is absolute, the returned Bezier will be relative to the bounds rectangle */ - Bezier ToRelative(const Rect & bounds) const + Bezier ToRelative(const BRect & bounds) const { // x' <- (x - x0)/w etc // special cases when w or h = 0 // (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}; + // BRect inverse = {-bounds.x/bounds.w, -bounds.y/bounds.h, BReal(1)/bounds.w, BReal(1)/bounds.h}; Bezier result; - if (bounds.w == Real(0)) + if (bounds.w == 0) { result.x0 = 0; result.x1 = 0; @@ -164,7 +166,7 @@ namespace IPDF result.x3 = (x3 - bounds.x)/bounds.w; } - if (bounds.h == Real(0)) + if (bounds.h == 0) { result.y0 = 0; result.y1 = 0; @@ -182,68 +184,68 @@ namespace IPDF } // Performs one round of De Casteljau subdivision and returns the [t,1] part. - Bezier DeCasteljauSubdivideLeft(const Real& t) + Bezier DeCasteljauSubdivideLeft(const BReal& t) { - Real one_minus_t = Real(1) - t; + BReal one_minus_t = BReal(1) - t; // X Coordinates - Real x01 = x1*t + x0*one_minus_t; - Real x12 = x2*t + x1*one_minus_t; - Real x23 = x3*t + x2*one_minus_t; + BReal x01 = x1*t + x0*one_minus_t; + BReal x12 = x2*t + x1*one_minus_t; + BReal x23 = x3*t + x2*one_minus_t; - Real x012 = x12*t + x01*one_minus_t; - Real x123 = x23*t + x12*one_minus_t; + BReal x012 = x12*t + x01*one_minus_t; + BReal x123 = x23*t + x12*one_minus_t; - Real x0123 = x123*t + x012*one_minus_t; + BReal x0123 = x123*t + x012*one_minus_t; // Y Coordinates - Real y01 = y1*t + y0*one_minus_t; - Real y12 = y2*t + y1*one_minus_t; - Real y23 = y3*t + y2*one_minus_t; + BReal y01 = y1*t + y0*one_minus_t; + BReal y12 = y2*t + y1*one_minus_t; + BReal y23 = y3*t + y2*one_minus_t; - Real y012 = y12*t + y01*one_minus_t; - Real y123 = y23*t + y12*one_minus_t; + BReal y012 = y12*t + y01*one_minus_t; + BReal y123 = y23*t + y12*one_minus_t; - Real y0123 = y123*t + y012*one_minus_t; + BReal y0123 = y123*t + y012*one_minus_t; return Bezier(x0, y0, x01, y01, x012, y012, x0123, y0123); } // Performs one round of De Casteljau subdivision and returns the [t,1] part. - Bezier DeCasteljauSubdivideRight(const Real& t) + Bezier DeCasteljauSubdivideRight(const BReal& t) { - Real one_minus_t = Real(1) - t; + BReal one_minus_t = BReal(1) - t; // X Coordinates - Real x01 = x1*t + x0*one_minus_t; - Real x12 = x2*t + x1*one_minus_t; - Real x23 = x3*t + x2*one_minus_t; + BReal x01 = x1*t + x0*one_minus_t; + BReal x12 = x2*t + x1*one_minus_t; + BReal x23 = x3*t + x2*one_minus_t; - Real x012 = x12*t + x01*one_minus_t; - Real x123 = x23*t + x12*one_minus_t; + BReal x012 = x12*t + x01*one_minus_t; + BReal x123 = x23*t + x12*one_minus_t; - Real x0123 = x123*t + x012*one_minus_t; + BReal x0123 = x123*t + x012*one_minus_t; // Y Coordinates - Real y01 = y1*t + y0*one_minus_t; - Real y12 = y2*t + y1*one_minus_t; - Real y23 = y3*t + y2*one_minus_t; + BReal y01 = y1*t + y0*one_minus_t; + BReal y12 = y2*t + y1*one_minus_t; + BReal y23 = y3*t + y2*one_minus_t; - Real y012 = y12*t + y01*one_minus_t; - Real y123 = y23*t + y12*one_minus_t; + BReal y012 = y12*t + y01*one_minus_t; + BReal y123 = y23*t + y12*one_minus_t; - Real y0123 = y123*t + y012*one_minus_t; + BReal y0123 = y123*t + y012*one_minus_t; return Bezier(x0123, y0123, x123, y123, x23, y23, x3, y3); } - Bezier ReParametrise(const Real& t0, const Real& t1) + Bezier ReParametrise(const BReal& t0, const BReal& t1) { //Debug("Reparametrise: %f -> %f",Double(t0),Double(t1)); Bezier new_bezier; // Subdivide to get from [0,t1] new_bezier = DeCasteljauSubdivideLeft(t1); // Convert t0 from [0,1] range to [0, t1] - Real new_t0 = t0 / t1; + BReal new_t0 = t0 / t1; //Debug("New t0 = %f", Double(new_t0)); new_bezier = new_bezier.DeCasteljauSubdivideRight(new_t0); @@ -251,40 +253,40 @@ namespace IPDF return new_bezier; } - std::vector ClipToRectangle(const Rect& r) + std::vector ClipToRectangle(const BRect & r) { // Find points of intersection with the rectangle. - Debug("Clipping Bezier to Rect %s", r.Str().c_str()); + Debug("Clipping Bezier to BRect %s", r.Str().c_str()); // Find its roots. - std::vector x_intersection = SolveXParam(r.x); + std::vector x_intersection = SolveXParam(r.x); //Debug("Found %d intersections on left edge", x_intersection.size()); // And for the other side. - std::vector x_intersection_pt2 = SolveXParam(r.x + r.w); + std::vector 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 y_intersection = SolveYParam(r.y); + std::vector y_intersection = SolveYParam(r.y); //Debug("Found %d intersections on top edge", y_intersection.size()); - std::vector y_intersection_pt2 = SolveYParam(r.y+r.h); + std::vector 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()); - x_intersection.push_back(Real(0)); - x_intersection.push_back(Real(1)); + x_intersection.push_back(BReal(0)); + x_intersection.push_back(BReal(1)); std::sort(x_intersection.begin(), x_intersection.end()); //Debug("Found %d intersections.\n", x_intersection.size()); /*for(auto t : x_intersection) { - Real ptx, pty; + BReal ptx, pty; Evaluate(ptx, pty, t); Debug("Root: t = %f, (%f,%f)", Double(t), Double(ptx), Double(pty)); }*/ @@ -295,14 +297,14 @@ namespace IPDF all_beziers.push_back(*this); return all_beziers; } - Real t0 = *(x_intersection.begin()); + BReal t0 = *(x_intersection.begin()); for (auto it = x_intersection.begin()+1; it != x_intersection.end(); ++it) { - Real t1 = *it; + BReal t1 = *it; if (t1 == t0) continue; - //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))); + //Debug(" -- t0: %f to t1: %f: %f", Double(t0), Double(t1), Double((t1 + t0)/BReal(2))); + BReal ptx, pty; + Evaluate(ptx, pty, ((t1 + t0) / BReal(2))); if (r.PointIn(ptx, pty)) { //Debug("Adding segment: (point at %f, %f)", Double(ptx), Double(pty)); @@ -318,26 +320,26 @@ namespace IPDF } /** Evaluate the Bezier at parametric parameter u, puts resultant point in (x,y) **/ - void Evaluate(Real & x, Real & y, const Real & u) const + void Evaluate(BReal & x, BReal & y, const BReal & u) const { - Real coeff[4]; + BReal coeff[4]; for (unsigned i = 0; i < 4; ++i) coeff[i] = Bernstein(i,3,u); x = x0*coeff[0] + x1*coeff[1] + x2*coeff[2] + x3*coeff[3]; y = y0*coeff[0] + y1*coeff[1] + y2*coeff[2] + y3*coeff[3]; } - std::vector Evaluate(const std::vector & u) const; + std::vector Evaluate(const std::vector & u) const; - std::vector SolveXParam(const Real & x) const; - std::vector SolveYParam(const Real & x) const; + std::vector SolveXParam(const BReal & x) const; + std::vector SolveYParam(const BReal & x) const; // Get points with same X - inline std::vector SolveX(const Real & x) const + inline std::vector SolveX(const BReal & x) const { return Evaluate(SolveXParam(x)); } // Get points with same Y - inline std::vector SolveY(const Real & y) const + inline std::vector SolveY(const BReal & y) const { return Evaluate(SolveYParam(y)); } @@ -357,6 +359,4 @@ namespace IPDF } -#undef Real - #endif //_BEZIER_H diff --git a/src/debugscript.cpp b/src/debugscript.cpp index f92153c..9bb5ea6 100644 --- a/src/debugscript.cpp +++ b/src/debugscript.cpp @@ -97,6 +97,22 @@ void DebugScript::ParseAction() currentAction.type = AT_Debug; getline(inp,currentAction.textargs); } + else if (actionType == "clear") + { + currentAction.type = AT_ClearDocument; + } + else if (actionType == "clearperf") + { + currentAction.type = AT_ClearPerformance; + } + else if (actionType == "printperf") + { + currentAction.type = AT_PrintPerformance; + } + else if (actionType == "recordperf") + { + currentAction.type = AT_RecordPerformance; + } } bool DebugScript::Execute(View *view, Screen *scr) @@ -176,9 +192,49 @@ bool DebugScript::Execute(View *view, Screen *scr) if (currentAction.textargs.size() > 0) Debug("%s", currentAction.textargs.c_str()); break; + case AT_ClearDocument: + view->Doc().ClearObjects(); + currentAction.loops = 1; + break; + case AT_ClearPerformance: + ClearPerformance(view, scr); + currentAction.loops = 1; + break; + case AT_PrintPerformance: + PrintPerformance(view, scr); + currentAction.loops = 1; + break; + case AT_RecordPerformance: + PrintPerformance(view, scr); + break; default: Fatal("Unknown script command in queue."); } currentAction.loops--; return false; } + +void DebugScript::ClearPerformance(View * view, Screen * scr) +{ + m_perf_start.clock = clock(); + m_perf_start.object_count = view->Doc().ObjectCount(); + m_perf_start.view_bounds = view->GetBounds(); + m_perf_last = m_perf_start; +} + +void DebugScript::PrintPerformance(View * view, Screen * scr) +{ + DebugScript::PerformanceData now; + now.clock = clock(); + now.object_count = view->Doc().ObjectCount(); + now.view_bounds = view->GetBounds(); + // object_count delta clock delta x deltax y deltay w deltaw h deltah + printf("%d\t%d\t%lu\t%lu\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n", + now.object_count, now.object_count - m_perf_last.object_count, + (uint64_t)now.clock, (uint64_t)(now.clock - m_perf_last.clock), + Double(now.view_bounds.x), Double(now.view_bounds.x - m_perf_last.view_bounds.x), + Double(now.view_bounds.y), Double(now.view_bounds.y - m_perf_last.view_bounds.y), + Double(now.view_bounds.w), Double(now.view_bounds.w - m_perf_last.view_bounds.w), + Double(now.view_bounds.h), Double(now.view_bounds.h - m_perf_last.view_bounds.h)); + m_perf_last = now; +} diff --git a/src/debugscript.h b/src/debugscript.h index 8b62b5c..9895ddc 100644 --- a/src/debugscript.h +++ b/src/debugscript.h @@ -36,6 +36,10 @@ private: AT_Label, AT_Goto, AT_Debug, + AT_ClearDocument, + AT_ClearPerformance, + AT_PrintPerformance, + AT_RecordPerformance, AT_Quit }; @@ -57,6 +61,20 @@ private: std::vector m_actions; std::map m_labels; unsigned m_index; + + struct PerformanceData + { + clock_t clock; + unsigned object_count; + Rect view_bounds; + }; + + PerformanceData m_perf_start; + PerformanceData m_perf_last; + + void PrintPerformance(View * view, Screen * scr); + void ClearPerformance(View * view, Screen * scr); + void ParseAction(); }; diff --git a/src/document.cpp b/src/document.cpp index bcf003b..c41c848 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -4,6 +4,7 @@ #include #include "../contrib/pugixml-1.4/src/pugixml.cpp" +#include "transformationtype.h" #include "stb_truetype.h" @@ -1059,8 +1060,8 @@ void Document::TranslateObjects(const Real & dx, const Real & dy, ObjectType typ for (unsigned i = 0; i < m_objects.paths.size(); ++i) { Path & p = m_objects.paths[i]; - p.x += dx; - p.y += dy; + p.m_bounds.x += dx; + p.m_bounds.y += dy; } return; #endif @@ -1081,14 +1082,14 @@ void Document::ScaleObjectsAboutPoint(const Real & x, const Real & y, const Real 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; + p.m_bounds.w /= scale_amount; + p.m_bounds.h /= scale_amount; + p.m_bounds.x -= x; + p.m_bounds.x /= scale_amount; + p.m_bounds.x += x; + p.m_bounds.y -= y; + p.m_bounds.y /= scale_amount; + p.m_bounds.y += y; } return; #endif diff --git a/src/document.h b/src/document.h index 57dbb9d..d67b0b2 100644 --- a/src/document.h +++ b/src/document.h @@ -94,6 +94,13 @@ namespace IPDF int ClipObjectToQuadChild(int object_id, QuadTreeNodeChildren type); #endif + void ClearObjects() + { + m_count = 0; + m_objects.Clear(); + } + + private: friend class View; Objects m_objects; diff --git a/src/eye_of_the_rabbit.script b/src/eye_of_the_rabbit.script index a96efa6..af3116d 100644 --- a/src/eye_of_the_rabbit.script +++ b/src/eye_of_the_rabbit.script @@ -1,7 +1,9 @@ # Test how well document scales back to original... gpu lazy +clearperf label start +printperf debug Add rabbit 1 loadsvg svg-tests/rabbit_simple.svg loop 250 pxzoom 508 305 1 @@ -11,9 +13,8 @@ loop 250 pxzoom 508 305 1 debug Add rabbit 3 loadsvg svg-tests/rabbit_simple.svg loop 500 pxzoom 508 305 -1 -loop 250 pxzoom 508 305 1 -loop 1000 wait -loop 250 pxzoom 508 305 1 +loop 500 pxzoom 508 305 1 debug Repeat -#goto start +clear +goto start wait diff --git a/src/gmprat.h b/src/gmprat.h index 5df43ef..e0472ca 100644 --- a/src/gmprat.h +++ b/src/gmprat.h @@ -21,6 +21,7 @@ class Gmprat //operator int64_t() const {return mpq_get_si(m_op);} //operator uint64_t() const {return mpq_get_ui(m_op);} //operator double() const {return mpq_get_d(m_op);} + //operator float() const {return (float)ToDouble();} double ToDouble() const {return mpq_get_d(m_op);} std::string Str(int base = 10) const { @@ -57,9 +58,16 @@ class Gmprat private: + friend std::ostream& operator<<(std::ostream& os, const Gmprat & fith); mpq_t m_op; }; +std::ostream & operator<<(std::ostream & os, const Gmprat & fith) +{ + os << fith.Str(); + return os; +} + diff --git a/src/ipdf.h b/src/ipdf.h index 9b4c04a..20e47c0 100644 --- a/src/ipdf.h +++ b/src/ipdf.h @@ -51,6 +51,15 @@ namespace IPDF std::vector beziers; // bezier curves - look up by data_indices /** Used by PATH only **/ std::vector paths; + + void Clear() + { + types.clear(); + bounds.clear(); + data_indices.clear(); + beziers.clear(); + paths.clear(); + } }; class View; diff --git a/src/main.h b/src/main.h index b0c7a47..108e392 100644 --- a/src/main.h +++ b/src/main.h @@ -74,7 +74,7 @@ void RatCatcher(int x, int y, int buttons, int wheel, Screen * scr, View * view) } -inline void MainLoop(Document & doc, Screen & scr, View & view, int max_frames = -1) +void MainLoop(Document & doc, Screen & scr, View & view, int max_frames = -1) { // order is important... segfaults occur when screen (which inits GL) is not constructed first -_- DebugScript script; diff --git a/src/path.cpp b/src/path.cpp index 251de1e..0516e5b 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -54,17 +54,12 @@ Path::Path(Objects & objects, unsigned start, unsigned end, const Colour & fill, 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(); + m_bounds = SolveBounds(objects).Convert(); #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) { //Debug("Transform %s -> %s", objects.bounds[i].Str().c_str(), bounds.Str().c_str()); - objects.bounds[i] = TransformRectCoordinates(bounds, objects.bounds[i]); + objects.bounds[i] = TransformRectCoordinates(m_bounds.Convert(), objects.bounds[i]); //Debug("-> %s", objects.bounds[i].Str().c_str()); } #endif @@ -198,18 +193,12 @@ vector & Path::FillPoints(const Objects & objects, const View & view) Rect Path::SolveBounds(const Objects & objects) { - #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 + 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) { - #ifdef TRANSFORM_BEZIERS_TO_PATH - objects.bounds[m_index] = Rect(Real(x.ToDouble()), Real(y.ToDouble()), Real(w.ToDouble()), Real(h.ToDouble())); - #endif + objects.bounds[m_index] = m_bounds.Convert(); return objects.bounds[m_index]; } diff --git a/src/path.h b/src/path.h index eb2b7b7..2aa7840 100644 --- a/src/path.h +++ b/src/path.h @@ -1,22 +1,26 @@ #ifndef _PATH_H #define _PATH_H +#include "transformationtype.h" #include #include #include "rect.h" #include "real.h" -#ifdef QUADTREE_DISABLED - -#define TRANSFORM_BEZIERS_TO_PATH #ifdef TRANSFORM_BEZIERS_TO_PATH -#include "gmprat.h" -#endif + #include "gmprat.h" #endif + namespace IPDF { + #ifdef TRANSFORM_BEZIERS_TO_PATH + typedef Gmprat PReal; + #else + typedef Real PReal; + #endif + typedef TRect PRect; struct Colour { @@ -55,12 +59,8 @@ namespace IPDF std::vector m_fill_points; - #ifdef TRANSFORM_BEZIERS_TO_PATH - Gmprat x; - Gmprat y; - Gmprat w; - Gmprat h; - #endif + PRect m_bounds; + 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 7f29ca8..72def69 100644 --- a/src/real.h +++ b/src/real.h @@ -20,6 +20,10 @@ #error "REALTYPE was not defined!" #endif +#define XSTR(x) STR(x) +#define STR(x) #x +#pragma message "REALTYPE = " XSTR(REALTYPE) + #if REALTYPE == REAL_VFPU #include "vfpu.h" #endif @@ -57,12 +61,15 @@ namespace IPDF #if REALTYPE == REAL_SINGLE typedef float Real; inline Real RealFromStr(const char * str) {return strtof(str, NULL);} + inline std::string Str(const Real & a) {std::stringstream s; s << a; return s.str();} #elif REALTYPE == REAL_DOUBLE typedef double Real; inline Real RealFromStr(const char * str) {return strtod(str, NULL);} + inline std::string Str(const Real & a) {std::stringstream s; s << a; return s.str();} #elif REALTYPE == REAL_LONG_DOUBLE typedef long double Real; inline Real RealFromStr(const char * str) {return strtold(str, NULL);} + inline std::string Str(const Real & a) {std::stringstream s; s << a; return s.str();} #elif REALTYPE == REAL_VFPU typedef VFPU::VFloat Real; inline float Float(const Real & r) {return r.m_value;} @@ -113,6 +120,7 @@ namespace IPDF inline Real Sqrt(const Real & r) {return Real(sqrt(r.ToDouble()));} inline Real RealFromStr(const char * str) {return Real(strtod(str, NULL));} inline Real Abs(const Real & a) {return (a > Real(0)) ? a : Real(0)-a;} + inline std::string Str(const Real & a) {return a.Str();} #else #error "Type of Real unspecified." @@ -128,6 +136,8 @@ 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) { if (a < INT64_MIN) @@ -194,7 +204,6 @@ namespace IPDF #endif #endif } - } #endif //_REAL_H diff --git a/src/rect.h b/src/rect.h index b092fbe..25ef94e 100644 --- a/src/rect.h +++ b/src/rect.h @@ -6,19 +6,21 @@ namespace IPDF { - struct Rect + template + struct TRect { - Real x; Real y; Real w; Real h; - //Rect() = default; // Needed so we can fread/fwrite this struct - Rect(Real _x=0, Real _y=0, Real _w=1, Real _h=1) : x(_x), y(_y), w(_w), h(_h) {} + T x; T y; T w; T h; + //TRect() = default; // Needed so we can fread/fwrite this struct + TRect(T _x=0, T _y=0, T _w=1, T _h=1) : x(_x), y(_y), w(_w), h(_h) {} + std::string Str() const { std::stringstream s; // float conversion needed because it is fucking impossible to get ostreams working with template classes - s << "{" << Float(x) << ", " << Float(y) << ", " << Float(x + w) << ", " << Float(y + h) << " (w: " << Float(w) <<", h: " << Float(h) <<")}"; + s << "{" << x << ", " << y << ", " << (x + w) << ", " << (y + h) << " (w: " << w <<", h: " << h <<")}"; return s.str(); } - inline bool PointIn(Real pt_x, Real pt_y) const + inline bool PointIn(T pt_x, T pt_y) const { if (pt_x <= x) return false; if (pt_y <= y) return false; @@ -27,7 +29,7 @@ namespace IPDF return true; } - inline bool Intersects(const Rect& other) const + inline bool Intersects(const TRect& other) const { if (x + w < other.x) return false; if (y + h < other.y) return false; @@ -35,13 +37,18 @@ namespace IPDF if (y > other.y + other.h) return false; return true; } + + template TRect Convert() {return TRect(B(x), B(y), B(w), B(h));} }; - inline Rect TransformRectCoordinates(const Rect& view, const Rect& r) + + + template + inline TRect TransformRectCoordinates(const TRect & view, const TRect & r) { - Rect out; - Real w = (view.w == Real(0))?Real(1):view.w; - Real h = (view.h == Real(0))?Real(1):view.h; + TRect out; + T w = (view.w == T(0))?T(1):view.w; + T h = (view.h == T(0))?T(1):view.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 @@ -49,14 +56,18 @@ namespace IPDF return out; } - inline Vec2 TransformPointCoordinates(const Rect& view, const Vec2& v) + + template + inline Vec2 TransformPointCoordinates(const TRect & view, const Vec2& v) { Vec2 out; out.x = (v.x - view.x) / view.w; out.y = (v.y - view.y) / view.h; return out; } - + + typedef TRect Rect; + } diff --git a/src/transformationtype.h b/src/transformationtype.h new file mode 100644 index 0000000..4f27d5f --- /dev/null +++ b/src/transformationtype.h @@ -0,0 +1,9 @@ +#ifndef _TRANSFORMATIONTYPE_H +#define _TRANSFORMATIONTYPE_H + +#ifdef QUADTREE_DISABLED +#define TRANSFORM_OBJECTS_NOT_VIEW +#define TRANSFORM_BEZIERS_TO_PATH +#endif + +#endif diff --git a/src/view.cpp b/src/view.cpp index 1bd5730..0807643 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -24,7 +24,7 @@ using namespace std; * @param bounds - Initial bounds of the View * @param colour - Colour to use for rendering this view. TODO: Make sure this actually works, or just remove it */ -View::View(Document & document, Screen & screen, const Rect & bounds, const Colour & colour) +View::View(Document & document, Screen & screen, const VRect & bounds, const Colour & colour) : m_use_gpu_transform(USE_GPU_TRANSFORM), m_use_gpu_rendering(USE_GPU_RENDERING), m_bounds_dirty(true), m_buffer_dirty(true), 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), @@ -84,7 +84,7 @@ View::~View() * Translate the view * @param x, y - Amount to translate */ -void View::Translate(Real x, Real y) +void View::Translate(VReal x, VReal y) { if (!m_use_gpu_transform) m_buffer_dirty = true; @@ -94,7 +94,7 @@ void View::Translate(Real x, Real y) #ifdef TRANSFORM_BEZIERS_TO_PATH type = PATH; #endif - m_document.TranslateObjects(-x, -y, type); + m_document.TranslateObjects(-x.ToDouble(), -y.ToDouble(), type); #endif x *= m_bounds.w; y *= m_bounds.h; @@ -125,7 +125,7 @@ void View::SetBounds(const Rect & bounds) * @param x, y - Coordinates to scale at (eg: Mouse cursor position) * @param scale_amount - Amount to scale by */ -void View::ScaleAroundPoint(Real x, Real y, Real scale_amount) +void View::ScaleAroundPoint(VReal x, VReal y, VReal scale_amount) { // (x0, y0, w, h) -> (x*w - (x*w - x0)*s, y*h - (y*h - y0)*s, w*s, h*s) @@ -148,8 +148,8 @@ void View::ScaleAroundPoint(Real x, Real y, Real scale_amount) x += m_bounds.x; y += m_bounds.y; - Real top = y - m_bounds.y; - Real left = x - m_bounds.x; + VReal top = y - m_bounds.y; + VReal left = x - m_bounds.x; top *= scale_amount; left *= scale_amount; diff --git a/src/view.h b/src/view.h index 5ea06a0..47eb0fb 100644 --- a/src/view.h +++ b/src/view.h @@ -5,19 +5,26 @@ #include "document.h" #include "framebuffer.h" #include "objectrenderer.h" +#include "path.h" +#include "transformationtype.h" #define USE_GPU_TRANSFORM true #define USE_GPU_RENDERING true #define USE_SHADING !(USE_GPU_RENDERING) && true -#ifdef QUADTREE_DISABLED - -#define TRANSFORM_OBJECTS_NOT_VIEW - +#ifdef TRANSFORM_BEZIERS_TO_PATH +#include "gmprat.h" #endif namespace IPDF { + #ifdef TRANSFORM_BEZIERS_TO_PATH + typedef Gmprat VReal; + #else + typedef Real VReal; + #endif + typedef TRect VRect; + class Screen; /** * The View class manages a rectangular view into the document. @@ -27,18 +34,18 @@ namespace IPDF class View { public: - View(Document & document, Screen & screen, const Rect & bounds = Rect(0,0,1,1), const Colour & colour = Colour(0.f,0.f,0.f,1.f)); + View(Document & document, Screen & screen, const VRect & bounds = VRect(0,0,1,1), const Colour & colour = Colour(0.f,0.f,0.f,1.f)); virtual ~View(); void Render(int width = 0, int height = 0); - void Translate(Real x, Real y); - void ScaleAroundPoint(Real x, Real y, Real scale_amount); + void Translate(VReal x, VReal y); + void ScaleAroundPoint(VReal x, VReal y, VReal scale_amount); void SetBounds(const Rect & new_bounds); Rect TransformToViewCoords(const Rect& inp) const; - const Rect& GetBounds() const { return m_bounds; } + const VRect& GetBounds() const { return m_bounds; } const bool UsingGPUTransform() const { return m_use_gpu_transform; } // whether view transform calculated on CPU or GPU @@ -95,7 +102,7 @@ namespace IPDF Document & m_document; Screen & m_screen; FrameBuffer m_cached_display; - Rect m_bounds; + VRect m_bounds; Colour m_colour; // Stores the view bounds. -- 2.20.1