Warning, /maui/mauikit/src/controls.5/DoodleCanvas.qml is written in an unsupported language. File is not indexed.

0001 import QtQuick 2.13
0002 import QtQuick.Controls 2.13
0003 
0004 /*!
0005         *           \since org.mauikit.controls.labs 1.0
0006         *           \inqmlmodule org.mauikit.controls.labs
0007         */
0008 Item
0009 {
0010     id: control
0011     property alias buffer: buffer
0012 
0013     /**
0014             *
0015             */
0016     property int brushSize : 16
0017 
0018     /**
0019             *
0020             */
0021     property real brushOpacity : 1
0022 
0023     /**
0024             *
0025             */
0026     property int brushShape : 1 //0 -Circular, 1 - rectangular.
0027 
0028     /**
0029             *
0030             */
0031     property int maxBrushSize: 100
0032 
0033     /**
0034             *
0035             */
0036     property color paintColor: "red"
0037 
0038     Canvas
0039     {
0040         id: pickCanvas
0041         width: 1
0042         height: 1
0043         visible: false
0044     }
0045 
0046     Canvas
0047     {
0048         id: buffer
0049 
0050         anchors.fill: parent
0051 
0052         property real lastX
0053         property real lastY
0054         property color paintColor: control.paintColor
0055         smooth: false
0056 
0057         function clear()
0058         {
0059             var bufferCtx = buffer.getContext("2d")
0060             bufferCtx.clearRect(0, 0, width, height)
0061             buffer.requestPaint()
0062         }
0063 
0064         MouseArea
0065         {
0066             id: mouseArea
0067             anchors.fill: parent
0068             propagateComposedEvents: false
0069             preventStealing: true
0070 
0071             property int spacing: 32
0072 
0073             property real deltaDab: Math.max(spacing / 100 * control.brushSize, 1)
0074             property var points: []
0075             property point lastDrawPoint
0076             property point startPos
0077             property point finalPos
0078             property real brushAngle: 0
0079 
0080             onPressed:
0081             {
0082                 var point = Qt.point(mouseX, mouseY)
0083                 points = []
0084 
0085                 startPos = Qt.point(point.x, point.y)
0086                 finalPos = Qt.point(point.x, point.y)
0087                 lastDrawPoint = point
0088                 if (control.brushShape != 1)
0089                 {//if brush is not square
0090                     drawDab(point)
0091                 }
0092                 points = []
0093                 points.push(point)
0094 
0095                 //Hide Color Picker later move it to the whole screen.
0096                 //                 colorPicker.visible = false
0097             }
0098 
0099 
0100             onPositionChanged:
0101             {
0102 
0103                 drawDab(Qt.point(mouseX, mouseY))
0104 
0105                 // **************** Fancy and intense bezier I don't quite understand yet:
0106                 var currentPoint = Qt.point(mouseX, mouseY)
0107                 var startPoint = lastDrawPoint
0108 
0109 
0110                 //Rotating the dab if brush is recangular.
0111                 if (control.brushShape == 1) {
0112                     spacing = 16
0113 
0114                     if ( (currentPoint.x > startPoint.x))
0115                     {
0116                         // dab.brushAngle = find_angle(Qt.point(startPoint.x, startPoint.y-10),
0117                         // startPoint, currentPoint)
0118                         // dab.requestPaint()
0119                         brushAngle = find_angle(Qt.point(startPoint.x, startPoint.y-10),startPoint, currentPoint)
0120 
0121                     } else
0122                     {
0123                         // dab.brushAngle = - find_angle(Qt.point(startPoint.x, startPoint.y-10),
0124                         // startPoint, currentPoint)
0125                         // dab.requestPaint()
0126                         brushAngle = - find_angle(Qt.point(startPoint.x, startPoint.y-10),startPoint, currentPoint)
0127 
0128                     }
0129                 } else
0130                 {
0131                     spacing = 32
0132                 }
0133 
0134                 // ##
0135                 var currentSpacing = Math.sqrt(Math.pow(currentPoint.x - startPoint.x, 2) + Math.pow(currentPoint.y - startPoint.y, 2))
0136                 var numDabs = Math.floor(currentSpacing / deltaDab)
0137 
0138                 if (points.length == 1 || numDabs < 3) {
0139                     var endPoint = currentPoint
0140                 } else {
0141                     var controlPoint = points[points.length - 1]
0142                     endPoint = Qt.point((controlPoint.x + currentPoint.x) / 2, (controlPoint.y + currentPoint.y) / 2)
0143                 }
0144 
0145                 var deltaT = 1 / numDabs
0146                 var betweenPoint = startPoint
0147                 var t = deltaT
0148                 var diff
0149                 while (t > 0 && t <= 1) {
0150                     var point = bezierCurve(startPoint, controlPoint, endPoint, t)
0151                     var deltaPoint = Math.sqrt(Math.pow(point.x - betweenPoint.x, 2) + Math.pow(point.y - betweenPoint.y, 2))
0152                     // check on bezier loop
0153                     if (diff && Math.abs(deltaPoint - deltaDab) > Math.abs(diff)) { break; }
0154                     diff = deltaPoint - deltaDab
0155                     if (Math.abs(diff <= 0.5)) {
0156                         drawDab(point)
0157                         diff = undefined
0158                         betweenPoint = point
0159                         t += deltaT
0160                     } else {
0161                         t -= diff / deltaDab * deltaT
0162                     }
0163                 }
0164                 points.push(currentPoint)
0165                 lastDrawPoint = betweenPoint
0166 
0167             }
0168 
0169             onReleased:
0170             {
0171 
0172                 var bufferCtx = buffer.getContext("2d")
0173 
0174                 //saving image
0175                 // Grab Buffer image
0176                 var bufferImage = bufferCtx.getImageData(0, 0, width, height)
0177 
0178 
0179                 // Auto save painting
0180                 //                         saveDrawing()
0181 
0182                 // Clear the buffer
0183                 buffer.requestPaint()
0184 
0185 
0186             }
0187 
0188             function drawDab(point)
0189             {
0190                 var ctx = buffer.getContext("2d")
0191 
0192                 //Bezier Dab
0193                 // ctx.save()
0194                 // var size = toolbar.maxBrushSize //toolbar.brushSize
0195                 // var x = point.x - size / 2
0196                 // var y = point.y - size / 2
0197                 // if (x < startPos.x) { startPos.x = Math.min(0, x) }
0198                 // if (y < startPos.y) { startPos.y = Math.min(0, y) }
0199                 // if (x > finalPos.x) { finalPos.x = Math.max(x, buffer.width) }
0200                 // if (y > finalPos.y) { finalPos.y = Math.max(y, buffer.height) }
0201                 // ctx.drawImage(dab, x, y)
0202                 // ctx.restore()
0203                 // buffer.requestPaint()
0204 
0205                 //Raster Circle:
0206                 //ctx.drawImage("brushes/circle.png", x, y, size, size)
0207 
0208                 //Simple dab
0209                 var size = control.brushSize
0210                 ctx.fillStyle =  Qt.rgba(control.paintColor.r, control.paintColor.g, control.paintColor.b, control.brushOpacity);
0211                 var x = point.x - size / 2
0212                 var y = point.y - size / 2
0213 
0214                 if (control.brushShape == 0)
0215                 {
0216                     ctx.beginPath();
0217                     x = point.x - size/8
0218                     y = point.y - size/8
0219                     ctx.arc(x, y, size/2 ,0,Math.PI*2,true);
0220                 } else
0221                 {
0222                     ctx.save()
0223                     ctx.translate(x+size/2,y+size/2)
0224                     ctx.beginPath()
0225                     ctx.rotate(brushAngle)
0226                     ctx.roundedRect(-size/4, -size/8, size/2, size/4, 2, 2)
0227                     ctx.restore()
0228                 }
0229                 ctx.fill()
0230                 buffer.requestPaint()
0231 
0232             }
0233         }
0234 
0235 
0236     }
0237 
0238     // Bezier Curve
0239     function bezierCurve(start, control, end, t)
0240     {
0241         var x, y
0242         // linear bezier curve
0243         if (!control) {
0244             x = (1 - t) * start.x + t * end.x
0245             y = (1 - t) * start.y + t * end.y
0246         }
0247         // quad bezier curve
0248         else {
0249             x = Math.pow((1 - t), 2) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x
0250             y = Math.pow((1 - t), 2) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y
0251         }
0252         return Qt.point(x, y)
0253     }
0254 
0255     // Convert RGB to HEX
0256     function rgbToHex(r, g, b)
0257     {
0258         if (r > 255 || g > 255 || b > 255)
0259             throw "Invalid color component";
0260         return ((r << 16) | (g << 8) | b).toString(16);
0261     }
0262 
0263     function find_angle(A,B,C) {
0264         var AB = Math.sqrt(Math.pow(B.x-A.x,2)+ Math.pow(B.y-A.y,2));
0265         var BC = Math.sqrt(Math.pow(B.x-C.x,2)+ Math.pow(B.y-C.y,2));
0266         var AC = Math.sqrt(Math.pow(C.x-A.x,2)+ Math.pow(C.y-A.y,2));
0267         return Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB));
0268     }
0269 }
0270 
0271 
0272