diff --git a/uppdev/Mirrors/Mirrors.upp b/uppdev/Mirrors/Mirrors.upp deleted file mode 100644 index 2f95bc283..000000000 --- a/uppdev/Mirrors/Mirrors.upp +++ /dev/null @@ -1,11 +0,0 @@ -uses - CtrlLib, - Report, - Painter; - -file - main.cpp; - -mainconfig - "" = "GUI"; - diff --git a/uppdev/Mirrors/init b/uppdev/Mirrors/init deleted file mode 100644 index e018374b0..000000000 --- a/uppdev/Mirrors/init +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _Mirrors_icpp_init_stub -#define _Mirrors_icpp_init_stub -#include "CtrlLib/init" -#include "Report/init" -#include "Painter/init" -#endif diff --git a/uppdev/Mirrors/main.cpp b/uppdev/Mirrors/main.cpp deleted file mode 100644 index 88558ed4c..000000000 --- a/uppdev/Mirrors/main.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include - -using namespace Upp; - -GUI_APP_MAIN -{ - Font fnt = Arial(200); - Size isz = GetTextSize("M", fnt); - String letters = "sSzZEeDNB12345679kKrRLCc"; - Report r; - Size page = r.GetPageSize(); -// r.DrawText(0, 0, letters, fnt); - for(int y = 0; y + isz.cy < page.cy; y += 3 * isz.cy / 2) - for(int x = 0; x < page.cx; x += 3 * isz.cx / 2) { - int ch = letters[Random(letters.GetCount())]; - PaintingPainter gw(isz.cx, isz.cy); - gw.Begin(); - if(Random(4) == 0) { - gw.Translate(isz.cx, 0); - gw.Scale(-1, 1); - } - gw.Character((isz.cx - fnt.Info()[ch]) / 2, 0, ch, fnt).Fill(Black()); -// gw.Rectangle(0, 0, isz.cx, isz.cy).Stroke(5, LtGray()); - gw.End(); - r.DrawPainting(x, y, isz.cx, isz.cy, gw); - } - r.NewPage(); - String pairs = "BNDH"; - for(int y = 0; y + isz.cy < page.cy; y += 3 * isz.cy / 2) - for(int x = 0; x < page.cx; x += 3 * isz.cx) { - int ch = pairs[Random(pairs.GetCount())]; - int cl = ToLower(ch); - if(Random(3) == 0) - cl = ToLower(pairs[Random(pairs.GetCount())]); - r.DrawText(x, y, String(ch, 1) + String(cl, 1), fnt); - } - r.NewPage(); - for(int i = 0; i < 10; i++) { - int a, b; - do { - a = Random(50) + 1; - b = Random(50) + 1; - } - while(a + b < 0 || a + b > 50); - r.DrawText(10, 10 + isz.cy * 2 * i, Format("%d + %d = ", a, b), fnt); - do { - a = Random(50) + 1; - b = Random(50) + 1; - } - while(a - b < 1); - r.DrawText(2000, 10 + isz.cy * 2 * i, Format("%d - %d = ", a, b), fnt); - } - Perform(r); -} diff --git a/uppdev/Painter/BufferPainter.h b/uppdev/Painter/BufferPainter.h index 5487c974e..cf8faaa03 100644 --- a/uppdev/Painter/BufferPainter.h +++ b/uppdev/Painter/BufferPainter.h @@ -188,8 +188,47 @@ struct SpanSource { virtual void Get(RGBA *span, int x, int y, unsigned len) = 0; }; -void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd); -void Render(ImageBuffer& ib, Rasterizer& r, SpanSource *s, RGBA *buffer, int opacity8, bool evenodd); +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); +}; + +struct SpanFiller : Rasterizer::Target { + RGBA *t; + const RGBA *s; + int y; + RGBA *buffer; + SpanSource *ss; + int alpha; + + void Start(int minx, int maxx); + void Render(int val); + void Render(int val, int len); +}; + +struct RecFiller : Rasterizer::Target { + Buffer buffer; + byte *t; + int x; + int maxx; + int maxlen; + int cx; + bool empty; + + void Span(int c, int len); + + virtual void Render(int val); + virtual void Render(int val, int len); + virtual void Start(int x, int len); + void Finish(); + void GetResult(Buffer& tgt, int& maxx, int& maxlen); + + RecFiller(int cx); +}; Image MipMap(const Image& img); Image MakeMipMap(const Image& img, int level); @@ -245,6 +284,8 @@ protected: const Pointf& c, double r, const RGBA& color2, int style); + virtual void ClipOp(); + virtual void ColorStopOp(double pos, const RGBA& color); virtual void ClearStopsOp(); diff --git a/uppdev/Painter/SolidFiller.cpp b/uppdev/Painter/Filler.cpp similarity index 65% rename from uppdev/Painter/SolidFiller.cpp rename to uppdev/Painter/Filler.cpp index 03c9d2327..5cd4a6d0d 100644 --- a/uppdev/Painter/SolidFiller.cpp +++ b/uppdev/Painter/Filler.cpp @@ -2,15 +2,6 @@ NAMESPACE_UPP -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) { @@ -69,19 +60,6 @@ void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd) r.Reset(); } -struct SpanFiller : Rasterizer::Target { - RGBA *t; - const RGBA *s; - int y; - RGBA *buffer; - SpanSource *ss; - int alpha; - - void Start(int minx, int maxx); - void Render(int val); - void Render(int val, int len); -}; - void SpanFiller::Start(int minx, int maxx) { t += minx; @@ -118,19 +96,4 @@ void SpanFiller::Render(int val, int len) AlphaBlendCover8(*t++, *s++, val); } -void Render(ImageBuffer& ib, Rasterizer& r, SpanSource *s, RGBA *buffer, int alpha, bool evenodd) -{ - Size sz = ib.GetSize(); - SpanFiller f; - f.ss = s; - f.buffer = buffer; - f.alpha = alpha; - for(int y = r.MinY(); y <= r.MaxY(); y++) { - f.t = ib[y]; - f.y = y; - r.Render(y, f, evenodd); - } - r.Reset(); -} - END_UPP_NAMESPACE diff --git a/uppdev/Painter/Mask.cpp b/uppdev/Painter/Mask.cpp new file mode 100644 index 000000000..1d723834d --- /dev/null +++ b/uppdev/Painter/Mask.cpp @@ -0,0 +1,188 @@ +#include "Painter.h" + +NAMESPACE_UPP + +RecFiller::RecFiller(int _cx) +{ + cx = _cx; + buffer.Alloc(2 * cx + 2); +} + +void RecFiller::Start(int xmin, int xmax) +{ + t = ~buffer; + x = 0; + maxlen = 0; + maxx = 0; + Render(0, xmin); +} + +void RecFiller::Render(int val) +{ + Render(val, 1); //!Optimize later! +/* + if(val == 0) { + *t++ = 0; + *t++ = 0; + } + else + if(val == 256) { + *t++ = 0; + *t++ = 128; + } + else + *t++ = val; + x++; +*/ +} + +void RecFiller::Span(int c, int len) +{ + while(len > 128) { + int n = min(len, 128); + *t++ = 0; + *t++ = c + n - 1; + len -= n; + } + if(len) { + *t++ = 0; + *t++ = c + len - 1; + } +} + +void RecFiller::Render(int val, int len) +{ + DLOG(val << " " << len); + if(val == 256) { + Span(128, len); + if(len > maxlen) { + maxx = x; + maxlen = len; + } + } + else + if(val == 0) + Span(0, len); + else { + memset(t, val, len); + t += len; + } + x += len; +} + +void RecFiller::Finish() +{ + while(x < cx) { + int n = min(cx - x, 128); + *t++ = 0; + *t++ = n - 1; + x += n; + } +} + +void RecFiller::GetResult(Buffer& tgt, int& _maxx, int& _maxlen) +{ + tgt.Clear(); + int l = t - ~buffer; + tgt.Alloc(l); + memcpy(~tgt, ~buffer, l); + _maxx = maxx; + _maxlen = maxlen; + LOGHEXDUMP(~tgt, l); + DDUMP(maxx); + DDUMP(maxlen); +} + +struct RasterizerMaskFilter : Rasterizer::Target { + Rasterizer::Target *t; + byte *mask; + int empty; + int full; + + void Start(int minx, int maxx); + void Render(int val, int len); + void Render(int val); + RasterizerMaskFilter() { empty = full = 0; } +}; + +void RasterizerMaskFilter::Render(int val) +{ + Render(val, 1); +/* for(;;) { + if(empty) { + f.t++; + empty--; + return; + } + if(full) { + t->Render(val); + full--; + return; + } + byte m = *mask++; + if(m) { + t->Render(val * m >> 8); + return; + } + else { + if(m < 128) + empty = m + 1; + else + full = m - 128 + 1; + } + } +*/ +} + +void RasterizerMaskFilter::Render(int val, int len) +{ + while(len) + if(empty) { + int n = min(len, empty); + t->Render(0, n); + empty -= n; + len -= n; + } + else + if(full) { + int n = min(len, full); + t->Render(256, n); + full -= n; + len -= n; + empty = false; + } + else { + byte m = *mask++; + if(m) { + int r = val * m >> 8; + if(r) + empty = false; + t->Render(r); + len--; + } + else { + if(m < 128) + empty = m + 1; + else + full = m - 128 + 1; + } + } +} + +struct RasterizerNil : Rasterizer::Target { + void Start(int minx, int maxx) {} + void Render(int val, int len) {} + void Render(int val) {} +}; + +void RasterizerMaskFilter::Start(int minx, int maxx) +{ + t->Start(minx, maxx); + Rasterizer::Target *h = t; + RasterizerNil nil; + t = &nil; + Render(0, minx); + t = h; +} + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/Painter.h b/uppdev/Painter/Painter.h index c2dedb03a..0a622bdea 100644 --- a/uppdev/Painter/Painter.h +++ b/uppdev/Painter/Painter.h @@ -91,6 +91,8 @@ protected: const Pointf& c, double r, const RGBA& color2, int style) = 0; + virtual void ClipOp() = 0; + virtual void CharacterOp(double x, double y, int ch, Font fnt); virtual void TextOp(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL); @@ -215,6 +217,8 @@ public: Painter& Stroke(double width, double x, double y, const RGBA& color1, double r, const RGBA& color2, int style = GRADIENT_PAD); + Painter& Clip(); + Painter& Character(double x, double y, int ch, Font fnt); Painter& Text(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL); Painter& Text(double x, double y, const WString& s, Font fnt, double *dx = NULL); diff --git a/uppdev/Painter/Painter.hpp b/uppdev/Painter/Painter.hpp index b59d72314..0c997859a 100644 --- a/uppdev/Painter/Painter.hpp +++ b/uppdev/Painter/Painter.hpp @@ -123,6 +123,13 @@ Painter& Painter::Stroke(double width, const Pointf& f, const RGBA& color1, cons return *this; } +inline +Painter& Painter::Clip() +{ + ClipOp(); + return *this; +} + inline Painter& Painter::ColorStop(double pos, const RGBA& color) { ColorStopOp(pos, color); diff --git a/uppdev/Painter/Painter.upp b/uppdev/Painter/Painter.upp index 33619d48a..4c9aed8b0 100644 --- a/uppdev/Painter/Painter.upp +++ b/uppdev/Painter/Painter.upp @@ -20,9 +20,8 @@ file Interpolator.cpp optimize_speed, Rasterizer.cpp optimize_speed, RasterizerClip.cpp optimize_speed, - ScanLineFiller.cpp, - SolidFiller.cpp optimize_speed, - SolidFillerMask.cpp, + Filler.cpp optimize_speed, + Mask.cpp, Path.cpp optimize_speed, Context.cpp, Render.cpp optimize_speed, diff --git a/uppdev/Painter/Render.cpp b/uppdev/Painter/Render.cpp index f35ca28e4..e9721158d 100644 --- a/uppdev/Painter/Render.cpp +++ b/uppdev/Painter/Render.cpp @@ -35,21 +35,43 @@ void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color) } byte *data = path.data; int opacity = int(256 * pathattr.opacity); - RGBA c; - if(!ss) - c = Mul8(color, opacity); Pointf pos = Pointf(0, 0); int i = 0; + Rasterizer::Target *rg; + SpanFiller span_filler; + SolidFiller solid_filler; + RecFiller record_filler(ib.GetWidth()); + bool clip = width == -2; + if(clip) { + rg = &record_filler; + } + else + if(ss) { + if(!span) + span.Alloc(ib.GetWidth() + 1); + span_filler.ss = ss; + span_filler.buffer = span; + span_filler.alpha = opacity; + rg = &span_filler; + } + else { + solid_filler.c = Mul8(color, opacity); + rg = &solid_filler; + } for(;;) { if(i >= path.type.GetCount() || path.type[i] == DIV) { g->End(); - if(ss) { - if(!span) - span.Alloc(ib.GetWidth() + 1); - Render(ib, rasterizer, ss, span, opacity, evenodd); + for(int y = rasterizer.MinY(); y <= rasterizer.MaxY(); y++) { + solid_filler.t = span_filler.t = ib[y]; + span_filler.y = y; + rasterizer.Render(y, *rg, evenodd); + if(clip) { + record_filler.Finish(); + Buffer h; + int maxx, maxlen; + record_filler.GetResult(h, maxx, maxlen); + } } - else - Render(ib, rasterizer, c, evenodd); rasterizer.Reset(); if(i >= path.type.GetCount()) break; @@ -108,4 +130,9 @@ void BufferPainter::StrokeOp(double width, const RGBA& color) RenderPath(width, NULL, color); } +void BufferPainter::ClipOp() +{ + RenderPath(-2, NULL, RGBAZero()); +} + END_UPP_NAMESPACE diff --git a/uppdev/Painter/ScanLineFiller.cpp b/uppdev/Painter/ScanLineFiller.cpp deleted file mode 100644 index 0063787bf..000000000 --- a/uppdev/Painter/ScanLineFiller.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "Painter.h" - -NAMESPACE_UPP - -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 < -} -*/ - -END_UPP_NAMESPACE diff --git a/uppdev/Painter/SolidFillerMask.cpp b/uppdev/Painter/SolidFillerMask.cpp deleted file mode 100644 index 301af5ee1..000000000 --- a/uppdev/Painter/SolidFillerMask.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "Painter.h" - -NAMESPACE_UPP - -/* -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; - } - } - } -} -*/ -END_UPP_NAMESPACE diff --git a/uppdev/PainterExamples/Clipping.cpp b/uppdev/PainterExamples/Clipping.cpp index 234119e1d..44e1b9580 100644 --- a/uppdev/PainterExamples/Clipping.cpp +++ b/uppdev/PainterExamples/Clipping.cpp @@ -1,9 +1,9 @@ #include "Examples.h" -#if 0 - void ClippingExample(Painter& sw) { + sw.Rectangle(0, 0, 100000, 100000).Clip(); + Font fnt = Roman(150).Bold(); String txt = "CLIPPED!"; Size tsz = GetTextSize(txt, fnt); @@ -17,5 +17,3 @@ void ClippingExample(Painter& sw) INITBLOCK { RegisterExample("Clipping", ClippingExample); } - -#endif