From 288562a8bb0074270dd94113ea10b0036357965c Mon Sep 17 00:00:00 2001 From: cxl Date: Wed, 11 Feb 2009 14:50:27 +0000 Subject: [PATCH] Painter 2.0 developing git-svn-id: svn://ultimatepp.org/upp/trunk@850 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppdev/Painter/Approximate.cpp | 27 ++++-- uppdev/Painter/BufferPainter.h | 28 +++--- uppdev/Painter/Gradient.cpp | 4 +- uppdev/Painter/Image.cpp | 54 ++++++------ uppdev/Painter/Interpolator.cpp | 9 +- uppdev/Painter/Math.cpp | 14 +-- uppdev/Painter/Painter.cpp | 92 ++++++++++++++++++-- uppdev/Painter/Painter.h | 79 ++++++++++------- uppdev/Painter/Painter.hpp | 14 +++ uppdev/Painter/Painter.upp | 4 +- uppdev/Painter/Path.cpp | 30 ++++++- uppdev/Painter/RadialGradient.cpp | 11 ++- uppdev/Painter/Render.cpp | 96 ++++++++++++--------- uppdev/Painter/SolidFiller.cpp | 1 + uppdev/Painter/Stroker.cpp | 10 +-- uppdev/Painter/Text.cpp | 1 + uppdev/Painter/Xform2D.cpp | 4 +- uppdev/PainterExamples/Arc.cpp | 11 +++ uppdev/PainterExamples/Big.cpp | 47 ++++++++++ uppdev/PainterExamples/Div.cpp | 17 ++++ uppdev/PainterExamples/Image.cpp | 8 ++ uppdev/PainterExamples/PainterExamples.upp | 3 + uppdev/PainterExamples/Pythagoras.cpp | 4 +- uppdev/PainterExamples/Radial.cpp | 4 - uppdev/PainterExamples/TextFillGradient.cpp | 13 ++- uppdev/PainterExamples/main.cpp | 1 + 26 files changed, 422 insertions(+), 164 deletions(-) create mode 100644 uppdev/PainterExamples/Arc.cpp create mode 100644 uppdev/PainterExamples/Big.cpp create mode 100644 uppdev/PainterExamples/Div.cpp diff --git a/uppdev/Painter/Approximate.cpp b/uppdev/Painter/Approximate.cpp index 666d74fac..f7c90a435 100644 --- a/uppdev/Painter/Approximate.cpp +++ b/uppdev/Painter/Approximate.cpp @@ -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 diff --git a/uppdev/Painter/BufferPainter.h b/uppdev/Painter/BufferPainter.h index b3778ce91..5487c974e 100644 --- a/uppdev/Painter/BufferPainter.h +++ b/uppdev/Painter/BufferPainter.h @@ -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 type; diff --git a/uppdev/Painter/Gradient.cpp b/uppdev/Painter/Gradient.cpp index b7cab7c35..5b5d45b8a 100644 --- a/uppdev/Painter/Gradient.cpp +++ b/uppdev/Painter/Gradient.cpp @@ -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)); diff --git a/uppdev/Painter/Image.cpp b/uppdev/Painter/Image.cpp index 316f596d9..34f9820d3 100644 --- a/uppdev/Painter/Image.cpp +++ b/uppdev/Painter/Image.cpp @@ -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); diff --git a/uppdev/Painter/Interpolator.cpp b/uppdev/Painter/Interpolator.cpp index 161963b4f..e2e5d5090 100644 --- a/uppdev/Painter/Interpolator.cpp +++ b/uppdev/Painter/Interpolator.cpp @@ -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 diff --git a/uppdev/Painter/Math.cpp b/uppdev/Painter/Math.cpp index 0c5ad8e57..5d3c40903 100644 --- a/uppdev/Painter/Math.cpp +++ b/uppdev/Painter/Math.cpp @@ -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 diff --git a/uppdev/Painter/Painter.cpp b/uppdev/Painter/Painter.cpp index aac4fd213..c933d6815 100644 --- a/uppdev/Painter/Painter.cpp +++ b/uppdev/Painter/Painter.cpp @@ -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 diff --git a/uppdev/Painter/Painter.h b/uppdev/Painter/Painter.h index e4a8ef249..c2dedb03a 100644 --- a/uppdev/Painter/Painter.h +++ b/uppdev/Painter/Painter.h @@ -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& 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" diff --git a/uppdev/Painter/Painter.hpp b/uppdev/Painter/Painter.hpp index 2098d1133..b59d72314 100644 --- a/uppdev/Painter/Painter.hpp +++ b/uppdev/Painter/Painter.hpp @@ -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) { diff --git a/uppdev/Painter/Painter.upp b/uppdev/Painter/Painter.upp index b836df173..33619d48a 100644 --- a/uppdev/Painter/Painter.upp +++ b/uppdev/Painter/Painter.upp @@ -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, diff --git a/uppdev/Painter/Path.cpp b/uppdev/Painter/Path.cpp index 3e27f8af8..07a4d4933 100644 --- a/uppdev/Painter/Path.cpp +++ b/uppdev/Painter/Path.cpp @@ -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(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 diff --git a/uppdev/Painter/RadialGradient.cpp b/uppdev/Painter/RadialGradient.cpp index 003899d49..dbd3f09e1 100644 --- a/uppdev/Painter/RadialGradient.cpp +++ b/uppdev/Painter/RadialGradient.cpp @@ -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) diff --git a/uppdev/Painter/Render.cpp b/uppdev/Painter/Render.cpp index ee6886136..f35ca28e4 100644 --- a/uppdev/Painter/Render.cpp +++ b/uppdev/Painter/Render.cpp @@ -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; } diff --git a/uppdev/Painter/SolidFiller.cpp b/uppdev/Painter/SolidFiller.cpp index 89524c8de..03c9d2327 100644 --- a/uppdev/Painter/SolidFiller.cpp +++ b/uppdev/Painter/SolidFiller.cpp @@ -100,6 +100,7 @@ void SpanFiller::Render(int val, int len) { if(val == 0) { t += len; + s += len; return; } const RGBA *e = t + len; diff --git a/uppdev/Painter/Stroker.cpp b/uppdev/Painter/Stroker.cpp index 840306697..e7e3192c5 100644 --- a/uppdev/Painter/Stroker.cpp +++ b/uppdev/Painter/Stroker.cpp @@ -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); } diff --git a/uppdev/Painter/Text.cpp b/uppdev/Painter/Text.cpp index 4a426b7fe..7239ae405 100644 --- a/uppdev/Painter/Text.cpp +++ b/uppdev/Painter/Text.cpp @@ -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 diff --git a/uppdev/Painter/Xform2D.cpp b/uppdev/Painter/Xform2D.cpp index 5deb62e4a..d7cb2c945 100644 --- a/uppdev/Painter/Xform2D.cpp +++ b/uppdev/Painter/Xform2D.cpp @@ -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; diff --git a/uppdev/PainterExamples/Arc.cpp b/uppdev/PainterExamples/Arc.cpp new file mode 100644 index 000000000..337278696 --- /dev/null +++ b/uppdev/PainterExamples/Arc.cpp @@ -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); +} diff --git a/uppdev/PainterExamples/Big.cpp b/uppdev/PainterExamples/Big.cpp new file mode 100644 index 000000000..6e934eb1c --- /dev/null +++ b/uppdev/PainterExamples/Big.cpp @@ -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); +} diff --git a/uppdev/PainterExamples/Div.cpp b/uppdev/PainterExamples/Div.cpp new file mode 100644 index 000000000..12d5d6abb --- /dev/null +++ b/uppdev/PainterExamples/Div.cpp @@ -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); +} diff --git a/uppdev/PainterExamples/Image.cpp b/uppdev/PainterExamples/Image.cpp index 8663cbbf5..24b99e4f6 100644 --- a/uppdev/PainterExamples/Image.cpp +++ b/uppdev/PainterExamples/Image.cpp @@ -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); } diff --git a/uppdev/PainterExamples/PainterExamples.upp b/uppdev/PainterExamples/PainterExamples.upp index 469bd0f82..0320a9ffa 100644 --- a/uppdev/PainterExamples/PainterExamples.upp +++ b/uppdev/PainterExamples/PainterExamples.upp @@ -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; diff --git a/uppdev/PainterExamples/Pythagoras.cpp b/uppdev/PainterExamples/Pythagoras.cpp index 2a1f0424a..5052e5865 100644 --- a/uppdev/PainterExamples/Pythagoras.cpp +++ b/uppdev/PainterExamples/Pythagoras.cpp @@ -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(); } diff --git a/uppdev/PainterExamples/Radial.cpp b/uppdev/PainterExamples/Radial.cpp index babe1d8d8..d193e4b75 100644 --- a/uppdev/PainterExamples/Radial.cpp +++ b/uppdev/PainterExamples/Radial.cpp @@ -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 diff --git a/uppdev/PainterExamples/TextFillGradient.cpp b/uppdev/PainterExamples/TextFillGradient.cpp index 19975d37e..0f948f878 100644 --- a/uppdev/PainterExamples/TextFillGradient.cpp +++ b/uppdev/PainterExamples/TextFillGradient.cpp @@ -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 { diff --git a/uppdev/PainterExamples/main.cpp b/uppdev/PainterExamples/main.cpp index f91794896..1b9cb1ddc 100644 --- a/uppdev/PainterExamples/main.cpp +++ b/uppdev/PainterExamples/main.cpp @@ -177,6 +177,7 @@ App::App() { ctrl.print <<= THISBACK(Print); Reset(); LoadFromFile(*this); + Title("Painter 2.0"); } App::~App()