From: David Gow Date: Mon, 25 Aug 2014 08:54:46 +0000 (+0800) Subject: Merge branch 'master' of git.ucc.asn.au:ipdf/code X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=67fbce330b046b1f0d63222f04d83410dc1b2faa;hp=441976b6cd6631af1d77fc60efc56948c562be1a Merge branch 'master' of git.ucc.asn.au:ipdf/code Conflicts: src/document.cpp --- diff --git a/src/Makefile b/src/Makefile index bc07e1e..af72dfa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ ARCH := $(shell uname -m) # TODO: stb_truetype doesn't compile with some of these warnings. CXX = g++ -std=gnu++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 vfpu.o quadtree.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o add_digits_asm.o sub_digits_asm.o mul_digits_asm.o div_digits_asm.o arbint.o moc_controlpanel.o controlpanel.o +OBJ = log.o real.o bezier.o document.o objectrenderer.o view.o screen.o vfpu.o quadtree.o graphicsbuffer.o framebuffer.o shaderprogram.o stb_truetype.o gl_core44.o add_digits_asm.o sub_digits_asm.o mul_digits_asm.o div_digits_asm.o arbint.o moc_controlpanel.o controlpanel.o group.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 diff --git a/src/bezier.h b/src/bezier.h index 07f2178..17bc5b6 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -78,14 +78,17 @@ namespace IPDF Real x1; Real y1; Real x2; Real y2; Real x3; Real y3; + + typedef enum {LINE, QUADRATIC, CUSP, LOOP, SERPENTINE} Type; + Type type; + Bezier() = default; // Needed so we can fread/fwrite this struct... for now. Bezier(Real _x0, Real _y0, Real _x1, Real _y1, Real _x2, Real _y2, Real _x3, Real _y3) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x3), y3(_y3) { - + //TODO: classify the curve + type = SERPENTINE; } - Bezier(Real _x0, Real _y0, Real _x1, Real _y1, Real _x2, Real _y2) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x2), y3(_y2) {} - std::string Str() const { std::stringstream s; @@ -97,7 +100,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) + 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) { x0 *= t.w; y0 *= t.h; diff --git a/src/controlpanel.cpp b/src/controlpanel.cpp index f2d0324..5b62e91 100644 --- a/src/controlpanel.cpp +++ b/src/controlpanel.cpp @@ -95,6 +95,16 @@ QMenu * ControlPanel::CreateViewMenu() view->addAction(m_view_set_bounds); connect(m_view_set_bounds, SIGNAL(triggered()), this, SLOT(SetViewBounds())); + m_view_show_object_bounds = new QAction("&Show Object Bounds", this); + m_view_show_object_bounds->setCheckable(true); + view->addAction(m_view_show_object_bounds); + connect(m_view_show_object_bounds, SIGNAL(triggered()), this, SLOT(ToggleShowObjectBounds())); + + m_view_enable_shading = new QAction("&Enable Shading", this); + m_view_enable_shading->setCheckable(true); + view->addAction(m_view_enable_shading); + connect(m_view_enable_shading, SIGNAL(triggered()), this, SLOT(ToggleEnableShading())); + return view; } @@ -147,6 +157,9 @@ void ControlPanel::UpdateAll() m_screen_cpu_rendering->setChecked(!using_gpu_rendering); m_screen_show_debug->setChecked(m_screen.DebugFontShown()); + m_view_show_object_bounds->setChecked(m_view.ShowingObjectBounds()); + m_view_enable_shading->setChecked(m_view.PerformingShading()); + // update things based on state const char * title; const char * tooltip; @@ -187,6 +200,20 @@ void ControlPanel::UpdateAll() setToolTip(tooltip); } +void ControlPanel::ToggleShowObjectBounds() +{ + bool state = m_view.ShowingObjectBounds(); + m_view.ShowObjectBounds(!state); + UpdateAll(); +} + +void ControlPanel::ToggleEnableShading() +{ + bool state = m_view.PerformingShading(); + m_view.PerformShading(!state); + UpdateAll(); +} + void ControlPanel::SetGPURendering() { m_view.SetGPURendering(true); diff --git a/src/controlpanel.h b/src/controlpanel.h index 90394f8..ea557d0 100644 --- a/src/controlpanel.h +++ b/src/controlpanel.h @@ -61,7 +61,9 @@ namespace IPDF private slots: void SetGPURendering(); void SetCPURendering(); + void ToggleShowObjectBounds(); void ToggleScreenDebugFont(); + void ToggleEnableShading(); void SetViewBounds(); void LoadSVGIntoDocument(); void SetDocumentFont(); @@ -105,6 +107,8 @@ namespace IPDF QAction * m_document_parse_svg; QAction * m_document_load_svg; QAction * m_view_set_bounds; + QAction * m_view_show_object_bounds; + QAction * m_view_enable_shading; QTextEdit * m_text_edit; diff --git a/src/document.cpp b/src/document.cpp index ba5a0f7..0b72a3e 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -310,7 +310,7 @@ void Document::Load(const string & filename) #endif } -unsigned Document::AddGroup(unsigned start_index, unsigned end_index) +unsigned Document::AddGroup(unsigned start_index, unsigned end_index, const Colour & fill) { Real xmin = 0; Real ymin = 0; Real xmax = 0; Real ymax = 0; @@ -331,9 +331,11 @@ unsigned Document::AddGroup(unsigned start_index, unsigned end_index) } Rect bounds(xmin,ymin, xmax-xmin, ymax-ymin); - unsigned result = Add(GROUP, bounds,0); - m_objects.groups[m_count-1].first = start_index; - m_objects.groups[m_count-1].second = end_index; + + Group group(start_index, end_index, 0U, fill); + + unsigned data_index = AddGroupData(group); + unsigned result = Add(GROUP, bounds,data_index); return result; } @@ -353,7 +355,6 @@ unsigned Document::Add(ObjectType type, const Rect & bounds, unsigned data_index m_objects.types.push_back(type); m_objects.bounds.push_back(bounds); m_objects.data_indices.push_back(data_index); - m_objects.groups.push_back(pair(data_index, data_index)); return (m_count++); // Why can't we just use the size of types or something? } @@ -363,6 +364,11 @@ unsigned Document::AddBezierData(const Bezier & bezier) return m_objects.beziers.size()-1; } +unsigned Document::AddGroupData(const Group & group) +{ + m_objects.groups.push_back(group); + return m_objects.groups.size()-1; +} void Document::DebugDumpObjects() { @@ -420,6 +426,22 @@ static void GetXYPair(const string & d, Real & x, Real & y, unsigned & i,const s y = strtod(GetToken(d, token, i, delims).c_str(),NULL); } +static bool GetKeyValuePair(const string & d, string & key, string & value, unsigned & i, const string & delims = "()[],{}<>;:=") +{ + key = ""; + string token; + while (GetToken(d, token, i, delims) == ":" || token == ";"); + key = token; + if (GetToken(d, token, i, delims) != ":") + { + Error("Expected \":\" seperating key:value pair"); + return false; + } + value = ""; + GetToken(d, value, i, delims); + return true; +} + static void TransformXYPair(Real & x, Real & y, const SVGMatrix & transform) { Real x0(x); @@ -513,6 +535,8 @@ void Document::ParseSVGNode(pugi::xml_node & root, SVGMatrix & parent_transform) ParseSVGTransform(attrib_trans.as_string(), transform); } + + if (strcmp(child.name(), "svg") == 0 || strcmp(child.name(),"g") == 0 || strcmp(child.name(), "group") == 0) { @@ -523,9 +547,64 @@ void Document::ParseSVGNode(pugi::xml_node & root, SVGMatrix & parent_transform) else if (strcmp(child.name(), "path") == 0) { string d = child.attribute("d").as_string(); - Debug("Path data attribute is \"%s\"", d.c_str()); - pair range = ParseSVGPathData(d, transform); - AddGroup(range.first, range.second); + //Debug("Path data attribute is \"%s\"", d.c_str()); + bool closed = false; + pair range = ParseSVGPathData(d, transform, closed); + if (closed) + { + Colour c(0,0,0,0); + string colour_str(""); + map style; + if (child.attribute("style")) + { + ParseSVGStyleData(child.attribute("style").as_string(), style); + } + + // Determine shading colour + if (child.attribute("fill")) + { + colour_str = child.attribute("fill").as_string(); + } + else if (style.find("fill") != style.end()) + { + colour_str = style["fill"]; + } + if (colour_str == "red") + c = {1,0,0,1}; + else if (colour_str == "blue") + c = {0,0,1,1}; + else if (colour_str == "green") + c = {0,1,0,1}; + else if (colour_str == "black") + c = {0,0,0,1}; + else if (colour_str == "white") + c = {1,1,1,1}; + else if (colour_str.size() == 7 && colour_str[0] == '#') + { + Debug("Parse colour string: \"%s\"", colour_str.c_str()); + char comp[2] = {colour_str[1], colour_str[2]}; + c.r = Real(strtoul(comp, NULL, 16))/Real(255); + comp[0] = colour_str[3]; comp[1] = colour_str[4]; + c.g = Real(strtoul(comp, NULL, 16))/Real(255); + comp[0] = colour_str[5]; comp[1] = colour_str[6]; + c.b = Real(strtoul(comp, NULL, 16))/Real(255); + c.a = 1; + Debug("Colour is: %f, %f, %f, %f", Float(c.r), Float(c.g), Float(c.b), Float(c.a)); + } + + // Determin shading alpha + if (child.attribute("fill-opacity")) + { + c.a = child.attribute("fill-opacity").as_float(); + } + else if (style.find("fill-opacity") != style.end()) + { + c.a = strtod(style["fill-opacity"].c_str(), NULL); + } + + Debug("fill-opacity is %f", Float(c.a)); + AddGroup(range.first, range.second, c); + } } else if (strcmp(child.name(), "line") == 0) @@ -583,6 +662,17 @@ void Document::ParseSVGNode(pugi::xml_node & root, SVGMatrix & parent_transform) } } +void Document::ParseSVGStyleData(const string & style, map & results) +{ + unsigned i = 0; + string key; + string value; + while (i < style.size() && GetKeyValuePair(style, key, value, i)) + { + results[key] = value; + } +} + /** * Parse an SVG string into a rectangle */ @@ -627,8 +717,9 @@ void Document::LoadSVG(const string & filename, const Rect & bounds) // Fear the wrath of the tokenizing svg data // Seriously this isn't really very DOM-like at all is it? -pair Document::ParseSVGPathData(const string & d, const SVGMatrix & transform) +pair Document::ParseSVGPathData(const string & d, const SVGMatrix & transform, bool & closed) { + closed = false; Real x[4] = {0,0,0,0}; Real y[4] = {0,0,0,0}; @@ -728,7 +819,7 @@ pair Document::ParseSVGPathData(const string & d, const SVGM } else if (command == "l" || command == "L" || command == "h" || command == "H" || command == "v" || command == "V") { - Debug("Construct lineto command, relative %d", relative); + //Debug("Construct lineto command, relative %d", relative); Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL)); Real dy; @@ -789,6 +880,7 @@ pair Document::ParseSVGPathData(const string & d, const SVGM x[0] = x3; y[0] = y3; command = "m"; + closed = true; } else { diff --git a/src/document.h b/src/document.h index 3ff607b..cab7684 100644 --- a/src/document.h +++ b/src/document.h @@ -4,6 +4,8 @@ #include "ipdf.h" #include "quadtree.h" +#include + #include "../contrib/pugixml-1.4/src/pugixml.hpp" #include "stb_truetype.h" @@ -50,17 +52,13 @@ namespace IPDF bool operator==(const Document & equ) const; bool operator!=(const Document & equ) const {return !(this->operator==(equ));} - unsigned AddGroup(unsigned start_index, unsigned end_index); + unsigned AddGroup(unsigned start_index, unsigned end_index, const Colour & shading=Colour(0.6,0.6,0.6,1)); unsigned AddBezier(const Bezier & bezier); unsigned Add(ObjectType type, const Rect & bounds, unsigned data_index = 0); unsigned AddBezierData(const Bezier & bezier); - + unsigned AddGroupData(const Group & group); - - - - /** SVG Related functions **/ /** Load an SVG text file and add to the document **/ @@ -70,10 +68,13 @@ namespace IPDF /** Parse an SVG node or SVG-group node, adding children to the document **/ void ParseSVGNode(pugi::xml_node & root, SVGMatrix & transform); /** Parse an SVG path with string **/ - std::pair ParseSVGPathData(const std::string & d, const SVGMatrix & transform); + std::pair ParseSVGPathData(const std::string & d, const SVGMatrix & transform, bool & closed); /** Modify an SVG transformation matrix **/ static void ParseSVGTransform(const std::string & s, SVGMatrix & transform); + + /** Extract CSS values (shudder) from style **/ + static void ParseSVGStyleData(const std::string & style, std::map & results); /** Font related functions **/ void SetFont(const std::string & font_filename); diff --git a/src/group.cpp b/src/group.cpp new file mode 100644 index 0000000..8407a4b --- /dev/null +++ b/src/group.cpp @@ -0,0 +1,8 @@ +#include "group.h" +using namespace std; + +namespace IPDF +{ + + +} diff --git a/src/group.h b/src/group.h new file mode 100644 index 0000000..f72369b --- /dev/null +++ b/src/group.h @@ -0,0 +1,33 @@ +#ifndef _GROUP_H +#define _GROUP_H + +#include +#include + +namespace IPDF +{ + + struct Colour + { + float r; float g; float b; float a; + Colour() = default; + Colour(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) {} + }; + + class Objects; + + struct Group + { + Group(unsigned _start, unsigned _end, unsigned _index, const Colour & _fill = Colour(0.8,0.8,0.8,1)) + : m_start(_start), m_end(_end), m_index(_index), m_fill(_fill) + { + + } + unsigned m_start; + unsigned m_end; + unsigned m_index; + Colour m_fill; + }; + +} +#endif //_GROUP_H diff --git a/src/ipdf.h b/src/ipdf.h index ff31533..f9d3a96 100644 --- a/src/ipdf.h +++ b/src/ipdf.h @@ -6,10 +6,7 @@ #include "bezier.h" #include "rect.h" -#define C_RED Colour(1,0,0,1) -#define C_GREEN Colour(0,1,0,1) -#define C_BLUE Colour(0,0,1,1) -#define C_BLACK Colour(0,0,0,1); +#include "group.h" namespace IPDF { @@ -43,35 +40,17 @@ namespace IPDF CT_OBJGROUPS }; - - - - - struct Colour - { - float r; float g; float b; float a; - Colour() = default; - Colour(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) {} - }; - - struct Group - { - Colour shading; - }; - struct Objects { /** Used by all objects **/ std::vector types; // types of objects std::vector bounds; // rectangle bounds of objects - - /** Used by BEZIER to identify data position in relevant vector **/ + /** Used by BEZIER and GROUP to identify data position in relevant vector **/ std::vector data_indices; - /** Used by BEZIER only **/ std::vector beziers; // bezier curves - look up by data_indices - - std::vector > groups; + /** Used by GROUP only **/ + std::vector groups; }; class View; diff --git a/src/objectrenderer.cpp b/src/objectrenderer.cpp index 8349bc1..6108f4f 100644 --- a/src/objectrenderer.cpp +++ b/src/objectrenderer.cpp @@ -5,6 +5,7 @@ #include "objectrenderer.h" #include "view.h" +#include using namespace std; @@ -227,12 +228,13 @@ void BezierRenderer::RenderUsingCPU(const Objects & objects, const View & view, Bezier control(objects.beziers[objects.data_indices[m_indexes[i]]].ToAbsolute(bounds),CPURenderBounds(Rect(0,0,1,1), view, target)); //Debug("%s -> %s via %s", objects.beziers[objects.data_indices[m_indexes[i]]].Str().c_str(), control.Str().c_str(), bounds.Str().c_str()); // Draw a rectangle around the bezier for debugging the bounds rectangle calculations - /* - ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y, target, Colour(1,0,0,1)); - ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y+pix_bounds.h, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, Colour(0,1,0,1)); - ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x, pix_bounds.y+pix_bounds.h, target, Colour(1,0,0,1)); - 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,1,0,1)); - */ + if (view.ShowingObjectBounds()) + { + ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y, target, Colour(1,0,0,1)); + ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y+pix_bounds.h, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, Colour(0,1,0,1)); + ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x, pix_bounds.y+pix_bounds.h, target, Colour(1,0,0,1)); + 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,1,0,1)); + } // Draw lines between the control points for debugging //ObjectRenderer::RenderLineOnCPU((int64_t)control.x0, (int64_t)control.y0, (int64_t)control.x1, (int64_t)control.y1,target); //ObjectRenderer::RenderLineOnCPU((int64_t)control.x1, (int64_t)control.y1, (int64_t)control.x2, (int64_t)control.y2,target); @@ -242,8 +244,7 @@ void BezierRenderer::RenderUsingCPU(const Objects & objects, const View & view, Real x[2]; Real y[2]; control.Evaluate(x[0], y[0], Real(0)); //Debug("target is (%lu, %lu)", target.w, target.h); - int64_t blen = 100; - //blen = min(max((int64_t)2, (int64_t)(target.w/view.GetBounds().w)), (int64_t)100); + int64_t blen = min(max((int64_t)2, (int64_t)(target.w/view.GetBounds().w)), (int64_t)100); Real invblen(1); invblen /= blen; //Debug("Using %li lines, inverse %f", blen, Double(invblen)); @@ -331,11 +332,21 @@ void BezierRenderer::RenderUsingGPU(unsigned first_obj_id, unsigned last_obj_id) glDrawElements(GL_LINES, (last_index-first_index)*2, GL_UNSIGNED_INT, (GLvoid*)(2*first_index*sizeof(uint32_t))); } +inline bool IsBlack(uint8_t * pixels, int64_t index) +{ + bool result = (pixels[index+0] == 0 && pixels[index+1] == 0 && pixels[index+2] == 0 && pixels[index+3] == 255); + //pixels[index+3] = 254; // hax + return result; +} + /** * Render Group (shading) */ void GroupRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target, unsigned first_obj_id, unsigned last_obj_id) { + if (!view.ShowingObjectBounds() && !view.PerformingShading()) + return; + for (unsigned i = 0; i < m_indexes.size(); ++i) { if (m_indexes[i] < first_obj_id) continue; @@ -344,49 +355,80 @@ void GroupRenderer::RenderUsingCPU(const Objects & objects, const View & view, c Rect bounds(CPURenderBounds(objects.bounds[m_indexes[i]], view, target)); PixelBounds pix_bounds(bounds); - + + const Group & group = objects.groups[objects.data_indices[m_indexes[i]]]; + if (group.m_fill.a == 0 || !view.PerformingShading()) + continue; - Colour c(0.5,0.5,1,1); // make the bounds just a little bit bigger - pix_bounds.x--; - pix_bounds.w++; - pix_bounds.y--; - pix_bounds.h++; - /* - ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y, target, c); - ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y+pix_bounds.h, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, c); - ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x, pix_bounds.y+pix_bounds.h, target, c); - ObjectRenderer::RenderLineOnCPU(pix_bounds.x+pix_bounds.w, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, c); - */ + pix_bounds.x-=1; + pix_bounds.w+=2; + pix_bounds.y-=1; + pix_bounds.h+=2; + // Attempt to shade the region // Assumes the outline has been drawn first... + //#ifdef SHADING_DUMB for (int64_t y = max((int64_t)0, pix_bounds.y); y <= min(pix_bounds.y+pix_bounds.h, target.h-1); ++y) { - bool inside = false; - bool online = false; - for (int64_t x = max((int64_t)0, pix_bounds.x); x <= min(pix_bounds.x+pix_bounds.w, target.w-1); ++x) + struct Segment { - int64_t index = (x+target.w*y)*4; - if (target.pixels[index+0] == 0 && target.pixels[index+1] == 0 && target.pixels[index+2] == 0 && target.pixels[index+3] == 255) + int64_t first; + int64_t second; + bool all_black; + }; + list segments; + int64_t min_x = max((int64_t)0, pix_bounds.x); + int64_t max_x = min(pix_bounds.x+pix_bounds.w, target.w-1); + int64_t yy = y*target.w; + + int64_t x = min_x; + while (x <= max_x) + { + bool start_black = IsBlack(target.pixels, 4*(x+yy)); + bool black = start_black; + segments.push_back({x,x,start_black}); + while (black == start_black && ++x <= max_x) { - online = true; - continue; + black = IsBlack(target.pixels, 4*(x+yy)); } - else if (online) + segments.back().second = x-1; + } + + // Keep only the interior segments + list::iterator j = segments.begin(); + //TODO: Magically delete unneeded segments here... + + // Fill in remaining segments + for (j=segments.begin(); j != segments.end(); ++j) + { + Colour c(group.m_fill); + if (j->all_black) { - inside = !inside; - online = false; + c.r = 1;//1; // Change to debug the outline scanning + c.g = 0; + c.b = 0; + c.a = 1; } - - if (inside) + for (x = max(min_x, j->first); x <= min(max_x, j->second); ++x) { - target.pixels[index+0] = c.r*255; - target.pixels[index+1] = c.g*255; - target.pixels[index+2] = c.b*255; - target.pixels[index+3] = c.a*255; + int64_t index = 4*(x+yy); + target.pixels[index+0] = 255*c.r; + target.pixels[index+1] = 255*c.g; + target.pixels[index+2] = 255*c.b; + target.pixels[index+3] = 255*c.a; } } } + //#endif //SHADING_DUMB + if (view.ShowingObjectBounds()) + { + const Colour & c = group.m_fill; + ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y, target, c); + ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y+pix_bounds.h, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, c); + ObjectRenderer::RenderLineOnCPU(pix_bounds.x, pix_bounds.y, pix_bounds.x, pix_bounds.y+pix_bounds.h, target, c); + ObjectRenderer::RenderLineOnCPU(pix_bounds.x+pix_bounds.w, pix_bounds.y, pix_bounds.x+pix_bounds.w, pix_bounds.y+pix_bounds.h, target, c); + } } @@ -472,14 +514,13 @@ void ObjectRenderer::RenderLineOnCPU(int64_t x0, int64_t y0, int64_t x1, int64_t // TODO: Avoid extra inner conditionals do - { + { if (x >= 0 && x < width && y >= 0 && y < height) { int64_t index = (transpose ? (y + x*target.w)*4 : (x + y*target.w)*4); for (int i = 0; i < 4; ++i) target.pixels[index+i] = rgba[i]; } - if (p < 0) p += two_dy; else diff --git a/src/objectrenderer.h b/src/objectrenderer.h index 70339e7..8f52aa0 100644 --- a/src/objectrenderer.h +++ b/src/objectrenderer.h @@ -11,6 +11,7 @@ #include "shaderprogram.h" #include "bufferbuilder.h" + namespace IPDF { class View; diff --git a/src/svg-tests/rectpath.svg b/src/svg-tests/rectpath.svg new file mode 100644 index 0000000..61fa957 --- /dev/null +++ b/src/svg-tests/rectpath.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/src/view.cpp b/src/view.cpp index d7d1e34..48e0a5a 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -20,7 +20,8 @@ using namespace std; View::View(Document & document, Screen & screen, const Rect & 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) + m_objbounds_vbo(), m_object_renderers(NUMBER_OF_OBJECT_TYPES), m_cpu_rendering_pixels(NULL), + m_show_object_bounds(false), m_perform_shading(USE_SHADING) { Debug("View Created - Bounds => {%s}", m_bounds.Str().c_str()); @@ -71,7 +72,7 @@ void View::Translate(Real x, Real y) y *= m_bounds.h; m_bounds.x += x; m_bounds.y += y; - Debug("View Bounds => %s", m_bounds.Str().c_str()); + //Debug("View Bounds => %s", m_bounds.Str().c_str()); if (!m_use_gpu_transform) m_buffer_dirty = true; m_bounds_dirty = true; diff --git a/src/view.h b/src/view.h index fe93e6c..56e80a3 100644 --- a/src/view.h +++ b/src/view.h @@ -6,8 +6,9 @@ #include "framebuffer.h" #include "objectrenderer.h" -#define USE_GPU_TRANSFORM true -#define USE_GPU_RENDERING true +#define USE_GPU_TRANSFORM false +#define USE_GPU_RENDERING false +#define USE_SHADING !(USE_GPU_RENDERING) && true namespace IPDF { @@ -41,6 +42,11 @@ namespace IPDF void SetGPURendering(bool state) {m_use_gpu_rendering = state; m_bounds_dirty = true; m_buffer_dirty = true;} + bool ShowingObjectBounds() const {return m_show_object_bounds;} // render bounds rectangles + void ShowObjectBounds(bool state) {m_show_object_bounds = state; m_bounds_dirty = true; m_buffer_dirty = true;} + + bool PerformingShading() const {return m_perform_shading;} + void PerformShading(bool state) {m_perform_shading = state; m_bounds_dirty = true; m_buffer_dirty = true;} void ForceBoundsDirty() {m_bounds_dirty = true;} void ForceBufferDirty() {m_buffer_dirty = true;} @@ -78,6 +84,10 @@ namespace IPDF // Trust me it will be easier to generalise things this way. Even though there are pointers. std::vector m_object_renderers; uint8_t * m_cpu_rendering_pixels; // pixels to be used for CPU rendering + + // Debug rendering + bool m_show_object_bounds; + bool m_perform_shading; #ifndef QUADTREE_DISABLED QuadTreeIndex m_current_quadtree_node; // The highest node we will traverse.