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;
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:

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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;

View file

@ -71,7 +71,7 @@ struct DiagramItem : Point2 {
void Paint(Painter& w, const Diagram& diagram, dword style = 0, const Index<Pointf> *conn = nullptr) const;
Sizef GetStdSize(const Diagram& diagram) const;
bool IsLine() const { return shape == SHAPE_LINE; }
bool IsLine() const { return shape == SHAPE_LINE; }
Vector<Pointf> 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;

View file

@ -29,7 +29,7 @@ Vector<Pointf> 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;

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();
}