Actually it's supposed to be "filling" shading implies the colour changes.
Whatever.
# 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
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;
* 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;
#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;
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);
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);
--- /dev/null
+#include "group.h"
+using namespace std;
+
+namespace IPDF
+{
+
+
+}
--- /dev/null
+#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
#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
{
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 **/
#include "objectrenderer.h"
#include "view.h"
+#include <list>
using namespace std;
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)
*/
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<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);
#include "shaderprogram.h"
#include "bufferbuilder.h"
+
namespace IPDF
{
class View;
--- /dev/null
+<?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>
+