From dd9e27dfd691a2ff749c873c5bfdfc6fe8263e63 Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Mon, 18 Aug 2025 11:17:01 +0200 Subject: [PATCH] Painter: Fixed RoundRect scaling issue, Diagram: rotation code refactored --- uppsrc/Painter/Painter.h | 6 +++--- uppsrc/Painter/SvgArc.cpp | 10 +++++----- uppsrc/RichEdit/DiagramMouse.cpp | 13 +++++++++---- uppsrc/RichText/Diagram.cpp | 4 ++-- uppsrc/RichText/Diagram.h | 6 ++++-- uppsrc/RichText/DiagramShape.cpp | 2 +- upptst/RoundRect2/RoundRect2.upp | 9 +++++++++ upptst/RoundRect2/main.cpp | 25 +++++++++++++++++++++++++ 8 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 upptst/RoundRect2/RoundRect2.upp create mode 100644 upptst/RoundRect2/main.cpp diff --git a/uppsrc/Painter/Painter.h b/uppsrc/Painter/Painter.h index 228db58ab..dd3620cc4 100644 --- a/uppsrc/Painter/Painter.h +++ b/uppsrc/Painter/Painter.h @@ -165,10 +165,10 @@ protected: virtual void BeginOnPathOp(double q, bool absolute) = 0; protected: - void DoArc0(double theta, double th_sweep, const Xform2D& m); - void DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle); + void DoArc0(double theta, double th_sweep, const Xform2D& m, double scale = 1); + void DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle, double scale = 1); void DoSvgArc(const Pointf& rr, double xangle, int large, int sweep, - const Pointf& p, const Pointf& p0); + const Pointf& p, const Pointf& p0, double scale = 1); void DrawLineStroke(int width, Color color); public: diff --git a/uppsrc/Painter/SvgArc.cpp b/uppsrc/Painter/SvgArc.cpp index 78b366a7d..68d842701 100644 --- a/uppsrc/Painter/SvgArc.cpp +++ b/uppsrc/Painter/SvgArc.cpp @@ -2,7 +2,7 @@ namespace Upp { -void Painter::DoArc0(double theta, double th_sweep, const Xform2D& m) +void Painter::DoArc0(double theta, double th_sweep, const Xform2D& m, double scale) { int nsegs = int(ceil(fabs(th_sweep / (M_PI * 0.5 + 0.001)))); for(int i = 0; i < nsegs; i++) { @@ -18,16 +18,16 @@ void Painter::DoArc0(double theta, double th_sweep, const Xform2D& m) } } -void Painter::DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle) +void Painter::DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle, double scale) { Xform2D m = Xform2D::Scale(r.x, r.y); m = m * Xform2D::Translation(c.x, c.y); Line(m.Transform(cos(angle), sin(angle))); - DoArc0(angle, sweep, m); + DoArc0(angle, sweep, m, scale); } void Painter::DoSvgArc(const Pointf& rr, double xangle, int large, int sweep, - const Pointf& p1, const Pointf& p0) + const Pointf& p1, const Pointf& p0, double scale) { Pointf r(fabs(rr.x), fabs(rr.y)); Xform2D m = Xform2D::Rotation(-xangle); @@ -61,7 +61,7 @@ void Painter::DoSvgArc(const Pointf& rr, double xangle, int large, int sweep, m.x *= r; m.y *= r; m = Xform2D::Translation(c.x, c.y) * m; - DoArc0(theta, th_sweep, m); + DoArc0(theta, th_sweep, m, scale); } } diff --git a/uppsrc/RichEdit/DiagramMouse.cpp b/uppsrc/RichEdit/DiagramMouse.cpp index 4048c09d5..d9b11454a 100644 --- a/uppsrc/RichEdit/DiagramMouse.cpp +++ b/uppsrc/RichEdit/DiagramMouse.cpp @@ -39,7 +39,7 @@ Point DiagramEditor::GetHandle(int i, Point p_) const p -= r.CenterPoint(); r -= r.CenterPoint(); - p = Xform2D::Rotation(-M_2PI * m.rotate / 360).Transform(p); + p = m.Rotation(-1).Transform(p); Rect rr = r.Inflated(5); r.Deflate(min(10, r.GetWidth() / 2), min(10, r.GetHeight() / 2)); @@ -328,6 +328,8 @@ void DiagramEditor::MouseMove(Point p, dword keyflags) if(h) (h < 0 ? a1 : a2) = a; }; + if(!m.IsLine()) + m.Normalize(); Rectf r = m.GetRect(); Pointf cp = r.CenterPoint(); if(m.IsLine()) { @@ -336,16 +338,17 @@ void DiagramEditor::MouseMove(Point p, dword keyflags) } else if(draghandle.x == -1 && draghandle.y == 1) { - Pointf bl = Xform2D::Rotation(M_2PI * base_rotate / 360).Transform(r.BottomLeft() - cp); + Pointf bl = Xform2D::Rotation(M_PI * base_rotate / 180.0).Transform(r.BottomLeft() - cp); m.rotate = base_rotate + 180.0 * (Bearing((Pointf)p0 - cp) - Bearing(bl)) / M_PI; if(grid && !GetShift()) m.rotate = int(m.rotate + 360 + 7) / 15 * 15; } else { - bool rotated = m.rotate && !m.IsLine(); + bool rotated = m.rotate; if(rotated) { p -= cp; - p = Xform2D::Rotation(-M_2PI * m.rotate / 360).Transform(p); + r -= cp; + p = m.Rotation(-1).Transform(p); p += cp; } Do(draghandle.x, r.left, r.right, p.x); @@ -371,6 +374,8 @@ void DiagramEditor::MouseMove(Point p, dword keyflags) else m.pt[1].y = m.pt[0].y + sz.cy; } + if(rotated) + r += cp; m.pt[0] = r.TopLeft(); m.pt[1] = r.BottomRight(); } diff --git a/uppsrc/RichText/Diagram.cpp b/uppsrc/RichText/Diagram.cpp index e7ecca404..1c558291a 100644 --- a/uppsrc/RichText/Diagram.cpp +++ b/uppsrc/RichText/Diagram.cpp @@ -82,7 +82,7 @@ bool DiagramItem::IsClick(Point p, const Diagram& diagram, bool relaxed) const Pointf cp = rect.CenterPoint(); if(rotate) { p -= cp; - p = Xform2D::Rotation(-M_PI * rotate / 180).Transform(p); + p = Rotation(-1).Transform(p); p += cp; } if(!rect.Contains(p)) @@ -279,7 +279,7 @@ Size Diagram::GetSize() const Pointf cp = r.CenterPoint(); Xform2D rot; if(m.rotate) - rot = Xform2D::Rotation(M_2PI * m.rotate / 360); + rot = m.Rotation(); auto Do = [&](Pointf p) { if(m.rotate) { p -= cp; diff --git a/uppsrc/RichText/Diagram.h b/uppsrc/RichText/Diagram.h index a0ae7bea3..46ca3fcc9 100644 --- a/uppsrc/RichText/Diagram.h +++ b/uppsrc/RichText/Diagram.h @@ -71,7 +71,7 @@ struct DiagramItem : Point2 { void Paint(Painter& w, const Diagram& diagram, dword style = 0, const Index *conn = nullptr) const; Sizef GetStdSize(const Diagram& diagram) const; - bool IsLine() const { return shape == SHAPE_LINE; } + bool IsLine() const { return shape == SHAPE_LINE; } Vector GetConnections() const; @@ -80,8 +80,10 @@ struct DiagramItem : Point2 { Rect GetTextEditRect() const; void FixPosition(); + + Xform2D Rotation(int d = 1) const { return Xform2D::Rotation(d * M_PI * rotate / 180); } - void Serialize(Stream& s) { Point2::Serialize(s); s % shape % ink % paper % qtf % width % cap[0] % cap[1] % dash % blob_id % flip_horz % flip_vert % aspect_ratio; } + void Serialize(Stream& s) { Point2::Serialize(s); s % shape % ink % paper % qtf % width % cap[0] % cap[1] % dash % blob_id % flip_horz % flip_vert % aspect_ratio; } void Reset(); void Save(StringBuffer& r) const; diff --git a/uppsrc/RichText/DiagramShape.cpp b/uppsrc/RichText/DiagramShape.cpp index 685f93832..945e35cd5 100644 --- a/uppsrc/RichText/DiagramShape.cpp +++ b/uppsrc/RichText/DiagramShape.cpp @@ -29,7 +29,7 @@ Vector DiagramItem::GetConnections() const if(shape == SHAPE_ITRIANGLE) p << r.TopLeft() << r.TopRight(); if(rotate) { - Xform2D rot = Xform2D::Rotation(M_2PI * rotate / 360); + Xform2D rot = Rotation(); Pointf c = r.CenterPoint(); for(Pointf& x : p) { x -= c; diff --git a/upptst/RoundRect2/RoundRect2.upp b/upptst/RoundRect2/RoundRect2.upp new file mode 100644 index 000000000..5872304d3 --- /dev/null +++ b/upptst/RoundRect2/RoundRect2.upp @@ -0,0 +1,9 @@ +uses + CtrlLib; + +file + main.cpp; + +mainconfig + "" = "GUI"; + diff --git a/upptst/RoundRect2/main.cpp b/upptst/RoundRect2/main.cpp new file mode 100644 index 000000000..ecadd1b6f --- /dev/null +++ b/upptst/RoundRect2/main.cpp @@ -0,0 +1,25 @@ +#include + +using namespace Upp; + +// The reason: stroke width should affect cubic tolerance +// the line arc is way to small, so it really contains just 2 points or so... + +struct MyApp : public TopWindow { + void Paint(Draw& w) override { + DrawPainter p(w, GetSize()); + p.Clear(White()); + p.Scale(22); + DLOG("-----------------------------"); + p.Move(10, 10); + p.Arc(10, 10, 0.1, M_PI, M_PI); +// p.RoundedRectangle(2, 2, 100, 100, 0.1) +// p.Stroke(5, Blue()); + p.Stroke(0.1, Blue()); + } +}; + +GUI_APP_MAIN +{ + MyApp().Run(); +}