Painter: Fixed RoundRect scaling issue, Diagram: rotation code refactored

This commit is contained in:
Mirek Fidler 2025-08-18 11:17:01 +02:00
parent 95e667a3e8
commit dd9e27dfd6
8 changed files with 58 additions and 17 deletions

View file

@ -165,10 +165,10 @@ protected:
virtual void BeginOnPathOp(double q, bool absolute) = 0; virtual void BeginOnPathOp(double q, bool absolute) = 0;
protected: protected:
void DoArc0(double theta, double th_sweep, const Xform2D& m); 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); 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, 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); void DrawLineStroke(int width, Color color);
public: public:

View file

@ -2,7 +2,7 @@
namespace Upp { 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)))); int nsegs = int(ceil(fabs(th_sweep / (M_PI * 0.5 + 0.001))));
for(int i = 0; i < nsegs; i++) { 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); Xform2D m = Xform2D::Scale(r.x, r.y);
m = m * Xform2D::Translation(c.x, c.y); m = m * Xform2D::Translation(c.x, c.y);
Line(m.Transform(cos(angle), sin(angle))); 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, 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)); Pointf r(fabs(rr.x), fabs(rr.y));
Xform2D m = Xform2D::Rotation(-xangle); 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.x *= r;
m.y *= r; m.y *= r;
m = Xform2D::Translation(c.x, c.y) * m; m = Xform2D::Translation(c.x, c.y) * m;
DoArc0(theta, th_sweep, m); DoArc0(theta, th_sweep, m, scale);
} }
} }

View file

@ -39,7 +39,7 @@ Point DiagramEditor::GetHandle(int i, Point p_) const
p -= r.CenterPoint(); p -= r.CenterPoint();
r -= 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); Rect rr = r.Inflated(5);
r.Deflate(min(10, r.GetWidth() / 2), min(10, r.GetHeight() / 2)); 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) if(h)
(h < 0 ? a1 : a2) = a; (h < 0 ? a1 : a2) = a;
}; };
if(!m.IsLine())
m.Normalize();
Rectf r = m.GetRect(); Rectf r = m.GetRect();
Pointf cp = r.CenterPoint(); Pointf cp = r.CenterPoint();
if(m.IsLine()) { if(m.IsLine()) {
@ -336,16 +338,17 @@ void DiagramEditor::MouseMove(Point p, dword keyflags)
} }
else else
if(draghandle.x == -1 && draghandle.y == 1) { 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; m.rotate = base_rotate + 180.0 * (Bearing((Pointf)p0 - cp) - Bearing(bl)) / M_PI;
if(grid && !GetShift()) if(grid && !GetShift())
m.rotate = int(m.rotate + 360 + 7) / 15 * 15; m.rotate = int(m.rotate + 360 + 7) / 15 * 15;
} }
else { else {
bool rotated = m.rotate && !m.IsLine(); bool rotated = m.rotate;
if(rotated) { if(rotated) {
p -= cp; p -= cp;
p = Xform2D::Rotation(-M_2PI * m.rotate / 360).Transform(p); r -= cp;
p = m.Rotation(-1).Transform(p);
p += cp; p += cp;
} }
Do(draghandle.x, r.left, r.right, p.x); Do(draghandle.x, r.left, r.right, p.x);
@ -371,6 +374,8 @@ void DiagramEditor::MouseMove(Point p, dword keyflags)
else else
m.pt[1].y = m.pt[0].y + sz.cy; m.pt[1].y = m.pt[0].y + sz.cy;
} }
if(rotated)
r += cp;
m.pt[0] = r.TopLeft(); m.pt[0] = r.TopLeft();
m.pt[1] = r.BottomRight(); m.pt[1] = r.BottomRight();
} }

View file

@ -82,7 +82,7 @@ bool DiagramItem::IsClick(Point p, const Diagram& diagram, bool relaxed) const
Pointf cp = rect.CenterPoint(); Pointf cp = rect.CenterPoint();
if(rotate) { if(rotate) {
p -= cp; p -= cp;
p = Xform2D::Rotation(-M_PI * rotate / 180).Transform(p); p = Rotation(-1).Transform(p);
p += cp; p += cp;
} }
if(!rect.Contains(p)) if(!rect.Contains(p))
@ -279,7 +279,7 @@ Size Diagram::GetSize() const
Pointf cp = r.CenterPoint(); Pointf cp = r.CenterPoint();
Xform2D rot; Xform2D rot;
if(m.rotate) if(m.rotate)
rot = Xform2D::Rotation(M_2PI * m.rotate / 360); rot = m.Rotation();
auto Do = [&](Pointf p) { auto Do = [&](Pointf p) {
if(m.rotate) { if(m.rotate) {
p -= cp; p -= cp;

View file

@ -81,6 +81,8 @@ struct DiagramItem : Point2 {
void FixPosition(); 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 Reset();

View file

@ -29,7 +29,7 @@ Vector<Pointf> DiagramItem::GetConnections() const
if(shape == SHAPE_ITRIANGLE) if(shape == SHAPE_ITRIANGLE)
p << r.TopLeft() << r.TopRight(); p << r.TopLeft() << r.TopRight();
if(rotate) { if(rotate) {
Xform2D rot = Xform2D::Rotation(M_2PI * rotate / 360); Xform2D rot = Rotation();
Pointf c = r.CenterPoint(); Pointf c = r.CenterPoint();
for(Pointf& x : p) { for(Pointf& x : p) {
x -= c; x -= c;

View file

@ -0,0 +1,9 @@
uses
CtrlLib;
file
main.cpp;
mainconfig
"" = "GUI";

View file

@ -0,0 +1,25 @@
#include <CtrlLib/CtrlLib.h>
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();
}