diff --git a/uppdev/Mirrors/main.cpp b/uppdev/Mirrors/main.cpp index 956e7cf93..88558ed4c 100644 --- a/uppdev/Mirrors/main.cpp +++ b/uppdev/Mirrors/main.cpp @@ -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); diff --git a/uppdev/ScanLine/Dasher.cpp b/uppdev/ScanLine/Dasher.cpp new file mode 100644 index 000000000..c7b44d6ce --- /dev/null +++ b/uppdev/ScanLine/Dasher.cpp @@ -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& 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); +} diff --git a/uppdev/ScanLine/Lion.cpp b/uppdev/ScanLine/Lion.cpp index 000fbb3e7..e9979dcf7 100644 --- a/uppdev/ScanLine/Lion.cpp +++ b/uppdev/ScanLine/Lion.cpp @@ -185,12 +185,12 @@ Image PaintLion(Size sz) } static Vector l = Lion(); - Rasterizer r(sz.cx, sz.cy); + static Rasterizer r(sz.cx, sz.cy); for(int i = 0; i < l.GetCount(); i++) { Vector& 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(); } diff --git a/uppdev/ScanLine/Path.cpp b/uppdev/ScanLine/Path.cpp index 9bfc70095..3104ceee0 100644 --- a/uppdev/ScanLine/Path.cpp +++ b/uppdev/ScanLine/Path.cpp @@ -1,20 +1,20 @@ #include "ScanLine.h" -void Painter::Move(Pointf p) +void BufferPainter::Move(Pointf p) { Segment& m = PathAdd(); m.kind = MOVE; m.p = p; } -void Painter::Line(Pointf p) +void BufferPainter::Line(Pointf p) { Segment& m = PathAdd(); m.kind = LINE; m.p = p; } -void Painter::Quadratic(Pointf p1, Pointf p) +void BufferPainter::Quadratic(Pointf p1, Pointf p) { QuadraticSegment& m = PathAdd(); 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(); m.kind = QUADRATIC; diff --git a/uppdev/ScanLine/Rasterizer2.cpp b/uppdev/ScanLine/Rasterizer.cpp similarity index 89% rename from uppdev/ScanLine/Rasterizer2.cpp rename to uppdev/ScanLine/Rasterizer.cpp index 6154e51dc..598edee0a 100644 --- a/uppdev/ScanLine/Rasterizer2.cpp +++ b/uppdev/ScanLine/Rasterizer.cpp @@ -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 diff --git a/uppdev/ScanLine/Rasterizer2.h b/uppdev/ScanLine/Rasterizer2.h deleted file mode 100644 index 09b4a8f41..000000000 --- a/uppdev/ScanLine/Rasterizer2.h +++ /dev/null @@ -1,47 +0,0 @@ -class Rasterizer { - struct Cell : MoveableWithSwap { - int16 x; - int16 cover; - int area; - - bool operator<(const Cell& b) const { return x < b.x; } - }; - - Rectf cliprect; - double x1, y1; - Buffer< Vector > 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); -}; diff --git a/uppdev/ScanLine/Rasterizer3.cpp b/uppdev/ScanLine/Rasterizer3.cpp deleted file mode 100644 index df4557523..000000000 --- a/uppdev/ScanLine/Rasterizer3.cpp +++ /dev/null @@ -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& 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& 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 diff --git a/uppdev/ScanLine/RasterizerClip.cpp b/uppdev/ScanLine/RasterizerClip.cpp index c8fea7754..0738c4d18 100644 --- a/uppdev/ScanLine/RasterizerClip.cpp +++ b/uppdev/ScanLine/RasterizerClip.cpp @@ -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; } diff --git a/uppdev/ScanLine/ScanLine.h b/uppdev/ScanLine/ScanLine.h index c43dc1ff0..24e0ca09d 100644 --- a/uppdev/ScanLine/ScanLine.h +++ b/uppdev/ScanLine/ScanLine.h @@ -3,8 +3,6 @@ #include -#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 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& 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 { + int16 x; + int16 cover; + int area; + + bool operator<(const Cell& b) const { return x < b.x; } + }; + + Rectf cliprect; + Pointf p0; + Buffer< Vector > 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 }; diff --git a/uppdev/ScanLine/ScanLine.upp b/uppdev/ScanLine/ScanLine.upp index 3c1123762..030fe632d 100644 --- a/uppdev/ScanLine/ScanLine.upp +++ b/uppdev/ScanLine/ScanLine.upp @@ -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, diff --git a/uppdev/ScanLine/Stroker.cpp b/uppdev/ScanLine/Stroker.cpp index 183ba8933..66d0e2e58 100644 --- a/uppdev/ScanLine/Stroker.cpp +++ b/uppdev/ScanLine/Stroker.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(); } diff --git a/uppdev/ScanLine/Xform.cpp b/uppdev/ScanLine/Xform.cpp new file mode 100644 index 000000000..eb4ace4e1 --- /dev/null +++ b/uppdev/ScanLine/Xform.cpp @@ -0,0 +1,2 @@ +#include "ScanLine.h" + diff --git a/uppdev/ScanLine/main.cpp b/uppdev/ScanLine/main.cpp index 22dafcbda..c0fa49d26 100644 --- a/uppdev/ScanLine/main.cpp +++ b/uppdev/ScanLine/main.cpp @@ -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 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;