From f5653dff761bf1d645ff0eb456c4d78c820d7759 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 1 Feb 2009 22:24:17 +0000 Subject: [PATCH] Developing rasterizer git-svn-id: svn://ultimatepp.org/upp/trunk@830 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppdev/AggCtrl/AggCtrl.upp | 2 + uppdev/FwSort/FwSort.cpp | 181 +++++++++++++++++- uppdev/FwSort/FwSort.upp | 2 +- uppdev/ScanLine/Rasterizer.cpp | 2 +- uppdev/ScanLine/Rasterizer2.cpp | 179 +++++++++++++----- uppdev/ScanLine/Rasterizer2.h | 50 +---- uppdev/ScanLine/Rasterizer2.hpp | 42 ----- uppdev/ScanLine/Rasterizer3.cpp | 281 ++++++++++++++++++++++++++++ uppdev/ScanLine/Rasterizer3.h | 45 +++++ uppdev/ScanLine/ScanLine.cpp | 234 ----------------------- uppdev/ScanLine/ScanLine.h | 109 ++++++++--- uppdev/ScanLine/ScanLine.upp | 8 +- uppdev/ScanLine/ScanLineFiller.cpp | 78 ++++++++ uppdev/ScanLine/SolidFiller.cpp | 67 +++++++ uppdev/ScanLine/SolidFillerMask.cpp | 71 +++++++ uppdev/ScanLine/main.cpp | 5 +- uppdev/aggtest/aggtest.lay | 2 +- uppdev/aggtest/aggtest.upp | 2 + uppdev/aggtest/init | 1 - uppdev/aggtest/main.cpp | 90 ++++----- 20 files changed, 1001 insertions(+), 450 deletions(-) delete mode 100644 uppdev/ScanLine/Rasterizer2.hpp create mode 100644 uppdev/ScanLine/Rasterizer3.cpp create mode 100644 uppdev/ScanLine/Rasterizer3.h delete mode 100644 uppdev/ScanLine/ScanLine.cpp create mode 100644 uppdev/ScanLine/ScanLineFiller.cpp create mode 100644 uppdev/ScanLine/SolidFiller.cpp create mode 100644 uppdev/ScanLine/SolidFillerMask.cpp diff --git a/uppdev/AggCtrl/AggCtrl.upp b/uppdev/AggCtrl/AggCtrl.upp index d19997015..d199aa39f 100644 --- a/uppdev/AggCtrl/AggCtrl.upp +++ b/uppdev/AggCtrl/AggCtrl.upp @@ -1,3 +1,5 @@ +optimize_speed; + uses CtrlLib, agg24; diff --git a/uppdev/FwSort/FwSort.cpp b/uppdev/FwSort/FwSort.cpp index e0d8d27dd..cc067c558 100644 --- a/uppdev/FwSort/FwSort.cpp +++ b/uppdev/FwSort/FwSort.cpp @@ -3,7 +3,7 @@ using namespace Upp; template -void FwSort(I begin, I end, const Less& less) +void FwSort2(I begin, I end, const Less& less) { while(begin != end && begin + 1 != end) { I min = begin; @@ -20,7 +20,160 @@ void FwSort(I begin, I end, const Less& less) } } -void Dump(const Vector& data) +template +void FwSortSimple(I begin, I end, const Less& less) +{ + while(begin != end) { + I min = begin; + for(I i = begin; ++i != end;) + if(less(*i, *min)) + min = i; + IterSwap(begin++, min); + } +} + +template +inline I SelectMin2(I ptr, const Less& less) +{ + return less(ptr[0], ptr[1]) ? ptr : ptr + 1; +} + +template +inline I SelectMin3(I ptr, const Less& less) +{ + I l = SelectMin2(ptr, less); + I h = ptr + 2; + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin4(I ptr, const Less& less) +{ + I l = SelectMin2(ptr, less); + I h = SelectMin2(ptr + 2, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin5(I ptr, const Less& less) +{ + I l = SelectMin4(ptr, less); + I h = ptr + 4; + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin6(I ptr, const Less& less) +{ + I l = SelectMin4(ptr, less); + I h = SelectMin2(ptr + 4, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin7(I ptr, const Less& less) +{ + I l = SelectMin4(ptr, less); + I h = SelectMin3(ptr + 4, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin8(I ptr, const Less& less) +{ + I l = SelectMin4(ptr, less); + I h = SelectMin4(ptr + 4, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin9(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = ptr + 8; + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin10(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin2(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin11(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin3(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin12(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin4(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin13(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin5(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin14(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin6(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin15(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin7(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +inline I SelectMin16(I ptr, const Less& less) +{ + I l = SelectMin8(ptr, less); + I h = SelectMin8(ptr + 8, less); + return less(*l, *h) ? l : h; +} + +template +void FwSort(I begin, int len, const Less& less) +{ + switch(len) { + case 16: IterSwap(begin, SelectMin16(begin, less)); begin++; + case 15: IterSwap(begin, SelectMin15(begin, less)); begin++; + case 14: IterSwap(begin, SelectMin14(begin, less)); begin++; + case 13: IterSwap(begin, SelectMin13(begin, less)); begin++; + case 12: IterSwap(begin, SelectMin12(begin, less)); begin++; + case 11: IterSwap(begin, SelectMin11(begin, less)); begin++; + case 10: IterSwap(begin, SelectMin10(begin, less)); begin++; + case 9: IterSwap(begin, SelectMin9(begin, less)); begin++; + case 8: IterSwap(begin, SelectMin8(begin, less)); begin++; + case 7: IterSwap(begin, SelectMin7(begin, less)); begin++; + case 6: IterSwap(begin, SelectMin6(begin, less)); begin++; + case 5: IterSwap(begin, SelectMin5(begin, less)); begin++; + case 4: IterSwap(begin, SelectMin4(begin, less)); begin++; + case 3: IterSwap(begin, SelectMin3(begin, less)); begin++; + case 2: IterSwap(begin, SelectMin2(begin, less)); + } +} + +template +void Dump(const Vector& data) { String s; for(int q = 0; q < data.GetCount(); q++) @@ -31,13 +184,21 @@ void Dump(const Vector& data) CONSOLE_APP_MAIN { #ifdef _DEBUG + Vector x; + x << 40 << 20 << 4 << 10 << 11 << 17 << 2 << 12; + FwSort(x.Begin(), x.GetCount(), StdLess()); + Dump(x); + Vector y; + y << "40" << "20" << "4" << "10" << "11" << "17" << "2" << "12"; + FwSort(y.Begin(), y.GetCount(), StdLess()); + Dump(y); for(int i = 0; i < 10; i++) { Vector data; - int n = rand() % 30; + int n = rand() % 16; for(int q = 0; q < n; q++) data.Add(rand() % 100); Dump(data); - FwSort(data.Begin(), data.End(), StdLess()); + FwSort(data.Begin(), data.GetCount(), StdLess()); Dump(data); LOG("----"); } @@ -45,15 +206,23 @@ CONSOLE_APP_MAIN Vector< Vector > set; for(int i = 0; i < 1000; i++) { Vector& data = set.Add(); - int n = rand() % 20; + int n = rand() % 15; n = 8; for(int q = 0; q < n; q++) data.Add(rand() % 100); } + double x = 100.0 * set.GetCount(); + RDUMP(x); dword time = GetTickCount(); while(time + 3000 > GetTickCount()) { Vector< Vector > s; s <<= set; + { + RTIMING("Simple FW sort"); + for(int i = 0; i < s.GetCount(); i++) + ForwardSort(s[i].Begin(), s[i].End(), StdLess()); + } + s <<= set; { RTIMING("Normal FW sort"); for(int i = 0; i < s.GetCount(); i++) @@ -63,7 +232,7 @@ CONSOLE_APP_MAIN { RTIMING("New FW sort"); for(int i = 0; i < s.GetCount(); i++) - FwSort(s[i].Begin(), s[i].End(), StdLess()); + FwSort(s[i].Begin(), s[i].GetCount(), StdLess()); } } #endif diff --git a/uppdev/FwSort/FwSort.upp b/uppdev/FwSort/FwSort.upp index edba507c9..6c0cc2149 100644 --- a/uppdev/FwSort/FwSort.upp +++ b/uppdev/FwSort/FwSort.upp @@ -7,5 +7,5 @@ file FwSort.cpp; mainconfig - "" = ""; + "" = "SSE2"; diff --git a/uppdev/ScanLine/Rasterizer.cpp b/uppdev/ScanLine/Rasterizer.cpp index cbc1bbb7c..4d892c582 100644 --- a/uppdev/ScanLine/Rasterizer.cpp +++ b/uppdev/ScanLine/Rasterizer.cpp @@ -1,6 +1,6 @@ #include "ScanLine.h" -#ifndef RASTERIZER2 +#ifdef RASTERIZER1 void Rasterizer::Reset() { diff --git a/uppdev/ScanLine/Rasterizer2.cpp b/uppdev/ScanLine/Rasterizer2.cpp index f526d1ff6..fedccee7f 100644 --- a/uppdev/ScanLine/Rasterizer2.cpp +++ b/uppdev/ScanLine/Rasterizer2.cpp @@ -36,7 +36,7 @@ Rasterizer::Rasterizer(int cx, int cy) inline Rasterizer::Cell *Rasterizer::AddCells(int y, int n) { Vector& v = cell[y]; - if(v.GetCount() == 0) { + if(v.GetAlloc() == 0) { v.Reserve(16); v.SetCount(n); return &v[0]; @@ -55,65 +55,104 @@ inline void Rasterizer::RenderHLine(int ey, int x1, int y1, int x2, int y2) Cell *c; if(y1 == y2) return; + int dy = y2 - y1; if(ex1 == ex2) { - int delta = y2 - y1; c = AddCells(ey, 1); c->x = ex1; - c->cover = y2 - y1; - c->area = (fx1 + fx2) * delta; + c->cover = dy; + c->area = (fx1 + fx2) * dy; return; } - int p = (256 - fx1) * (y2 - y1); - int first = 256; - int incr = 1; int dx = x2 - x1; if(dx < 0) { - p = fx1 * (y2 - y1); - first = 0; - incr = -1; + 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->x = ex1; - c->cover = delta; - c->area = (fx1 + first) * delta; - c++; - ex1 += incr; - y1 += delta; - if(ex1 != ex2) { - p = (y2 - y1 + delta) * 256; - int lift = p / dx; - int rem = p % dx; - if (rem < 0) { - lift--; - rem += dx; + int delta = p / dx; + int mod = p % dx; + if(mod < 0) { + delta--; + mod += dx; } - mod -= dx; - while(ex1 != ex2) { - delta = lift; - mod += rem; - if(mod >= 0) { - mod -= dx; - delta++; + c = AddCells(ey, abs(ex2 - ex1) + 1); + c->x = ex1; + c->cover = delta; + c->area = fx1 * delta; + c++; + 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->x = ex1; + c->cover = delta; + c->area = delta * 256; + c++; + y1 += delta; + ex1--; } - c->x = ex1; - c->cover = delta; - c->area = delta * 256; - c++; - y1 += delta; - ex1 += incr; } + c->x = ex2; + dy = y2 - y1; + c->cover = dy; + c->area = (fx2 + 256) * dy; + } + 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->x = ex1; + c->cover = delta; + c->area = (fx1 + 256) * delta; + c++; + 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->x = ex1; + c->cover = delta; + c->area = delta * 256; + c++; + y1 += delta; + ex1++; + } + } + c->x = ex2; + dy = y2 - y1; + c->cover = dy; + c->area = fx2 * dy; } - delta = y2 - y1; - c->x = ex2; - c->cover = delta; - c->area = (fx2 + 256 - first) * delta; } void Rasterizer::LineRaw(int x1, int y1, int x2, int y2) @@ -226,15 +265,51 @@ void Rasterizer::LineRaw(int x1, int y1, int x2, int y2) RenderHLine(ey1, x_from, 256 - first, x2, fy2); } -bool Rasterizer::BeginRender(int y, const Cell *&c, const Cell *&e) +inline unsigned Alpha(int area) { - if(y < min_y || y > max_y) return false; +// return min(abs(area >> 9), 256); + int cover = area >> 9; + if(cover < 0) cover = -cover; +/* if(evenodd) { + cover &= 511; + if(cover > 256) + cover = 512 - cover; + }*/ +/* if(cover > 255) { + cover = 255; + }*/ + return cover; +} + +void Rasterizer::Render(int y, Target& g) +{ + PAINTER_TIMING("Render"); + const Cell *c, *e; + if(y < min_y || y > max_y) return; Vector& cl = cell[y]; - if(cl.GetCount() == 0) return false; + if(cl.GetCount() == 0) return; Sort(cl); c = cl; e = cl.End(); - return true; + g.Start(c->x, (e - 1)->x); + int cover = 0; + while(c < e) { + int x = c->x; + int area = c->area; + cover += c->cover; + c++; + while(c < e && c->x == x) { + area += c->area; + cover += c->cover; + c++; + } + if(area) { + g.Render(abs(((cover << 9) - area) >> 9)); + x++; + } + if(c < e && c->x > x) + g.Render(abs(cover), c->x - x); + } } #endif diff --git a/uppdev/ScanLine/Rasterizer2.h b/uppdev/ScanLine/Rasterizer2.h index a15982c15..45f38b9f3 100644 --- a/uppdev/ScanLine/Rasterizer2.h +++ b/uppdev/ScanLine/Rasterizer2.h @@ -25,6 +25,12 @@ class Rasterizer { 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 Move(double x, double y); @@ -35,51 +41,9 @@ public: void SetClip(const Rectf& rect); - template void Render(int y, Target& g); - + void Reset(); Rasterizer(int cx, int cy); }; - -inline unsigned Alpha(int area) -{ - int cover = area >> 9; - if(cover < 0) cover = -cover; -/* if(evenodd) { - cover &= 511; - if(cover > 256) - cover = 512 - cover; - }*/ - if(cover > 255) cover = 255; - return (cover + 1) / 2; -} - -template -void Rasterizer::Render(int y, Target& g) -{ - PAINTER_TIMING("Render"); - const Cell *c, *e; - if(!BeginRender(y, c, e)) - return; - g.Start(c->x); - int cover = 0; - while(c < e) { - int x = c->x; - int area = c->area; - cover += c->cover; - c++; - while(c < e && c->x == x) { - area += c->area; - cover += c->cover; - c++; - } - if(area) { - g.Render(Alpha((cover << (8 + 1)) - area)); - x++; - } - if(c < e && c->x > x) - g.Render(Alpha(cover << (8 + 1)), c->x - x); - } -} diff --git a/uppdev/ScanLine/Rasterizer2.hpp b/uppdev/ScanLine/Rasterizer2.hpp deleted file mode 100644 index 577c58fdb..000000000 --- a/uppdev/ScanLine/Rasterizer2.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "ScanLine.h" - -inline unsigned Alpha(int area) -{ - int cover = area >> 9; - if(cover < 0) cover = -cover; -/* if(evenodd) { - cover &= 511; - if(cover > 256) - cover = 512 - cover; - }*/ - if(cover > 255) cover = 255; - return (cover + 1) / 2; -} - -template -void Rasterizer::Render(int y, Target& g) -{ - PAINTER_TIMING("Render"); - const Cell *c, *e; - if(!BeginRender(y, c, e)) - return; - g.Start(c->x); - int cover = 0; - while(c < e) { - int x = c->x; - int area = c->area; - cover += c->cover; - c++; - while(c < e && c->x == x) { - area += c->area; - cover += c->cover; - c++; - } - if(area) { - g.Render(Alpha((cover << (8 + 1)) - area)); - x++; - } - if(c < e && c->x > x) - g.Render(Alpha(cover << (8 + 1)), c->x - x); - } -} diff --git a/uppdev/ScanLine/Rasterizer3.cpp b/uppdev/ScanLine/Rasterizer3.cpp new file mode 100644 index 000000000..df4557523 --- /dev/null +++ b/uppdev/ScanLine/Rasterizer3.cpp @@ -0,0 +1,281 @@ +#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/Rasterizer3.h b/uppdev/ScanLine/Rasterizer3.h new file mode 100644 index 000000000..e940d40dc --- /dev/null +++ b/uppdev/ScanLine/Rasterizer3.h @@ -0,0 +1,45 @@ +class Rasterizer { + Rectf cliprect; + double x1, y1; + Buffer< Vector > cell; + int xmax, ymax; + int min_y; + int max_y; + Size sz; + + inline dword Cell(int x, int w, int c) { return (x << 18) + (w << 9) + c; } + inline int GetX(dword cell) { return cell >> 18; } + inline int GetW(dword cell) { return (cell >> 9) & 511; } + inline int GetC(dword cell) { return (cell & 256) ? -512 | (cell & 511) : (cell & 511); } + + void Init(); + dword *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); + +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 Move(double x, double y); + void Line(double x, double y); + + int MinY() const { return min_y; } + int MaxY() const { return max_y; } + + void SetClip(const Rectf& rect); + + void Render(int y, Target& g); + + void Reset(); + + Rasterizer(int cx, int cy); +}; diff --git a/uppdev/ScanLine/ScanLine.cpp b/uppdev/ScanLine/ScanLine.cpp deleted file mode 100644 index 785171d62..000000000 --- a/uppdev/ScanLine/ScanLine.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "ScanLine.h" - -ScanLine And0(const ScanLine& a, const ScanLine& b) -{ - ScanLine r; - r.len = 0; - r.x = b.x; - byte aval = 0; - int acount = 0; - byte bval = 0; - int ai = 0; - int bi = 0; - int bcount = b.x - a.x; - while(bcount) { - if(ai >= a.data.GetCount()) - return r; - aval = a.data[ai++]; - if(aval > 128) { - acount = aval - 128; - aval = a.data[ai++]; - int n = min(acount, bcount); - acount -= n; - bcount -= n; - } - else - bcount--; - } - while(ai < a.data.GetCount() && bi < b.data.GetCount()) { - if(acount == 0) { - aval = a.data[ai++]; - if(aval > 128) { - acount = aval - 128; - aval = a.data[ai++]; - } - } - if(bcount == 0) { - bval = b.data[bi++]; - if(bval > 128) { - bcount = bval - 128; - bval = b.data[bi++]; - } - } - if(acount && bcount) { - int l = min(acount, bcount); - acount -= l; - bcount -= l; - r.len += l; - while(l) { - int n = min(l, 127); - r.data.Cat(n + 128); - r.data.Cat((aval * bval) >> 7); - l -= n; - } - } - else { - r.data.Cat((aval * bval) >> 7); - r.len++; - if(acount) acount--; - if(bcount) bcount--; - } - } - return r; -} - -ScanLine And(const ScanLine& a, const ScanLine& b) -{ - return a.x < b.x ? And0(a, b) : And0(b, a); -} - -ScanLine Pack(int x, const byte *data, int len) -{ - ScanLine r; - int i = 0; - r.x = x; - r.len = 0; - while(i < len) { - int n = i; - byte val = data[i++]; - while(i < len && data[i] == val) - i++; - n = i - n; - if(n > 1) { - r.len += n; - while(n) { - int q = min(n, 127); - r.data.Cat(q + 128); - r.data.Cat(val); - n -= q; - } - } - else { - r.data.Cat(val); - r.len++; - } - } - return r; -} - -String ScanLine::ToString() const -{ - String s; - s << "datalen: " << data.GetCount() << "x = " << x << ", len = " << len << ", right = " << len + x << ": "; - for(int i = 0; i < data.GetCount(); i++) { - byte val = data[i]; - if(val > 128) { - int n = val - 128; - val = data[++i]; - while(n--) - s << (int)val << ", "; - } - else - s << (int)val << ", "; - } - return s; -} - -void Apply(RGBA *t, int len, const RGBA& c, const ScanLine& s) -{ - PAINTER_TIMING("Apply"); - RGBA *e = t + len; - const char *q = ~s.data; - const char *qe = s.data.End(); - t += s.x; - while(t < e && q < qe) { - byte val = *q++; - if(val > 128) { - RGBA *e1 = min(e, t + val - 128); - byte val = *q++; - if(val == 128 && c.a == 255) { - int l = e1 - t; - while(l >= 16) { - t[0] = c; t[1] = c; t[2] = c; t[3] = c; - t[4] = c; t[5] = c; t[6] = c; t[7] = c; - t[8] = c; t[9] = c; t[10] = c; t[11] = c; - t[12] = c; t[13] = c; t[14] = c; t[15] = c; - t += 16; - l -= 16; - } - switch(l) { - case 15: t[14] = c; - case 14: t[13] = c; - case 13: t[12] = c; - case 12: t[11] = c; - case 11: t[10] = c; - case 10: t[9] = c; - case 9: t[8] = c; - case 8: t[7] = c; - case 7: t[6] = c; - case 6: t[5] = c; - case 5: t[4] = c; - case 4: t[3] = c; - case 3: t[2] = c; - case 2: t[1] = c; - case 1: t[0] = c; - } - t = e1; - } - else { - RGBA c1; - if(val != 128) - c1 = Mul7(c, val); - else - c1 = c; - while(t < e1) - AlphaBlend(*t++, c1); - } - } - else - AlphaBlendCover7(*t++, c, val); -// DDUMP(t - e); - } -} - -struct SolidFiller { - RGBA *t; - RGBA c; - - void Start(int x) { t += x; } - void Render(byte val) { AlphaBlendCover7(*t++, c, val); } - void Render(byte val, int len); -}; - -void SolidFiller::Render(byte val, int len) -{ - if(((val - 128) | (c.a - 255)) == 0) { - while(len >= 16) { - t[0] = c; t[1] = c; t[2] = c; t[3] = c; - t[4] = c; t[5] = c; t[6] = c; t[7] = c; - t[8] = c; t[9] = c; t[10] = c; t[11] = c; - t[12] = c; t[13] = c; t[14] = c; t[15] = c; - t += 16; - len -= 16; - } - switch(len) { - case 15: t[14] = c; - case 14: t[13] = c; - case 13: t[12] = c; - case 12: t[11] = c; - case 11: t[10] = c; - case 10: t[9] = c; - case 9: t[8] = c; - case 8: t[7] = c; - case 7: t[6] = c; - case 6: t[5] = c; - case 5: t[4] = c; - case 4: t[3] = c; - case 3: t[2] = c; - case 2: t[1] = c; - case 1: t[0] = c; - } - t += len; - } - else { - RGBA c1; - if(val != 128) - c1 = Mul7(c, val); - else - c1 = c; - RGBA *e = t + len; - while(t < e) - AlphaBlend(*t++, c1); - } -} - -void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color) -{ - Size sz = ib.GetSize(); - SolidFiller f; - f.c = color; - for(int y = r.MinY(); y <= r.MaxY(); y++) { - f.t = ib[y]; - r.Render(y, f); - } -} diff --git a/uppdev/ScanLine/ScanLine.h b/uppdev/ScanLine/ScanLine.h index 6214090f3..eead863b6 100644 --- a/uppdev/ScanLine/ScanLine.h +++ b/uppdev/ScanLine/ScanLine.h @@ -9,13 +9,13 @@ using namespace Upp; #define PAINTER_TIMING(x) // RTIMING(x) -inline RGBA Mul7(const RGBA& s, int mul) +inline RGBA Mul8(const RGBA& s, int mul) { RGBA t; - t.r = (mul * s.r) >> 7; - t.g = (mul * s.g) >> 7; - t.b = (mul * s.b) >> 7; - t.a = (mul * s.a) >> 7; + t.r = (mul * s.r) >> 8; + t.g = (mul * s.g) >> 8; + t.b = (mul * s.b) >> 8; + t.a = (mul * s.a) >> 8; return t; } @@ -28,35 +28,35 @@ inline void AlphaBlend(RGBA& t, const RGBA& c) t.a = c.a + (alpha * t.a >> 8); } -inline void AlphaBlendCover7(RGBA& t, const RGBA& c, byte cover) +inline void AlphaBlendCover8(RGBA& t, const RGBA& c, int cover) { -#if 0 - AlphaBlend(t, Mul7(c, cover)); -#else - int a = c.a * cover >> 7; + int a = c.a * cover >> 8; int alpha = 256 - (a + (a >> 7)); - t.r = (c.r * cover >> 7) + (alpha * t.r >> 8); - t.g = (c.g * cover >> 7) + (alpha * t.g >> 8); - t.b = (c.b * cover >> 7) + (alpha * t.b >> 8); + t.r = (c.r * cover >> 8) + (alpha * t.r >> 8); + t.g = (c.g * cover >> 8) + (alpha * t.g >> 8); + t.b = (c.b * cover >> 8) + (alpha * t.b >> 8); t.a = a + (alpha * t.a >> 8); -#endif } struct ScanLine { - int x, len; - String data; - + int xmin, xmax; + Buffer data; + int datalen; + + bool IsFull(); + bool IsEmpty(); + String ToString() const; }; -void Apply(RGBA *t, int len, const RGBA& color, const ScanLine& s); -ScanLine And(const ScanLine& a, const ScanLine& b); -ScanLine Pack(int x, const byte *data, int len); - #ifdef RASTERIZER2 #include "Rasterizer2.h" +#elif defined(RASTERIZER3) + +#include "Rasterizer3.h" + #else #include "Rasterizer.h" @@ -65,4 +65,71 @@ ScanLine Pack(int x, const byte *data, int len); void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color); +struct VertexTarget { + virtual void Move(Pointf p) = 0; + virtual void Line(Pointf p) = 0; + virtual void End() = 0; +}; + +struct VertexProcessor : VertexTarget { + VertexTarget *target; +}; + +class Stroker : VertexProcessor { +public: + virtual void Move(double x, double y); + virtual void Line(double x, double y); + virtual void End(); +}; + +class Dasher : VertexProcessor { +public: + virtual void Move(double x, double y); + virtual void Line(double x, double y); + virtual void End(); +}; + +class Transformer : VertexProcessor { +public: + virtual void Move(double x, double y); + virtual void Line(double x, double y); + virtual void End(); +}; + +struct LineSegment { + byte kind; + Pointf x; +}; + +struct QuadraticSegment { + byte kind; + Pointf x; + Pointf x1; +}; + +struct CubicSegment { + byte kind; + Pointf x; + Pointf x1; + Pointf x2; +}; + +void Quadratic(VertexTarget& t, Pointf x0, Pointf x1, Pointf x, double epsilon); +void Cubic(VertexTarget& t, Pointf x0, Pointf x1, Pointf x2, Pointf x, double epsilon); + +class Painter { + Vector path; + + template + T& PathAdd() { + int q = path.GetCount(); + path.SetCount(q + sizeof(T)); + return *(T *)&path[q]; + } + + void Move(Pointf t) { + } +}; + + #endif diff --git a/uppdev/ScanLine/ScanLine.upp b/uppdev/ScanLine/ScanLine.upp index eaf6ce2ad..494b15e69 100644 --- a/uppdev/ScanLine/ScanLine.upp +++ b/uppdev/ScanLine/ScanLine.upp @@ -6,13 +6,17 @@ uses file ScanLine.h, - ScanLine.cpp, + ScanLineFiller.cpp, + SolidFiller.cpp, + SolidFillerMask.cpp, Rasterizer.h, Rasterizer.cpp, Rasterizer2.h, Rasterizer2.cpp, - Rasterizer2.hpp, + Rasterizer3.h, + Rasterizer3.cpp, RasterizerClip.cpp, + help.txt, Lion.cpp, main.cpp; diff --git a/uppdev/ScanLine/ScanLineFiller.cpp b/uppdev/ScanLine/ScanLineFiller.cpp new file mode 100644 index 000000000..559f83817 --- /dev/null +++ b/uppdev/ScanLine/ScanLineFiller.cpp @@ -0,0 +1,78 @@ +#include "ScanLine.h" + +struct RecScan : Rasterizer::Target { + ScanLine sl; + byte *t; + int x; + + virtual void Render(int val); + virtual void Render(int val, int len); + virtual void Start(int x, int len); + void Finish(); +}; + +void RecScan::Start(int xmin, int xmax) +{ + sl.data.Alloc((xmax - xmin + 1) * 2); + t = ~sl.data; + sl.xmin = 0; +} + +void RecScan::Render(int val) +{ + if(val == 0) { + *t++ = 0; + *t++ = 0; + } + else + if(val == 256) { + *t++ = 0; + *t++ = 0; + } + else + *t++ = val; + x++; +} + +void RecScan::Render(int val, int len) +{ + x += len; + if(val == 256) { + while(len > 0) { + int n = min(len, 128); + *t++ = 0; + *t++ = 128 + n - 1; + len -= n; + } + return; + } + if(val == 0) { + while(len > 0) { + int n = min(len, 128); + *t++ = 0; + *t++ = n - 1; + len -= n; + } + return; + } + while(len--) + *t++ = val; +} +/* +void RecScan::Finish(int cx) +{ + cx = cx - x; + while(cx > 0) { + int n = min(cx, 128); + *t++ = 0; + *t++ = n - 1; + cx -= n; + } + sl.datalen = t - ~sl.data; +} + +void RecScan::Shrink() +{ + if(sl.datalen + 30 < +} +*/ \ No newline at end of file diff --git a/uppdev/ScanLine/SolidFiller.cpp b/uppdev/ScanLine/SolidFiller.cpp new file mode 100644 index 000000000..87890ab3a --- /dev/null +++ b/uppdev/ScanLine/SolidFiller.cpp @@ -0,0 +1,67 @@ +#include "ScanLine.h" + +struct SolidFiller : Rasterizer::Target { + RGBA *t; + RGBA c; + + void Start(int minx, int maxx) { t += minx; } + void Render(int val) { AlphaBlendCover8(*t++, c, val); } + void Render(int val, int len); +}; + +void SolidFiller::Render(int val, int len) +{ + if(val == 0) { + t += len; + return; + } + if(((val - 256) | (c.a - 255)) == 0) { + while(len >= 16) { + t[0] = c; t[1] = c; t[2] = c; t[3] = c; + t[4] = c; t[5] = c; t[6] = c; t[7] = c; + t[8] = c; t[9] = c; t[10] = c; t[11] = c; + t[12] = c; t[13] = c; t[14] = c; t[15] = c; + t += 16; + len -= 16; + } + switch(len) { + case 15: t[14] = c; + case 14: t[13] = c; + case 13: t[12] = c; + case 12: t[11] = c; + case 11: t[10] = c; + case 10: t[9] = c; + case 9: t[8] = c; + case 8: t[7] = c; + case 7: t[6] = c; + case 6: t[5] = c; + case 5: t[4] = c; + case 4: t[3] = c; + case 3: t[2] = c; + case 2: t[1] = c; + case 1: t[0] = c; + } + t += len; + } + else { + RGBA c1; + if(val != 256) + c1 = Mul8(c, val); + else + c1 = c; + RGBA *e = t + len; + while(t < e) + AlphaBlend(*t++, c1); + } +} + +void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color) +{ + Size sz = ib.GetSize(); + SolidFiller f; + f.c = color; + for(int y = r.MinY(); y <= r.MaxY(); y++) { + f.t = ib[y]; + r.Render(y, f); + } +} diff --git a/uppdev/ScanLine/SolidFillerMask.cpp b/uppdev/ScanLine/SolidFillerMask.cpp new file mode 100644 index 000000000..619504ace --- /dev/null +++ b/uppdev/ScanLine/SolidFillerMask.cpp @@ -0,0 +1,71 @@ +#include "ScanLine.h" + +/* +struct SolidFillerWithMask : Rasterizer::Target { + SolidFiller f; + byte *mask; + int empty; + int full; + + void Start(int minx, int maxx) { t += x; } + void Render(int val); + void Render(int val, int len); +}; + +void SolidFillerWithMask::Render(byte val) +{ + for(;;) { + if(empty) { + f.t++; + empty--; + return; + } + if(full) { + f.Render(val); + full--; + return; + } + byte m = *mask++; + if(m) { + f.Render(val * m >> 8); + return; + } + else { + if(m < 128) + empty = m + 1; + else + full = m - 128 + 1; + } + } +} + +void SolidFillerWithMask::Render(byte val, int len) +{ + while(len) { + if(empty) { + int n = min(len, empty); + f.Skip(n); + empty -= n; + } + else + if(full) { + int n = min(len, full); + f.Render(val, n); + full -= n; + } + else { + byte m = *mask++; + if(m) { + f.Render(val * m >> 8); + len--; + } + else { + if(m < 128) + empty = m + 1; + else + full = m - 128 + 1; + } + } + } +} +*/ diff --git a/uppdev/ScanLine/main.cpp b/uppdev/ScanLine/main.cpp index a1b119d96..085a61e61 100644 --- a/uppdev/ScanLine/main.cpp +++ b/uppdev/ScanLine/main.cpp @@ -35,9 +35,6 @@ struct App : TopWindow { } 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(500, 500); Fill(~ib, White(), ib.GetLength()); /* Apply(ib[20], 100, Black(), a); @@ -112,6 +109,8 @@ struct App : TopWindow { }; GUI_APP_MAIN { + DUMP(sizeof(LineSegment)); + DUMP(sizeof(CubicSegment)); #ifdef _DEBUG App().Run(); #else _DEBUG diff --git a/uppdev/aggtest/aggtest.lay b/uppdev/aggtest/aggtest.lay index 6ed60e9bd..a20953708 100644 --- a/uppdev/aggtest/aggtest.lay +++ b/uppdev/aggtest/aggtest.lay @@ -1,4 +1,4 @@ -LAYOUT(aggtestLayout, 156, 172) +LAYOUT(aggtestLayout, 772, 776) ITEM(AggTestCtrl, MyAgg, HSizePosZ(4, 4).VSizePosZ(8, 8)) END_LAYOUT diff --git a/uppdev/aggtest/aggtest.upp b/uppdev/aggtest/aggtest.upp index 47827f731..ba1cf7422 100644 --- a/uppdev/aggtest/aggtest.upp +++ b/uppdev/aggtest/aggtest.upp @@ -1,3 +1,5 @@ +optimize_speed; + uses CtrlLib, AggCtrl; diff --git a/uppdev/aggtest/init b/uppdev/aggtest/init index a494a9818..9371480d8 100644 --- a/uppdev/aggtest/init +++ b/uppdev/aggtest/init @@ -2,5 +2,4 @@ #define _aggtest_icpp_init_stub #include "CtrlLib/init" #include "AggCtrl/init" -#include "SDraw/init" #endif diff --git a/uppdev/aggtest/main.cpp b/uppdev/aggtest/main.cpp index a8bddcaa4..12427f7f9 100644 --- a/uppdev/aggtest/main.cpp +++ b/uppdev/aggtest/main.cpp @@ -1,43 +1,47 @@ -#include "aggtest.h" - -// this function is defined in lion.cpp, where's also the description of the lion -unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); - -void AggTestCtrl::parse_lion() { - npaths = ::parse_lion(path, colors, path_idx); - agg::pod_array_adaptor pathidx(path_idx, 100); - agg::bounding_rect(path, pathidx, 0, npaths, &x1, &y1, &x2, &y2); - base_dx=(x2-x1); - base_dy=(y2-y1); -}; -AggTestCtrl::AggTestCtrl(): -pixf(rbuf),rb(pixf),r(rb), -x1(0),y1(0),x2(0),y2(0), -npaths(0),base_dx(0),base_dy(0),scale(1.0){ - SetPixFmt(agg::pix_format_bgr24); - parse_lion(); -}; -void AggTestCtrl::onDraw(Draw& dest){ - rb.clear(agg::rgba8(255, 255, 255)); - agg::trans_affine mtx; - mtx *= agg::trans_affine_translation(-base_dx/2.0, -base_dy/2.0); - mtx *= agg::trans_affine_scaling(scale, scale); - mtx *= agg::trans_affine_translation(rbuf.width()/2, rbuf.height()/2); - agg::conv_transform trans(path, mtx); - agg::render_all_paths(rasterizer, sl, r, trans, colors, path_idx, npaths); -}; -void AggTestCtrl::onInit(){ -}; -void AggTestCtrl::onResize(int width,int height){ - scale=Upp::min(width/base_dx,height/base_dy); - rb.reset_clipping(true); -}; -aggtest::aggtest(){ - CtrlLayout(*this, "AggCtrl"); - SetMinSize(Size(16,16)); - Sizeable(); -}; - -GUI_APP_MAIN { - aggtest().Run(); -} +#include "aggtest.h" + +// this function is defined in lion.cpp, where's also the description of the lion +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); + +void AggTestCtrl::parse_lion() { + npaths = ::parse_lion(path, colors, path_idx); + agg::pod_array_adaptor pathidx(path_idx, 100); + agg::bounding_rect(path, pathidx, 0, npaths, &x1, &y1, &x2, &y2); + base_dx=(x2-x1); + base_dy=(y2-y1); +}; +AggTestCtrl::AggTestCtrl(): +pixf(rbuf),rb(pixf),r(rb), +x1(0),y1(0),x2(0),y2(0), +npaths(0),base_dx(0),base_dy(0),scale(1.0){ + SetPixFmt(agg::pix_format_bgr24); + parse_lion(); +}; +void AggTestCtrl::onDraw(Draw& dest){ + scale = 1; + rb.clear(agg::rgba8(255, 255, 255)); + for(int i = 0; i < 200; i++) { + RTIMING("Lion"); + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-base_dx/2.0, -base_dy/2.0); + mtx *= agg::trans_affine_scaling(scale, scale); + mtx *= agg::trans_affine_translation(rbuf.width()/2, rbuf.height()/2); + agg::conv_transform trans(path, mtx); + agg::render_all_paths(rasterizer, sl, r, trans, colors, path_idx, npaths); + } +}; +void AggTestCtrl::onInit(){ +}; +void AggTestCtrl::onResize(int width,int height){ + scale=Upp::min(width/base_dx,height/base_dy); + rb.reset_clipping(true); +}; +aggtest::aggtest(){ + CtrlLayout(*this, "AggCtrl"); + SetMinSize(Size(16,16)); + Sizeable(); +}; + +GUI_APP_MAIN { + aggtest().Run(); +}