MauiKit Controls

DoodleCanvas.qml
1import QtQuick
2import QtQuick.Controls
3
4/**
5@since org.mauikit.controls 1.0
6@brief The canvas element for the Doodle component.
7
8@note Use the Doodle element instead, since it has the features implemneted.
9*/
10Item
11{
12 id: control
13 property alias buffer: buffer
14
15 /**
16 *
17 */
18 property int brushSize : 16
19
20 /**
21 *
22 */
23 property real brushOpacity : 1
24
25 /**
26 *
27 */
28 property int brushShape : 1 //0 -Circular, 1 - rectangular.
29
30 /**
31 *
32 */
33 property int maxBrushSize: 100
34
35 /**
36 *
37 */
38 property color paintColor: "red"
39
40
41 Canvas
42 {
43 id: pickCanvas
44 width: 1
45 height: 1
46 visible: false
47 }
48
49
50 Canvas
51 {
52 id: buffer
53
54 anchors.fill: parent
55
56 property real lastX
57 property real lastY
58 property color paintColor: control.paintColor
59 smooth: false
60
61 function clear()
62 {
63 var bufferCtx = buffer.getContext("2d")
64 bufferCtx.clearRect(0, 0, width, height)
65 buffer.requestPaint()
66 }
67
68 MouseArea
69 {
70 id: mouseArea
71 anchors.fill: parent
72 propagateComposedEvents: false
73 preventStealing: true
74
75 property int spacing: 32
76
77 property real deltaDab: Math.max(spacing / 100 * control.brushSize, 1)
78 property var points: []
79 property point lastDrawPoint
80 property point startPos
81 property point finalPos
82 property real brushAngle: 0
83
84 onPressed:
85 {
86 var point = Qt.point(mouseX, mouseY)
87 points = []
88
89 startPos = Qt.point(point.x, point.y)
90 finalPos = Qt.point(point.x, point.y)
91 lastDrawPoint = point
92 if (control.brushShape != 1)
93 {//if brush is not square
94 drawDab(point)
95 }
96 points = []
97 points.push(point)
98
99 //Hide Color Picker later move it to the whole screen.
100 // colorPicker.visible = false
101 }
102
103
104 onPositionChanged:
105 {
106
107 drawDab(Qt.point(mouseX, mouseY))
108
109 // **************** Fancy and intense bezier I don't quite understand yet:
110 var currentPoint = Qt.point(mouseX, mouseY)
111 var startPoint = lastDrawPoint
112
113
114 //Rotating the dab if brush is recangular.
115 if (control.brushShape == 1) {
116 spacing = 16
117
118 if ( (currentPoint.x > startPoint.x))
119 {
120 // dab.brushAngle = find_angle(Qt.point(startPoint.x, startPoint.y-10),
121 // startPoint, currentPoint)
122 // dab.requestPaint()
123 brushAngle = find_angle(Qt.point(startPoint.x, startPoint.y-10),startPoint, currentPoint)
124
125 } else
126 {
127 // dab.brushAngle = - find_angle(Qt.point(startPoint.x, startPoint.y-10),
128 // startPoint, currentPoint)
129 // dab.requestPaint()
130 brushAngle = - find_angle(Qt.point(startPoint.x, startPoint.y-10),startPoint, currentPoint)
131
132 }
133 } else
134 {
135 spacing = 32
136 }
137
138 // ##
139 var currentSpacing = Math.sqrt(Math.pow(currentPoint.x - startPoint.x, 2) + Math.pow(currentPoint.y - startPoint.y, 2))
140 var numDabs = Math.floor(currentSpacing / deltaDab)
141
142 if (points.length == 1 || numDabs < 3) {
143 var endPoint = currentPoint
144 } else {
145 var controlPoint = points[points.length - 1]
146 endPoint = Qt.point((controlPoint.x + currentPoint.x) / 2, (controlPoint.y + currentPoint.y) / 2)
147 }
148
149 var deltaT = 1 / numDabs
150 var betweenPoint = startPoint
151 var t = deltaT
152 var diff
153 while (t > 0 && t <= 1) {
154 var point = bezierCurve(startPoint, controlPoint, endPoint, t)
155 var deltaPoint = Math.sqrt(Math.pow(point.x - betweenPoint.x, 2) + Math.pow(point.y - betweenPoint.y, 2))
156 // check on bezier loop
157 if (diff && Math.abs(deltaPoint - deltaDab) > Math.abs(diff)) { break; }
158 diff = deltaPoint - deltaDab
159 if (Math.abs(diff <= 0.5)) {
160 drawDab(point)
161 diff = undefined
162 betweenPoint = point
163 t += deltaT
164 } else {
165 t -= diff / deltaDab * deltaT
166 }
167 }
168 points.push(currentPoint)
169 lastDrawPoint = betweenPoint
170
171 }
172
173 onReleased:
174 {
175
176 var bufferCtx = buffer.getContext("2d")
177
178 //saving image
179 // Grab Buffer image
180 var bufferImage = bufferCtx.getImageData(0, 0, width, height)
181
182
183 // Auto save painting
184 // saveDrawing()
185
186 // Clear the buffer
187 buffer.requestPaint()
188
189
190 }
191
192 function drawDab(point)
193 {
194 var ctx = buffer.getContext("2d")
195
196 //Bezier Dab
197 // ctx.save()
198 // var size = toolbar.maxBrushSize //toolbar.brushSize
199 // var x = point.x - size / 2
200 // var y = point.y - size / 2
201 // if (x < startPos.x) { startPos.x = Math.min(0, x) }
202 // if (y < startPos.y) { startPos.y = Math.min(0, y) }
203 // if (x > finalPos.x) { finalPos.x = Math.max(x, buffer.width) }
204 // if (y > finalPos.y) { finalPos.y = Math.max(y, buffer.height) }
205 // ctx.drawImage(dab, x, y)
206 // ctx.restore()
207 // buffer.requestPaint()
208
209 //Raster Circle:
210 //ctx.drawImage("brushes/circle.png", x, y, size, size)
211
212 //Simple dab
213 var size = control.brushSize
214 ctx.fillStyle = Qt.rgba(control.paintColor.r, control.paintColor.g, control.paintColor.b, control.brushOpacity);
215 var x = point.x - size / 2
216 var y = point.y - size / 2
217
218 if (control.brushShape == 0)
219 {
220 ctx.beginPath();
221 x = point.x - size/8
222 y = point.y - size/8
223 ctx.arc(x, y, size/2 ,0,Math.PI*2,true);
224 } else
225 {
226 ctx.save()
227 ctx.translate(x+size/2,y+size/2)
228 ctx.beginPath()
229 ctx.rotate(brushAngle)
230 ctx.roundedRect(-size/4, -size/8, size/2, size/4, 2, 2)
231 ctx.restore()
232 }
233 ctx.fill()
234 buffer.requestPaint()
235
236 }
237 }
238
239
240 }
241
242 // Bezier Curve
243 function bezierCurve(start, control, end, t)
244 {
245 var x, y
246 // linear bezier curve
247 if (!control) {
248 x = (1 - t) * start.x + t * end.x
249 y = (1 - t) * start.y + t * end.y
250 }
251 // quad bezier curve
252 else {
253 x = Math.pow((1 - t), 2) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x
254 y = Math.pow((1 - t), 2) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y
255 }
256 return Qt.point(x, y)
257 }
258
259 // Convert RGB to HEX
260 function rgbToHex(r, g, b)
261 {
262 if (r > 255 || g > 255 || b > 255)
263 throw "Invalid color component";
264 return ((r << 16) | (g << 8) | b).toString(16);
265 }
266
267 function find_angle(A,B,C) {
268 var AB = Math.sqrt(Math.pow(B.x-A.x,2)+ Math.pow(B.y-A.y,2));
269 var BC = Math.sqrt(Math.pow(B.x-C.x,2)+ Math.pow(B.y-C.y,2));
270 var AC = Math.sqrt(Math.pow(C.x-A.x,2)+ Math.pow(C.y-A.y,2));
271 return Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB));
272 }
273}
274
275
276
277
Q_SCRIPTABLE Q_NOREPLY void start()
const QList< QKeySequence > & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:56:16 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.