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);
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];
#include "real.h"
#include "rect.h"
+
+
namespace IPDF
{
extern int Factorial(int n);
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;
}
}
}
-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;
m_objects.bounds[i].y -= y;
m_objects.bounds[i].y /= scale_amount;
m_objects.bounds[i].y += 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);
+ 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; }
# Test how well document scales back to original...
-gpu
+cpu
lazy
label start
debug Add rabbit 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
if (!RecreateBuffer(data))
{
Bind();
- glBufferData(target, length, data, usage);
+ glBufferData(target, length+1, data, usage);
}
if (data != NULL)
m_invalidated = false;
void GraphicsBuffer::Resize(size_t length)
{
- if (m_invalidated)
+ if (m_invalidated && m_buffer_size > length)
{
m_buffer_size = length;
}
{
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
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");
}
-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())
{
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();
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
}
/**
*/
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;
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);
}
}
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),
};
builder.Add(coeffs);
}
+
m_bezier_coeffs.UnMap();
glGenTextures(1, &m_bezier_buffer_texture);
glBindTexture(GL_TEXTURE_BUFFER, m_bezier_buffer_texture);
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);
}
}
+ #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)
{
}
}
+
+
+
/**
* For debug, save pixels to bitmap
*/
SDL_FreeSurface(surf);
}
+
+
+
/**
* Bresenham's lines
*/
#include "shaderprogram.h"
#include "bufferbuilder.h"
+#define BEZIER_CPU_DECASTELJAU
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;
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
m_size = 1;
#endif
#ifdef PARANOID_CACHE_RESULTS
- m_cached_result = NAN;
+ m_cache_valid = false;
#endif
int dp = 0;
#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)
{
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
{
////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)
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);
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)
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;
// 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
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;
}
{
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
//#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
#endif
#ifdef PARANOID_CACHE_RESULTS
m_cached_result = value;
+ m_cache_valid = true;
#endif
}
#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)
{
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
class Arena
{
public:
- Arena(int64_t block_size = 10000000);
+ Arena(int64_t block_size = 10000);
~Arena();
void * allocate(size_t bytes);
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);
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;
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
}
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];
}
}
#include "rect.h"
#include "real.h"
+#ifdef QUADTREE_DISABLED
+
+#define TRANSFORM_BEZIERS_TO_PATH
+
+
+#endif
+
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?
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;
}
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>
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)
{
#include "main.h"
#include "real.h"
+#include "progressbar.h"
using namespace std;
using namespace IPDF;
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);
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);
#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;
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;
#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;
#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);
}
/**
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;
};
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();
}
/**
m_object_renderers[i]->FinaliseBuffers();
}
if (UsingGPURendering())
+ {
dynamic_cast<BezierRenderer*>(m_object_renderers[BEZIER])->PrepareBezierGPUBuffer(m_document.m_objects);
+ }
m_render_dirty = false;
}
#ifdef QUADTREE_DISABLED
-#define TRANSFORM_OBJECTS_NOT_VIEW
+//#define TRANSFORM_OBJECTS_NOT_VIEW
#endif