mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Developing Painter
git-svn-id: svn://ultimatepp.org/upp/trunk@851 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
ce986f5b27
commit
5ea57805bf
13 changed files with 282 additions and 284 deletions
|
|
@ -1,11 +0,0 @@
|
|||
uses
|
||||
CtrlLib,
|
||||
Report,
|
||||
Painter;
|
||||
|
||||
file
|
||||
main.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef _Mirrors_icpp_init_stub
|
||||
#define _Mirrors_icpp_init_stub
|
||||
#include "CtrlLib/init"
|
||||
#include "Report/init"
|
||||
#include "Painter/init"
|
||||
#endif
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
188
uppdev/Painter/Mask.cpp
Normal 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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue