mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Painter 2.0 clipping
git-svn-id: svn://ultimatepp.org/upp/trunk@852 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
7865e5bcd2
commit
64994ce5aa
9 changed files with 204 additions and 160 deletions
|
|
@ -154,7 +154,7 @@ private:
|
|||
bool BeginRender(int y, const Cell *&c, const Cell *&e);
|
||||
|
||||
public:
|
||||
struct Target {
|
||||
struct Filler {
|
||||
virtual void Start(int x, int len) = 0;
|
||||
virtual void Render(int val) = 0;
|
||||
virtual void Render(int val, int len) = 0;
|
||||
|
|
@ -166,29 +166,18 @@ public:
|
|||
|
||||
int MinY() const { return min_y; }
|
||||
int MaxY() const { return max_y; }
|
||||
void Render(int y, Target& g, bool evenodd);
|
||||
void Render(int y, Filler& g, bool evenodd);
|
||||
|
||||
void Reset();
|
||||
|
||||
Rasterizer(int cx, int cy);
|
||||
};
|
||||
|
||||
struct ScanLine {
|
||||
int xmin, xmax;
|
||||
Buffer<byte> data;
|
||||
int datalen;
|
||||
|
||||
bool IsFull();
|
||||
bool IsEmpty();
|
||||
|
||||
String ToString() const;
|
||||
};
|
||||
|
||||
struct SpanSource {
|
||||
virtual void Get(RGBA *span, int x, int y, unsigned len) = 0;
|
||||
};
|
||||
|
||||
struct SolidFiller : Rasterizer::Target {
|
||||
struct SolidFiller : Rasterizer::Filler {
|
||||
RGBA *t;
|
||||
RGBA c;
|
||||
|
||||
|
|
@ -197,7 +186,7 @@ struct SolidFiller : Rasterizer::Target {
|
|||
void Render(int val, int len);
|
||||
};
|
||||
|
||||
struct SpanFiller : Rasterizer::Target {
|
||||
struct SpanFiller : Rasterizer::Filler {
|
||||
RGBA *t;
|
||||
const RGBA *s;
|
||||
int y;
|
||||
|
|
@ -210,24 +199,54 @@ struct SpanFiller : Rasterizer::Target {
|
|||
void Render(int val, int len);
|
||||
};
|
||||
|
||||
struct RecFiller : Rasterizer::Target {
|
||||
class ClipLine {
|
||||
byte *data;
|
||||
|
||||
public:
|
||||
void Set(const byte *s, int len) { data = new byte[len]; memcpy(data, s, len); }
|
||||
void SetFull() { ASSERT(!data); data = (byte *)1; }
|
||||
|
||||
bool IsEmpty() const { return !data; }
|
||||
bool IsFull() const { return data == (byte *)1; }
|
||||
operator const byte*() const { return data; }
|
||||
|
||||
ClipLine() { data = NULL; }
|
||||
~ClipLine() { if(!IsFull()) delete[] data; }
|
||||
};
|
||||
|
||||
struct ClipFiller : Rasterizer::Filler {
|
||||
Buffer<byte> buffer;
|
||||
byte *t;
|
||||
int x;
|
||||
int maxx;
|
||||
int maxlen;
|
||||
int cx;
|
||||
int last;
|
||||
byte *lastn;
|
||||
bool empty;
|
||||
bool full;
|
||||
|
||||
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);
|
||||
|
||||
void Clear();
|
||||
void Finish(ClipLine& cl);
|
||||
|
||||
RecFiller(int cx);
|
||||
ClipFiller(int cx);
|
||||
};
|
||||
|
||||
struct MaskFillerFilter : Rasterizer::Filler {
|
||||
Rasterizer::Filler *t;
|
||||
const byte *mask;
|
||||
int empty;
|
||||
int full;
|
||||
|
||||
void Start(int minx, int maxx);
|
||||
void Render(int val, int len);
|
||||
void Render(int val);
|
||||
|
||||
void Set(Rasterizer::Filler *f, const byte *m) { t = f; mask = m; empty = full = 0; }
|
||||
};
|
||||
|
||||
Image MipMap(const Image& img);
|
||||
|
|
@ -345,9 +364,14 @@ public:
|
|||
|
||||
ImageBuffer& ib;
|
||||
|
||||
Attr attr;
|
||||
Attr pathattr;
|
||||
Array<Attr> attrstack;
|
||||
Attr attr;
|
||||
Attr pathattr;
|
||||
Array<Attr> attrstack;
|
||||
Vector< Buffer<ClipLine> > clip;
|
||||
|
||||
Image gradient;
|
||||
RGBA gradient1, gradient2;
|
||||
int gradientn;
|
||||
|
||||
Path path;
|
||||
Pointf current, ccontrol, qcontrol, move;
|
||||
|
|
@ -359,17 +383,18 @@ public:
|
|||
void *PathAddRaw(int type, int size);
|
||||
template <class T> T& PathAdd(int type) { return *(T *)PathAddRaw(type, sizeof(T)); }
|
||||
|
||||
Pointf PathPoint(const Pointf& p, bool rel);
|
||||
Pointf EndPoint(const Pointf& p, bool rel);
|
||||
void DoMove0();
|
||||
void ClearPath();
|
||||
void RenderPath(double width, SpanSource *ss, const RGBA& color);
|
||||
void RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags);
|
||||
void RenderRadial(double width, const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2, int style);
|
||||
void MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx);
|
||||
Image GetGradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2);
|
||||
void ColorStop0(Attr& a, double pos, const RGBA& color);
|
||||
Pointf PathPoint(const Pointf& p, bool rel);
|
||||
Pointf EndPoint(const Pointf& p, bool rel);
|
||||
void DoMove0();
|
||||
void ClearPath();
|
||||
Buffer<ClipLine> RenderPath(double width, SpanSource *ss, const RGBA& color);
|
||||
void RenderImage(double width, const Image& image, const Xform2D& transsrc,
|
||||
dword flags);
|
||||
void RenderRadial(double width, const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2, int style);
|
||||
void MakeGradient(RGBA color1, RGBA color2, int cx);
|
||||
void Gradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2);
|
||||
void ColorStop0(Attr& a, double pos, const RGBA& color);
|
||||
|
||||
public:
|
||||
BufferPainter(ImageBuffer& ib);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ void BufferPainter::EndOp()
|
|||
}
|
||||
pathattr = attr = attrstack.Top();
|
||||
attrstack.Drop();
|
||||
#if 0
|
||||
clip.SetCount(attr.cliplevel);
|
||||
#if 0
|
||||
if(attr.mask)
|
||||
FinishMask();
|
||||
#endif
|
||||
|
|
@ -126,6 +126,8 @@ BufferPainter::BufferPainter(ImageBuffer& ib)
|
|||
attr.mask = false;
|
||||
attr.noaa = false;
|
||||
pathattr = attr;
|
||||
|
||||
gradientn = Null;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -2,19 +2,26 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void BufferPainter::MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx)
|
||||
void BufferPainter::MakeGradient(RGBA color1, RGBA color2, int n)
|
||||
{
|
||||
if(n == gradientn && color1 == gradient1 && color2 == gradient2)
|
||||
return;
|
||||
gradientn = n;
|
||||
gradient1 = color1;
|
||||
gradient2 = color2;
|
||||
ImageBuffer ib(n, 1);
|
||||
RGBA *t = ib[0];
|
||||
int l = 0;
|
||||
RGBA cl = color1;
|
||||
for(int i = 0; i <= pathattr.stop.GetCount(); i++) {
|
||||
int h;
|
||||
RGBA ch;
|
||||
if(i < pathattr.stop.GetCount()) {
|
||||
h = (int)(pathattr.stop[i] * (cx - 1));
|
||||
h = (int)(pathattr.stop[i] * (n - 1));
|
||||
ch = pathattr.stop_color[i];
|
||||
}
|
||||
else {
|
||||
h = cx - 1;
|
||||
h = n - 1;
|
||||
ch = color2;
|
||||
}
|
||||
int w = h - l;
|
||||
|
|
@ -29,19 +36,18 @@ void BufferPainter::MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx)
|
|||
l = h;
|
||||
}
|
||||
*t = cl;
|
||||
gradient = ib;
|
||||
}
|
||||
|
||||
Image BufferPainter::GetGradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2)
|
||||
void BufferPainter::Gradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2)
|
||||
{
|
||||
int n = minmax(int(Distance(p1, p2) * pathattr.mtx.GetScale()), 2, 4096);
|
||||
ImageBuffer ib(n, 1);
|
||||
MakeGradient(ib, color1, color2, n);
|
||||
return ib;
|
||||
MakeGradient(color1, color2, minmax(int(Distance(p1, p2) * pathattr.mtx.GetScale()), 2, 4096));
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
|
||||
{
|
||||
Fill(GetGradient(color1, color2, p1, p2), p1, p2,
|
||||
Gradient(color1, color2, p1, p2);
|
||||
Fill(gradient, p1, p2,
|
||||
FILL_VPAD | FILL_FAST |
|
||||
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
|
||||
? FILL_HREPEAT : FILL_HREFLECT));
|
||||
|
|
@ -49,7 +55,8 @@ void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p
|
|||
|
||||
void BufferPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
|
||||
{
|
||||
Stroke(width, GetGradient(color1, color2, p1, p2), p1, p2,
|
||||
Gradient(color1, color2, p1, p2);
|
||||
Stroke(width, gradient, p1, p2,
|
||||
FILL_VPAD | FILL_FAST |
|
||||
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
|
||||
? FILL_HREPEAT : FILL_HREFLECT));
|
||||
|
|
|
|||
|
|
@ -2,115 +2,96 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
RecFiller::RecFiller(int _cx)
|
||||
ClipFiller::ClipFiller(int _cx)
|
||||
{
|
||||
cx = _cx;
|
||||
buffer.Alloc(2 * cx + 2);
|
||||
}
|
||||
|
||||
void RecFiller::Start(int xmin, int xmax)
|
||||
void ClipFiller::Clear()
|
||||
{
|
||||
t = ~buffer;
|
||||
x = 0;
|
||||
maxlen = 0;
|
||||
maxx = 0;
|
||||
empty = true;
|
||||
full = true;
|
||||
last = -1;
|
||||
}
|
||||
|
||||
void ClipFiller::Start(int xmin, int xmax)
|
||||
{
|
||||
Render(0, xmin);
|
||||
}
|
||||
|
||||
void RecFiller::Render(int val)
|
||||
void ClipFiller::Span(int val, int len)
|
||||
{
|
||||
Render(val, 1); //!Optimize later!
|
||||
/*
|
||||
if(val == 0) {
|
||||
*t++ = 0;
|
||||
*t++ = 0;
|
||||
int v = val >> 1;
|
||||
if(last == val) {
|
||||
int n = min(v + 128 - *lastn - 1, len);
|
||||
*lastn += n;
|
||||
len -= n;
|
||||
}
|
||||
else
|
||||
if(val == 256) {
|
||||
*t++ = 0;
|
||||
*t++ = 128;
|
||||
}
|
||||
else
|
||||
*t++ = val;
|
||||
x++;
|
||||
*/
|
||||
}
|
||||
|
||||
void RecFiller::Span(int c, int len)
|
||||
{
|
||||
last = -1;
|
||||
while(len > 128) {
|
||||
int n = min(len, 128);
|
||||
*t++ = 0;
|
||||
*t++ = c + n - 1;
|
||||
*t++ = v + n - 1;
|
||||
len -= n;
|
||||
}
|
||||
if(len) {
|
||||
*t++ = 0;
|
||||
*t++ = c + len - 1;
|
||||
last = val;
|
||||
lastn = t;
|
||||
*t++ = v + len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void RecFiller::Render(int val, int len)
|
||||
void ClipFiller::Render(int val, int len)
|
||||
{
|
||||
DLOG(val << " " << len);
|
||||
if(val == 256) {
|
||||
Span(128, len);
|
||||
if(len > maxlen) {
|
||||
maxx = x;
|
||||
maxlen = len;
|
||||
}
|
||||
Span(256, len);
|
||||
empty = false;
|
||||
}
|
||||
else
|
||||
if(val == 0)
|
||||
Span(0, len);
|
||||
else {
|
||||
memset(t, val, len);
|
||||
t += len;
|
||||
full = false;
|
||||
if(val == 0)
|
||||
Span(0, len);
|
||||
else {
|
||||
memset(t, val, len);
|
||||
t += len;
|
||||
empty = false;
|
||||
last = -1;
|
||||
}
|
||||
}
|
||||
x += len;
|
||||
}
|
||||
|
||||
void RecFiller::Finish()
|
||||
void ClipFiller::Render(int val)
|
||||
{
|
||||
Render(val, 1);
|
||||
}
|
||||
|
||||
void ClipFiller::Finish(ClipLine& cl)
|
||||
{
|
||||
if(empty)
|
||||
return;
|
||||
while(x < cx) {
|
||||
int n = min(cx - x, 128);
|
||||
*t++ = 0;
|
||||
*t++ = n - 1;
|
||||
x += n;
|
||||
full = false;
|
||||
}
|
||||
if(full)
|
||||
cl.SetFull();
|
||||
else
|
||||
cl.Set(~buffer, t - ~buffer);
|
||||
}
|
||||
|
||||
void RecFiller::GetResult(Buffer<byte>& tgt, int& _maxx, int& _maxlen)
|
||||
void MaskFillerFilter::Render(int val)
|
||||
{
|
||||
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(;;) {
|
||||
for(;;) {
|
||||
if(empty) {
|
||||
f.t++;
|
||||
t->Render(0);
|
||||
empty--;
|
||||
return;
|
||||
}
|
||||
|
|
@ -124,17 +105,15 @@ void RasterizerMaskFilter::Render(int val)
|
|||
t->Render(val * m >> 8);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if(m < 128)
|
||||
empty = m + 1;
|
||||
else
|
||||
full = m - 128 + 1;
|
||||
}
|
||||
m = *mask++;
|
||||
if(m < 128)
|
||||
empty = m + 1;
|
||||
else
|
||||
full = m - 128 + 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void RasterizerMaskFilter::Render(int val, int len)
|
||||
void MaskFillerFilter::Render(int val, int len)
|
||||
{
|
||||
while(len)
|
||||
if(empty) {
|
||||
|
|
@ -146,21 +125,19 @@ void RasterizerMaskFilter::Render(int val, int len)
|
|||
else
|
||||
if(full) {
|
||||
int n = min(len, full);
|
||||
t->Render(256, n);
|
||||
t->Render(val, 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 {
|
||||
m = *mask++;
|
||||
if(m < 128)
|
||||
empty = m + 1;
|
||||
else
|
||||
|
|
@ -169,17 +146,17 @@ void RasterizerMaskFilter::Render(int val, int len)
|
|||
}
|
||||
}
|
||||
|
||||
struct RasterizerNil : Rasterizer::Target {
|
||||
struct NilFiller : Rasterizer::Filler {
|
||||
void Start(int minx, int maxx) {}
|
||||
void Render(int val, int len) {}
|
||||
void Render(int val) {}
|
||||
};
|
||||
|
||||
void RasterizerMaskFilter::Start(int minx, int maxx)
|
||||
void MaskFillerFilter::Start(int minx, int maxx)
|
||||
{
|
||||
t->Start(minx, maxx);
|
||||
Rasterizer::Target *h = t;
|
||||
RasterizerNil nil;
|
||||
Rasterizer::Filler *h = t;
|
||||
NilFiller nil;
|
||||
t = &nil;
|
||||
Render(0, minx);
|
||||
t = h;
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ struct PainterRadialSpan : SpanSource {
|
|||
int cx, cy, r, fx, fy;
|
||||
int style;
|
||||
int alpha;
|
||||
RGBA gradient[2048];
|
||||
const RGBA *gradient;
|
||||
bool focus;
|
||||
double C;
|
||||
|
||||
|
|
@ -201,7 +201,8 @@ void BufferPainter::RenderRadial(double width, const Pointf& f, const RGBA& colo
|
|||
sg.interpolator.Set(Inverse(pathattr.mtx));
|
||||
sg.style = style;
|
||||
sg.Set((int)c.x, (int)c.y, (int)r, (int)f.x, (int)f.y);
|
||||
MakeGradient(sg.gradient, color1, color2, 2048);
|
||||
MakeGradient(color1, color2, 2048);
|
||||
sg.gradient = gradient[0];
|
||||
RenderPath(width, &sg, RGBAZero());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ void Rasterizer::LineRaw(int x1, int y1, int x2, int y2)
|
|||
RenderHLine(ey1, x_from, 256 - first, x2, fy2);
|
||||
}
|
||||
|
||||
void Rasterizer::Render(int y, Target& g, bool evenodd)
|
||||
void Rasterizer::Render(int y, Rasterizer::Filler& g, bool evenodd)
|
||||
{
|
||||
PAINTER_TIMING("Render");
|
||||
const Cell *c, *e;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ void BufferPainter::ClearOp(const RGBA& color)
|
|||
UPP::Fill(~ib, color, ib.GetLength());
|
||||
}
|
||||
|
||||
void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
|
||||
Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
|
||||
{
|
||||
Buffer<ClipLine> newclip;
|
||||
if(width == 0)
|
||||
return;
|
||||
return newclip;
|
||||
Transformer trans(pathattr.mtx);
|
||||
trans.target = &rasterizer;
|
||||
LinearPathConsumer *g;
|
||||
|
|
@ -37,13 +38,14 @@ void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
|
|||
int opacity = int(256 * pathattr.opacity);
|
||||
Pointf pos = Pointf(0, 0);
|
||||
int i = 0;
|
||||
Rasterizer::Target *rg;
|
||||
Rasterizer::Filler *rg;
|
||||
SpanFiller span_filler;
|
||||
SolidFiller solid_filler;
|
||||
RecFiller record_filler(ib.GetWidth());
|
||||
bool clip = width == -2;
|
||||
if(clip) {
|
||||
rg = &record_filler;
|
||||
ClipFiller clip_filler(ib.GetWidth());
|
||||
bool doclip = width == -2;
|
||||
if(doclip) {
|
||||
rg = &clip_filler;
|
||||
newclip.Alloc(ib.GetHeight());
|
||||
}
|
||||
else
|
||||
if(ss) {
|
||||
|
|
@ -58,19 +60,29 @@ void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
|
|||
solid_filler.c = Mul8(color, opacity);
|
||||
rg = &solid_filler;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if(i >= path.type.GetCount() || path.type[i] == DIV) {
|
||||
g->End();
|
||||
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);
|
||||
Rasterizer::Filler *rf = rg;
|
||||
MaskFillerFilter mf;
|
||||
if(clip.GetCount()) {
|
||||
const ClipLine& s = clip.Top()[y];
|
||||
if(s.IsEmpty()) goto empty;
|
||||
if(!s.IsFull()) {
|
||||
mf.Set(rg, s);
|
||||
rf = &mf;
|
||||
}
|
||||
}
|
||||
if(doclip)
|
||||
clip_filler.Clear();
|
||||
rasterizer.Render(y, *rf, evenodd);
|
||||
if(doclip)
|
||||
clip_filler.Finish(newclip[y]);
|
||||
empty:;
|
||||
}
|
||||
rasterizer.Reset();
|
||||
if(i >= path.type.GetCount())
|
||||
|
|
@ -113,11 +125,12 @@ void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
|
|||
}
|
||||
default:
|
||||
NEVER();
|
||||
return;
|
||||
return newclip;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
current = Null;
|
||||
return newclip;
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const RGBA& color)
|
||||
|
|
@ -132,7 +145,14 @@ void BufferPainter::StrokeOp(double width, const RGBA& color)
|
|||
|
||||
void BufferPainter::ClipOp()
|
||||
{
|
||||
RenderPath(-2, NULL, RGBAZero());
|
||||
Buffer<ClipLine> newclip = RenderPath(-2, NULL, RGBAZero());
|
||||
if(attr.hasclip)
|
||||
clip.Top() = newclip;
|
||||
else {
|
||||
clip.Add() = newclip;
|
||||
attr.hasclip = true;
|
||||
attr.cliplevel = clip.GetCount();
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
void ClippingExample(Painter& sw)
|
||||
{
|
||||
sw.Rectangle(0, 0, 100000, 100000).Clip();
|
||||
|
||||
Font fnt = Roman(150).Bold();
|
||||
String txt = "CLIPPED!";
|
||||
Size tsz = GetTextSize(txt, fnt);
|
||||
|
|
@ -12,8 +10,32 @@ void ClippingExample(Painter& sw)
|
|||
sw.Text(0, 0, txt, fnt).Fill(Green());
|
||||
sw.End();
|
||||
sw.Text(0, 0, txt, fnt).Stroke(0.5, Black());
|
||||
|
||||
}
|
||||
|
||||
void NoClippingExample(Painter& sw)
|
||||
{
|
||||
Font fnt = Roman(150).Bold();
|
||||
String txt = "CLIPPED!";
|
||||
Size tsz = GetTextSize(txt, fnt);
|
||||
sw.Text(0, 0, txt, fnt).Fill(Green());
|
||||
sw.Text(0, 0, txt, fnt).Stroke(0.5, Black());
|
||||
}
|
||||
|
||||
void ClippingExample2(Painter& sw)
|
||||
{
|
||||
sw.Begin();
|
||||
sw.Ellipse(200, 200, 200, 200).Stroke(2, Red()).Clip();
|
||||
sw.Begin();
|
||||
sw.Ellipse(200, 200, 100, 300).Clip().Stroke(2, Red());
|
||||
sw.Text(0, 0, "CL", Arial(360).Bold()).Fill(Blue());
|
||||
sw.End();
|
||||
sw.Text(0, 0, "CL", Arial(360).Bold()).Opacity(0.4).Fill(Black());
|
||||
sw.End();
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
RegisterExample("Clipping", ClippingExample);
|
||||
RegisterExample("Clipping removed (to benchmark) ", NoClippingExample);
|
||||
RegisterExample("Clipping 2", ClippingExample2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,8 @@ void TextFillGradient(Painter& sw)
|
|||
Font fnt = Arial(100).Bold().Italic();
|
||||
Size tsz = GetTextSize(txt, fnt);
|
||||
sw.Text(100, 100, txt, fnt)
|
||||
.Fill(100, 100, Blue(), 100 + tsz.cx, 100/* + tsz.cy*/, LtRed());
|
||||
.Fill(100, 100, Blue(), 100 + tsz.cx, 100 + tsz.cy, LtRed());
|
||||
sw.Translate(0, 200);
|
||||
sw.Rectangle(100, 100, tsz.cx, tsz.cy)
|
||||
.Stroke(1, Blue())
|
||||
.Fill(TestImg::test(), 100, 100, 100 + tsz.cx, 100 + tsz.cy);
|
||||
sw.Move(100, 300).RelLine(tsz.cx + 50, 0).RelLine(-30, tsz.cy).RelLine(-tsz.cx / 2, 0)
|
||||
.Fill(100, 300, Blue(), 100 + tsz.cx, 300/* + tsz.cy*/, LtRed())
|
||||
// .Fill(TestImg::test(), 100, 300, 100 + tsz.cx, 300 + tsz.cy)
|
||||
.Stroke(1, Blue());
|
||||
/* sw.Text(100, 100, txt, fnt)
|
||||
.Fill(TestImg::test(), 100, 100, 100 + tsz.cx, 100 + tsz.cy)
|
||||
.Stroke(1, Black());*/
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue