From 85336af25da0c613460bbeda4ff7553933e13064 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Mon, 25 Aug 2014 22:44:33 +0800 Subject: [PATCH] Shading still doesn't work Actually it's supposed to be "filling" shading implies the colour changes. Whatever. --- src/Makefile | 2 +- src/bezier.h | 11 ++++-- src/document.cpp | 4 +- src/document.h | 2 +- src/group.cpp | 8 ++++ src/group.h | 33 ++++++++++++++++ src/ipdf.h | 23 +----------- src/objectrenderer.cpp | 77 ++++++++++++++++++++++++++------------ src/objectrenderer.h | 1 + src/svg-tests/rectpath.svg | 17 +++++++++ 10 files changed, 125 insertions(+), 53 deletions(-) create mode 100644 src/group.cpp create mode 100644 src/group.h create mode 100644 src/svg-tests/rectpath.svg 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 9273cee..6a134b7 100644 --- a/src/bezier.h +++ b/src/bezier.h @@ -62,14 +62,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; @@ -81,7 +84,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/document.cpp b/src/document.cpp index 8a5635c..72a12c1 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -284,7 +284,7 @@ void Document::Load(const string & filename) #endif } -unsigned Document::AddGroup(unsigned start_index, unsigned end_index, const Colour & shading) +unsigned Document::AddGroup(unsigned start_index, unsigned end_index, const Colour & fill) { Real xmin = 0; Real ymin = 0; Real xmax = 0; Real ymax = 0; @@ -306,7 +306,7 @@ unsigned Document::AddGroup(unsigned start_index, unsigned end_index, const Colo Rect bounds(xmin,ymin, xmax-xmin, ymax-ymin); - Group group = {start_index, end_index, shading}; + Group group(start_index, end_index, 0U, fill); unsigned data_index = AddGroupData(group); unsigned result = Add(GROUP, bounds,data_index); diff --git a/src/document.h b/src/document.h index df818f2..cab7684 100644 --- a/src/document.h +++ b/src/document.h @@ -52,7 +52,7 @@ 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, const Colour & shading=Colour(0.1,0.1,0.1,1)); + 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); 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 968a3ed..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,24 +40,6 @@ 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 - { - unsigned start; - unsigned end; - Colour shading; - }; - struct Objects { /** Used by all objects **/ diff --git a/src/objectrenderer.cpp b/src/objectrenderer.cpp index 967f7e1..6108f4f 100644 --- a/src/objectrenderer.cpp +++ b/src/objectrenderer.cpp @@ -5,6 +5,7 @@ #include "objectrenderer.h" #include "view.h" +#include using namespace std; @@ -331,6 +332,13 @@ 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) */ @@ -349,50 +357,73 @@ void GroupRenderer::RenderUsingCPU(const Objects & objects, const View & view, c PixelBounds pix_bounds(bounds); const Group & group = objects.groups[objects.data_indices[m_indexes[i]]]; - const Colour & c = group.shading; - if (c.a == 0 || !view.PerformingShading()) + if (group.m_fill.a == 0 || !view.PerformingShading()) continue; // make the bounds just a little bit bigger - pix_bounds.x--; - pix_bounds.w++; - pix_bounds.y--; - pix_bounds.h++; + 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); 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 @@ + + + + + + + + + -- 2.20.1