Painter 2.0 developing

git-svn-id: svn://ultimatepp.org/upp/trunk@850 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-02-11 14:50:27 +00:00
parent 64ac4f9174
commit 288562a8bb
26 changed files with 422 additions and 164 deletions

View file

@ -5,13 +5,13 @@ NAMESPACE_UPP
static void sQuadratic(LinearPathConsumer& t, const Pointf& p1, const Pointf& p2, const Pointf& p3,
double qt, int lvl)
{
if(lvl < 32) {
if(lvl < 16) {
Pointf d = p3 - p1;
double q = d.x * d.x + d.y * d.y;
double q = Squared(d);
if(q > 1e-30) {
Pointf pd = p2 - p1;
double u = (pd.x * d.x + pd.y * d.y) / q;
if(u <= 0 || u >= 1 || SquareDist(u * d, d) > qt) {
if(u <= 0 || u >= 1 || SquaredDistance(u * d, pd) > qt) {
Pointf p12 = Mid(p1, p2);
Pointf p23 = Mid(p2, p3);
Pointf div = Mid(p12, p23);
@ -35,7 +35,7 @@ static void sCubic(LinearPathConsumer& t,
const Pointf& p1, const Pointf& p2, const Pointf& p3, const Pointf& p4,
double qt, int lvl)
{
if(lvl < 32) {
if(lvl < 16) {
Pointf d = p4 - p1;
double q = d.x * d.x + d.y * d.y;
if(q >= 1e-30) {
@ -44,7 +44,7 @@ static void sCubic(LinearPathConsumer& t,
double u1 = (d2.x * d.x + d2.y * d.y) / q;
double u2 = (d3.x * d.x + d3.y * d.y) / q;
if(u1 <= 0 || u1 >= 1 || u2 <= 0 || u2 >= 1 ||
SquareDist(u1 * d, d2) > qt || SquareDist(u2 * d, d3) > qt) {
SquaredDistance(u1 * d, d2) > qt || SquaredDistance(u2 * d, d3) > qt) {
Pointf p12 = Mid(p1, p2);
Pointf p23 = Mid(p2, p3);
Pointf p34 = Mid(p3, p4);
@ -69,4 +69,21 @@ void ApproximateCubic(LinearPathConsumer& t,
t.Line(p4);
}
void ApproximateArc(LinearPathConsumer& t, const Pointf& c, const Pointf& r,
double angle, double sweep, double tolerance)
{
while(angle + sweep < 0)
angle += 2000 * M_PI;
double fid = acos(1 - tolerance / max(r.x, r.y));
if(abs(sweep / fid) > 1000)
fid = sweep / 1000;
double a = angle;
double e = angle + sweep;
while(fid > 0 ? a < e : a > e) {
t.Line(Polar(a) * r + c);
a += fid;
}
t.Line(Polar(angle + sweep) * r + c);
}
END_UPP_NAMESPACE

View file

@ -1,12 +1,11 @@
double SquareDist(const Pointf& p1, const Pointf& p2);
Pointf Mid(const Pointf& a, const Pointf& b);
Pointf Ortogonal(const Pointf& p);
double SquareLength(const Pointf& p);
Pointf Orthogonal(const Pointf& p);
double Squared(const Pointf& p);
double Length(const Pointf& p);
double Bearing(const Pointf& p);
double Distance(const Pointf& p1, const Pointf& p2);
double SquareDistance(const Pointf& p1, const Pointf& p2);
Pointf PolarPointf(double a);
double SquaredDistance(const Pointf& p1, const Pointf& p2);
Pointf Polar(double a);
Pointf Polar(const Pointf& p, double r, double a);
struct LinearPathConsumer {
@ -21,6 +20,8 @@ void ApproximateQuadratic(LinearPathConsumer& t,
void ApproximateCubic(LinearPathConsumer& t,
const Pointf& x0, const Pointf& x1, const Pointf& x2, const Pointf& x,
double tolerance);
void ApproximateArc(LinearPathConsumer& t, const Pointf& p, const Pointf& r,
double angle, double sweep, double tolerance);
struct LinearPathFilter : LinearPathConsumer {
virtual void End();
@ -205,9 +206,10 @@ class LinearInterpolator {
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; }
void Set(const Xform2D& m) { xform = m; }
void Begin(int x, int y, int len);
Point Get();
};
class BufferPainter : public Painter {
@ -220,7 +222,9 @@ protected:
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);
@ -259,7 +263,7 @@ protected:
public:
enum {
MOVE, LINE, QUADRATIC, CUBIC, ARC
MOVE, LINE, QUADRATIC, CUBIC, ARC, DIV
};
struct LinearData {
Pointf p;
@ -271,8 +275,10 @@ public:
Pointf p2;
};
struct ArcData : LinearData {
double cx, cy;
double angle1, angle2;
Pointf r;
double angle, sweep;
Pointf EndPoint() const;
};
struct Path {
Vector<byte> type;

View file

@ -41,7 +41,7 @@ Image BufferPainter::GetGradient(const RGBA& color1, const RGBA& color2, const P
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(GetGradient(color1, color2, p1, p2), p1, p2,
FILL_VPAD | FILL_FAST |
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
? FILL_HREPEAT : FILL_HREFLECT));
@ -49,7 +49,7 @@ void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p
void BufferPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
Stroke(width, GetGradient(color1, color2, p1, p2), p1.x, p1.y, p2.x, p2.y,
Stroke(width, GetGradient(color1, color2, p1, p2), p1, p2,
FILL_VPAD | FILL_FAST |
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
? FILL_HREPEAT : FILL_HREFLECT));

View file

@ -132,8 +132,8 @@ struct PainterImageSpan : SpanSource {
cy = image.GetHeight();
maxx = cx - 1;
maxy = cy - 1;
ax = 6000000 / cx * cx;
ay = 6000000 / cy * cy;
ax = 6000000 / cx * cx * 2;
ay = 6000000 / cy * cy * 2;
}
RGBA Pixel(int x, int y) { return image[y][x]; }
@ -163,45 +163,43 @@ struct PainterImageSpan : SpanSource {
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;
Point h = interpolator.Get();
// h -= 128;
Point l = h >> 8;
if(hstyle == FILL_HREPEAT)
x_lr = (x_lr + ax) % cx;
l.x = (l.x + ax) % cx;
if(vstyle == FILL_VREPEAT)
y_lr = (y_lr + ay) % cy;
l.y = (l.y + ay) % cy;
if(fast) {
if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy)
*span = Pixel(x_lr, y_lr);
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy)
*span = Pixel(l.x, l.y);
else
if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy))
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
*span = RGBAZero();
else
*span = GetPixel(x_lr, y_lr);
*span = GetPixel(l.x, l.y);
}
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));
v.Set(0);
// v.Set(256 * 256 / 2);
h.x &= 255;
h.y &= 255;
Point u = -h + 256;
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy) {
v.Put(u.x * u.y, Pixel(l.x, l.y));
v.Put(h.x * u.y, Pixel(l.x + 1, l.y));
v.Put(u.x * h.y, Pixel(l.x, l.y + 1));
v.Put(h.x * h.y, Pixel(l.x + 1, l.y + 1));
}
else
if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy))
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > 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));
v.Put(u.x * u.y, GetPixel(l.x, l.y));
v.Put(h.x * u.y, GetPixel(l.x + 1, l.y));
v.Put(u.x * h.y, GetPixel(l.x, l.y + 1));
v.Put(h.x * h.y, GetPixel(l.x + 1, l.y + 1));
}
span->r = byte(v.r >> 16);
span->g = byte(v.g >> 16);

View file

@ -31,16 +31,15 @@ int LinearInterpolator::Dda2::Get()
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);
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)
Point LinearInterpolator::Get()
{
x = ddax.Get();
y = dday.Get();
return Point(ddax.Get(), dday.Get());
}
END_UPP_NAMESPACE

View file

@ -12,19 +12,19 @@ Pointf Mid(const Pointf& a, const Pointf& b)
return (a + b) / 2;
}
Pointf Ortogonal(const Pointf& p)
Pointf Orthogonal(const Pointf& p)
{
return Pointf(-p.y, p.x);
}
double SquareLength(const Pointf& p)
double Squared(const Pointf& p)
{
return p.x * p.x + p.y * p.y;
}
double Length(const Pointf& p)
{
return sqrt(SquareLength(p));
return sqrt(Squared(p));
}
double Bearing(const Pointf& p)
@ -37,19 +37,19 @@ double Distance(const Pointf& p1, const Pointf& p2)
return Length(p1 - p2);
}
double SquareDistance(const Pointf& p1, const Pointf& p2)
double SquaredDistance(const Pointf& p1, const Pointf& p2)
{
return SquareLength(p1 - p2);
return Squared(p1 - p2);
}
Pointf PolarPointf(double a)
Pointf Polar(double a)
{
return Pointf(cos(a), sin(a));
}
Pointf Polar(const Pointf& p, double r, double a)
{
return p + r * PolarPointf(a);
return p + r * Polar(a);
}
END_UPP_NAMESPACE

View file

@ -4,13 +4,13 @@ NAMESPACE_UPP
Painter& Painter::Move(const Pointf& p)
{
MoveOp(p, false);
Move(p, false);
return *this;
}
Painter& Painter::Line(const Pointf& p)
{
LineOp(p, false);
Line(p, false);
return *this;
}
@ -182,6 +182,77 @@ Painter& Painter::RelCubic(double x2, double y2, double x, double y)
return *this;
}
Painter& Painter::Arc(const Pointf& c, double rx, double ry, double angle, double sweep, bool rel)
{
return Arc(c, Pointf(rx, ry), angle, sweep, rel);
}
Painter& Painter::Arc(const Pointf& c, double r, double angle, double sweep, bool rel)
{
return Arc(c, Pointf(r, r), angle, sweep, rel);
}
Painter& Painter::Arc(double x, double y, double rx, double ry, double angle, double sweep, bool rel)
{
return Arc(Pointf(x, y), rx, ry, angle, sweep, rel);
}
Painter& Painter::Arc(double x, double y, double r, double angle, double sweep, bool rel)
{
return Arc(Pointf(x, y), r, angle, sweep, rel);
}
Painter& Painter::Arc(const Pointf& c, const Pointf& r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, false);
}
Painter& Painter::Arc(const Pointf& c, double rx, double ry, double angle, double sweep)
{
return Arc(c, rx, ry, angle, sweep, false);
}
Painter& Painter::Arc(const Pointf& c, double r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, false);
}
Painter& Painter::Arc(double x, double y, double rx, double ry, double angle, double sweep)
{
return Arc(x, y, rx, ry, angle, sweep, false);
}
Painter& Painter::Arc(double x, double y, double r, double angle, double sweep)
{
return Arc(x, y, r, angle, sweep, false);
}
Painter& Painter::RelArc(const Pointf& c, const Pointf& r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, true);
}
Painter& Painter::RelArc(const Pointf& c, double rx, double ry, double angle, double sweep)
{
return Arc(c, rx, ry, angle, sweep, true);
}
Painter& Painter::RelArc(const Pointf& c, double r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, true);
}
Painter& Painter::RelArc(double x, double y, double rx, double ry, double angle, double sweep)
{
return Arc(x, y, rx, ry, angle, sweep, true);
}
Painter& Painter::RelArc(double x, double y, double r, double angle, double sweep)
{
return Arc(x, y, r, angle, sweep, true);
}
Xform2D GetLineSzXform(const Pointf& p1, const Pointf& p2, const Sizef& sz)
{
Xform2D m = Xform2D::Scale(Distance(p1, p2) / sz.cx);
@ -293,12 +364,17 @@ Painter& Painter::Dash(const char *dash, double start)
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;
return Move(x, y).RelLine(cx, 0).RelLine(0, cy).RelLine(-cx, 0).Close();
}
Painter& Painter::Ellipse(double x, double y, double rx, double ry)
{
return Move(x + rx, y).Arc(x, y, rx, ry, 0, 2 * M_PI).Close();
}
Painter& Painter::Circle(double x, double y, double r)
{
return Ellipse(x, y, r, r);
}
END_UPP_NAMESPACE

View file

@ -68,7 +68,9 @@ protected:
virtual void QuadraticOp(const Pointf& p, bool rel) = 0;
virtual void CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) = 0;
virtual void CubicOp(const Pointf& p2, const Pointf& p, bool rel) = 0;
virtual void ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel) = 0;
virtual void CloseOp() = 0;
virtual void DivOp() = 0;
virtual void FillOp(const RGBA& color) = 0;
virtual void FillOp(const Image& image, const Xform2D& transsrc, dword flags) = 0;
@ -115,48 +117,63 @@ public:
void Clear(const RGBA& color);
Painter& Move(const Pointf& p, bool rel);
Painter& Line(const Pointf& p, bool rel);
Painter& Quadratic(const Pointf& p1, const Pointf& p, bool rel);
Painter& Quadratic(const Pointf& p, bool rel);
Painter& Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel);
Painter& Cubic(const Pointf& p2, const Pointf& p, bool rel);
Painter& Move(const Pointf& p);
Painter& Move(double x, double y, bool rel);
Painter& Move(double x, double y);
Painter& RelMove(const Pointf& p);
Painter& RelMove(double x, double y);
Painter& Line(const Pointf& p, bool rel);
Painter& Line(const Pointf& p);
Painter& Line(double x, double y, bool rel);
Painter& Line(double x, double y);
Painter& RelLine(const Pointf& p);
Painter& RelLine(double x, double y);
Painter& Quadratic(const Pointf& p1, const Pointf& p, bool rel);
Painter& Quadratic(const Pointf& p1, const Pointf& p);
Painter& Quadratic(const Pointf& p);
Painter& Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p);
Painter& Cubic(const Pointf& p2, const Pointf& p);
Painter& RelMove(const Pointf& p);
Painter& RelLine(const Pointf& p);
Painter& RelQuadratic(const Pointf& p1, const Pointf& p);
Painter& RelQuadratic(const Pointf& p);
Painter& RelCubic(const Pointf& p1, const Pointf& p2, const Pointf& p);
Painter& RelCubic(const Pointf& p2, const Pointf& p);
Painter& Move(double x, double y, bool rel);
Painter& Line(double x, double y, bool rel);
Painter& Quadratic(double x1, double y1, double x, double y, bool rel);
Painter& Quadratic(double x, double y, bool rel);
Painter& Cubic(double x1, double y1, double x2, double y2, double x, double y, bool rel);
Painter& Cubic(double x2, double y2, double x, double y, bool rel);
Painter& Move(double x, double y);
Painter& Line(double x, double y);
Painter& Quadratic(double x1, double y1, double x, double y, bool rel);
Painter& Quadratic(const Pointf& p, bool rel);
Painter& Quadratic(double x1, double y1, double x, double y);
Painter& Quadratic(double x, double y);
Painter& Cubic(double x1, double y1, double x2, double y2, double x, double y);
Painter& Cubic(double x2, double y2, double x, double y);
Painter& RelMove(double x, double y);
Painter& RelLine(double x, double y);
Painter& RelQuadratic(const Pointf& p1, const Pointf& p);
Painter& RelQuadratic(double x1, double y1, double x, double y);
Painter& RelQuadratic(double x, double y);
Painter& RelQuadratic(const Pointf& p);
Painter& Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel);
Painter& Cubic(const Pointf& p2, const Pointf& p, bool rel);
Painter& Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p);
Painter& Cubic(const Pointf& p2, const Pointf& p);
Painter& Cubic(double x1, double y1, double x2, double y2, double x, double y, bool rel);
Painter& Cubic(double x2, double y2, double x, double y, bool rel);
Painter& Cubic(double x1, double y1, double x2, double y2, double x, double y);
Painter& Cubic(double x2, double y2, double x, double y);
Painter& RelCubic(const Pointf& p1, const Pointf& p2, const Pointf& p);
Painter& RelCubic(const Pointf& p2, const Pointf& p);
Painter& RelCubic(double x1, double y1, double x2, double y2, double x, double y);
Painter& RelCubic(double x2, double y2, double x, double y);
Painter& Arc(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel);
Painter& Arc(const Pointf& c, double rx, double ry, double angle, double sweep, bool rel);
Painter& Arc(const Pointf& c, double r, double angle, double sweep, bool rel);
Painter& Arc(double x, double y, double rx, double ry, double angle, double sweep, bool rel);
Painter& Arc(double x, double y, double r, double angle, double sweep, bool rel);
Painter& Arc(const Pointf& c, const Pointf& r, double angle, double sweep);
Painter& Arc(const Pointf& c, double rx, double ry, double angle, double sweep);
Painter& Arc(const Pointf& c, double r, double angle, double sweep);
Painter& Arc(double x, double y, double rx, double ry, double angle, double sweep);
Painter& Arc(double x, double y, double r, double angle, double sweep);
Painter& RelArc(const Pointf& c, const Pointf& r, double angle, double sweep);
Painter& RelArc(const Pointf& c, double rx, double ry, double angle, double sweep);
Painter& RelArc(const Pointf& c, double r, double angle, double sweep);
Painter& RelArc(double x, double y, double rx, double ry, double angle, double sweep);
Painter& RelArc(double x, double y, double r, double angle, double sweep);
Painter& Close();
Painter& Div();
Painter& Path(CParser& p);
Painter& Path(const char *path);
@ -213,7 +230,7 @@ public:
Painter& LineCap(int linecap);
Painter& LineJoin(int linejoin);
Painter& MiterLimit(double l);
Painter& EvenOdd(bool evenodd);
Painter& EvenOdd(bool evenodd = true);
Painter& Dash(const Vector<double>& dash, double start);
Painter& Dash(const char *dash, double start = 0);
Painter& NoAA(bool noaa);
@ -225,6 +242,8 @@ public:
Painter& Scale(double scale);
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"

View file

@ -46,6 +46,13 @@ Painter& Painter::Cubic(const Pointf& p2, const Pointf& p, bool rel)
return *this;
}
inline
Painter& Painter::Arc(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel)
{
ArcOp(c, r, angle, sweep, rel);
return *this;
}
inline
Painter& Painter::Close()
{
@ -53,6 +60,13 @@ Painter& Painter::Close()
return *this;
}
inline
Painter& Painter::Div()
{
DivOp();
return *this;
}
inline
Painter& Painter::Fill(const RGBA& color)
{

View file

@ -7,8 +7,8 @@ file
Painter.hpp,
Painter.cpp,
PainterPath.cpp,
FontWin32.cpp,
FontX11.cpp,
FontWin32.cpp optimize_speed,
FontX11.cpp optimize_speed,
Text.cpp,
BufferPainter.h,
Math.cpp,

View file

@ -13,8 +13,8 @@ void BufferPainter::ClearPath()
Pointf BufferPainter::PathPoint(const Pointf& p, bool rel)
{
Pointf r;
r.x = IsNull(p.x) ? current.x : rel ? p.x + current.x : r.x;
r.y = IsNull(p.y) ? current.y : rel ? p.y + current.y : r.y;
r.x = IsNull(p.x) ? current.x : rel ? p.x + current.x : p.x;
r.y = IsNull(p.y) ? current.y : rel ? p.y + current.y : p.y;
if(IsNull(current)) {
ClearPath();
pathrect.left = pathrect.right = r.x;
@ -27,7 +27,7 @@ Pointf BufferPainter::PathPoint(const Pointf& p, bool rel)
pathrect.right = max(pathrect.right, r.x);
pathrect.bottom = max(pathrect.bottom, r.y);
}
return p;
return r;
}
Pointf BufferPainter::EndPoint(const Pointf& p, bool rel)
@ -87,6 +87,24 @@ void BufferPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel)
CubicOp(2 * current - ccontrol, p2, p, rel);
}
Pointf BufferPainter::ArcData::EndPoint() const
{
return r * Polar(angle + sweep) + p;
}
void BufferPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel)
{
DoMove0();
ArcData& m = PathAdd<ArcData>(ARC);
m.p = PathPoint(c, rel);
m.r = r;
m.angle = angle;
m.sweep = sweep;
PathPoint(c + r, rel);
PathPoint(c - r, rel);
current = m.EndPoint();
}
void BufferPainter::CloseOp()
{
if(!IsNull(move) && current != move) {
@ -95,4 +113,10 @@ void BufferPainter::CloseOp()
}
}
void BufferPainter::DivOp()
{
CloseOp();
path.type.Add(DIV);
}
END_UPP_NAMESPACE

View file

@ -162,12 +162,12 @@ struct PainterRadialSpan : SpanSource {
interpolator.Begin(x, y, len);
RGBA *span = (RGBA *)_span;
while(len--) {
interpolator.Get(x, y);
Point p = interpolator.Get();
int h;
if(focus) {
const double q256 = 1 / 256.0;
double dx = q256 * x - cx - fx;
double dy = q256 * y - cy - fy;
double dx = q256 * p.x - cx - fx;
double dy = q256 * p.y - cy - fy;
if(dx == 0 && dy == 0)
h = 0;
else {
@ -178,9 +178,8 @@ struct PainterRadialSpan : SpanSource {
}
}
else {
x >>= 2;
y >>= 2;
int dc = Upp::fastint_sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
p >>= 2;
int dc = Upp::fastint_sqrt((p.x - cx) * (p.x - cx) + (p.y - cy) * (p.y - cy));
h = 2047 * dc / r;
}
if(style == GRADIENT_REPEAT)

View file

@ -39,52 +39,62 @@ void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
if(!ss)
c = Mul8(color, opacity);
Pointf pos = Pointf(0, 0);
{
PAINTER_TIMING("Pipeline");
for(int i = 0; i < path.type.GetCount(); i++) {
switch(path.type[i]) {
case MOVE: {
const LinearData *d = (LinearData *)data;
data += sizeof(LinearData);
g->Move(pos = d->p);
int i = 0;
for(;;) {
if(i >= path.type.GetCount() || path.type[i] == DIV) {
g->End();
if(ss) {
if(!span)
span.Alloc(ib.GetWidth() + 1);
Render(ib, rasterizer, ss, span, opacity, evenodd);
}
else
Render(ib, rasterizer, c, evenodd);
rasterizer.Reset();
if(i >= path.type.GetCount())
break;
}
case LINE: {
const LinearData *d = (LinearData *)data;
data += sizeof(LinearData);
g->Line(pos = d->p);
break;
}
case QUADRATIC: {
const QuadraticData *d = (QuadraticData *)data;
data += sizeof(QuadraticData);
ApproximateQuadratic(*g, pos, d->p1, d->p, pathattr.tolerance);
pos = d->p;
break;
}
case CUBIC: {
const CubicData *d = (CubicData *)data;
data += sizeof(CubicData);
ApproximateCubic(*g, pos, d->p1, d->p2, d->p, pathattr.tolerance);
pos = d->p;
break;
}
case ARC:
default:
NEVER();
return;
}
}
else
switch(path.type[i]) {
case MOVE: {
const LinearData *d = (LinearData *)data;
data += sizeof(LinearData);
g->Move(pos = d->p);
break;
}
case LINE: {
const LinearData *d = (LinearData *)data;
data += sizeof(LinearData);
g->Line(pos = d->p);
break;
}
case QUADRATIC: {
const QuadraticData *d = (QuadraticData *)data;
data += sizeof(QuadraticData);
ApproximateQuadratic(*g, pos, d->p1, d->p, pathattr.tolerance);
pos = d->p;
break;
}
case CUBIC: {
const CubicData *d = (CubicData *)data;
data += sizeof(CubicData);
ApproximateCubic(*g, pos, d->p1, d->p2, d->p, pathattr.tolerance);
pos = d->p;
break;
}
case ARC: {
const ArcData *d = (ArcData *)data;
data += sizeof(ArcData);
ApproximateArc(*g, d->p, d->r, d->angle, d->sweep, pathattr.tolerance);
pos = d->EndPoint();
break;
}
default:
NEVER();
return;
}
i++;
}
g->End();
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;
}

View file

@ -100,6 +100,7 @@ void SpanFiller::Render(int val, int len)
{
if(val == 0) {
t += len;
s += len;
return;
}
const RGBA *e = t + len;

View file

@ -49,7 +49,7 @@ void Stroker::Line(const Pointf& p3)
return;
p2 = p3;
v1 = v;
o1 = Ortogonal(v1) * w2 / l;
o1 = Orthogonal(v1) * w2 / l;
a1 = p1 + o1;
b1 = p1 - o1;
if(IsNull(p0)) {
@ -66,7 +66,7 @@ void Stroker::Line(const Pointf& p3)
double l = Length(v2);
if(l < 1e-30)
return;
Pointf o2 = Ortogonal(v2) * w2 / l;
Pointf o2 = Orthogonal(v2) * w2 / l;
Pointf a2 = p2 + o2;
Pointf b2 = p2 - o2;
@ -74,7 +74,7 @@ void Stroker::Line(const Pointf& p3)
if(d > 1e-30) {
Pointf ts = a1 + v1 * (v2.y * (a1.x - a2.x) - v2.x * (a1.y - a2.y)) / d;
PutMove(a1);
if(linejoin != LINEJOIN_MITER || SquareDistance(ts, p2) > qmiter) {
if(linejoin != LINEJOIN_MITER || SquaredDistance(ts, p2) > qmiter) {
PutLine(a1 + v1);
if(linejoin == LINEJOIN_ROUND)
Round(p2, o1, o2, w2);
@ -91,7 +91,7 @@ void Stroker::Line(const Pointf& p3)
if(d < -1e-30) {
Pointf ts = b2 + v2 * (v1.y * (a2.x - a1.x) - v1.x * (a2.y - a1.y)) / d;
PutMove(b2);
if(linejoin != LINEJOIN_MITER || SquareDistance(ts, p2) > qmiter) {
if(linejoin != LINEJOIN_MITER || SquaredDistance(ts, p2) > qmiter) {
if(linejoin == LINEJOIN_ROUND)
Round(p2, -o2, -o1, w2);
PutLine(b1 + v1);
@ -127,7 +127,7 @@ void Stroker::Cap(const Pointf& p, const Pointf& v, const Pointf& o,
{
PutMove(a);
if(linecap == LINECAP_SQUARE) {
Pointf nv = Ortogonal(o);
Pointf nv = Orthogonal(o);
PutLine(a + nv);
PutLine(b + nv);
}

View file

@ -10,6 +10,7 @@ void Painter::TextOp(double x, double y, const wchar *text, Font fnt, int n, dou
while(n) {
int ch = *text++;
Character(x, y, ch, fnt);
Div();
if(dx)
x += *dx++;
else

View file

@ -69,8 +69,8 @@ Xform2D Xform2D::Rotation(double fi)
double sinf = sin(fi);
Xform2D m;
m.x.x = cosf;
m.x.y = sinf;
m.y.x = -sinf;
m.x.y = -sinf;
m.y.x = sinf;
m.y.y = cosf;
m.t.x = m.t.y = 0;
return m;

View file

@ -0,0 +1,11 @@
#include "Examples.h"
void Arc(Painter& sw)
{
sw.Move(400, 200).Arc(400, 200, 200, 100, 0.0, M_PI).Stroke(4, Blue());
sw.Move(400, 400).Arc(400, 400, 100, 100, 0.0, M_PI / 3).Fill(LtCyan()).Stroke(2, Black());
}
INITBLOCK {
RegisterExample("Arc example", Arc);
}

View file

@ -0,0 +1,47 @@
#include "Examples.h"
void Big(Painter& sw)
{
int n = 0;
double sgn = 1;
for(int r = 400; r > 5; r -= 3) {
for(int i = 0; i < 400; i++) {
Pointf p = Polar(sgn * i * M_2PI / 400) * r + Pointf(400, 400);
if(i)
sw.Line(p);
else
sw.Move(p);
sw.Line(Polar(sgn * (i * M_2PI / 400 + M_2PI / 800)) * (r - 6) + Pointf(400, 400));
n += 2;
}
sw.Close();
sgn = -sgn;
}
sw.Fill(Black());
sw.Text(0, 0, "Elements: " + AsString(n), Arial(20)).Fill(Blue());
}
void BigStroke(Painter& sw)
{
int n = 0;
double r = 400;
int i = 0;
while(r > 5) {
Pointf p = Polar(i * M_2PI / 400) * r + Pointf(400, 400);
if(i)
sw.Line(p);
else
sw.Move(p);
sw.Line(Polar((i * M_2PI / 400 + M_2PI / 800)) * (r - 3) + Pointf(400, 400));
n += 2;
r = r - 0.01;
i++;
}
sw.Stroke(1, Black());
sw.Text(0, 0, "Elements: " + AsString(n), Arial(20)).Fill(Blue());
}
INITBLOCK {
RegisterExample("Really Big Polygon", Big);
RegisterExample("Really Big Stroke", BigStroke);
}

View file

@ -0,0 +1,17 @@
#include "Examples.h"
void Div(Painter& sw)
{
sw.Character(100, 100, 'O', Arial(100))
.Character(100, 150, 'O', Arial(100))
.Fill(Black());
sw.Translate(200, 0);
sw.Character(100, 100, 'O', Arial(100))
.Div()
.Character(100, 150, 'O', Arial(100))
.Fill(Black());
}
INITBLOCK {
RegisterExample("Div", Div);
}

View file

@ -43,6 +43,13 @@ void ImagePad(Painter& sw)
.Stroke(2, Black());
}
void ImagePadFast(Painter& sw)
{
sw.Rectangle(10, 10, 1000, 600)
.Fill(TestImg::test(), 100, 100, 500, 100, FILL_PAD|FILL_FAST)
.Stroke(2, Black());
}
void ImageRepeat(Painter& sw)
{
sw.Rectangle(10, 10, 1000, 600)
@ -55,6 +62,7 @@ INITBLOCK {
RegisterExample("Image fill exact fast", ImageExactFast);
RegisterExample("Image fill reflect", ImageReflect);
RegisterExample("Image fill pad", ImagePad);
RegisterExample("Image fill pad fast", ImagePadFast);
RegisterExample("Image fill repeat", ImageRepeat);
RegisterExample("Image vpad&hreflect", ImageVPadHReflect);
}

View file

@ -20,13 +20,16 @@ file
TextFillSolid.cpp,
TextFillGradient.cpp,
TextStrokeGradient.cpp,
Div.cpp,
MaskBlending.cpp,
RadialMaskBlending.cpp,
RichText.cpp,
Stroke.cpp,
Dash.cpp,
Path.cpp,
Arc.cpp,
ThinLine.cpp,
Big.cpp,
Examples.lay,
Test.iml;

View file

@ -16,13 +16,13 @@ void DoRect(Painter &sw, double size, bool image)
sw.Begin();
sw.Translate(0, size);
sw.Rotate(-M_PI/4.0);
sw.Rotate(M_PI/4.0);
DoRect(sw, size / M_SQRT2, image);
sw.End();
sw.Begin();
sw.Translate(size / 2, 1.5 * size);
sw.Rotate(M_PI/4.0);
sw.Rotate(-M_PI/4.0);
DoRect(sw, size / M_SQRT2, image);
sw.End();
}

View file

@ -1,7 +1,5 @@
#include "Examples.h"
#if 0
void Radial(Painter& sw)
{
sw.Circle(400.5, 400.5, 200)
@ -12,5 +10,3 @@ void Radial(Painter& sw)
INITBLOCK {
RegisterExample("Radial gradient", Radial);
}
#endif

View file

@ -6,7 +6,18 @@ void TextFillGradient(Painter& sw)
Font fnt = Arial(100).Bold().Italic();
Size tsz = GetTextSize(txt, fnt);
sw.Text(100, 100, txt, fnt)
.Fill(100, 100, Blue(), 100 + tsz.cx, 100 + tsz.cy, LtRed());
.Fill(100, 100, Blue(), 100 + tsz.cx, 100/* + tsz.cy*/, LtRed());
sw.Translate(0, 200);
sw.Rectangle(100, 100, tsz.cx, tsz.cy)
.Stroke(1, Blue())
.Fill(TestImg::test(), 100, 100, 100 + tsz.cx, 100 + tsz.cy);
sw.Move(100, 300).RelLine(tsz.cx + 50, 0).RelLine(-30, tsz.cy).RelLine(-tsz.cx / 2, 0)
.Fill(100, 300, Blue(), 100 + tsz.cx, 300/* + tsz.cy*/, LtRed())
// .Fill(TestImg::test(), 100, 300, 100 + tsz.cx, 300 + tsz.cy)
.Stroke(1, Blue());
/* sw.Text(100, 100, txt, fnt)
.Fill(TestImg::test(), 100, 100, 100 + tsz.cx, 100 + tsz.cy)
.Stroke(1, Black());*/
}
INITBLOCK {

View file

@ -177,6 +177,7 @@ App::App() {
ctrl.print <<= THISBACK(Print);
Reset();
LoadFromFile(*this);
Title("Painter 2.0");
}
App::~App()