]> Shamusworld >> Repos - architektonas/blob - src/painter.cpp
8fe59ab9ad64720bd06d901b662d602ccf052c2c
[architektonas] / src / painter.cpp
1 //
2 // painter.cpp: Paint abstraction layer between Archtektonas and Qt
3 //
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // WHO  WHEN        WHAT
11 // ---  ----------  ------------------------------------------------------------
12 // JLH  09/20/2011  Created this file
13 //
14
15 #include "painter.h"
16
17 #include "mathconstants.h"
18
19
20 // Set class variable defaults
21 Vector Painter::origin(-10.0, -10.0);
22 double Painter::zoom = 1.0;
23 Vector Painter::screenSize(200.0, 200.0);
24
25
26 Painter::Painter(QPainter * p/*= NULL*/): painter(p)
27 {
28 }
29
30 Painter::~Painter()
31 {
32 }
33
34 Vector Painter::CartesianToQtCoords(Vector v)
35 {
36         // Convert regular Cartesian coordinates to the inverted Y-axis Qt coordinates
37         // at the current origin and zoom level.
38         return Vector((v.x - origin.x) * zoom, screenSize.y - ((v.y - origin.y) * zoom));
39 }
40
41 Vector Painter::QtToCartesianCoords(Vector v)
42 {
43         // Convert screen location, with inverted Y-axis coordinates, to regular
44         // Cartesian coordinates at the current zoom level.
45         return Vector((v.x / zoom) + origin.x, ((screenSize.y - v.y) / zoom) + origin.y);
46 /*
47 How to do it:
48
49 e.g., we have a point on the screen at Qt coords of 10, 10, screenSize is 100, 100.
50 origin is -10, -10 and zoom level is 2 (200%)
51
52 1st, invert the Y: 10, 10 -> 10, 90
53 2nd, add origin:   10, 90 ->  0, 80 (no, not right--err, yes, it is)
54 3rd, aply zoom:     0, 80 ->  0, 40
55
56 or, is it:
57
58 1st, invert the Y: 10, 10 -> 10, 90
59 2nd, aply zoom:    10, 90 ->  5, 45
60 3rd, add origin:    5, 45 -> -5, 35
61
62 it depends on whether or not origin is in Qt coords or cartesian. If Qt, then the 1st
63 is correct, otherwise, the 2nd is correct.
64
65 The way we calculate the Cartesian to Qt shows the 2nd (origin is cartesian) to be correct.
66 */
67 }
68
69 void Painter::SetRenderHint(int hint)
70 {
71         if (!painter)
72                 return;
73
74         painter->setRenderHint((QPainter::RenderHint)hint);
75 }
76
77 void Painter::SetBrush(QBrush brush)
78 {
79         if (!painter)
80                 return;
81
82         painter->setBrush(brush);
83 }
84
85 void Painter::SetFont(QFont font)
86 {
87         if (!painter)
88                 return;
89
90         painter->setFont(font);
91 }
92
93 void Painter::SetPen(QPen pen)
94 {
95         if (!painter)
96                 return;
97
98         painter->setPen(pen);
99 }
100
101 void Painter::DrawAngledText(Vector center, double angle, QString text)
102 {
103         // Strategy: Since Qt doesn't have any rotated text drawing functions,
104         // we instead translate the origin to the center of the text to be drawn and
105         // then rotate the frame to the desired angle.
106         center = CartesianToQtCoords(center);
107
108         // We may need this stuff... If dimension text is large enough.
109 //      int textWidth = QFontMetrics(painter->font()).width(text);
110 //      int textHeight = QFontMetrics(painter->font()).height();
111         QRectF textBox(-100, -100, 200, 200);   // x, y, w, h; x/y = upper left corner
112
113         // This is in pixels. Might not render correctly at all zoom levels.
114         // Need to figure out if dimensions are always rendered at one size regardless of zoom,
115         // or if they have a definite size, and are thus zoomable.
116         // If zoomable, this is incorrect:
117         int yOffset = -12;
118
119         // Fix text so it isn't upside down...
120         if ((angle > PI * 0.5) && (angle < PI * 1.5))
121         {
122                 angle += PI;
123                 yOffset = 12;
124         }
125
126         textBox.translate(0, yOffset);
127         painter->save();
128         painter->translate(center.x, center.y);
129         // Angles are backwards in the Qt coord system, so we flip ours...
130         painter->rotate(-angle * RADIANS_TO_DEGREES);
131         painter->drawText(textBox, Qt::AlignCenter, text);
132         painter->restore();
133 }
134
135 void Painter::DrawArc(Vector center, double radius, double startAngle, double span)
136 {
137         center = CartesianToQtCoords(center);
138         // Need to multiply scalar quantities by the zoom factor as well...
139         radius *= zoom;
140         QRectF rectangle(QPointF(center.x - radius, center.y - radius),
141                 QPointF(center.x + radius, center.y + radius));
142         int angle1 = (int)(startAngle * RADIANS_TO_DEGREES * 16.0);
143         int angle2 = (int)(span * RADIANS_TO_DEGREES * 16.0);
144         painter->drawArc(rectangle, angle1, angle2);
145 }
146
147 void Painter::DrawEllipse(Vector center, double axis1, double axis2)
148 {
149         // Need to multiply scalar quantities by the zoom factor as well...
150         center = CartesianToQtCoords(center);
151         painter->drawEllipse(QPointF(center.x, center.y), axis1 * zoom, axis2 * zoom);
152 }
153
154 // This function is for drawing object handles without regard for zoom level;
155 // we don't want our object handle size to depend on the zoom level!
156 void Painter::DrawHandle(Vector center)
157 {
158         center = CartesianToQtCoords(center);
159         painter->drawEllipse(QPointF(center.x, center.y), 4.0, 4.0);
160 }
161
162 void Painter::DrawLine(int x1, int y1, int x2, int y2)
163 {
164         if (!painter)
165                 return;
166
167         Vector v1 = CartesianToQtCoords(Vector(x1, y1));
168         Vector v2 = CartesianToQtCoords(Vector(x2, y2));
169         painter->drawLine(v1.x, v1.y, v2.x, v2.y);
170 }
171
172 void Painter::DrawLine(Vector v1, Vector v2)
173 {
174         if (!painter)
175                 return;
176
177         v1 = CartesianToQtCoords(v1);
178         v2 = CartesianToQtCoords(v2);
179         painter->drawLine(QPointF(v1.x, v1.y), QPointF(v2.x, v2.y));
180 }
181
182 void Painter::DrawPoint(int x, int y)
183 {
184         if (!painter)
185                 return;
186
187         Vector v = CartesianToQtCoords(Vector(x, y));
188         painter->drawPoint(v.x, v.y);
189 }
190
191 void Painter::DrawRoundedRect(QRectF rect, double radiusX, double radiusY)
192 {
193         if (!painter)
194                 return;
195
196         painter->drawRoundedRect(rect, radiusX, radiusY);
197 }
198
199 void Painter::DrawText(QRectF rect, int type, QString text)
200 {
201         if (!painter)
202                 return;
203
204         painter->drawText(rect, (Qt::AlignmentFlag)type, text);
205 }