Developing Painter2.0

git-svn-id: svn://ultimatepp.org/upp/trunk@848 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-02-10 17:31:20 +00:00
parent 6be9238f51
commit 5f7bdbb994
34 changed files with 1242 additions and 116 deletions

View file

@ -55,7 +55,7 @@ private:
const Pointf& a0, const Pointf& b0);
public:
Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin);
void Init(double width, double miterlimit, double tolerance, int linecap, int linejoin);
};
class Dasher : public LinearPathFilter {
@ -64,7 +64,7 @@ public:
virtual void Line(const Pointf& p);
private:
const Vector<double>& pattern;
const Vector<double> *pattern;
int patterni;
double sum, rem;
bool flag;
@ -73,7 +73,7 @@ private:
void Put(const Pointf& p);
public:
Dasher(const Vector<double>& pattern, double distance);
void Init(const Vector<double>& pattern, double distance);
};
struct Transformer : public LinearPathFilter {
@ -117,6 +117,11 @@ inline void AlphaBlendCover8(RGBA& t, const RGBA& c, int cover)
t.a = a + (alpha * t.a >> 8);
}
inline int Q8(double x)
{
return int(x * 256 + 0.5);
}
class Rasterizer : public LinearPathConsumer {
public:
virtual void Move(const Pointf& p);
@ -134,7 +139,6 @@ private:
Rectf cliprect;
Pointf p0;
Buffer< Vector<Cell> > cell;
int xmax, ymax;
int min_y;
int max_y;
Size sz;
@ -180,10 +184,31 @@ struct ScanLine {
};
struct SpanSource {
virtual void Get(RGBA *_span, int x, int y, unsigned len);
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);
Image MipMap(const Image& img);
Image MakeMipMap(const Image& img, int level);
class LinearInterpolator {
struct Dda2 {
int count, lift, rem, mod, p;
void Set(int a, int b, int len);
int Get();
};
Xform2D xform;
Dda2 ddax, dday;
public:
void Begin(int x, int y, int len);
void Get(int& x, int& y);
void Set(const Xform2D& m) { xform = m; }
};
class BufferPainter : public Painter {
protected:
@ -198,8 +223,23 @@ protected:
virtual void CloseOp();
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 ColorStopOp(double pos, const RGBA& color);
virtual void ClearStopsOp();
@ -267,16 +307,21 @@ public:
Rectf pathrect;
Rasterizer rasterizer;
Buffer<RGBA> span;
void *PathAddRaw(int type, int size);
template <class T> T& PathAdd(int type) { return *(T *)PathAddRaw(type, sizeof(T)); }
void DoMove0();
void ClearPath();
void RenderPath(LinearPathFilter *first_filter, LinearPathFilter *last_filter,
const RGBA& color, bool evenodd);
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);
public:

View file

@ -29,26 +29,26 @@ void Dasher::Line(const Pointf& p)
pos += rem;
Put(pos / len * v + p0);
flag = !flag;
rem = pattern[patterni];
patterni = (patterni + 1) % pattern.GetCount();
rem = (*pattern)[patterni];
patterni = (patterni + 1) % pattern->GetCount();
}
rem -= len - pos;
Put(p);
p0 = p;
}
Dasher::Dasher(const Vector<double>& p, double distance)
: pattern(p)
void Dasher::Init(const Vector<double>& p, double distance)
{
sum = Sum0(pattern);
pattern = &p;
sum = Sum0(p);
if(sum == 0)
return;
distance -= int(distance / sum) * sum;
patterni = 0;
flag = false;
for(;;) {
rem = pattern[patterni];
patterni = (patterni + 1) % pattern.GetCount();
rem = (*pattern)[patterni];
patterni = (patterni + 1) % pattern->GetCount();
flag = !flag;
if(rem > distance) {
rem -= distance;

View file

@ -0,0 +1,114 @@
//----------------------------------------------------------------------------
// 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_WIN32
inline double fx_to_dbl(const FIXED& p) {
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
}
void RenderCharPath(const char* gbuf, unsigned total_size, Painter& sw, double xx, double yy)
{
const char* cur_glyph = gbuf;
const char* end_glyph = gbuf + total_size;
while(cur_glyph < end_glyph) {
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
const char* end_poly = cur_glyph + th->cb;
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
sw.Move(xx + fx_to_dbl(th->pfxStart.x), yy - fx_to_dbl(th->pfxStart.y));
while(cur_poly < end_poly) {
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
if (pc->wType == TT_PRIM_LINE)
for(int i = 0; i < pc->cpfx; i++)
sw.Line(xx + fx_to_dbl(pc->apfx[i].x), yy - fx_to_dbl(pc->apfx[i].y));
if (pc->wType == TT_PRIM_QSPLINE) {
int u;
for (u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
POINTFX pnt_c = pc->apfx[u+1];
if (u < pc->cpfx - 2) { // If not on last spline, compute C
*(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
*(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
}
sw.Quadratic(xx + fx_to_dbl(pnt_b.x), yy - fx_to_dbl(pnt_b.y),
xx + fx_to_dbl(pnt_c.x), yy - fx_to_dbl(pnt_c.y));
}
}
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
}
sw.Close();
cur_glyph += th->cb;
}
}
struct FontChar {
Font fnt;
int chr;
bool operator==(const FontChar& b) const { return fnt == b.fnt && chr == b.chr; }
unsigned GetHashValue() const { return CombineHash(fnt, chr); }
};
struct sMakeCharOutline : LRUCache<String, FontChar>::Maker {
FontChar fc;
FontChar Key() const { return fc; }
int Make(String& s) const {
static ScreenDraw w;
w.SetFont(fc.fnt);
GLYPHMETRICS gm;
MAT2 m_matrix;
memset(&m_matrix, 0, sizeof(m_matrix));
m_matrix.eM11.value = 1;
m_matrix.eM22.value = 1;
s.Clear();
int gsz = GetGlyphOutlineW(w.GetHandle(), fc.chr, GGO_NATIVE, &gm, 0, NULL, &m_matrix);
if(gsz < 0)
return 0;
StringBuffer gb(gsz);
gsz = GetGlyphOutlineW(w.GetHandle(), fc.chr, GGO_NATIVE, &gm, gsz, ~gb, &m_matrix);
if(gsz < 0)
return 0;
s = gb;
return gsz;
}
};
void Painter::CharacterOp(double x, double y, int ch, Font fnt)
{
PAINTER_TIMING("CharacterOp");
String s;
INTERLOCKED {
static LRUCache<String, FontChar> cache;
cache.Shrink(100000);
sMakeCharOutline h;
h.fc.fnt = fnt;
h.fc.chr = ch;
s = cache.Get(h);
}
RenderCharPath(s, s.GetLength(), *this, x, y + fnt.Info().GetAscent());
EvenOdd(true);
}
#endif
END_UPP_NAMESPACE

152
uppdev/Painter/FontX11.cpp Normal file
View file

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

View file

@ -0,0 +1,58 @@
#include "Painter.h"
NAMESPACE_UPP
void BufferPainter::MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx)
{
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));
ch = pathattr.stop_color[i];
}
else {
h = cx - 1;
ch = color2;
}
int w = h - l;
for(int j = 0; j < w; j++) {
t->r = ((w - j) * cl.r + j * ch.r) / w;
t->g = ((w - j) * cl.g + j * ch.g) / w;
t->b = ((w - j) * cl.b + j * ch.b) / w;
t->a = ((w - j) * cl.a + j * ch.a) / w;
t++;
}
cl = ch;
l = h;
}
*t = cl;
}
Image BufferPainter::GetGradient(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;
}
void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
Fill(GetGradient(color1, color2, p1, p2), p1.x, p1.y, p2.x, p2.y,
FILL_VPAD | FILL_FAST |
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
? FILL_HREPEAT : FILL_HREFLECT));
}
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.x, p1.y, p2.x, p2.y,
FILL_VPAD | FILL_FAST |
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
? FILL_HREPEAT : FILL_HREFLECT));
}
END_UPP_NAMESPACE

240
uppdev/Painter/Image.cpp Normal file
View file

@ -0,0 +1,240 @@
#include "Painter.h"
NAMESPACE_UPP
#if 0 // does not seem to help...
Image MipMap(const Image& img)
{
Size ssz = img.GetSize() / 2;
Size msz = (img.GetSize() + 1) / 2;
ImageBuffer ib(msz);
for(int y = 0; y < ssz.cy; y++) {
const RGBA *s1 = img[2 * y];
const RGBA *s2 = img[2 * y + 1];
const RGBA *e = s1 + 2 * ssz.cx;
RGBA *t = ib[y];
while(s1 < e) {
t->r = (s1[0].r + s1[1].r + s2[0].r + s2[1].r) >> 2;
t->g = (s1[0].g + s1[1].g + s2[0].g + s2[1].g) >> 2;
t->b = (s1[0].b + s1[1].b + s2[0].b + s2[1].b) >> 2;
t->a = (s1[0].a + s1[1].a + s2[0].a + s2[1].a) >> 2;
t++;
s1 += 2;
s2 += 2;
}
if(ssz.cx < msz.cx) {
t->r = (s1[0].r + s2[0].r) >> 2;
t->g = (s1[0].g + s2[0].g) >> 2;
t->b = (s1[0].b + s2[0].b) >> 2;
t->a = (s1[0].a + s2[0].a) >> 2;
}
}
if(ssz.cy < msz.cy) {
const RGBA *s1 = img[img.GetSize().cy - 1];
const RGBA *e = s1 + 2 * ssz.cx;
RGBA *t = ib[msz.cy - 1];
while(s1 < e) {
t->r = (s1[0].r + s1[1].r) >> 2;
t->g = (s1[0].g + s1[1].g) >> 2;
t->b = (s1[0].b + s1[1].b) >> 2;
t->a = (s1[0].a + s1[1].a) >> 2;
t++;
s1 += 2;
}
if(ssz.cx < msz.cx) {
t->r = s1[0].r >> 2;
t->g = s1[0].g >> 2;
t->b = s1[0].b >> 2;
t->a = s1[0].a >> 2;
}
}
return ib;
}
Image MakeMipMap(const Image& m, int level);
struct MipMapMaker : ImageMaker {
int level;
Image image;
virtual String Key() const {
String h;
RawCat(h, image.GetSerialId());
RawCat(h, level);
return h;
}
virtual Image Make() const {
Size sz = image.GetSize();
if(sz.cx && sz.cx) {
if(level <= 0)
return image;
return MipMap(MakeMipMap(image, level - 1));
}
return Image();
}
};
Image MakeMipMap(const Image& img, int level)
{
MipMapMaker m;
m.image = img;
m.level = level;
return MakeImage(m);
}
#endif
struct PainterImageSpan : SpanSource {
struct RGBAV {
dword r, g, b, a;
void Set(dword v) { r = g = b = a = v; }
void Put(dword weight, const RGBA& src) {
r += weight * src.r;
g += weight * src.g;
b += weight * src.b;
a += weight * src.a;
}
};
LinearInterpolator interpolator;
int ax, ay, cx, cy, maxx, maxy;
byte style;
byte hstyle, vstyle;
bool fast;
bool fixed;
Image image;
void Set(const Xform2D& m, const Image& img) {
int level = 0;
#if 0 // no mipmap for now
double q = 1;
if(!fast) {
double q = 1;
Pointf sc = m.GetScaleXY();
if(sc.x >= 0.01 && sc.y >= 0.01)
while(sc.x < 0.5 && sc.y < 0.5) {
level++;
sc.x *= 2;
sc.y *= 2;
q /= 2;
}
}
if(q != 1)
interpolator.Set(Inverse(m) * Xform2D::Scale(q));
else
#endif
interpolator.Set(Inverse(m));
image = img;
// image = MakeMipMap(img, level);
cx = image.GetWidth();
cy = image.GetHeight();
maxx = cx - 1;
maxy = cy - 1;
ax = 6000000 / cx * cx;
ay = 6000000 / cy * cy;
}
RGBA Pixel(int x, int y) { return image[y][x]; }
RGBA GetPixel(int x, int y) {
if(hstyle == FILL_HPAD)
x = minmax(x, 0, maxx);
else
if(hstyle == FILL_HREFLECT)
x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx;
else
if(hstyle == FILL_HREPEAT)
x = (x + ax) % cx;
if(vstyle == FILL_VPAD)
y = minmax(y, 0, maxy);
else
if(vstyle == FILL_VREFLECT)
y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy;
else
if(vstyle == FILL_VREPEAT)
y = (y + ay) % cy;
return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[y][x] : RGBAZero();
}
virtual void Get(RGBA *span, int x, int y, unsigned len)
{
interpolator.Begin(x, y, len);
fixed = hstyle && vstyle;
while(len--) {
int x_hr;
int y_hr;
interpolator.Get(x_hr, y_hr);
x_hr -= 128;
y_hr -= 128;
int x_lr = x_hr >> 8;
int y_lr = y_hr >> 8;
if(hstyle == FILL_HREPEAT)
x_lr = (x_lr + ax) % cx;
if(vstyle == FILL_VREPEAT)
y_lr = (y_lr + ay) % cy;
if(fast) {
if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy)
*span = Pixel(x_lr, y_lr);
else
if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy))
*span = RGBAZero();
else
*span = GetPixel(x_lr, y_lr);
}
else {
RGBAV v;
v.Set(256 * 256 / 2);
x_hr &= 255;
y_hr &= 255;
if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy) {
v.Put((256 - x_hr) * (256 - y_hr), Pixel(x_lr, y_lr));
v.Put(x_hr * (256 - y_hr), Pixel(x_lr + 1, y_lr));
v.Put((256 - x_hr) * y_hr, Pixel(x_lr, y_lr + 1));
v.Put(x_hr * y_hr, Pixel(x_lr + 1, y_lr + 1));
}
else
if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy))
v.Set(0);
else {
v.Put((256 - x_hr) * (256 - y_hr), GetPixel(x_lr, y_lr));
v.Put(x_hr * (256 - y_hr), GetPixel(x_lr + 1, y_lr));
v.Put((256 - x_hr) * y_hr, GetPixel(x_lr, y_lr + 1));
v.Put(x_hr * y_hr, GetPixel(x_lr + 1, y_lr + 1));
}
span->r = byte(v.r >> 16);
span->g = byte(v.g >> 16);
span->b = byte(v.b >> 16);
span->a = byte(v.a >> 16);
}
++span;
}
}
};
void BufferPainter::RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags)
{
Close();
if(image.GetWidth() == 0 || image.GetHeight() == 0)
return;
PainterImageSpan ss;
ss.style = flags & 15;
ss.hstyle = flags & 3;
ss.vstyle = flags & 12;
ss.fast = flags & FILL_FAST;
ss.Set(transsrc * pathattr.mtx, image);
RenderPath(width, &ss, RGBAZero());
}
void BufferPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags)
{
RenderImage(-1, image, transsrc, flags);
}
void BufferPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags)
{
RenderImage(width, image, transsrc, flags);
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,46 @@
#include "Painter.h"
NAMESPACE_UPP
void LinearInterpolator::Dda2::Set(int p1, int p2, int len)
{
count = len <= 0 ? 1 : len;
lift = (p2 - p1) / count;
rem = (p2 - p1) % count;
mod = rem;
p = p1;
if(mod <= 0) {
mod += count;
rem += count;
lift--;
}
mod -= count;
}
int LinearInterpolator::Dda2::Get()
{
int pp = p;
mod += rem;
p += lift;
if(mod > 0) {
mod -= count;
p++;
}
return pp;
}
void LinearInterpolator::Begin(int x, int y, int len)
{
Pointf p1 = xform.Transform(Pointf(x, y) + 0.5);
Pointf p2 = xform.Transform(Pointf(x + len, y) + 0.5);
ddax.Set(Q8(p1.x), Q8(p2.x), len);
dday.Set(Q8(p1.y), Q8(p2.y), len);
}
void LinearInterpolator::Get(int& x, int& y)
{
x = ddax.Get();
y = dday.Get();
}
END_UPP_NAMESPACE

View file

@ -182,12 +182,81 @@ Painter& Painter::RelCubic(double x2, double y2, double x, double y)
return *this;
}
Xform2D GetLineSzXform(const Pointf& p1, const Pointf& p2, const Sizef& sz)
{
Xform2D m = Xform2D::Scale(Distance(p1, p2) / sz.cx);
m = m * Xform2D::Rotation(Bearing(p2 - p1));
m = m * Xform2D::Translation(p1.x, p1.y);
return m;
}
Painter& Painter::Fill(const Image& image, Pointf p1, Pointf p2, dword flags)
{
return Fill(image, GetLineSzXform(p1, p2, image.GetSize()), flags);
}
Painter& Painter::Fill(const Image& image, double x1, double y1,
double x2, double y2, dword flags)
{
return Fill(image, Pointf(x1, y1), Pointf(x2, y2), flags);
}
Painter& Painter::Fill(double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
{
return Fill(Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
}
Painter& Painter::Fill(double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
{
return Fill(Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
}
Painter& Painter::Fill(const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Fill(c, color1, c, r, color2, style);
}
Painter& Painter::Fill(double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Fill(Pointf(x, y), color1, r, color2, style);
}
Painter& Painter::Translate(double x, double y)
{
Transform(Xform2D::Translation(x, y));
return *this;
}
Painter& Painter::Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2, dword flags)
{
return Stroke(width, image, GetLineSzXform(p1, p2, image.GetSize()), flags);
}
Painter& Painter::Stroke(double width, const Image& image, double x1, double y1, double x2, double y2, dword flags)
{
return Stroke(width, image, Pointf(x1, y1), Pointf(x2, y2), flags);
}
Painter& Painter::Stroke(double width, double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
{
return Stroke(width, Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
}
Painter& Painter::Stroke(double width, double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
{
return Stroke(width, Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
}
Painter& Painter::Stroke(double width, const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Stroke(width, c, color1, c, r, color2, style);
}
Painter& Painter::Stroke(double width, double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Stroke(width, Pointf(x, y), color1, r, color2, style);
}
Painter& Painter::Rotate(double a)
{
Transform(Xform2D::Rotation(a));
@ -222,4 +291,14 @@ Painter& Painter::Dash(const char *dash, double start)
return *this;
}
Painter& Painter::Rectangle(double x, double y, double cx, double cy)
{
Move(x, y);
Line(x + cx, y);
Line(x + cx, y + cy);
Line(x, y + cy);
Close();
return *this;
}
END_UPP_NAMESPACE

View file

@ -21,6 +21,8 @@ struct Xform2D {
static Xform2D Scale(double scale);
static Xform2D Rotation(double fi);
static Xform2D Sheer(double fi);
Xform2D();
};
Xform2D operator*(const Xform2D& a, const Xform2D& b);
@ -69,8 +71,26 @@ protected:
virtual void CloseOp() = 0;
virtual void FillOp(const RGBA& color) = 0;
virtual void FillOp(const Image& image, const Xform2D& transsrc, dword flags) = 0;
virtual void FillOp(const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2,
int style) = 0;
virtual void FillOp(const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style) = 0;
virtual void StrokeOp(double width, const RGBA& rgba) = 0;
virtual void StrokeOp(double width, const Image& image, const Xform2D& transsrc,
dword flags) = 0;
virtual void StrokeOp(double width, const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2,
int style) = 0;
virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style) = 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 ColorStopOp(double pos, const RGBA& color) = 0;
virtual void ClearStopsOp() = 0;
@ -142,8 +162,47 @@ public:
Painter& Path(const char *path);
Painter& Fill(const RGBA& color);
Painter& Fill(const Image& image, const Xform2D& transsrc = Xform2D::Identity(), dword flags = 0);
Painter& Fill(const Image& image, Pointf p1, Pointf p2, dword flags = 0);
Painter& Fill(const Image& image, double x1, double y1, double x2, double y2,
dword flags = 0);
Painter& Fill(const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(double x1, double y1, const RGBA& color1,
double x2, double y2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(double fx, double fy, const RGBA& color1,
double cx, double cy, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(const Pointf& c, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(double x, double y, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, const RGBA& color);
Painter& Stroke(double width, const Image& image, const Xform2D& transsrc, dword flags = 0);
Painter& Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2,
dword flags = 0);
Painter& Stroke(double width, const Image& image, double x1, double y1, double x2, double y2,
dword flags = 0);
Painter& Stroke(double width, const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, double x1, double y1, const RGBA& color1,
double x2, double y2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, double fx, double fy, const RGBA& color1,
double cx, double cy, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, const Pointf& c, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, double x, double y, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
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);
Painter& Text(double x, double y, const String& s, Font fnt, double *dx = NULL);
Painter& Text(double x, double y, const char *text, Font fnt, int n = -1, double *dx = NULL);
void Begin();
void End();
@ -164,6 +223,8 @@ public:
Painter& Rotate(double a);
Painter& Scale(double scalex, double scaley);
Painter& Scale(double scale);
Painter& Rectangle(double x, double y, double cx, double cy);
};
#include "Painter.hpp"

View file

@ -60,6 +60,27 @@ Painter& Painter::Fill(const RGBA& color)
return *this;
}
inline
Painter& Painter::Fill(const Image& image, const Xform2D& transsrc, dword flags)
{
FillOp(image, transsrc, flags);
return *this;
}
inline
Painter& Painter::Fill(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
FillOp(p1, color1, p2, color2, style);
return *this;
}
inline
Painter& Painter::Fill(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
FillOp(f, color1, c, r, color2, style);
return *this;
}
inline
Painter& Painter::Stroke(double width, const RGBA& color)
{
@ -67,6 +88,27 @@ Painter& Painter::Stroke(double width, const RGBA& color)
return *this;
}
inline
Painter& Painter::Stroke(double width, const Image& image, const Xform2D& transsrc, dword flags)
{
StrokeOp(width, image, transsrc, flags);
return *this;
}
inline
Painter& Painter::Stroke(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
StrokeOp(width, p1, color1, p2, color2, style);
return *this;
}
inline
Painter& Painter::Stroke(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
StrokeOp(width, f, color1, c, r, color2, style);
return *this;
}
inline Painter& Painter::ColorStop(double pos, const RGBA& color)
{
ColorStopOp(pos, color);

View file

@ -1,5 +1,3 @@
optimize_speed;
uses
Core,
CtrlLib;
@ -9,6 +7,9 @@ file
Painter.hpp,
Painter.cpp,
PainterPath.cpp,
FontWin32.cpp,
FontX11.cpp,
Text.cpp,
BufferPainter.h,
Math.cpp,
Xform2D.cpp,
@ -16,14 +17,18 @@ file
Stroker.cpp,
Dasher.cpp,
Transformer.cpp,
Rasterizer.cpp,
RasterizerClip.cpp,
Interpolator.cpp optimize_speed,
Rasterizer.cpp optimize_speed,
RasterizerClip.cpp optimize_speed,
ScanLineFiller.cpp,
SolidFiller.cpp,
SolidFiller.cpp optimize_speed,
SolidFillerMask.cpp,
Path.cpp,
Path.cpp optimize_speed,
Context.cpp,
Render.cpp;
Render.cpp optimize_speed,
Image.cpp optimize_speed,
Gradient.cpp optimize_speed,
RadialGradient.cpp optimize_speed;
mainconfig
"" = "GUI";

View file

@ -0,0 +1,219 @@
#include "Painter.h"
NAMESPACE_UPP
uint16 g_sqrt_table[1024] =
{
0,
2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444,
8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585,
11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890,
14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864,
15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618,
17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212,
19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684,
20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058,
22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351,
23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576,
24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743,
25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859,
26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931,
28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963,
29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960,
30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924,
30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859,
31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768,
32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652,
33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514,
34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354,
35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175,
36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978,
37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763,
37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533,
38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287,
39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028,
40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755,
40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469,
41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171,
42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861,
42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541,
43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210,
44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869,
44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519,
45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160,
46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791,
46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415,
47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030,
48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637,
48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237,
49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830,
49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416,
50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995,
51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567,
51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134,
52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694,
52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248,
53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797,
53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340,
54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877,
54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410,
55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937,
55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459,
56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977,
57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490,
57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999,
58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503,
58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002,
59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498,
59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989,
60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477,
60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960,
60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440,
61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916,
61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388,
62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857,
62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323,
63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785,
63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243,
64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699,
64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151,
65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504
};
int8 g_elder_bit_table[256] = //---------g_elder_bit_table
{
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
unsigned fastint_sqrt(unsigned val)
{
unsigned t = val;
int bit=0;
unsigned shift = 11;
bit = t >> 24;
if(bit)
bit = g_elder_bit_table[bit] + 24;
else {
bit = (t >> 16) & 0xFF;
if(bit)
bit = g_elder_bit_table[bit] + 16;
else {
bit = (t >> 8) & 0xFF;
if(bit)
bit = g_elder_bit_table[bit] + 8;
else
bit = g_elder_bit_table[t];
}
}
bit -= 9;
if(bit > 0) {
bit = (bit >> 1) + (bit & 1);
shift -= bit;
val >>= (bit << 1);
}
return g_sqrt_table[val] >> shift;
}
struct PainterRadialSpan : SpanSource {
LinearInterpolator interpolator;
int cx, cy, r, fx, fy;
int style;
int alpha;
RGBA gradient[2048];
bool focus;
double C;
void prepare() {}
void Set(int _x, int _y, int _r, int _fx, int _fy)
{
cx = _x;
cy = _y;
r = _r;
fx = _fx;
fy = _fy;
focus = cx != fx || cy != fy;
if(focus) {
fx -= cx;
fy -= cy;
double fx2 = double(fx) * double(fx);
double fy2 = double(fy) * double(fy);
C = fx * fx + fy * fy - r * r;
}
else {//WRONG!
cx <<= 6;
cy <<= 6;
r <<= 6;
}
}
void Get(RGBA *_span, int x, int y, unsigned len)
{
if(r <= 0)
return;
interpolator.Begin(x, y, len);
RGBA *span = (RGBA *)_span;
while(len--) {
interpolator.Get(x, y);
int h;
if(focus) {
const double q256 = 1 / 256.0;
double dx = q256 * x - cx - fx;
double dy = q256 * y - cy - fy;
if(dx == 0 && dy == 0)
h = 0;
else {
double A = dx * dx + dy * dy;
double b = (fx * dx + fy * dy);
double t = (sqrt(b * b - A * C) - b) / (A);
h = t >= 0.001 ? int(2047 / t) : 2047;
}
}
else {
x >>= 2;
y >>= 2;
int dc = Upp::fastint_sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
h = 2047 * dc / r;
}
if(style == GRADIENT_REPEAT)
h = h & 2047;
else
if(style == GRADIENT_REFLECT)
h = (h & 2048) ? (2047 - h & 2047) : (h & 2047);
else
h = minmax(h, 0, 2047);
*span++ = gradient[h];
}
}
};
void BufferPainter::RenderRadial(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style)
{
PainterRadialSpan sg;
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);
RenderPath(width, &sg, RGBAZero());
}
void BufferPainter::FillOp(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
RenderRadial(-1, f, color1, c, r, color2, style);
}
void BufferPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
RenderRadial(width, f, color1, c, r, color2, style);
}
END_UPP_NAMESPACE

View file

@ -30,6 +30,7 @@ Rasterizer::Rasterizer(int cx, int cy)
sz.cy = cy;
cell.Alloc(sz.cy + 1);
cliprect = Sizef(sz);
Init();
Reset();
}

View file

@ -4,14 +4,9 @@
NAMESPACE_UPP
inline int Cv(double x)
{
return int(x * 256 + 0.5);
}
void Rasterizer::CvLine(double x1, double y1, double x2, double y2)
{
LineRaw(Cv(x1), Cv(y1), Cv(x2), Cv(y2));
LineRaw(Q8(x1), Q8(y1), Q8(x2), Q8(y2));
}
void Rasterizer::LineClip(double x1, double y1, double x2, double y2)

View file

@ -7,19 +7,37 @@ void BufferPainter::ClearOp(const RGBA& color)
UPP::Fill(~ib, color, ib.GetLength());
}
void BufferPainter::RenderPath(LinearPathFilter *first_filter,
LinearPathFilter *last_filter, const RGBA& color, bool evenodd)
void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
{
if(width == 0)
return;
Transformer trans(pathattr.mtx);
trans.target = &rasterizer;
LinearPathConsumer *g;
if(first_filter) {
last_filter->target = &trans;
g = first_filter;
Stroker stroker;
Dasher dasher;
bool evenodd = pathattr.evenodd;
if(width > 0) {
stroker.Init(width, pathattr.miter_limit, pathattr.tolerance, pathattr.cap, pathattr.join);
stroker.target = &trans;
if(pathattr.dash.GetCount()) {
dasher.Init(pathattr.dash, pathattr.dash_start);
dasher.target = &stroker;
g = &dasher;
}
else
g = &stroker;
evenodd = false;
}
else
else {
Close();
g = &trans;
}
byte *data = path.data;
int opacity = int(256 * pathattr.opacity);
RGBA c;
if(!ss)
c = Mul8(color, opacity);
Pointf pos = Pointf(0, 0);
{
PAINTER_TIMING("Pipeline");
@ -59,27 +77,25 @@ void BufferPainter::RenderPath(LinearPathFilter *first_filter,
}
}
g->End();
Render(ib, rasterizer, color, evenodd);
if(ss) {
if(!span)
span.Alloc(ib.GetWidth() + 1);
Render(ib, rasterizer, ss, span, opacity, evenodd);
}
else
Render(ib, rasterizer, c, evenodd);
rasterizer.Reset();
current = Null;
}
void BufferPainter::FillOp(const RGBA& color)
{
Close();
RenderPath(NULL, NULL, color, pathattr.evenodd);
RenderPath(-1, NULL, color);
}
void BufferPainter::StrokeOp(double width, const RGBA& color)
{
Stroker stroker(width, pathattr.miter_limit, pathattr.tolerance, pathattr.cap, pathattr.join);
if(pathattr.dash.GetCount()) {
Dasher dasher(pathattr.dash, pathattr.dash_start);
dasher.target = &stroker;
RenderPath(&dasher, &stroker, color, false);
}
else
RenderPath(&stroker, &stroker, color, false);
RenderPath(width, NULL, color);
}
END_UPP_NAMESPACE

View file

@ -70,20 +70,41 @@ void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd)
}
struct SpanFiller : Rasterizer::Target {
RGBA *t;
RGBA *t;
const RGBA *s;
int y;
RGBA *buffer;
SpanSource *ss;
int alpha;
void Start(int minx, int maxx) { t += minx; }
void Render(int val) { AlphaBlendCover8(*t++, *s++, val); }
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;
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;
return;
}
const RGBA *e = t + len;
if(alpha != 256)
val = alpha * val >> 8;
if(val == 256)
while(t < e) {
if(s->a == 255)
@ -96,13 +117,16 @@ void SpanFiller::Render(int val, int len)
AlphaBlendCover8(*t++, *s++, val);
}
void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd)
void Render(ImageBuffer& ib, Rasterizer& r, SpanSource *s, RGBA *buffer, int alpha, bool evenodd)
{
Size sz = ib.GetSize();
SolidFiller f;
f.c = color;
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();

View file

@ -4,10 +4,10 @@
NAMESPACE_UPP
Stroker::Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin)
: linecap(linecap),
linejoin(linejoin)
void Stroker::Init(double width, double miterlimit, double tolerance, int _linecap, int _linejoin)
{
linecap = _linecap;
linejoin = _linejoin;
w2 = width / 2;
qmiter = miterlimit * w2;
qmiter *= qmiter;

51
uppdev/Painter/Text.cpp Normal file
View file

@ -0,0 +1,51 @@
#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);
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

@ -24,6 +24,12 @@ bool Xform2D::IsRegular() const
return abs(d.x - d.y) < 1e-10 * abs(max(d.x, d.y));
}
Xform2D::Xform2D()
{
x.x = y.y = 1;
x.y = y.x = t.x = t.y = 0;
}
Xform2D operator*(const Xform2D& a, const Xform2D& b)
{
Xform2D r;
@ -40,7 +46,6 @@ Xform2D Xform2D::Translation(double x, double y)
{
Xform2D m;
m.x.x = m.y.y = 1;
m.x.y = m.y.x = 0;
m.t = Pointf(x, y);
return m;
}
@ -50,7 +55,6 @@ Xform2D Xform2D::Scale(double sx, double sy)
Xform2D m;
m.x.x = sx;
m.y.y = sy;
m.x.y = m.y.x = m.t.x = m.t.y = 0;
return m;
}
@ -76,7 +80,6 @@ Xform2D Xform2D::Sheer(double fi)
{
Xform2D m;
m.x.x = m.y.y = 1;
m.y.x = m.t.x = m.t.y = 0;
m.x.y = atan(fi);
return m;
}
@ -85,7 +88,6 @@ Xform2D Xform2D::Identity()
{
Xform2D m;
m.x.x = m.y.y = 1;
m.x.y = m.y.x = m.t.x = m.t.y = 0;
return m;
}
@ -100,8 +102,8 @@ Xform2D Inverse(const Xform2D& m)
double det = Determinant(m);
r.x = Pointf(m.y.y, -m.x.y) / det;
r.y = Pointf(-m.y.x, m.x.x) / det;
r.t.x = -m.t.x * m.x.x - m.t.y * m.x.y;
r.t.y = -m.t.x * m.y.x - m.t.y * m.y.y;
r.t.x = -m.t.x * r.x.x - m.t.y * r.x.y;
r.t.y = -m.t.x * r.y.x - m.t.y * r.y.y;
return r;
}

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void GradientStop(Painter& sw)
{
sw.Rectangle(20.5, 20.5, 500, 100)
@ -15,5 +13,3 @@ void GradientStop(Painter& sw)
INITBLOCK {
RegisterExample("Gradient stops", GradientStop);
}
#endif

View file

@ -3,6 +3,14 @@
void Dash(Painter& sw)
{
sw.Move(50, 50).Line(400, 200).Dash("2").Stroke(5, Blue());
sw.Translate(0, 10);
sw.Move(50, 50).Line(400, 200).Dash("10 5").Stroke(5, Blue());
sw.Translate(0, 10);
sw.Move(50, 50).Line(400, 200).Dash("10 5 5 5").Stroke(5, Blue());
sw.Translate(0, 10);
sw.Move(50, 50).Line(400, 200).Dash("1").Stroke(5, Blue());
sw.Translate(0, 10);
sw.Move(50, 50).Line(400, 200).Dash("1 2 3 4 5").Stroke(5, Blue());
}
INITBLOCK {

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void FillGradient(Painter& sw)
{
sw.Rectangle(10, 10, 1000, 600)
@ -28,5 +26,3 @@ INITBLOCK {
RegisterExample("Linear gradient - REFLECT", FillGradientReflect);
RegisterExample("Linear gradient - REPEAT", FillGradientRepeat);
}
#endif

View file

@ -1,19 +1,30 @@
#include "Examples.h"
#if 0
void ImageExact(Painter& sw)
{
sw.Rectangle(10, 10, 1000, 600)
// .Fill(TestImg::test(), 200, 100, 300, 300) _DBG_
.Fill(TestImg::test(), 100, 100, 500, 100)
.Stroke(2, Black());
}
void ImageExactFast(Painter& sw)
{
sw.Rectangle(10, 10, 1000, 600)
.Fill(TestImg::test(), 100, 100, 500, 100, FILL_FAST)
.Stroke(2, Black());
/*
int cx = 400;
for(int l = 0; l < 5; l++) {
sw.Translate(cx, 0);
cx /= 2;
sw.Rectangle(10, 10, 1000, 600)
.Fill(MakeMipMap(TestImg::test(), l), 100, 100, 100 + cx, 100, FILL_FAST);
}*/
}
void ImageReflect(Painter& sw)
{
sw.Rectangle(10, 10, 1000, 600)
// .Fill(TestImg::test(), 200, 100, 300, 300, GRADIENT_REFLECT) _DBG_
.Fill(TestImg::test(), 100, 100, 500, 100, FILL_REFLECT)
.Stroke(2, Black());
}
@ -41,10 +52,9 @@ void ImageRepeat(Painter& sw)
INITBLOCK {
RegisterExample("Image fill exact", ImageExact);
RegisterExample("Image fill exact fast", ImageExactFast);
RegisterExample("Image fill reflect", ImageReflect);
RegisterExample("Image fill pad", ImagePad);
RegisterExample("Image fill repeat", ImageRepeat);
RegisterExample("Image vpad&hreflect", ImageVPadHReflect);
}
#endif

View file

@ -189,7 +189,6 @@ void PaintLion(Painter& sw)
}
}
/*
void Demo(Painter& sw)
{
PaintLion(sw);
@ -200,7 +199,6 @@ void Demo(Painter& sw)
.Fill(TestImg::test(), 0, 400, 500, 400, FILL_REFLECT)
.Stroke(5, 0, 500, Blue(), tsz.cx, 500, LtRed())
.Stroke(1, White());
for(int i = 0; i < 10; i++) {
sw.Begin();
sw.Opacity(0.5);
@ -211,9 +209,8 @@ void Demo(Painter& sw)
sw.End();
}
}
*/
INITBLOCK {
RegisterExample("Lion", PaintLion);
// RegisterExample("U++ Painter", Demo);
RegisterExample("U++ Painter", Demo);
}

View file

@ -1,4 +1,4 @@
description "Antialiased renderer class, Painter, examples";
description "Antialiased renderer class, Painter, examples, version 2.0";
uses
CtrlLib,

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void Path(Painter& sw)
{
sw.Translate(52, 52);
@ -19,5 +17,3 @@ void Path(Painter& sw)
INITBLOCK {
RegisterExample("Path example", Path);
}
#endif

View file

@ -9,11 +9,9 @@ void DoRect(Painter &sw, double size, bool image)
sw.Line(0, size);
sw.Line(size, size);
sw.Line(size, 0);
#if 0
if(image)
sw.Fill(TestImg::test(), 0, 0, size, 0);
else
#endif
sw.Fill(Blue());
sw.Begin();
@ -38,8 +36,6 @@ void PythagorasTree(Painter& sw)
sw.End();
}
#if 0
void PythagorasTreeImage(Painter& sw)
{
sw.Begin();
@ -48,9 +44,8 @@ void PythagorasTreeImage(Painter& sw)
DoRect(sw, 160, true);
sw.End();
}
#endif
INITBLOCK {
RegisterExample("Pythagoras tree", PythagorasTree);
// RegisterExample("Pythagoras tree image", PythagorasTreeImage);
RegisterExample("Pythagoras tree image", PythagorasTreeImage);
}

View file

@ -1,13 +1,13 @@
#include "Examples.h"
#if 0
void RadialFocus(Painter& sw)
{
sw.Circle(400.5, 400.5, 200)
.Fill(300, 300, White(), 400.5, 400.5, 200, LtBlue())
;
}
#endif
void RadialFocusPad(Painter& sw)
{
@ -34,10 +34,8 @@ void RadialFocusRepeat(Painter& sw)
}
INITBLOCK {
RegisterExample("Radial gradient - focus", RadialFocus);
// RegisterExample("Radial gradient - focus", RadialFocus);
RegisterExample("Radial gradient - focus - PAD", RadialFocusPad);
RegisterExample("Radial gradient - focus - REFLECT", RadialFocusReflect);
RegisterExample("Radial gradient - focus - REPEAT", RadialFocusRepeat);
}
#endif

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void PathSpiral(Painter& sw)
{
sw.Path("M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 "
@ -14,5 +12,3 @@ void PathSpiral(Painter& sw)
INITBLOCK {
RegisterExample("Path spiral", PathSpiral);
}
#endif

View file

@ -1,10 +1,8 @@
#include "Examples.h"
#if 0
void Stroke(Painter& sw)
{
const char *txt = "GRM";//ADIENT TEXT";
const char *txt = "GRM";
Font fnt = Arial(100).Bold();
Size tsz = GetTextSize(txt, fnt);
sw.Scale(3, 3);
@ -18,5 +16,3 @@ void Stroke(Painter& sw)
INITBLOCK {
RegisterExample("Stroke", Stroke);
}
#endif

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void TextFillGradient(Painter& sw)
{
const char *txt = "GRADIENT TEXT";
@ -14,5 +12,3 @@ void TextFillGradient(Painter& sw)
INITBLOCK {
RegisterExample("Filling text with linear gradient", TextFillGradient);
}
#endif

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void TextFillSolid(Painter& sw)
{
sw.Text(100, 100, "Hello world!", Roman(120).Italic().Bold())
@ -11,5 +9,3 @@ void TextFillSolid(Painter& sw)
INITBLOCK {
RegisterExample("Filling text with solid color", TextFillSolid);
}
#endif

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void TextStrokeGradient(Painter& sw)
{
const char *txt = "GRADIENT TEXT";
@ -14,5 +12,3 @@ void TextStrokeGradient(Painter& sw)
INITBLOCK {
RegisterExample("Stroking text with linear gradient", TextStrokeGradient);
}
#endif

View file

@ -2,7 +2,7 @@
void ThinPolygon(Painter& sw)
{
// sw.Translate(52, 52);
sw.Translate(52, 52);
for(int i = 0; i < 2; i++) {
sw.Move(36.000000, 142.000000);
sw.Line(480.000000, 148.000000);