mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-03 06:12:43 -06:00
Painter20 dasher
git-svn-id: svn://ultimatepp.org/upp/trunk@840 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
68c2a1caaa
commit
068030de69
13 changed files with 231 additions and 505 deletions
|
|
@ -40,16 +40,16 @@ GUI_APP_MAIN
|
|||
for(int i = 0; i < 10; i++) {
|
||||
int a, b;
|
||||
do {
|
||||
a = Random(35) + 1;
|
||||
b = Random(35) + 1;
|
||||
a = Random(50) + 1;
|
||||
b = Random(50) + 1;
|
||||
}
|
||||
while(a + b < 0 || a + b > 20);
|
||||
while(a + b < 0 || a + b > 50);
|
||||
r.DrawText(10, 10 + isz.cy * 2 * i, Format("%d + %d = ", a, b), fnt);
|
||||
do {
|
||||
a = Random(35) + 1;
|
||||
b = Random(35) + 1;
|
||||
a = Random(50) + 1;
|
||||
b = Random(50) + 1;
|
||||
}
|
||||
while(a - b < 0);
|
||||
while(a - b < 1);
|
||||
r.DrawText(2000, 10 + isz.cy * 2 * i, Format("%d - %d = ", a, b), fnt);
|
||||
}
|
||||
Perform(r);
|
||||
|
|
|
|||
62
uppdev/ScanLine/Dasher.cpp
Normal file
62
uppdev/ScanLine/Dasher.cpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
void Dasher::Put(const Pointf& p)
|
||||
{
|
||||
if(flag)
|
||||
PutLine(p);
|
||||
else
|
||||
PutMove(p);
|
||||
}
|
||||
|
||||
void Dasher::Move(const Pointf& p)
|
||||
{
|
||||
PutMove(p);
|
||||
p0 = p;
|
||||
}
|
||||
|
||||
void Dasher::Line(const Pointf& p)
|
||||
{
|
||||
if(pattern.GetCount() == 0) {
|
||||
PutLine(p);
|
||||
return;
|
||||
}
|
||||
Pointf v = p - p0;
|
||||
double len = Length(v);
|
||||
double pos = 0;
|
||||
while(pos + rem < len) {
|
||||
pos += rem;
|
||||
Put(pos / len * v + p0);
|
||||
flag = !flag;
|
||||
rem = pattern[patterni];
|
||||
patterni = (patterni + 1) % pattern.GetCount();
|
||||
}
|
||||
rem -= len - pos;
|
||||
Put(p);
|
||||
p0 = p;
|
||||
}
|
||||
|
||||
Dasher::Dasher(double width, const Vector<double>& p, double distance)
|
||||
{
|
||||
pattern.SetCount(p.GetCount());
|
||||
double sum = 0;
|
||||
for(int i = 0; i < p.GetCount(); i++)
|
||||
sum += (pattern[i] = p[i] * width);
|
||||
if(sum == 0) {
|
||||
pattern.Clear();
|
||||
return;
|
||||
}
|
||||
distance -= int(distance / sum) * sum;
|
||||
patterni = 0;
|
||||
flag = false;
|
||||
for(;;) {
|
||||
rem = pattern[patterni];
|
||||
patterni = (patterni + 1) % pattern.GetCount();
|
||||
flag = !flag;
|
||||
if(rem > distance) {
|
||||
rem -= distance;
|
||||
break;
|
||||
}
|
||||
distance -= rem;
|
||||
}
|
||||
p0 = Pointf(0, 0);
|
||||
}
|
||||
|
|
@ -185,12 +185,12 @@ Image PaintLion(Size sz)
|
|||
}
|
||||
|
||||
static Vector<ColorPolygon> l = Lion();
|
||||
Rasterizer r(sz.cx, sz.cy);
|
||||
static Rasterizer r(sz.cx, sz.cy);
|
||||
for(int i = 0; i < l.GetCount(); i++) {
|
||||
Vector<Pointf>& p = l[i].point;
|
||||
r.Move(p[0].x, p[0].y);
|
||||
r.Move(p[0]);
|
||||
for(int j = 1; j < p.GetCount(); j++)
|
||||
r.Line(p[j].x, p[j].y);
|
||||
r.Line(p[j]);
|
||||
Render(ib, r, l[i].color, false);
|
||||
r.Reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
void Painter::Move(Pointf p)
|
||||
void BufferPainter::Move(Pointf p)
|
||||
{
|
||||
Segment& m = PathAdd<Segment>();
|
||||
m.kind = MOVE;
|
||||
m.p = p;
|
||||
}
|
||||
|
||||
void Painter::Line(Pointf p)
|
||||
void BufferPainter::Line(Pointf p)
|
||||
{
|
||||
Segment& m = PathAdd<Segment>();
|
||||
m.kind = LINE;
|
||||
m.p = p;
|
||||
}
|
||||
|
||||
void Painter::Quadratic(Pointf p1, Pointf p)
|
||||
void BufferPainter::Quadratic(Pointf p1, Pointf p)
|
||||
{
|
||||
QuadraticSegment& m = PathAdd<QuadraticSegment>();
|
||||
m.kind = QUADRATIC;
|
||||
|
|
@ -22,7 +22,7 @@ void Painter::Quadratic(Pointf p1, Pointf p)
|
|||
m.p1 = p1;
|
||||
}
|
||||
|
||||
void Painter::Cubic(Pointf p1, Pointf p2, Pointf p)
|
||||
void BufferPainter::Cubic(Pointf p1, Pointf p2, Pointf p)
|
||||
{
|
||||
CubicSegment& m = PathAdd<CubicSegment>();
|
||||
m.kind = QUADRATIC;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
#ifdef RASTERIZER2
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
|
||||
void Rasterizer::Init()
|
||||
{
|
||||
x1 = y1 = 0;
|
||||
p0 = Pointf(0, 0);
|
||||
min_y = INT_MAX;
|
||||
max_y = INT_MIN;
|
||||
}
|
||||
|
|
@ -157,9 +155,33 @@ inline void Rasterizer::RenderHLine(int ey, int x1, int y1, int x2, int y2)
|
|||
|
||||
void Rasterizer::LineRaw(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
// PAINTER_TIMING("LineRaw");
|
||||
PAINTER_TIMING("LineRaw");
|
||||
LLOG("Rasterizer::LineRaw " << x1 / 256.0 << ':' << y1 / 256.0
|
||||
<< " - " << x2 / 256.0 << ':' << y2 / 256.0);
|
||||
int ex1 = x1 >> 8;
|
||||
int ex2 = x2 >> 8;
|
||||
int ey1 = y1 >> 8;
|
||||
int ey2 = y2 >> 8;
|
||||
|
||||
ASSERT(ey1 >= 0 && ey1 <= sz.cy && ey2 >= 0 && ey2 <= sz.cy);
|
||||
|
||||
if(ey1 < min_y) {
|
||||
if(ey1 < 0) return;
|
||||
min_y = ey1;
|
||||
}
|
||||
if(ey1 > max_y) {
|
||||
if(ey1 > sz.cy) return;
|
||||
max_y = min(ey1, sz.cy - 1);
|
||||
}
|
||||
if(ey2 < min_y) {
|
||||
if(ey2 < 0) return;
|
||||
min_y = ey2;
|
||||
}
|
||||
if(ey2 > max_y) {
|
||||
if(ey2 > sz.cy) return;
|
||||
max_y = min(ey2, sz.cy - 1);
|
||||
}
|
||||
|
||||
enum dx_limit_e { dx_limit = 16384 << 8 };
|
||||
int dx = x2 - x1;
|
||||
if(dx >= dx_limit || dx <= -dx_limit) {
|
||||
|
|
@ -170,24 +192,14 @@ void Rasterizer::LineRaw(int x1, int y1, int x2, int y2)
|
|||
return;
|
||||
}
|
||||
int dy = y2 - y1;
|
||||
int ex1 = x1 >> 8;
|
||||
int ex2 = x2 >> 8;
|
||||
int ey1 = y1 >> 8;
|
||||
int ey2 = y2 >> 8;
|
||||
int fy1 = y1 & 255;
|
||||
int fy2 = y2 & 255;
|
||||
|
||||
ASSERT(ey1 >= 0 && ey1 <= sz.cy && ey2 >= 0 && ey2 <= sz.cy);
|
||||
|
||||
Cell *c;
|
||||
int x_from, x_to;
|
||||
int p, rem, mod, lift, delta, first, incr;
|
||||
|
||||
if(ey1 < min_y) min_y = ey1;
|
||||
if(ey1 > max_y) max_y = min(ey1, sz.cy - 1);
|
||||
if(ey2 < min_y) min_y = ey2;
|
||||
if(ey2 > max_y) max_y = min(ey2, sz.cy - 1);
|
||||
|
||||
if(ey1 == ey2) {
|
||||
RenderHLine(ey1, x1, fy1, x2, fy2);
|
||||
return;
|
||||
|
|
@ -310,5 +322,3 @@ void Rasterizer::Render(int y, Target& g, bool evenodd)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
class Rasterizer {
|
||||
struct Cell : MoveableWithSwap<Cell> {
|
||||
int16 x;
|
||||
int16 cover;
|
||||
int area;
|
||||
|
||||
bool operator<(const Cell& b) const { return x < b.x; }
|
||||
};
|
||||
|
||||
Rectf cliprect;
|
||||
double x1, y1;
|
||||
Buffer< Vector<Cell> > cell;
|
||||
int xmax, ymax;
|
||||
int min_y;
|
||||
int max_y;
|
||||
Size sz;
|
||||
|
||||
void Init();
|
||||
Cell *AddCells(int y, int n);
|
||||
void RenderHLine(int ey, int x1, int y1, int x2, int y2);
|
||||
void LineClip(double x1, double y1, double x2, double y2);
|
||||
int CvX(double x);
|
||||
int CvY(double y);
|
||||
void CvLine(double x1, double y1, double x2, double y2);
|
||||
bool BeginRender(int y, const Cell *&c, const Cell *&e);
|
||||
|
||||
public:
|
||||
struct Target {
|
||||
virtual void Start(int x, int len) = 0;
|
||||
virtual void Render(int val) = 0;
|
||||
virtual void Render(int val, int len) = 0;
|
||||
};
|
||||
|
||||
void LineRaw(int x1, int y1, int x2, int y2);
|
||||
|
||||
void SetClip(const Rectf& rect);
|
||||
void Move(double x, double y);
|
||||
void Line(double x, double y);
|
||||
|
||||
int MinY() const { return min_y; }
|
||||
int MaxY() const { return max_y; }
|
||||
void Render(int y, Target& g, bool evenodd);
|
||||
|
||||
void Reset();
|
||||
|
||||
Rasterizer(int cx, int cy);
|
||||
};
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
#ifdef RASTERIZER3
|
||||
|
||||
void Rasterizer::Init()
|
||||
{
|
||||
x1 = y1 = 0;
|
||||
min_y = INT_MAX;
|
||||
max_y = INT_MIN;
|
||||
}
|
||||
|
||||
void Rasterizer::Reset()
|
||||
{
|
||||
PAINTER_TIMING("Rasterizer::Reset");
|
||||
Init();
|
||||
for(int i = 0; i < sz.cy; i++)
|
||||
cell[i].SetCount(0);
|
||||
}
|
||||
|
||||
void Rasterizer::SetClip(const Rectf& rect)
|
||||
{
|
||||
cliprect = rect & Sizef(sz);
|
||||
}
|
||||
|
||||
Rasterizer::Rasterizer(int cx, int cy)
|
||||
{
|
||||
sz.cx = cx;
|
||||
sz.cy = cy;
|
||||
cell.Alloc(sz.cy);
|
||||
ymax = (sz.cy << 8) - 1;
|
||||
xmax = (sz.cx << 8) - 1;
|
||||
cliprect = Sizef(sz);
|
||||
Reset();
|
||||
}
|
||||
|
||||
inline dword *Rasterizer::AddCells(int y, int n)
|
||||
{
|
||||
Vector<dword>& v = cell[y];
|
||||
if(v.GetCount() == 0) {
|
||||
v.Reserve(16);
|
||||
v.SetCount(n);
|
||||
return &v[0];
|
||||
}
|
||||
y = v.GetCount();
|
||||
v.SetCount(y + n);
|
||||
return &v[y];
|
||||
}
|
||||
|
||||
inline void Rasterizer::RenderHLine(int ey, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int ex1 = x1 >> 8;
|
||||
int ex2 = x2 >> 8;
|
||||
int fx1 = x1 & 255;
|
||||
int fx2 = x2 & 255;
|
||||
dword *c;
|
||||
if(y1 == y2)
|
||||
return;
|
||||
int dy = y2 - y1;
|
||||
if(ex1 == ex2) {
|
||||
*AddCells(ey, 1) = Cell(ex1, fx1 + fx2, dy);
|
||||
return;
|
||||
}
|
||||
int dx = x2 - x1;
|
||||
if(dx < 0) {
|
||||
int p = fx1 * dy;
|
||||
dx = -dx;
|
||||
int delta = p / dx;
|
||||
int mod = p % dx;
|
||||
if(mod < 0) {
|
||||
delta--;
|
||||
mod += dx;
|
||||
}
|
||||
c = AddCells(ey, abs(ex2 - ex1) + 1);
|
||||
*c++ = Cell(ex1, fx1, delta);
|
||||
ex1--;
|
||||
y1 += delta;
|
||||
if(ex1 != ex2) {
|
||||
p = (y2 - y1 + delta) * 256;
|
||||
int lift = p / dx;
|
||||
int rem = p % dx;
|
||||
if (rem < 0) {
|
||||
lift--;
|
||||
rem += dx;
|
||||
}
|
||||
mod -= dx;
|
||||
while(ex1 != ex2) {
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if(mod >= 0) {
|
||||
mod -= dx;
|
||||
delta++;
|
||||
}
|
||||
*c++ = Cell(ex1, 256, delta);
|
||||
y1 += delta;
|
||||
ex1--;
|
||||
}
|
||||
}
|
||||
*c++ = Cell(ex2, fx2 + 256, y2 - y1);
|
||||
}
|
||||
else {
|
||||
int p = (256 - fx1) * dy;
|
||||
int delta = p / dx;
|
||||
int mod = p % dx;
|
||||
if(mod < 0) {
|
||||
delta--;
|
||||
mod += dx;
|
||||
}
|
||||
c = AddCells(ey, abs(ex2 - ex1) + 1);
|
||||
*c++ = Cell(ex1, fx1 + 256, delta);
|
||||
ex1++;
|
||||
y1 += delta;
|
||||
if(ex1 != ex2) {
|
||||
p = (y2 - y1 + delta) * 256;
|
||||
int lift = p / dx;
|
||||
int rem = p % dx;
|
||||
if (rem < 0) {
|
||||
lift--;
|
||||
rem += dx;
|
||||
}
|
||||
mod -= dx;
|
||||
while(ex1 != ex2) {
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if(mod >= 0) {
|
||||
mod -= dx;
|
||||
delta++;
|
||||
}
|
||||
*c++ = Cell(ex1, 256, delta);
|
||||
y1 += delta;
|
||||
ex1++;
|
||||
}
|
||||
}
|
||||
*c++ = Cell(ex2, fx2, y2 - y1);
|
||||
}
|
||||
}
|
||||
|
||||
void Rasterizer::LineRaw(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
// PAINTER_TIMING("LineRaw");
|
||||
enum dx_limit_e { dx_limit = 16384 << 8 };
|
||||
int dx = x2 - x1;
|
||||
if(dx >= dx_limit || dx <= -dx_limit) {
|
||||
int cx = (x1 + x2) >> 1;
|
||||
int cy = (y1 + y2) >> 1;
|
||||
LineRaw(x1, y1, cx, cy);
|
||||
LineRaw(cx, cy, x2, y2);
|
||||
return;
|
||||
}
|
||||
int dy = y2 - y1;
|
||||
int ex1 = x1 >> 8;
|
||||
int ex2 = x2 >> 8;
|
||||
int ey1 = y1 >> 8;
|
||||
int ey2 = y2 >> 8;
|
||||
int fy1 = y1 & 255;
|
||||
int fy2 = y2 & 255;
|
||||
|
||||
ASSERT(ey1 >= 0 && ey1 < sz.cy && ey2 >= 0 && ey2 < sz.cy);
|
||||
|
||||
int x_from, x_to;
|
||||
int p, rem, mod, lift, delta, first, incr;
|
||||
|
||||
if(ey1 < min_y) min_y = ey1;
|
||||
if(ey1 > max_y && ey1 < sz.cy) max_y = ey1;
|
||||
if(ey2 < min_y) min_y = ey2;
|
||||
if(ey2 > max_y && ey2 < sz.cy) max_y = ey2;
|
||||
|
||||
if(ey1 == ey2) {
|
||||
RenderHLine(ey1, x1, fy1, x2, fy2);
|
||||
return;
|
||||
}
|
||||
incr = 1;
|
||||
if(dx == 0) {
|
||||
int ex = x1 >> 8;
|
||||
int two_fx = (x1 - (ex << 8)) << 1;
|
||||
first = 256;
|
||||
if(dy < 0) {
|
||||
first = 0;
|
||||
incr = -1;
|
||||
}
|
||||
x_from = x1;
|
||||
delta = first - fy1;
|
||||
*AddCells(ey1, 1) = Cell(ex1, two_fx, delta);
|
||||
ey1 += incr;
|
||||
delta = first + first - 256;
|
||||
while(ey1 != ey2) {
|
||||
*AddCells(ey1, 1) = Cell(ex1, two_fx, delta);
|
||||
ey1 += incr;
|
||||
}
|
||||
delta = fy2 - 256 + first;
|
||||
*AddCells(ey1, 1) = Cell(ex1, two_fx, delta);
|
||||
return;
|
||||
}
|
||||
p = (256 - fy1) * dx;
|
||||
first = 256;
|
||||
if(dy < 0) {
|
||||
p = fy1 * dx;
|
||||
first = 0;
|
||||
incr = -1;
|
||||
dy = -dy;
|
||||
}
|
||||
delta = p / dy;
|
||||
mod = p % dy;
|
||||
if(mod < 0) {
|
||||
delta--;
|
||||
mod += dy;
|
||||
}
|
||||
x_from = x1 + delta;
|
||||
RenderHLine(ey1, x1, fy1, x_from, first);
|
||||
ey1 += incr;
|
||||
if(ey1 != ey2) {
|
||||
p = dx << 8;
|
||||
lift = p / dy;
|
||||
rem = p % dy;
|
||||
if(rem < 0) {
|
||||
lift--;
|
||||
rem += dy;
|
||||
}
|
||||
mod -= dy;
|
||||
while(ey1 != ey2) {
|
||||
delta = lift;
|
||||
mod += rem;
|
||||
if(mod >= 0) {
|
||||
mod -= dy;
|
||||
delta++;
|
||||
}
|
||||
x_to = x_from + delta;
|
||||
RenderHLine(ey1, x_from, 256 - first, x_to, first);
|
||||
x_from = x_to;
|
||||
ey1 += incr;
|
||||
}
|
||||
}
|
||||
RenderHLine(ey1, x_from, 256 - first, x2, fy2);
|
||||
}
|
||||
|
||||
inline unsigned Alpha(int area)
|
||||
{
|
||||
int cover = area >> 9;
|
||||
if(cover < 0) cover = -cover;
|
||||
/* if(evenodd) {
|
||||
cover &= 511;
|
||||
if(cover > 256)
|
||||
cover = 512 - cover;
|
||||
}*/
|
||||
return cover;
|
||||
}
|
||||
|
||||
void Rasterizer::Render(int y, Target& g)
|
||||
{
|
||||
PAINTER_TIMING("Render");
|
||||
const dword *c, *e;
|
||||
if(y < min_y || y > max_y) return;
|
||||
Vector<dword>& cl = cell[y];
|
||||
if(cl.GetCount() == 0) return;
|
||||
Sort(cl);
|
||||
c = cl;
|
||||
e = cl.End();
|
||||
g.Start(GetX(*c), GetX(*(e - 1)));
|
||||
int cover = 0;
|
||||
while(c < e) {
|
||||
int x = GetX(*c);
|
||||
int cv = GetC(*c);
|
||||
DDUMP(cv);
|
||||
int area = GetW(*c) * cv;
|
||||
cover += cv;
|
||||
c++;
|
||||
while(c < e && GetX(*c) == x) {
|
||||
int cv = GetC(*c);
|
||||
area += GetW(*c) * cv;
|
||||
cover += cv;
|
||||
c++;
|
||||
}
|
||||
if(area) {
|
||||
g.Render(Alpha((cover << (8 + 1)) - area));
|
||||
x++;
|
||||
}
|
||||
if(c < e && GetX(*c) > x)
|
||||
g.Render(Alpha(cover << (8 + 1)), GetX(*c) - x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,14 +1,8 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
void Rasterizer::Move(double x, double y)
|
||||
{
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
}
|
||||
|
||||
inline int Cv(double x)
|
||||
{
|
||||
return fround(x * 256);
|
||||
return int(x * 256 + 0.5);
|
||||
}
|
||||
|
||||
void Rasterizer::CvLine(double x1, double y1, double x2, double y2)
|
||||
|
|
@ -92,10 +86,14 @@ void Rasterizer::LineClip(double x1, double y1, double x2, double y2)
|
|||
CvLine(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void Rasterizer::Line(double x2, double y2)
|
||||
void Rasterizer::Move(const Pointf& p)
|
||||
{
|
||||
p0 = p;
|
||||
}
|
||||
|
||||
void Rasterizer::Line(const Pointf& p)
|
||||
{
|
||||
PAINTER_TIMING("Line");
|
||||
LineClip(x1, y1, x2, y2);
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
LineClip(p0.x, p0.y, p.x, p.y);
|
||||
p0 = p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
#define RASTERIZER2
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#define PAINTER_TIMING(x) // RTIMING(x)
|
||||
|
|
@ -49,22 +47,6 @@ struct ScanLine {
|
|||
String ToString() const;
|
||||
};
|
||||
|
||||
#ifdef RASTERIZER2
|
||||
|
||||
#include "Rasterizer2.h"
|
||||
|
||||
#elif defined(RASTERIZER3)
|
||||
|
||||
#include "Rasterizer3.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "Rasterizer.h"
|
||||
|
||||
#endif
|
||||
|
||||
void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd);
|
||||
|
||||
double SquareDist(const Pointf& p1, const Pointf& p2);
|
||||
Pointf Mid(const Pointf& a, const Pointf& b);
|
||||
Pointf Ortogonal(const Pointf& p);
|
||||
|
|
@ -79,18 +61,20 @@ Pointf Polar(const Pointf& p, double r, double a);
|
|||
struct VertexTarget {
|
||||
virtual void Move(const Pointf& p) = 0;
|
||||
virtual void Line(const Pointf& p) = 0;
|
||||
virtual void End() = 0;
|
||||
virtual void End();
|
||||
};
|
||||
|
||||
struct VertexProcessor : VertexTarget {
|
||||
struct VertexFilter : VertexTarget {
|
||||
VertexTarget *target;
|
||||
|
||||
void PutMove(const Pointf& p) { target->Move(p); }
|
||||
void PutLine(const Pointf& p) { target->Line(p); }
|
||||
void PutEnd() { target->End(); }
|
||||
virtual void End();
|
||||
|
||||
void PutMove(const Pointf& p) { target->Move(p); }
|
||||
void PutLine(const Pointf& p) { target->Line(p); }
|
||||
void PutEnd() { target->End(); }
|
||||
|
||||
VertexProcessor& operator|(VertexProcessor& b) { target = &b; return b; }
|
||||
void operator|(VertexTarget& b) { target = &b; }
|
||||
VertexFilter& operator|(VertexFilter& b) { target = &b; return b; }
|
||||
void operator|(VertexTarget& b) { target = &b; }
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -103,7 +87,7 @@ enum {
|
|||
LINEJOIN_BEVEL,
|
||||
};
|
||||
|
||||
class Stroker : public VertexProcessor {
|
||||
class Stroker : public VertexFilter {
|
||||
double w2;
|
||||
double qmiter;
|
||||
double fid;
|
||||
|
|
@ -127,19 +111,79 @@ public:
|
|||
Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin);
|
||||
};
|
||||
|
||||
class Transformer : VertexProcessor {
|
||||
struct Dasher : public VertexFilter {
|
||||
Vector<double> pattern;
|
||||
int patterni;
|
||||
double rem;
|
||||
bool flag;
|
||||
Pointf p0;
|
||||
|
||||
void Put(const Pointf& p);
|
||||
|
||||
public:
|
||||
virtual void Move(double x, double y);
|
||||
virtual void Line(double x, double y);
|
||||
virtual void End();
|
||||
virtual void Move(const Pointf& p);
|
||||
virtual void Line(const Pointf& p);
|
||||
|
||||
Dasher(double width, const Vector<double>& pattern, double distance);
|
||||
};
|
||||
|
||||
void ApproximateQuadratic(VertexTarget& t, const Pointf& p1, const Pointf& p2, const Pointf& p3, double tolerance);
|
||||
void ApproximateCubic(VertexTarget& t, const Pointf& x0, const Pointf& x1, const Pointf& x2, const Pointf& x, double tolerance);
|
||||
|
||||
#define Painter NewPainter
|
||||
class Rasterizer : public VertexTarget {
|
||||
public:
|
||||
virtual void Move(const Pointf& p);
|
||||
virtual void Line(const Pointf& p);
|
||||
|
||||
class Painter {
|
||||
private:
|
||||
struct Cell : MoveableWithSwap<Cell> {
|
||||
int16 x;
|
||||
int16 cover;
|
||||
int area;
|
||||
|
||||
bool operator<(const Cell& b) const { return x < b.x; }
|
||||
};
|
||||
|
||||
Rectf cliprect;
|
||||
Pointf p0;
|
||||
Buffer< Vector<Cell> > cell;
|
||||
int xmax, ymax;
|
||||
int min_y;
|
||||
int max_y;
|
||||
Size sz;
|
||||
|
||||
void Init();
|
||||
Cell *AddCells(int y, int n);
|
||||
void RenderHLine(int ey, int x1, int y1, int x2, int y2);
|
||||
void LineClip(double x1, double y1, double x2, double y2);
|
||||
int CvX(double x);
|
||||
int CvY(double y);
|
||||
void CvLine(double x1, double y1, double x2, double y2);
|
||||
bool BeginRender(int y, const Cell *&c, const Cell *&e);
|
||||
|
||||
public:
|
||||
struct Target {
|
||||
virtual void Start(int x, int len) = 0;
|
||||
virtual void Render(int val) = 0;
|
||||
virtual void Render(int val, int len) = 0;
|
||||
};
|
||||
|
||||
void LineRaw(int x1, int y1, int x2, int y2);
|
||||
|
||||
void SetClip(const Rectf& rect);
|
||||
|
||||
int MinY() const { return min_y; }
|
||||
int MaxY() const { return max_y; }
|
||||
void Render(int y, Target& g, bool evenodd);
|
||||
|
||||
void Reset();
|
||||
|
||||
Rasterizer(int cx, int cy);
|
||||
};
|
||||
|
||||
void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd);
|
||||
|
||||
class BufferPainter {
|
||||
enum {
|
||||
MOVE, LINE, QUADRATIC, CUBIC
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,14 +9,13 @@ file
|
|||
ScanLineFiller.cpp,
|
||||
SolidFiller.cpp,
|
||||
SolidFillerMask.cpp,
|
||||
Rasterizer2.h,
|
||||
Rasterizer2.cpp,
|
||||
Rasterizer3.h,
|
||||
Rasterizer3.cpp,
|
||||
RasterizerClip.cpp,
|
||||
Math.cpp,
|
||||
Bezier.cpp,
|
||||
Stroker.cpp,
|
||||
Dasher.cpp,
|
||||
Xform.cpp,
|
||||
Rasterizer.cpp,
|
||||
RasterizerClip.cpp,
|
||||
Path.cpp,
|
||||
help.txt,
|
||||
Lion.cpp,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
#define LLOG(x) LOG(x)
|
||||
|
||||
void VertexTarget::End()
|
||||
{
|
||||
}
|
||||
|
||||
void VertexFilter::End()
|
||||
{
|
||||
PutEnd();
|
||||
}
|
||||
|
||||
Stroker::Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin)
|
||||
: linecap(linecap),
|
||||
linejoin(linejoin)
|
||||
|
|
@ -13,6 +24,7 @@ Stroker::Stroker(double width, double miterlimit, double tolerance, int linecap,
|
|||
|
||||
void Stroker::Move(const Pointf& p)
|
||||
{
|
||||
LLOG("Stroker::Move " << p);
|
||||
Finish();
|
||||
p1 = p;
|
||||
p0 = p2 = Null;
|
||||
|
|
@ -33,16 +45,19 @@ void Stroker::Round(const Pointf& p, const Pointf& v1, const Pointf& v2, double
|
|||
|
||||
void Stroker::Line(const Pointf& p3)
|
||||
{
|
||||
if(p3 == p2)
|
||||
return;
|
||||
LLOG("Stroker::Line " << p3);
|
||||
if(IsNull(p1)) {
|
||||
Move(p3);
|
||||
return;
|
||||
}
|
||||
if(IsNull(p2)) {
|
||||
Pointf v = p3 - p1;
|
||||
double l = Length(v);
|
||||
if(l < 1e-30)
|
||||
return;
|
||||
p2 = p3;
|
||||
v1 = p2 - p1;
|
||||
o1 = Ortogonal(v1) * w2 / Length(v1);
|
||||
v1 = v;
|
||||
o1 = Ortogonal(v1) * w2 / l;
|
||||
a1 = p1 + o1;
|
||||
b1 = p1 - o1;
|
||||
if(IsNull(p0)) {
|
||||
|
|
@ -56,7 +71,10 @@ void Stroker::Line(const Pointf& p3)
|
|||
}
|
||||
|
||||
Pointf v2 = p3 - p2;
|
||||
Pointf o2 = Ortogonal(v2) * w2 / Length(v2);
|
||||
double l = Length(v2);
|
||||
if(l < 1e-30)
|
||||
return;
|
||||
Pointf o2 = Ortogonal(v2) * w2 / l;
|
||||
Pointf a2 = p2 + o2;
|
||||
Pointf b2 = p2 - o2;
|
||||
|
||||
|
|
@ -128,7 +146,7 @@ void Stroker::Cap(const Pointf& p, const Pointf& v, const Pointf& o,
|
|||
|
||||
void Stroker::Finish()
|
||||
{
|
||||
if(IsNull(p1) || IsNull(p2))
|
||||
if(IsNull(p1) || IsNull(p2) || IsNull(p0))
|
||||
return;
|
||||
if(p2 == p0)
|
||||
Line(p0 + v0);
|
||||
|
|
@ -140,11 +158,11 @@ void Stroker::Finish()
|
|||
Cap(p0, v0, o0, b0, a0);
|
||||
Cap(p2, -v1, -o1, a1 + v1, b1 + v1);
|
||||
}
|
||||
p1 = p2 = Null;
|
||||
PutEnd();
|
||||
p0 = p1 = p2 = Null;
|
||||
}
|
||||
|
||||
void Stroker::End()
|
||||
{
|
||||
Finish();
|
||||
PutEnd();
|
||||
}
|
||||
|
|
|
|||
2
uppdev/ScanLine/Xform.cpp
Normal file
2
uppdev/ScanLine/Xform.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#include "ScanLine.h"
|
||||
|
||||
|
|
@ -2,16 +2,6 @@
|
|||
|
||||
Image PaintLion(Size sz);
|
||||
|
||||
struct Raget : VertexTarget {
|
||||
Rasterizer& r;
|
||||
|
||||
virtual void Line(Pointf p) { r.Line(p.x, p.y); DUMP(p); }
|
||||
virtual void Move(Pointf p) { r.Move(p.x, p.y); }
|
||||
virtual void End() {}
|
||||
|
||||
Raget(Rasterizer& r) : r(r) {}
|
||||
};
|
||||
|
||||
struct App : TopWindow {
|
||||
double x1, y1, x2, y2, x3, y3;
|
||||
|
||||
|
|
@ -40,58 +30,6 @@ struct App : TopWindow {
|
|||
|
||||
virtual void Paint(Draw& w);
|
||||
|
||||
virtual void Paint1(Draw& w) {
|
||||
ImageBuffer ib(600, 600);
|
||||
Fill(~ib, White(), ib.GetLength());
|
||||
/* Apply(ib[20], 100, Black(), a);
|
||||
a.x = 10;
|
||||
Apply(ib[30], 100, Blue(), a);
|
||||
for(int i = 0; i < 20; i++) {
|
||||
b = Pack(i, line1, __countof(line1));
|
||||
Apply(ib[50 + 2 * i], 100, Black(), And(a, b));
|
||||
}
|
||||
*/
|
||||
Rasterizer r(600, 600);
|
||||
// r.SetClip(RectfC(100, 100, 200, 200));
|
||||
|
||||
|
||||
#if 0
|
||||
r.Move(195.000000, 65.000000);
|
||||
r.Line(0.000000, 0.000000);
|
||||
r.Line(183.000000, 501.000000);
|
||||
r.Line(195.000000, 65.000000);
|
||||
#endif
|
||||
#if 0
|
||||
r.Move(x1, y1);
|
||||
r.Line(x2, y2);
|
||||
r.Line(x3, y3);
|
||||
r.Line(x1, y1);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
r.Move(200, 300);
|
||||
// ApproximateQuadratic(q, Pointf(200, 300), Pointf(400, 50), Pointf(600, 300), 0.3);
|
||||
r.Line(200, 300);
|
||||
Render(ib, r, Red(), false);
|
||||
#endif
|
||||
r.Move(100, 200);
|
||||
// ApproximateCubic(q, Pointf(100, 200), Pointf(100, 100), Pointf(250, 100), Pointf(250, 200), 2);
|
||||
r.Line(150, 400);
|
||||
r.Line(100, 200);
|
||||
Render(ib, r, Blue(), false);
|
||||
|
||||
LOG("---------");
|
||||
/*
|
||||
r.Move(200, 300);
|
||||
Quadratic(q, Pointf(200, 300), Pointf(400, 50), Pointf(600, 300), 10);
|
||||
r.Line(200, 300);
|
||||
Render(ib, r, Blue(), false);
|
||||
*/
|
||||
w.DrawRect(GetSize(), White());
|
||||
w.DrawImage(0, 0, ib);
|
||||
w.DrawText(0, GetSize().cy - 40, Text());
|
||||
// w.DrawImage(300, 300, PaintLion(GetSize()));
|
||||
}
|
||||
|
||||
App() {
|
||||
p1 = p4 = Pointf(100, 100);
|
||||
|
|
@ -100,26 +38,6 @@ struct App : TopWindow {
|
|||
}
|
||||
};
|
||||
|
||||
struct RasterizerTarget : VertexTarget {
|
||||
Rasterizer& r;
|
||||
ImageBuffer& ib;
|
||||
|
||||
virtual void Line(const Pointf& p)
|
||||
{
|
||||
r.Line(p.x, p.y);
|
||||
}
|
||||
virtual void Move(const Pointf& p)
|
||||
{
|
||||
r.Move(p.x, p.y);
|
||||
}
|
||||
virtual void End()
|
||||
{
|
||||
Render(ib, r, Black(), false);
|
||||
}
|
||||
|
||||
RasterizerTarget(ImageBuffer& ib, Rasterizer& r) : ib(ib), r(r) {}
|
||||
};
|
||||
|
||||
#if 1
|
||||
void App::Paint(Draw& w)
|
||||
{
|
||||
|
|
@ -127,17 +45,21 @@ void App::Paint(Draw& w)
|
|||
ImageBuffer ib(sz.cx, sz.cy);
|
||||
Rasterizer r(sz.cx, sz.cy);
|
||||
Fill(~ib, White(), ib.GetLength());
|
||||
RasterizerTarget tgt(ib, r);
|
||||
|
||||
Stroker s(20, 4, 0.3, LINECAP_ROUND, LINEJOIN_ROUND);
|
||||
Stroker s(20, 4, 0.3, LINECAP_BUTT, LINEJOIN_MITER);
|
||||
Vector<double> dash;
|
||||
dash << 4 << 2;
|
||||
Dasher d(20, dash, GetMousePos().y);
|
||||
|
||||
s|tgt;
|
||||
d|s|r;
|
||||
|
||||
s.Move(p1);
|
||||
s.Line(p2);
|
||||
// s.Line(p3);
|
||||
// s.Line(p4);
|
||||
s.End();
|
||||
d.Move(p1);
|
||||
d.Line(p2);
|
||||
d.Line(p3);
|
||||
d.Line(p4);
|
||||
d.End();
|
||||
|
||||
Render(ib, r, Black(), false);
|
||||
|
||||
w.DrawImage(0, 0, ib);
|
||||
}
|
||||
|
|
@ -176,9 +98,8 @@ void App::Paint(Draw& w)
|
|||
#endif
|
||||
|
||||
GUI_APP_MAIN {
|
||||
App().Run();
|
||||
#ifdef _DEBUG
|
||||
// App().Run();
|
||||
App().Run();
|
||||
#else _DEBUG
|
||||
Size sz(800, 600);
|
||||
int time;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue