diff --git a/uppdev/LineClip/LineClip.h b/uppdev/LineClip/LineClip.h new file mode 100644 index 000000000..780f3a1f3 --- /dev/null +++ b/uppdev/LineClip/LineClip.h @@ -0,0 +1,25 @@ +#ifndef _LineClip_LineClip_h +#define _LineClip_LineClip_h + +#include +#include + +using namespace Upp; + +class LineClip : public TopWindow { +public: + double x1, y1, x2, y2; + Rectf cliprect; + + bool Clip(Painter& sw, double x1, double y1, double x2, double y2); + + virtual void Paint(Draw& w); + virtual void LeftDown(Point p, dword keyflags); + virtual void MouseMove(Point p, dword keyflags); + + typedef LineClip CLASSNAME; + LineClip(); +}; + +#endif + diff --git a/uppdev/LineClip/LineClip.lay b/uppdev/LineClip/LineClip.lay new file mode 100644 index 000000000..61cdae01d --- /dev/null +++ b/uppdev/LineClip/LineClip.lay @@ -0,0 +1,5 @@ + +LAYOUT(LineClipLayout, 200, 100) + +END_LAYOUT + diff --git a/uppdev/LineClip/LineClip.upp b/uppdev/LineClip/LineClip.upp new file mode 100644 index 000000000..4b2f74da3 --- /dev/null +++ b/uppdev/LineClip/LineClip.upp @@ -0,0 +1,12 @@ +uses + CtrlLib, + Painter; + +file + LineClip.h, + main.cpp, + LineClip.lay; + +mainconfig + "" = "GUI"; + diff --git a/uppdev/LineClip/init b/uppdev/LineClip/init new file mode 100644 index 000000000..5972c17aa --- /dev/null +++ b/uppdev/LineClip/init @@ -0,0 +1,5 @@ +#ifndef _LineClip_icpp_init_stub +#define _LineClip_icpp_init_stub +#include "CtrlLib/init" +#include "Painter/init" +#endif diff --git a/uppdev/LineClip/main.cpp b/uppdev/LineClip/main.cpp new file mode 100644 index 000000000..572becfa2 --- /dev/null +++ b/uppdev/LineClip/main.cpp @@ -0,0 +1,89 @@ +#include "LineClip.h" + +bool LineClip::Clip(Painter& sw, double x1, double y1, double x2, double y2) +{ + if(x1 < cliprect.left) { + if(x2 < cliprect.left) + return false; + y1 = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1; + x1 = cliprect.left; + } + else + if(x1 > cliprect.right) { + if(x2 > cliprect.right) + return false; + y1 = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1; + x1 = cliprect.right; + } + if(x2 < cliprect.left) { + y2 = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1; + x2 = cliprect.left; + } + else + if(x2 > cliprect.right) { + y2 = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1; + x2 = cliprect.right; + } + if(y1 < cliprect.top) { + if(y2 < cliprect.top) + return false; + x1 = (x2 - x1) * (cliprect.top - y1) / (y2 - y1) + x1; + y1 = cliprect.top; + } + else + if(y1 > cliprect.bottom) { + if(y2 > cliprect.bottom) + return false; + x1 = (x2 - x1) * (cliprect.bottom - y1) / (y2 - y1) + x1; + y1 = cliprect.bottom; + } + if(y2 < cliprect.top) { + x2 = (x2 - x1) * (cliprect.top - y1) / (y2 - y1) + x1; + y2 = cliprect.top; + } + else + if(y2 > cliprect.bottom) { + x2 = (x2 - x1) * (cliprect.bottom - y1) / (y2 - y1) + x1; + y2 = cliprect.bottom; + } + sw.Move(x1, y1).Line(x2, y2).Stroke(1, LtRed()); + return true; +} + +void LineClip::Paint(Draw& w) +{ + ImageBuffer ib(GetSize()); + BufferPainter sw(ib); + sw.Clear(White()); + sw.Rectangle(100, 100, 100, 100).Fill(WhiteGray()); + sw.Move(x1, y1).Line(x2, y2).Stroke(1, Gray()); + if(!Clip(sw, x1, y1, x2, y2)) + sw.Text(0, 0, "No clip", Arial(20)).Fill(Black()); + w.DrawImage(0, 0, ib); +} + +void LineClip::LeftDown(Point p, dword keyflags) +{ + x1 = p.x; + y1 = p.y; + Refresh(); +} + +void LineClip::MouseMove(Point p, dword keyflags) +{ + x2 = p.x; + y2 = p.y; + Refresh(); +} + +LineClip::LineClip() +{ + cliprect = RectfC(100, 100, 100, 100); + x1 = y1 = x2 = y2 = 0; + Refresh(); +} + +GUI_APP_MAIN +{ + LineClip().Run(); +} diff --git a/uppdev/ScanLine/Rasterizer.cpp b/uppdev/ScanLine/Rasterizer.cpp index ca344ea14..57507edc9 100644 --- a/uppdev/ScanLine/Rasterizer.cpp +++ b/uppdev/ScanLine/Rasterizer.cpp @@ -1,22 +1,28 @@ #include "ScanLine.h" -Rasterizer::Rasterizer(int cy) +Rasterizer::Rasterizer(Size _sz) { + sz = _sz; + x1 = y1 = 0; min_y = INT_MAX; max_y = INT_MIN; finish = true; current.Init(); - cell.Alloc(cy); + cell.Alloc(sz.cy); + cliprect = Sizef(sz); } inline void Rasterizer::AddCurrent() { - if(current.area | current.cover) + if((current.area | current.cover) && current_y >= 0 && current_y < sz.cy) { cell[current_y].Add(current); +// DLOG(current.x << ", y=" << current_y); + } } inline void Rasterizer::SetCurrent(int x, int y) { + DLOG("cury=" << y); if(current.x != x || current_y != y) { AddCurrent(); current.x = x; @@ -90,15 +96,15 @@ inline void Rasterizer::RenderHLine(int ey, int x1, int y1, int x2, int y2) current.area += (fx2 + 256 - first) * delta; } -void Rasterizer::Line(int x1, int y1, int x2, int y2) +void Rasterizer::LineRaw(int x1, int y1, int x2, int y2) { 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; - Line(x1, y1, cx, cy); - Line(cx, cy, x2, y2); + LineRaw(x1, y1, cx, cy); + LineRaw(cx, cy, x2, y2); return; } int dy = y2 - y1; @@ -109,13 +115,15 @@ void Rasterizer::Line(int x1, int y1, int x2, int y2) int fy1 = y1 & 255; int fy2 = y2 & 255; + DLOG(ex1 << ", " << ey1 << " - " << ex2 << ", " << ey2); + 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 = ey1; + if(ey1 > max_y && ey1 < sz.cy) max_y = ey1; if(ey2 < min_y) min_y = ey2; - if(ey2 > max_y) max_y = ey2; + if(ey2 > max_y && ey2 < sz.cy) max_y = ey2; SetCurrent(ex1, ey1); @@ -225,7 +233,9 @@ ScanLine Rasterizer::Get(int y) const Cell *e = cl.End(); r.x = c->x; int cover = 0; + DDUMP(y); while(c < e) { + DDUMP(c->x); int x = c->x; int area = c->area; cover += c->cover; @@ -240,7 +250,7 @@ ScanLine Rasterizer::Get(int y) else r.data.Cat(0); r.len++; - x++; + x++; if(c < e && c->x > x) { byte val = Alpha(cover << (8 + 1)); int n = c->x - x; diff --git a/uppdev/ScanLine/RasterizerClip.cpp b/uppdev/ScanLine/RasterizerClip.cpp new file mode 100644 index 000000000..4afaa4e51 --- /dev/null +++ b/uppdev/ScanLine/RasterizerClip.cpp @@ -0,0 +1,65 @@ +#include "ScanLine.h" + +void Rasterizer::Move(double x, double y) +{ + x1 = x; + y1 = y; +} + +void Rasterizer::LineClip(double x1, double y1, double x2, double y2) +{ + if(y1 < cliprect.top) { + if(y2 < cliprect.top) + return; + x1 = (x2 - x1) * (cliprect.top - y1) / (y2 - y1) + x1; + y1 = cliprect.top; + } + else + if(y1 > cliprect.bottom) { + if(y2 > cliprect.bottom) + return; + x1 = (x2 - x1) * (cliprect.bottom - y1) / (y2 - y1) + x1; + y1 = cliprect.bottom; + } + if(y2 < cliprect.top) { + x2 = (x2 - x1) * (cliprect.top - y1) / (y2 - y1) + x1; + y2 = cliprect.top; + } + else + if(y2 > cliprect.bottom) { + x2 = (x2 - x1) * (cliprect.bottom - y1) / (y2 - y1) + x1; + y2 = cliprect.bottom; + } +/* + if(x1 < cliprect.left) { + if(x2 < cliprect.left) + return; + y1 = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1; + x1 = cliprect.left; + } + else + if(x1 > cliprect.right) { + if(x2 > cliprect.right) + return; + y1 = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1; + x1 = cliprect.right; + } + if(x2 < cliprect.left) { + y2 = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1; + x2 = cliprect.left; + } + else + if(x2 > cliprect.right) { + y2 = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1; + x2 = cliprect.right; + } +*/ + LineRaw(int(x1 * 256 + 0.5), int(y1 * 256 + 0.5), int(x2 * 256 + 0.5), int(y2 * 256 + 0.5)); +} + +void Rasterizer::Line(double x2, double y2) +{ + LineClip(x1, y1, x2, y2); + x1 = x2; + y1 = y2; +} diff --git a/uppdev/ScanLine/ScanLine.cpp b/uppdev/ScanLine/ScanLine.cpp index 7006a676e..1c75bad7c 100644 --- a/uppdev/ScanLine/ScanLine.cpp +++ b/uppdev/ScanLine/ScanLine.cpp @@ -99,7 +99,7 @@ ScanLine Pack(int x, const byte *data, int len) String ScanLine::ToString() const { String s; - s << "x = " << x << ", len = " << len << ": "; + s << "x = " << x << ", len = " << len << ", right = " << len + x << ": "; for(int i = 0; i < data.GetCount(); i++) { byte val = data[i]; if(val > 128) { @@ -118,16 +118,15 @@ String ScanLine::ToString() const void Apply(RGBA *t, int len, const RGBA& color, const ScanLine& s) { t += s.x; - len -= s.x; int si = 0; - while(len >= 0 && si < s.data.GetLength()) { + const RGBA *e = t + len; + while(t < e && si < s.data.GetLength()) { byte val = s.data[si++]; if(val > 128) { - int n = min(len, val - 128); + int n = min(e - t, val - 128); val = s.data[si++]; while(n--) AlphaBlendCover7(*t++, color, val); - len -= n; } else AlphaBlendCover7(*t++, color, val); diff --git a/uppdev/ScanLine/ScanLine.h b/uppdev/ScanLine/ScanLine.h index a29621897..e3a09f016 100644 --- a/uppdev/ScanLine/ScanLine.h +++ b/uppdev/ScanLine/ScanLine.h @@ -54,27 +54,36 @@ class Rasterizer { unsigned start; unsigned num; }; - + + Rectf cliprect; + double x1, y1; Buffer< Vector > cell; int current_y; Cell current; int min_y; int max_y; + Size sz; bool finish; void AddCurrent(); void SetCurrent(int x, int y); void RenderHLine(int ey, int x1, int y1, int x2, int y2); + void LineClip(double x1, double y1, double x2, double y2); public: - void Line(int x1, int y1, int x2, int y2); + void LineRaw(int x1, int y1, int x2, int y2); + + void Move(double x, double y); + void Line(double x, double y); - int MinY() const { return min_y; } - int MaxY() const { return max_y; } + int MinY() const { return min_y; } + int MaxY() const { return max_y; } + + void SetClip(const Rectf& rect) { cliprect = rect; } ScanLine Get(int y); - Rasterizer(int cy); + Rasterizer(Size sz); }; #endif diff --git a/uppdev/ScanLine/ScanLine.upp b/uppdev/ScanLine/ScanLine.upp index 335c93eac..ef8c73543 100644 --- a/uppdev/ScanLine/ScanLine.upp +++ b/uppdev/ScanLine/ScanLine.upp @@ -6,6 +6,7 @@ file ScanLine.h, ScanLine.cpp, Rasterizer.cpp, + RasterizerClip.cpp, main.cpp; mainconfig diff --git a/uppdev/ScanLine/main.cpp b/uppdev/ScanLine/main.cpp index bbf01a13d..0be1237b4 100644 --- a/uppdev/ScanLine/main.cpp +++ b/uppdev/ScanLine/main.cpp @@ -1,32 +1,83 @@ #include "ScanLine.h" struct App : TopWindow { + double x1, y1, x2, y2, x3, y3; + + String Text() { + return Format("Move(%f, %f) Line(%f, %f) Line(%f, %f)", x1, y1, x2, y2, x3, y3); + } + + virtual void LeftDown(Point p, dword keyflags) + { + x1 = p.x; + y1 = p.y; + Refresh(); + ClearClipboard(); + AppendClipboardText(Text()); + } + virtual void RightDown(Point p, dword) + { + x2 = p.x; + y2 = p.y; + Refresh(); + ClearClipboard(); + AppendClipboardText(Text()); + } + virtual void MouseMove(Point p, dword keyflags) + { + x3 = p.x; + y3 = p.y; + Refresh(); + ClearClipboard(); + AppendClipboardText(Text()); + } + virtual void Paint(Draw& w) { ScanLine a, b; static byte line1[] = { 1, 50, 100, 128, 128, 128, 128, 128, 100, 50, 1 }; a = Pack(0, line1, __countof(line1)); - ImageBuffer ib(400, 400); + ImageBuffer ib(500, 500); Fill(~ib, White(), ib.GetLength()); - Apply(ib[20], 100, Black(), a); +/* 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(400); - r.Line(100 * 256, 100 * 256, 300 * 256, 100 * 256); - r.Line(300 * 256, 100 * 256, 200 * 256, 300 * 256); - r.Line(200 * 256, 300 * 256, 100 * 256, 100 * 256); +*/ + Rasterizer r(Size(500, 500)); + r.SetClip(RectfC(100, 100, 200, 200)); + +#if 0 + r.Move(121.000000, 121.000000); + r.Line(0.000000, 0.000000); + r.Line(597.000000, 44.000000); + r.Line(121.000000, 121.000000); +#endif + r.Move(153.000000, 297.000000); + r.Line(173.000000, 255.000000); + r.Line(564.000000, 213.000000); + r.Line(153.000000, 297.000000); +#if 0 + r.Move(x1, y1); + r.Line(x2, y2); + r.Line(x3, y3); + r.Line(x1, y1); +#endif for(int y = r.MinY(); y <= r.MaxY(); y++) { ScanLine sl = r.Get(y); DUMP(sl); - Apply(ib[y], 400, Black(), sl); + Apply(ib[y], 400, Blue(), sl); } w.DrawRect(GetSize(), White()); w.DrawImage(0, 0, ib); + w.DrawText(0, GetSize().cy - 40, Text()); + } + + App() { + x1 = y1 = x2 = y2 = 0; } };