Developing Painter

git-svn-id: svn://ultimatepp.org/upp/trunk@851 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-02-11 20:48:27 +00:00
parent ce986f5b27
commit 5ea57805bf
13 changed files with 282 additions and 284 deletions

View file

@ -1,11 +0,0 @@
uses
CtrlLib,
Report,
Painter;
file
main.cpp;
mainconfig
"" = "GUI";

View file

@ -1,6 +0,0 @@
#ifndef _Mirrors_icpp_init_stub
#define _Mirrors_icpp_init_stub
#include "CtrlLib/init"
#include "Report/init"
#include "Painter/init"
#endif

View file

@ -1,56 +0,0 @@
#include <CtrlLib/CtrlLib.h>
#include <Report/Report.h>
#include <Painter/Painter.h>
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);
}

View file

@ -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<byte> 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<byte>& 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();

View file

@ -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

188
uppdev/Painter/Mask.cpp Normal file
View file

@ -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<byte>& 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

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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<byte> 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

View file

@ -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

View file

@ -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

View file

@ -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