Merge branch 'master' of git.ucc.asn.au:ipdf/code
authorDavid Gow <[email protected]>
Mon, 25 Aug 2014 08:54:46 +0000 (16:54 +0800)
committerDavid Gow <[email protected]>
Mon, 25 Aug 2014 08:54:46 +0000 (16:54 +0800)
Conflicts:
src/document.cpp

14 files changed:
src/Makefile
src/bezier.h
src/controlpanel.cpp
src/controlpanel.h
src/document.cpp
src/document.h
src/group.cpp [new file with mode: 0644]
src/group.h [new file with mode: 0644]
src/ipdf.h
src/objectrenderer.cpp
src/objectrenderer.h
src/svg-tests/rectpath.svg [new file with mode: 0644]
src/view.cpp
src/view.h

index bc07e1e..af72dfa 100644 (file)
@@ -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
index 07f2178..17bc5b6 100644 (file)
@@ -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;
index f2d0324..5b62e91 100644 (file)
@@ -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);
index 90394f8..ea557d0 100644 (file)
@@ -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;
index ba5a0f7..0b72a3e 100644 (file)
@@ -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<unsigned, unsigned>(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<unsigned, unsigned> range = ParseSVGPathData(d, transform);
-                       AddGroup(range.first, range.second);
+                       //Debug("Path data attribute is \"%s\"", d.c_str());
+                       bool closed = false;
+                       pair<unsigned, unsigned> range = ParseSVGPathData(d, transform, closed);
+                       if (closed)
+                       {
+                               Colour c(0,0,0,0);
+                               string colour_str("");
+                               map<string, string> 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<string, string> & 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<unsigned, unsigned> Document::ParseSVGPathData(const string & d, const SVGMatrix & transform)
+pair<unsigned, unsigned> 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<unsigned, unsigned> 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<unsigned, unsigned> Document::ParseSVGPathData(const string & d, const SVGM
                        x[0] = x3;
                        y[0] = y3;
                        command = "m";
+                       closed = true;
                }
                else
                {
index 3ff607b..cab7684 100644 (file)
@@ -4,6 +4,8 @@
 #include "ipdf.h"
 #include "quadtree.h"
 
+#include <map>
+
 #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<unsigned, unsigned> ParseSVGPathData(const std::string & d, const SVGMatrix & transform);
+                       std::pair<unsigned, unsigned> 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<std::string, std::string> & 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 (file)
index 0000000..8407a4b
--- /dev/null
@@ -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 (file)
index 0000000..f72369b
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _GROUP_H
+#define _GROUP_H
+
+#include <vector>
+#include <algorithm>
+
+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
index ff31533..f9d3a96 100644 (file)
@@ -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<ObjectType> types; // types of objects
                std::vector<Rect> 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<unsigned> data_indices;
-
                /** Used by BEZIER only **/
                std::vector<Bezier> beziers; // bezier curves - look up by data_indices
-               
-               std::vector<std::pair<unsigned, unsigned> > groups;
+               /** Used by GROUP only **/
+               std::vector<Group> groups;
        };
 
        class View;
index 8349bc1..6108f4f 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "objectrenderer.h"
 #include "view.h"
+#include <list>
 
 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<Segment> 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<Segment>::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
index 70339e7..8f52aa0 100644 (file)
@@ -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 (file)
index 0000000..61fa957
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:xlink="http://www.w3.org/1999/xlink"
+     width="100" height="100"
+
+   >
+       <path 
+               d = "M 0,0 0,100 100,100 100,0 Z M 25,25 25,75 75,75 75,25 25,25"
+               fill="#f0f0f0"
+       />
+       
+       
+ </svg>
+
index d7d1e34..48e0a5a 100644 (file)
@@ -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;
index fe93e6c..56e80a3 100644 (file)
@@ -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<ObjectRenderer*> 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.

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