Painter 2.0 FINISHED!

git-svn-id: svn://ultimatepp.org/upp/trunk@854 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-02-12 14:34:54 +00:00
parent c9f4311517
commit 034c443223
27 changed files with 1562 additions and 615 deletions

View file

@ -177,32 +177,11 @@ struct SpanSource {
virtual void Get(RGBA *span, int x, int y, unsigned len) = 0;
};
struct SolidFiller : Rasterizer::Filler {
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::Filler {
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);
};
class ClipLine {
class ClipLine : NoCopy {
byte *data;
public:
void Clear() { if(!IsFull()) delete[] data; data = NULL; }
void Set(const byte *s, int len) { data = new byte[len]; memcpy(data, s, len); }
void SetFull() { ASSERT(!data); data = (byte *)1; }
@ -211,52 +190,7 @@ public:
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 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 Clear();
void Finish(ClipLine& cl);
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; }
};
struct NoAAFillerFilter : Rasterizer::Filler {
Rasterizer::Filler *t;
void Start(int minx, int maxx);
void Render(int val, int len);
void Render(int val);
void Set(Rasterizer::Filler *f) { t = f; }
~ClipLine() { Clear(); }
};
Image MipMap(const Image& img);
@ -331,6 +265,8 @@ protected:
virtual void BeginOp();
virtual void EndOp();
virtual void BeginMaskOp();
public:
enum {
MOVE, LINE, QUADRATIC, CUBIC, ARC, DIV
@ -372,12 +308,14 @@ public:
bool noaa;
};
ImageBuffer& ib;
ImageBuffer& ib;
Attr attr;
Attr pathattr;
Array<Attr> attrstack;
Vector< Buffer<ClipLine> > clip;
Array< ImageBuffer > mask;
Image gradient;
RGBA gradient1, gradient2;
@ -405,6 +343,7 @@ public:
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);
void FinishMask();
public:
BufferPainter(ImageBuffer& ib);

View file

@ -17,10 +17,8 @@ void BufferPainter::EndOp()
pathattr = attr = attrstack.Top();
attrstack.Drop();
clip.SetCount(attr.cliplevel);
#if 0
if(attr.mask)
FinishMask();
#endif
}
void BufferPainter::TransformOp(const Xform2D& m)

137
uppdev/Painter/DrawOp.cpp Normal file
View file

@ -0,0 +1,137 @@
#include "Painter.h"
NAMESPACE_UPP
void Painter::OffsetOp(Point p)
{
Begin();
Translate(p.x, p.y);
}
void Painter::RectPath(int x, int y, int cx, int cy)
{
Move(x, y).Line(x + cx, y).Line(x + cx, y + cy).Line(x, y + cy).Close();
}
void Painter::RectPath(const Rect& r)
{
RectPath(r.left, r.top, r.GetWidth(), r.GetHeight());
}
bool Painter::ClipOp(const Rect& r)
{
Begin();
RectPath(r);
Clip();
return true;
}
bool Painter::ClipoffOp(const Rect& r)
{
Begin();
RectPath(r);
Clip();
Translate(r.left, r.top);
return true;
}
bool Painter::ExcludeClipOp(const Rect& r)
{
return true;
}
bool Painter::IntersectClipOp(const Rect& r)
{
return true;
RectPath(r);
Clip();
return true;
}
Rect Painter::GetClipOp() const
{
return Rect(0, 0, 0, 0);
}
bool Painter::IsPaintingOp(const Rect& r) const
{
return true;
}
void Painter::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
RectPath(x, y, cx, cy);
Fill(color);
}
void Painter::DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color)
{
// Color and src support!!!
RectPath(x, y, cx, cy);
Fill(img, Xform2D::Translation(x, y));
}
void Painter::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
double h = width / 2;
Move(x1 + h, y1 + h);
Line(x2 + h, y2 + h);
Stroke(max(width, 0), color);
}
void Painter::DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts,
int count_count, int width, Color color, Color doxor)
{
}
void Painter::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc, const int *disjunct_polygon_counts,
int dpcc, Color color, int width, Color outline, uint64 pattern, Color doxor)
{
}
void Painter::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
}
void Painter::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
{
Sizef sz = r.GetSize();
Ellipse(r.left + sz.cx / 2, r.top + sz.cy / 2, sz.cx / 2, sz.cy / 2);
Fill(color);
Stroke(max(pen, 0), pencolor);
}
void Painter::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx)
{
Begin();
EvenOdd(true);
if(angle)
Rotate(angle * M_2PI / 36000);
if(n < 0)
n = wstrlen(text);
double *ddx = NULL;
Buffer<double> h;
if(dx) {
h.Alloc(n);
ddx = h;
for(int i = 0; i < n; i++)
ddx[i] = dx[i];
}
Text(x, y, text, font, n, ddx);
Fill(ink);
End();
}
void Painter::DrawPaintingOp(const Rect& target, const Painting& p)
{
Size sz = target.GetSize();
Sizef psz = p.GetSize();
Begin();
Translate(target.left, target.top);
Scale(sz.cx / psz.cx, sz.cy / psz.cy);
Paint(p);
End();
}
END_UPP_NAMESPACE

View file

@ -1,114 +0,0 @@
#include "Painter.h"
NAMESPACE_UPP
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, bool evenodd)
{
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, evenodd);
}
r.Reset();
}
void SpanFiller::Start(int minx, int maxx)
{
t += minx;
ss->Get(buffer, minx, y, maxx - minx + 1);
s = buffer;
}
void SpanFiller::Render(int val)
{
if(alpha != 256)
val = alpha * val >> 8;
AlphaBlendCover8(*t++, *s++, val);
}
void SpanFiller::Render(int val, int len)
{
if(val == 0) {
t += len;
s += len;
return;
}
const RGBA *e = t + len;
if(alpha != 256)
val = alpha * val >> 8;
if(val == 256)
while(t < e) {
if(s->a == 255)
*t++ = *s++;
else
AlphaBlend(*t++, *s++);
}
else
while(t < e)
AlphaBlendCover8(*t++, *s++, val);
}
void NoAAFillerFilter::Start(int minx, int maxx)
{
t->Start(minx, maxx);
}
void NoAAFillerFilter::Render(int val, int len)
{
t->Render(val < 128 ? 0 : 256, len);
}
void NoAAFillerFilter::Render(int val)
{
t->Render(val < 128 ? 0 : 256);
}
END_UPP_NAMESPACE

272
uppdev/Painter/Fillers.cpp Normal file
View file

@ -0,0 +1,272 @@
#include "Painter.h"
#include "Fillers.h"
NAMESPACE_UPP
void SolidFiller::Start(int minx, int maxx)
{
t += minx;
}
void SolidFiller::Render(int val)
{
AlphaBlendCover8(*t++, c, val);
}
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 SpanFiller::Start(int minx, int maxx)
{
t += minx;
ss->Get(buffer, minx, y, maxx - minx + 1);
s = buffer;
}
void SpanFiller::Render(int val)
{
if(alpha != 256)
val = alpha * val >> 8;
AlphaBlendCover8(*t++, *s++, val);
}
void SpanFiller::Render(int val, int len)
{
if(val == 0) {
t += len;
s += len;
return;
}
const RGBA *e = t + len;
if(alpha != 256)
val = alpha * val >> 8;
if(val == 256)
while(t < e) {
if(s->a == 255)
*t++ = *s++;
else
AlphaBlend(*t++, *s++);
}
else
while(t < e)
AlphaBlendCover8(*t++, *s++, val);
}
ClipFiller::ClipFiller(int _cx)
{
cx = _cx;
buffer.Alloc(2 * cx);
}
void ClipFiller::Clear()
{
t = ~buffer;
x = 0;
empty = true;
full = true;
last = -1;
}
void ClipFiller::Start(int xmin, int xmax)
{
Render(0, xmin);
}
void ClipFiller::Span(int val, int len)
{
int v = val >> 1;
if(last == val) {
int n = min(v + 128 - *lastn - 1, len);
*lastn += n;
len -= n;
}
last = -1;
while(len > 128) {
int n = min(len, 128);
*t++ = 0;
*t++ = v + n - 1;
len -= n;
}
if(len) {
*t++ = 0;
last = val;
lastn = t;
*t++ = v + len - 1;
}
}
void ClipFiller::Render(int val, int len)
{
if(val == 256) {
Span(256, len);
empty = false;
}
else {
full = false;
if(val == 0)
Span(0, len);
else {
memset(t, val, len);
t += len;
empty = false;
last = -1;
}
}
x += len;
}
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 MaskFillerFilter::Render(int val)
{
for(;;) {
if(empty) {
t->Render(0);
empty--;
return;
}
if(full) {
t->Render(val);
full--;
return;
}
byte m = *mask++;
if(m) {
t->Render(val * m >> 8);
return;
}
m = *mask++;
if(m < 128)
empty = m + 1;
else
full = m - 128 + 1;
}
}
void MaskFillerFilter::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(val, n);
full -= n;
len -= n;
}
else {
byte m = *mask++;
if(m) {
t->Render(val * m >> 8);
len--;
}
else {
m = *mask++;
if(m < 128)
empty = m + 1;
else
full = m - 128 + 1;
}
}
}
struct NilFiller : Rasterizer::Filler {
void Start(int minx, int maxx) {}
void Render(int val, int len) {}
void Render(int val) {}
};
void MaskFillerFilter::Start(int minx, int maxx)
{
t->Start(minx, maxx);
Rasterizer::Filler *h = t;
NilFiller nil;
t = &nil;
Render(0, minx);
t = h;
}
void NoAAFillerFilter::Start(int minx, int maxx)
{
t->Start(minx, maxx);
}
void NoAAFillerFilter::Render(int val, int len)
{
t->Render(val < 128 ? 0 : 256, len);
}
void NoAAFillerFilter::Render(int val)
{
t->Render(val < 128 ? 0 : 256);
}
END_UPP_NAMESPACE

70
uppdev/Painter/Fillers.h Normal file
View file

@ -0,0 +1,70 @@
NAMESPACE_UPP
struct SolidFiller : Rasterizer::Filler {
RGBA *t;
RGBA c;
void Start(int minx, int maxx);
void Render(int val);
void Render(int val, int len);
};
struct SpanFiller : Rasterizer::Filler {
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 ClipFiller : Rasterizer::Filler {
Buffer<byte> buffer;
byte *t;
int x;
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 Clear();
void Finish(ClipLine& cl);
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; }
};
struct NoAAFillerFilter : Rasterizer::Filler {
Rasterizer::Filler *t;
void Start(int minx, int maxx);
void Render(int val, int len);
void Render(int val);
void Set(Rasterizer::Filler *f) { t = f; }
};
END_UPP_NAMESPACE

View file

@ -93,7 +93,7 @@ struct sMakeCharOutline : LRUCache<String, FontChar>::Maker {
}
};
void Painter::CharacterOp(double x, double y, int ch, Font fnt)
void Painter::CharacterOp(const Pointf& p, int ch, Font fnt)
{
PAINTER_TIMING("CharacterOp");
String s;
@ -105,7 +105,7 @@ void Painter::CharacterOp(double x, double y, int ch, Font fnt)
h.fc.chr = ch;
s = cache.Get(h);
}
RenderCharPath(s, s.GetLength(), *this, x, y + fnt.Info().GetAscent());
RenderCharPath(s, s.GetLength(), *this, p.x, p.y + fnt.Info().GetAscent());
EvenOdd(true);
}

View file

@ -1,152 +1,152 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all coM_PIes.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
// Recycled for U++ by Miroslav Fidler 2008
#include "Painter.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
static inline double ft_dbl(int p)
{
return double(p) / 64.0;
}
bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy)
{
FT_Vector v_last;
FT_Vector v_control;
FT_Vector v_start;
double x1, y1, x2, y2, x3, y3;
FT_Vector* point;
FT_Vector* limit;
char* tags;
int n; // index of contour in outline
char tag; // current point's state
int first = 0; // index of first point in contour
for(n = 0; n < outline.n_contours; n++) {
int last = outline.contours[n];
limit = outline.points + last;
v_start = outline.points[first];
v_last = outline.points[last];
v_control = v_start;
point = outline.points + first;
tags = outline.tags + first;
tag = FT_CURVE_TAG(tags[0]);
if(tag == FT_CURVE_TAG_CUBIC) return false;
if(tag == FT_CURVE_TAG_CONIC) {
if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) {
// start at last point if it is on the curve
v_start = v_last;
limit--;
}
else {
// if both first and last points are conic,
// start at their middle and record its position
// for closure
v_start.x = (v_start.x + v_last.x) / 2;
v_start.y = (v_start.y + v_last.y) / 2;
v_last = v_start;
}
point--;
tags--;
}
path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
while(point < limit) {
point++;
tags++;
tag = FT_CURVE_TAG(tags[0]);
switch(tag) {
case FT_CURVE_TAG_ON:
path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy);
continue;
case FT_CURVE_TAG_CONIC:
v_control.x = point->x;
v_control.y = point->y;
Do_Conic:
if(point < limit) {
FT_Vector vec;
FT_Vector v_middle;
point++;
tags++;
tag = FT_CURVE_TAG(tags[0]);
vec.x = point->x;
vec.y = point->y;
if(tag == FT_CURVE_TAG_ON) {
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
continue;
}
if(tag != FT_CURVE_TAG_CONIC) return false;
v_middle.x = (v_control.x + vec.x) / 2;
v_middle.y = (v_control.y + vec.y) / 2;
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy);
v_control = vec;
goto Do_Conic;
}
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
goto Close;
default:
FT_Vector vec1, vec2;
if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
return false;
vec1.x = point[0].x;
vec1.y = point[0].y;
vec2.x = point[1].x;
vec2.y = point[1].y;
point += 2;
tags += 2;
if(point <= limit) {
FT_Vector vec;
vec.x = point->x;
vec.y = point->y;
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
continue;
}
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
goto Close;
}
}
Close:
path.Close();
first = last + 1;
}
return true;
}
void Painter::CharacterOp(double x, double y, int ch, Font fnt)
{
PAINTER_TIMING("CharacterOp");
FontInfo fi = fnt.Info();
FT_Face face = XftLockFace(fi.GetXftFont());
int glyph_index = FT_Get_Char_Index(face, ch);
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)
RenderOutline(face->glyph->outline, *this, x, y + fnt.Info().GetAscent());
XftUnlockFace(fi.GetXftFont());
}
#endif
END_UPP_NAMESPACE
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all coM_PIes.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
// Recycled for U++ by Miroslav Fidler 2008
#include "Painter.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
static inline double ft_dbl(int p)
{
return double(p) / 64.0;
}
bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy)
{
FT_Vector v_last;
FT_Vector v_control;
FT_Vector v_start;
double x1, y1, x2, y2, x3, y3;
FT_Vector* point;
FT_Vector* limit;
char* tags;
int n; // index of contour in outline
char tag; // current point's state
int first = 0; // index of first point in contour
for(n = 0; n < outline.n_contours; n++) {
int last = outline.contours[n];
limit = outline.points + last;
v_start = outline.points[first];
v_last = outline.points[last];
v_control = v_start;
point = outline.points + first;
tags = outline.tags + first;
tag = FT_CURVE_TAG(tags[0]);
if(tag == FT_CURVE_TAG_CUBIC) return false;
if(tag == FT_CURVE_TAG_CONIC) {
if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) {
// start at last point if it is on the curve
v_start = v_last;
limit--;
}
else {
// if both first and last points are conic,
// start at their middle and record its position
// for closure
v_start.x = (v_start.x + v_last.x) / 2;
v_start.y = (v_start.y + v_last.y) / 2;
v_last = v_start;
}
point--;
tags--;
}
path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
while(point < limit) {
point++;
tags++;
tag = FT_CURVE_TAG(tags[0]);
switch(tag) {
case FT_CURVE_TAG_ON:
path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy);
continue;
case FT_CURVE_TAG_CONIC:
v_control.x = point->x;
v_control.y = point->y;
Do_Conic:
if(point < limit) {
FT_Vector vec;
FT_Vector v_middle;
point++;
tags++;
tag = FT_CURVE_TAG(tags[0]);
vec.x = point->x;
vec.y = point->y;
if(tag == FT_CURVE_TAG_ON) {
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
continue;
}
if(tag != FT_CURVE_TAG_CONIC) return false;
v_middle.x = (v_control.x + vec.x) / 2;
v_middle.y = (v_control.y + vec.y) / 2;
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy);
v_control = vec;
goto Do_Conic;
}
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
goto Close;
default:
FT_Vector vec1, vec2;
if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
return false;
vec1.x = point[0].x;
vec1.y = point[0].y;
vec2.x = point[1].x;
vec2.y = point[1].y;
point += 2;
tags += 2;
if(point <= limit) {
FT_Vector vec;
vec.x = point->x;
vec.y = point->y;
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
continue;
}
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
goto Close;
}
}
Close:
path.Close();
first = last + 1;
}
return true;
}
void Painter::CharacterOp(const Pointf& p, int ch, Font fnt)
{
PAINTER_TIMING("CharacterOp");
FontInfo fi = fnt.Info();
FT_Face face = XftLockFace(fi.GetXftFont());
int glyph_index = FT_Get_Char_Index(face, ch);
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)
RenderOutline(face->glyph->outline, *this, p.x, p.y + fnt.Info().GetAscent());
XftUnlockFace(fi.GetXftFont());
}
#endif
END_UPP_NAMESPACE

View file

@ -2,164 +2,81 @@
NAMESPACE_UPP
ClipFiller::ClipFiller(int _cx)
void BufferPainter::BeginMaskOp()
{
cx = _cx;
buffer.Alloc(2 * cx + 2);
attr.mask = true;
Size sz = ib.GetSize();
mask.Add() = ib;
ib.Create(sz);
Clear(RGBAZero());
Begin();
}
void ClipFiller::Clear()
static inline byte *sSpan(byte *t, int c, int& len)
{
t = ~buffer;
x = 0;
empty = true;
full = true;
last = -1;
}
void ClipFiller::Start(int xmin, int xmax)
{
Render(0, xmin);
}
void ClipFiller::Span(int val, int len)
{
int v = val >> 1;
if(last == val) {
int n = min(v + 128 - *lastn - 1, len);
*lastn += n;
len -= n;
}
last = -1;
while(len > 128) {
int n = min(len, 128);
*t++ = 0;
*t++ = v + n - 1;
*t++ = c + n - 1;
len -= n;
}
if(len) {
*t++ = 0;
last = val;
lastn = t;
*t++ = v + len - 1;
*t++ = c + len - 1;
len = 0;
}
return t;
}
void ClipFiller::Render(int val, int len)
void BufferPainter::FinishMask()
{
if(val == 256) {
Span(256, len);
empty = false;
Buffer<byte> wb(2 * ib.GetWidth());
bool creating = false;
if(!attr.hasclip) {
clip.Add().Alloc(ib.GetHeight());
attr.hasclip = true;
attr.cliplevel = clip.GetCount();
creating = true;
}
else {
full = false;
if(val == 0)
Span(0, len);
else {
memset(t, val, len);
t += len;
empty = false;
last = -1;
}
}
x += len;
}
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 MaskFillerFilter::Render(int val)
{
for(;;) {
if(empty) {
t->Render(0);
empty--;
return;
}
if(full) {
t->Render(val);
full--;
return;
}
byte m = *mask++;
if(m) {
t->Render(val * m >> 8);
return;
}
m = *mask++;
if(m < 128)
empty = m + 1;
else
full = m - 128 + 1;
}
}
void MaskFillerFilter::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(val, n);
full -= n;
len -= n;
}
else {
byte m = *mask++;
if(m) {
int r = val * m >> 8;
t->Render(r);
len--;
}
else {
m = *mask++;
if(m < 128)
empty = m + 1;
Buffer<ClipLine>& cl = clip.Top();
for(int y = 0; y < ib.GetHeight(); y++)
if(creating || !cl[y].IsEmpty()) {
bool full = true;
bool empty = true;
int c0 = 0;
int c256 = 0;
const RGBA *s = ib[y];
const RGBA *e = ib[y] + ib.GetWidth();
byte *t = wb;
while(s < e) {
int val = s->a * (56 * s->r + 183 * s->g + 20 * s->b) >> 16;
if(val == 0) {
if(c256) t = sSpan(t, 128, c256);
c0++;
full = false;
}
else
full = m - 128 + 1;
if(val == 256) {
if(c0) t = sSpan(t, 0, c0);
c256++;
empty = false;
}
else {
if(c256) t = sSpan(t, 128, c256);
if(c0) t = sSpan(t, 0, c0);
*t++ = val;
full = empty = false;
}
s++;
}
if(c256) t = sSpan(t, 128, c256);
if(c0) t = sSpan(t, 0, c0);
cl[y].Clear();
cl[y].Set(~wb, t - ~wb);
}
}
struct NilFiller : Rasterizer::Filler {
void Start(int minx, int maxx) {}
void Render(int val, int len) {}
void Render(int val) {}
};
void MaskFillerFilter::Start(int minx, int maxx)
{
t->Start(minx, maxx);
Rasterizer::Filler *h = t;
NilFiller nil;
t = &nil;
Render(0, minx);
t = h;
ib = mask.Top();
mask.Drop();
attr.mask = false;
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,260 @@
#include "Painter.h"
NAMESPACE_UPP
template <class T>
void sGet(T& r, StringStream& ss)
{
ss.Get(&r, sizeof(T));
}
template <class T>
T sGet(StringStream& ss)
{
T r;
ss.Get(&r, sizeof(T));
return r;
}
void Painter::Paint(const Painting& pic)
{
StringStream ss(pic.cmd);
Pointf p, p1, p2;
RGBA c, c1;
Value v;
int f, ch, n, hasdx;
Xform2D m;
double r, w;
Font fnt;
int ii = 0;
for(;;) {
int cmd = ss.Get();
if(cmd < 0)
return;
bool rel = cmd & 1;
switch(cmd) {
case PAINTING_CLEAR:
ClearOp(sGet<RGBA>(ss));
break;
case PAINTING_MOVE:
case PAINTING_MOVE_REL:
sGet(p, ss);
MoveOp(p, rel);
break;
case PAINTING_LINE:
case PAINTING_LINE_REL:
sGet(p, ss);
LineOp(p, rel);
break;
case PAINTING_QUADRATIC:
case PAINTING_QUADRATIC_REL:
sGet(p1, ss);
sGet(p, ss);
QuadraticOp(p1, p, rel);
break;
case PAINTING_QUADRATIC_S:
case PAINTING_QUADRATIC_S_REL:
sGet(p, ss);
QuadraticOp(p, rel);
break;
case PAINTING_CUBIC:
case PAINTING_CUBIC_REL:
sGet(p1, ss);
sGet(p2, ss);
sGet(p, ss);
CubicOp(p1, p2, p, rel);
break;
case PAINTING_CUBIC_S:
case PAINTING_CUBIC_S_REL:
sGet(p2, ss);
sGet(p, ss);
CubicOp(p2, p, rel);
break;
case PAINTING_ARC:
case PAINTING_ARC_REL:
sGet(p, ss);
sGet(p1, ss);
sGet(r, ss);
sGet(w, ss);
ArcOp(p, p1, r, w, rel);
break;
case PAINTING_CLOSE:
CloseOp();
break;
case PAINTING_DIV:
DivOp();
break;
case PAINTING_FILL_SOLID:
FillOp(sGet<RGBA>(ss));
break;
case PAINTING_FILL_IMAGE:
sGet(m, ss);
f = ss.Get();
if(ii >= pic.data.GetCount())
return;
v = pic.data[ii++];
if(!v.Is<Image>())
return;
FillOp((Image)v, m, f);
break;
case PAINTING_FILL_GRADIENT:
sGet(p, ss);
sGet(c, ss);
sGet(p1, ss);
sGet(c1, ss);
f = ss.Get();
FillOp(p, c, p1, c1, f);
break;
case PAINTING_FILL_RADIAL:
sGet(p, ss);
sGet(c, ss);
sGet(p1, ss);
sGet(r, ss);
sGet(c1, ss);
f = ss.Get();
FillOp(p, c, p1, r, c1, f);
break;
case PAINTING_STROKE_SOLID:
sGet(w, ss);
sGet(c, ss);
StrokeOp(w, c);
break;
case PAINTING_STROKE_IMAGE:
sGet(w, ss);
sGet(m, ss);
f = ss.Get();
if(ii >= pic.data.GetCount())
return;
v = pic.data[ii++];
if(!v.Is<Image>())
return;
StrokeOp(w, (Image)v, m, f);
break;
case PAINTING_STROKE_GRADIENT:
sGet(w, ss);
sGet(p, ss);
sGet(c, ss);
sGet(p1, ss);
sGet(c1, ss);
f = ss.Get();
StrokeOp(w, p, c, p1, c1, f);
break;
case PAINTING_STROKE_RADIAL:
sGet(w, ss);
sGet(p, ss);
sGet(c, ss);
sGet(p1, ss);
sGet(r, ss);
sGet(c1, ss);
f = ss.Get();
StrokeOp(w, p, c, p1, r, c1, f);
break;
case PAINTING_CLIP:
ClipOp();
break;
case PAINTING_CHARACTER:
sGet(p, ss);
ch = ss.Get32();
sGet(fnt, ss);
CharacterOp(p, ch, fnt);
break;
case PAINTING_TEXT:
{
sGet(p, ss);
n = ss.Get32();
hasdx = ss.Get();
sGet(fnt, ss);
Buffer<wchar> txt(n);
Buffer<double> dx(hasdx * n);
for(int i = 0; i < n; i++) {
txt[i] = ss.Get32();
if(hasdx)
sGet(dx[i], ss);
}
TextOp(p, txt, fnt, n, hasdx ? ~dx : NULL);
}
break;
case PAINTING_COLORSTOP:
sGet(r, ss);
sGet(c, ss);
ColorStopOp(r, c);
break;
case PAINTING_CLEARSTOPS:
ClearStopsOp();
break;
case PAINTING_OPACITY:
OpacityOp(sGet<double>(ss));
break;
case PAINTING_LINECAP:
LineCapOp(ss.Get());
break;
case PAINTING_LINEJOIN:
LineJoinOp(ss.Get());
break;
case PAINTING_MITERLIMIT:
MiterLimitOp(ss.Get());
break;
case PAINTING_EVENODD:
EvenOddOp(ss.Get());
break;
case PAINTING_DASH:
{
n = ss.Get32();
Vector<double> dash;
for(int i = 0; i < n; i++)
dash.Add(sGet<double>(ss));
r = sGet<double>(ss);
DashOp(dash, r);
}
break;
case PAINTING_NOAA:
NoAAOp(ss.Get());
break;
case PAINTING_TRANSFORM:
sGet(m, ss);
TransformOp(m);
break;
case PAINTING_BEGIN:
BeginOp();
break;
case PAINTING_END:
EndOp();
break;
case PAINTING_BEGINMASK:
BeginMaskOp();
break;
}
}
}
void PaintImageBufferPaintingFn(ImageBuffer& ib, const Painting& p, Size sz, Point pos, bool noaa)
{
BufferPainter sw(ib);
sw.NoAA(noaa);
Sizef psz = p.GetSize();
sw.Translate(-pos.x, -pos.y);
sw.Scale(sz.cx / psz.cx, sz.cy / psz.cy);
sw.Paint(p);
}
void PaintImageBufferDrawingFn(ImageBuffer& ib, const Drawing& iw, bool noaa)
{
BufferPainter sw(ib);
sw.NoAA(noaa);
Sizef sz = ib.GetSize();
Size isz = iw.GetSize();
sw.Scale(sz.cx / isz.cx, sz.cy / isz.cy);
sw.DrawDrawing(0, 0, isz.cx, isz.cy, iw);
}
void RegisterPaintingFns__(void (*ig)(ImageBuffer& ib, const Painting& pw, Size sz, Point pos, bool noaa),
void (*iw)(ImageBuffer& ib, const Drawing& p, bool noaa));
INITBLOCK
{
RegisterPaintingFns__(PaintImageBufferPaintingFn, PaintImageBufferDrawingFn);
}
END_UPP_NAMESPACE

View file

@ -362,6 +362,64 @@ Painter& Painter::Dash(const char *dash, double start)
return *this;
}
Painter& Painter::Character(double x, double y, int ch, Font fnt)
{
return Character(Pointf(x, y), ch, fnt);
}
void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, double *dx)
{
FontInfo fi = fnt.Info();
double x = p.x;
while(n) {
int ch = *text++;
Character(x, p.y, ch, fnt);
Div();
if(dx)
x += *dx++;
else
x += fi[ch];
n--;
}
}
Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, double *dx)
{
return Text(Pointf(x, y), text, fnt, n < 0 ? wstrlen(text) : n, dx);
}
Painter& Painter::Text(const Pointf& p, const WString& s, Font fnt, double *dx)
{
return Text(p, ~s, fnt, s.GetLength(), dx);
}
Painter& Painter::Text(double x, double y, const WString& s, Font fnt, double *dx)
{
return Text(Pointf(x, y), s, fnt, dx);
}
Painter& Painter::Text(const Pointf& p, const String& s, Font fnt, double *dx)
{
return Text(p, s.ToWString(), fnt, dx);
}
Painter& Painter::Text(double x, double y, const String& s, Font fnt, double *dx)
{
return Text(Pointf(x, y), s, fnt, dx);
}
Painter& Painter::Text(const Pointf& p, const char *text, Font fnt, int n, double *dx)
{
if(n < 0)
n = strlen(text);
return Text(p, ToUnicode(text, n, CHARSET_DEFAULT), fnt, n, dx);
}
Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, double *dx)
{
return Text(Pointf(x, y), text, fnt, n, dx);
}
Painter& Painter::Rectangle(double x, double y, double cx, double cy)
{
return Move(x, y).RelLine(cx, 0).RelLine(0, cy).RelLine(-cx, 0).Close();

View file

@ -58,7 +58,31 @@ enum {
GRADIENT_REFLECT = 2,
};
class Painter {
class Painter : public Draw {
public:
void OffsetOp(Point p);
void RectPath(int x, int y, int cx, int cy);
void RectPath(const Rect& r);
bool ClipOp(const Rect& r);
bool ClipoffOp(const Rect& r);
bool ExcludeClipOp(const Rect& r);
bool IntersectClipOp(const Rect& r);
Rect GetClipOp() const;
bool IsPaintingOp(const Rect& r) const;
void DrawRectOp(int x, int y, int cx, int cy, Color color);
void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
void DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts,
int count_count, int width, Color color, Color doxor);
void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc,
const int *disjunct_polygon_counts, int dpcc, Color color,
int width, Color outline, uint64 pattern, Color doxor);
void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx);
void DrawPaintingOp(const Rect& target, const Painting& p);
protected:
virtual void ClearOp(const RGBA& color) = 0;
@ -93,8 +117,9 @@ protected:
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);
virtual void CharacterOp(const Pointf& p, int ch, Font fnt);
virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1,
double *dx = NULL);
virtual void ColorStopOp(double pos, const RGBA& color) = 0;
virtual void ClearStopsOp() = 0;
@ -112,6 +137,8 @@ protected:
virtual void BeginOp() = 0;
virtual void EndOp() = 0;
virtual void BeginMaskOp() = 0;
protected:
Pointf ReadPoint(CParser& p);
@ -219,15 +246,22 @@ public:
Painter& Clip();
Painter& Character(const Pointf& p, int ch, Font fnt);
Painter& Character(double x, double y, int ch, Font fnt);
Painter& Text(const Pointf& p, const wchar *text, Font fnt, int n = -1, double *dx = NULL);
Painter& Text(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL);
Painter& Text(const Pointf& p, const WString& s, Font fnt, double *dx = NULL);
Painter& Text(double x, double y, const WString& s, Font fnt, double *dx = NULL);
Painter& Text(const Pointf& p, const String& s, Font fnt, double *dx = NULL);
Painter& Text(double x, double y, const String& s, Font fnt, double *dx = NULL);
Painter& Text(const Pointf& p, const char *text, Font fnt, int n = -1, double *dx = NULL);
Painter& Text(double x, double y, const char *text, Font fnt, int n = -1, double *dx = NULL);
void Begin();
void End();
void BeginMask();
Painter& ColorStop(double pos, const RGBA& color);
Painter& ClearStops();
Painter& Opacity(double o);
@ -245,12 +279,15 @@ public:
Painter& Scale(double scalex, double scaley);
Painter& Scale(double scale);
void Paint(const Painting& p);
Painter& Rectangle(double x, double y, double cx, double cy);
Painter& Ellipse(double x, double y, double rx, double ry);
Painter& Circle(double x, double y, double r);
};
#include "Painter.hpp"
#include "Painting.h"
#include "BufferPainter.h"
END_UPP_NAMESPACE

View file

@ -206,3 +206,21 @@ inline void Painter::End()
{
EndOp();
}
inline void Painter::BeginMask()
{
BeginMaskOp();
}
inline Painter& Painter::Character(const Pointf& p, int ch, Font fnt)
{
CharacterOp(p, ch, fnt);
return *this;
}
inline
Painter& Painter::Text(const Pointf& p, const wchar *text, Font fnt, int n, double *dx)
{
TextOp(p, text, fnt, n, dx);
return *this;
}

View file

@ -9,7 +9,10 @@ file
PainterPath.cpp,
FontWin32.cpp optimize_speed,
FontX11.cpp optimize_speed,
Text.cpp,
DrawOp.cpp,
Painting.h,
Painting.cpp,
PaintPainting.icpp,
BufferPainter.h,
Math.cpp,
Xform2D.cpp,
@ -20,12 +23,13 @@ file
Interpolator.cpp optimize_speed,
Rasterizer.cpp optimize_speed,
RasterizerClip.cpp optimize_speed,
Filler.cpp optimize_speed,
Mask.cpp,
Path.cpp optimize_speed,
Context.cpp,
Fillers.h,
Fillers.cpp optimize_speed,
Render.cpp optimize_speed,
Image.cpp optimize_speed,
Mask.cpp optimize_speed,
Gradient.cpp optimize_speed,
RadialGradient.cpp optimize_speed;

276
uppdev/Painter/Painting.cpp Normal file
View file

@ -0,0 +1,276 @@
#include "Painter.h"
NAMESPACE_UPP
void PaintingPainter::ClearOp(const RGBA& color)
{
Put(PAINTING_CLEAR);
Put(color);
}
void PaintingPainter::MoveOp(const Pointf& p, bool rel)
{
Put(PAINTING_MOVE + rel);
Putf(p);
}
void PaintingPainter::LineOp(const Pointf& p, bool rel)
{
Put(PAINTING_LINE + rel);
Putf(p);
}
void PaintingPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool rel)
{
Put(PAINTING_QUADRATIC + rel);
Putf(p1);
Putf(p);
}
void PaintingPainter::QuadraticOp(const Pointf& p, bool rel)
{
Put(PAINTING_QUADRATIC_S + rel);
Putf(p);
}
void PaintingPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel)
{
Put(PAINTING_CUBIC + rel);
Putf(p1);
Putf(p2);
Putf(p);
}
void PaintingPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel)
{
Put(PAINTING_CUBIC_S + rel);
Putf(p2);
Putf(p);
}
void PaintingPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel)
{
Put(PAINTING_ARC + rel);
Putf(c);
Putf(r);
Putf(angle);
Putf(sweep);
}
void PaintingPainter::CloseOp()
{
Put(PAINTING_CLOSE);
}
void PaintingPainter::DivOp()
{
Put(PAINTING_DIV);
}
void PaintingPainter::FillOp(const RGBA& color)
{
Put(PAINTING_FILL_SOLID);
Put(color);
}
void PaintingPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags)
{
Put(PAINTING_FILL_IMAGE);
Putf(transsrc);
Put(flags);
data.Add(image);
}
void PaintingPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2,
const RGBA& color2, int style)
{
Put(PAINTING_FILL_GRADIENT);
Putf(p1);
Put(color1);
Putf(p2);
Put(color2);
Put(style);
}
void PaintingPainter::FillOp(const Pointf& f, const RGBA& color1,
const Pointf& p, double r, const RGBA& color2, int style)
{
Put(PAINTING_FILL_RADIAL);
Putf(f);
Put(color1);
Putf(p);
Putf(r);
Put(color2);
Put(style);
}
void PaintingPainter::StrokeOp(double width, const RGBA& color)
{
Put(PAINTING_STROKE_SOLID);
Putf(width);
Put(color);
}
void PaintingPainter::StrokeOp(double width, const Image& image,
const Xform2D& transsrc, dword flags)
{
Put(PAINTING_STROKE_IMAGE);
Putf(width);
Putf(transsrc);
Put(flags);
data.Add(image);
}
void PaintingPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2, int style)
{
Put(PAINTING_STROKE_GRADIENT);
Putf(width);
Putf(p1);
Put(color1);
Putf(p2);
Put(color2);
Put(style);
}
void PaintingPainter::StrokeOp(double width, const Pointf& f,
const RGBA& color1, const Pointf& p, double r,
const RGBA& color2, int style)
{
Put(PAINTING_STROKE_RADIAL);
Putf(width);
Putf(f);
Put(color1);
Putf(p);
Putf(r);
Put(color2);
Put(style);
}
void PaintingPainter::ClipOp()
{
Put(PAINTING_CLIP);
}
void PaintingPainter::CharacterOp(const Pointf& p, int ch, Font fnt)
{
Put(PAINTING_CHARACTER);
Putf(p);
Put32(ch);
Put(fnt);
}
void PaintingPainter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, double *dx)
{
Put(PAINTING_TEXT);
Putf(p);
Put32(n);
Put((bool)dx);
Put(fnt);
for(int i = 0; i < n; i++) {
Put32(text[i]);
if(dx)
Putf(dx[i]);
}
}
void PaintingPainter::ColorStopOp(double pos, const RGBA& color)
{
Put(PAINTING_COLORSTOP);
Putf(pos);
Put(color);
}
void PaintingPainter::ClearStopsOp()
{
Put(PAINTING_CLEARSTOPS);
}
void PaintingPainter::OpacityOp(double o)
{
Put(PAINTING_OPACITY);
Putf(o);
}
void PaintingPainter::LineCapOp(int linecap)
{
Put(PAINTING_LINECAP);
Put(linecap);
}
void PaintingPainter::LineJoinOp(int linejoin)
{
Put(PAINTING_LINEJOIN);
Put(linejoin);
}
void PaintingPainter::MiterLimitOp(double l)
{
Put(PAINTING_MITERLIMIT);
Putf(l);
}
void PaintingPainter::EvenOddOp(bool evenodd)
{
Put(PAINTING_EVENODD);
Put(evenodd);
}
void PaintingPainter::DashOp(const Vector<double>& dash, double start)
{
Put(PAINTING_DASH);
Put32(dash.GetCount());
for(int i = 0; i < dash.GetCount(); i++)
Putf(dash[i]);
Putf(start);
}
void PaintingPainter::NoAAOp(bool noaa)
{
Put(PAINTING_NOAA);
Put(noaa);
}
void PaintingPainter::TransformOp(const Xform2D& m)
{
Put(PAINTING_TRANSFORM);
Putf(m);
}
void PaintingPainter::BeginOp()
{
Put(PAINTING_BEGIN);
}
void PaintingPainter::EndOp()
{
Put(PAINTING_END);
}
void PaintingPainter::BeginMaskOp()
{
Put(PAINTING_BEGINMASK);
}
Painting PaintingPainter::GetResult()
{
Painting p;
p.cmd = cmd.GetResult();
p.data = data;
p.size = size;
return p;
}
void PaintingPainter::Create(double cx, double cy)
{
cmd.Create();
size.cx = cx;
size.cy = cy;
}
void PaintingPainter::Create(Sizef sz)
{
Create(sz.cx, sz.cy);
}
END_UPP_NAMESPACE

133
uppdev/Painter/Painting.h Normal file
View file

@ -0,0 +1,133 @@
enum {
PAINTING_CLEAR,
PAINTING_MOVE = 4,
PAINTING_MOVE_REL,
PAINTING_LINE,
PAINTING_LINE_REL,
PAINTING_QUADRATIC,
PAINTING_QUADRATIC_REL,
PAINTING_QUADRATIC_S,
PAINTING_QUADRATIC_S_REL,
PAINTING_CUBIC,
PAINTING_CUBIC_REL,
PAINTING_CUBIC_S,
PAINTING_CUBIC_S_REL,
PAINTING_ARC,
PAINTING_ARC_REL,
PAINTING_CLOSE,
PAINTING_DIV,
PAINTING_FILL_SOLID,
PAINTING_FILL_IMAGE,
PAINTING_FILL_GRADIENT,
PAINTING_FILL_RADIAL,
PAINTING_STROKE_SOLID,
PAINTING_STROKE_IMAGE,
PAINTING_STROKE_GRADIENT,
PAINTING_STROKE_RADIAL,
PAINTING_CLIP,
PAINTING_CHARACTER,
PAINTING_TEXT,
PAINTING_COLORSTOP,
PAINTING_CLEARSTOPS,
PAINTING_OPACITY,
PAINTING_LINECAP,
PAINTING_LINEJOIN,
PAINTING_MITERLIMIT,
PAINTING_EVENODD,
PAINTING_DASH,
PAINTING_NOAA,
PAINTING_TRANSFORM,
PAINTING_BEGIN,
PAINTING_END,
PAINTING_BEGINMASK,
};
class PaintingPainter : public Painter {
StringStream cmd;
ValueArray data;
Sizef size;
void Put(int c) { cmd.Put(c); }
void Put32(int c) { cmd.Put32(c); }
void Put(const RGBA& c) { cmd.Put(&c, sizeof(RGBA)); }
void Putf(const double& d) { cmd.Put(&d, sizeof(double)); }
void Putf(const Pointf& p) { cmd.Put(&p, sizeof(p)); }
void Putf(const Xform2D& m) { cmd.Put(&m, sizeof(m)); }
void Put(const Font& f) { cmd.Put(&f, sizeof(Font)); }
protected:
virtual void ClearOp(const RGBA& color);
virtual void MoveOp(const Pointf& p, bool rel);
virtual void LineOp(const Pointf& p, bool rel);
virtual void QuadraticOp(const Pointf& p1, const Pointf& p, bool rel);
virtual void QuadraticOp(const Pointf& p, bool rel);
virtual void CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel);
virtual void CubicOp(const Pointf& p2, const Pointf& p, bool rel);
virtual void ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel);
virtual void CloseOp();
virtual void DivOp();
virtual void FillOp(const RGBA& color);
virtual void FillOp(const Image& image, const Xform2D& transsrc, dword flags);
virtual void FillOp(const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2,
int style);
virtual void FillOp(const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style);
virtual void StrokeOp(double width, const RGBA& rgba);
virtual void StrokeOp(double width, const Image& image, const Xform2D& transsrc,
dword flags);
virtual void StrokeOp(double width, const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2,
int style);
virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style);
virtual void ClipOp();
virtual void CharacterOp(const Pointf& p, int ch, Font fnt);
virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1,
double *dx = NULL);
virtual void ColorStopOp(double pos, const RGBA& color);
virtual void ClearStopsOp();
virtual void OpacityOp(double o);
virtual void LineCapOp(int linecap);
virtual void LineJoinOp(int linejoin);
virtual void MiterLimitOp(double l);
virtual void EvenOddOp(bool evenodd);
virtual void DashOp(const Vector<double>& dash, double start);
virtual void NoAAOp(bool noaa);
virtual void TransformOp(const Xform2D& m);
virtual void BeginOp();
virtual void EndOp();
virtual void BeginMaskOp();
public:
Painting GetResult();
operator Painting() { return GetResult(); }
void Create(double cx, double cy);
void Create(Sizef sz);
Sizef GetSize() const { return size; }
PaintingPainter() {}
PaintingPainter(double cx, double cy) { Create(cx, cy); }
PaintingPainter(Sizef sz) { Create(sz); }
};

View file

@ -1,5 +1,7 @@
#include "Painter.h"
// The genesis of this code can be dated back to LibART
#define LLOG(x) // LOG(x)
NAMESPACE_UPP

View file

@ -1,4 +1,5 @@
#include "Painter.h"
#include "Fillers.h"
NAMESPACE_UPP

View file

@ -1,52 +0,0 @@
#include "Painter.h"
NAMESPACE_UPP
void Painter::TextOp(double x, double y, const wchar *text, Font fnt, int n, double *dx)
{
FontInfo fi = fnt.Info();
if(n < 0)
n = wstrlen(text);
while(n) {
int ch = *text++;
Character(x, y, ch, fnt);
Div();
if(dx)
x += *dx++;
else
x += fi[ch];
n--;
}
}
Painter& Painter::Character(double x, double y, int ch, Font fnt)
{
CharacterOp(x, y, ch, fnt);
return *this;
}
Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, double *dx)
{
TextOp(x, y, text, fnt, n, dx);
return *this;
}
Painter& Painter::Text(double x, double y, const WString& s, Font fnt, double *dx)
{
Text(x, y, s, fnt, s.GetLength(), dx);
return *this;
}
Painter& Painter::Text(double x, double y, const String& s, Font fnt, double *dx)
{
Text(x, y, s.ToWString(), fnt, dx);
return *this;
}
Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, double *dx)
{
Text(x, y, ToUnicode(text, n < 0 ? strlen(text) : n, CHARSET_DEFAULT), fnt, dx);
return *this;
}
END_UPP_NAMESPACE

View file

@ -2,4 +2,7 @@
#define _Painter_icpp_init_stub
#include "Core/init"
#include "CtrlLib/init"
#define BLITZ_INDEX__ F8939D4A0BC2FDAEDB6EE5CF1693AFE34
#include "PaintPainting.icpp"
#undef BLITZ_INDEX__
#endif

View file

@ -1,5 +1,7 @@
#include "Examples.h"
#ifndef _DEBUG
void Big(Painter& sw)
{
int n = 0;
@ -45,3 +47,5 @@ INITBLOCK {
RegisterExample("Really Big Polygon", Big);
RegisterExample("Really Big Stroke", BigStroke);
}
#endif

View file

@ -23,7 +23,7 @@ struct App : TopWindow {
FrameBottom< WithCtrlLayout<StaticRect> > ctrl;
typedef App CLASSNAME;
void DoPaint0(Painter& sw);
void DoPaint(Painter& sw);
void Print();

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void MaskBlending(Painter& sw)
{
const char *txt = "This is just a test of alpha mask blending";
@ -25,5 +23,3 @@ void MaskBlending(Painter& sw)
INITBLOCK {
RegisterExample("Blending using alpha mask", MaskBlending);
}
#endif

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void RadialMaskBlending(Painter& sw)
{
const char *txt = "This is just a test of radial mask blending";
@ -31,5 +29,3 @@ void RadialMaskBlending(Painter& sw)
INITBLOCK {
RegisterExample("Blending using radial alpha mask", RadialMaskBlending);
}
#endif

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void RichTextExample(Painter& sw)
{
const char *qtf =
@ -79,5 +77,3 @@ INITBLOCK
{
RegisterExample("RichText", RichTextExample);
}
#endif

View file

@ -40,26 +40,22 @@ void App::DoPaint0(Painter& sw)
void App::DoPaint(Painter& sw)
{
#if 0
if(ctrl.painting) {
PaintingPainter h(2000, 2000);
DoPaint0(h);
sw.Paint(h);
}
else
#endif
DoPaint0(sw);
}
void App::Print()
{
#if 0
PaintingPainter sw(1000, 1000);
DoPaint(sw);
PrinterJob pb;
if(pb.Execute())
pb.GetDraw().DrawPainting(0, 0, 4000, 4000, sw);
#endif
}
void App::Benchmark()

View file

@ -1,60 +1,60 @@
description "PNG image file format U++ encapsulation";
uses
Core,
Draw;
library(!WIN32) png;
options
-DPNG_NO_READ_SHIFT,
-DPNG_NO_READ_SWAP,
-DPNG_NO_READ_INVERT,
-DPNG_NO_READ_DITHER,
-DPNG_NO_READ_BACKGROUND,
-DPNG_NO_READ_GAMMA,
-DPNG_NO_READ_SWAP_ALPHA,
-DPNG_NO_READ_INVERT_ALPHA,
-DPNG_NO_READ_STRIP_ALPHA,
-DPNG_NO_READ_USER_TRANSFORM,
-DPNG_NO_READ_RGB_TO_GRAY,
-DPNG_NO_PROGRESSIVE_READ,
-DPNG_NO_READ_COMPOSITE_NODIV,
-DPNG_NO_MNG_FEATURES,
-DPNG_NO_READ_EMPTY_PLTE,
-DPNG_NO_WRITE_SHIFT,
-DPNG_NO_WRITE_PACK,
-DPNG_NO_WRITE_SWAP,
-DPNG_NO_WRITE_PACKSWAP,
-DPNG_NO_WRITE_INVERT,
-DPNG_NO_WRITE_FILLER,
-DPNG_NO_WRITE_SWAP_ALPHA,
-DPNG_NO_WRITE_INVERT_ALPHA,
-DPNG_NO_USER_TRANSFORM_PTR,
-DPNG_NO_WRITE_EMPTY_PLTE,
-DPNG_NO_EASY_ACCESS,
-DPNG_NO_READ_bKGD,
-DPNG_NO_READ_cHRM,
-DPNG_NO_READ_gAMA,
-DPNG_NO_READ_iCCP,
-DPNG_NO_READ_oFFs,
-DPNG_NO_READ_pCAL,
-DPNG_NO_READ_sCAL,
-DPNG_NO_READ_sBIT,
-DPNG_NO_READ_sPLT,
-DPNG_NO_READ_sRGB,
-DPNG_NO_READ_tIME,
-DPNG_NO_READ_zTXt,
-DPNG_NO_READ_OPT_PLTE,
-DPNG_NO_INFO_IMAGE;
options(MSC8ARM) "-D_WIN32_WCE -DARM -D_ARM_ -DUNDER_CE -DUNICODE -D_UNICODE";
file
png.h,
pnglib.c,
pngupp.cpp,
pngreg.icpp,
Info readonly separator,
Copying;
description "PNG image file format U++ encapsulation";
uses
Core,
Draw;
library(!WIN32) png;
options
-DPNG_NO_READ_SHIFT,
-DPNG_NO_READ_SWAP,
-DPNG_NO_READ_INVERT,
-DPNG_NO_READ_DITHER,
-DPNG_NO_READ_BACKGROUND,
-DPNG_NO_READ_GAMMA,
-DPNG_NO_READ_SWAP_ALPHA,
-DPNG_NO_READ_INVERT_ALPHA,
-DPNG_NO_READ_STRIP_ALPHA,
-DPNG_NO_READ_USER_TRANSFORM,
-DPNG_NO_READ_RGB_TO_GRAY,
-DPNG_NO_PROGRESSIVE_READ,
-DPNG_NO_READ_COMPOSITE_NODIV,
-DPNG_NO_MNG_FEATURES,
-DPNG_NO_READ_EMPTY_PLTE,
-DPNG_NO_WRITE_SHIFT,
-DPNG_NO_WRITE_PACK,
-DPNG_NO_WRITE_SWAP,
-DPNG_NO_WRITE_PACKSWAP,
-DPNG_NO_WRITE_INVERT,
-DPNG_NO_WRITE_FILLER,
-DPNG_NO_WRITE_SWAP_ALPHA,
-DPNG_NO_WRITE_INVERT_ALPHA,
-DPNG_NO_USER_TRANSFORM_PTR,
-DPNG_NO_WRITE_EMPTY_PLTE,
-DPNG_NO_EASY_ACCESS,
-DPNG_NO_READ_bKGD,
-DPNG_NO_READ_cHRM,
-DPNG_NO_READ_gAMA,
-DPNG_NO_READ_iCCP,
-DPNG_NO_READ_oFFs,
-DPNG_NO_READ_pCAL,
-DPNG_NO_READ_sCAL,
-DPNG_NO_READ_sBIT,
-DPNG_NO_READ_sPLT,
-DPNG_NO_READ_sRGB,
-DPNG_NO_READ_tIME,
-DPNG_NO_READ_zTXt,
-DPNG_NO_READ_OPT_PLTE,
-DPNG_NO_INFO_IMAGE;
options(MSC8ARM) "-D_WIN32_WCE -DARM -D_ARM_ -DUNDER_CE -DUNICODE -D_UNICODE";
file
png.h,
pnglib.c,
pngupp.cpp,
pngreg.icpp,
Info readonly separator,
Copying;