From 1e327a6d6d5eac09f5692d9091043e87ea688e5d Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 13 Jan 2015 11:29:11 +0100 Subject: initial import --- qml/cover/CoverPage.qml | 42 ++++++++++++++++++++++++ qml/finesketch.qml | 40 +++++++++++++++++++++++ qml/items/SketchArea.qml | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ qml/items/SketchView.qml | 80 +++++++++++++++++++++++++++++++++++++++++++++ qml/pages/SketchPage.qml | 12 +++++++ 5 files changed, 258 insertions(+) create mode 100644 qml/cover/CoverPage.qml create mode 100644 qml/finesketch.qml create mode 100644 qml/items/SketchArea.qml create mode 100644 qml/items/SketchView.qml create mode 100644 qml/pages/SketchPage.qml (limited to 'qml') diff --git a/qml/cover/CoverPage.qml b/qml/cover/CoverPage.qml new file mode 100644 index 0000000..7679cfc --- /dev/null +++ b/qml/cover/CoverPage.qml @@ -0,0 +1,42 @@ +/* + Copyright (C) 2013 Jolla Ltd. + Contact: Thomas Perl + All rights reserved. + + You may use this file under the terms of BSD license as follows: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Jolla Ltd nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +CoverBackground { + Label { + id: label + anchors.centerIn: parent + text: "Finescript" + } +} + + diff --git a/qml/finesketch.qml b/qml/finesketch.qml new file mode 100644 index 0000000..e116e6f --- /dev/null +++ b/qml/finesketch.qml @@ -0,0 +1,40 @@ +/* + Copyright (C) 2013 Jolla Ltd. + Contact: Thomas Perl + All rights reserved. + + You may use this file under the terms of BSD license as follows: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Jolla Ltd nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import "pages" + +ApplicationWindow +{ + id: appWindow + initialPage: Component { SketchPage { } } + cover: Qt.resolvedUrl("cover/CoverPage.qml") +} diff --git a/qml/items/SketchArea.qml b/qml/items/SketchArea.qml new file mode 100644 index 0000000..3a528d9 --- /dev/null +++ b/qml/items/SketchArea.qml @@ -0,0 +1,84 @@ +import QtQuick 2.0 + +SketchView { + id: area + autoRepaint: false + + property color fingerLineColor: Qt.rgba(1.0, 0.0, 0.0, 1.0) + property color stylusLineColor: Qt.rgba(0.0, 0.0, 0.0, 1.0) + property color eraserLineColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) + property real curLineWidth: 4 + + function _boundingBox(points) { + if (!points.length) return Qt.rect(0, 0, 0, 0); + var x1 = points[0].x, y1 = points[0].y; + var x2 = x1, y2 = y1; + + for (var i = 1; i < points.length; i++) { + if (points[i].x < x1) x1 = points[i].x; + if (points[i].y < y1) y1 = points[i].y; + if (points[i].x > x2) x2 = points[i].x; + if (points[i].y > y2) y2 = points[i].y; + } + + return Qt.rect(x1, y1, x2 - x1, y2 - y1); + } + + function _isStylusOn() { + return stylus.pressure > 0.15; + } + function _isEraserOn() { + return !_isStylusOn() && stylus.y > 0.85; + } + + MouseArea { + anchors.fill: parent + preventStealing: true + + onPressed: { + var point = Qt.point(mouse.x, mouse.y); + var stroke = { + lineWidth : curLineWidth, + lineColor : fingerLineColor, + stylus : false, + eraser : false, + boundingBox : Qt.rect(0, 0, area.width, area.height), + points : [point] + } + strokes.push(stroke); + canvas.requestPaint(); + } + onReleased: { + canvas.requestPaint(); + } + onPositionChanged: { + var cur_stroke = strokes[area.strokes.length - 1]; + var point = Qt.point(mouse.x, mouse.y); + var prev_point = cur_stroke.points[cur_stroke.points.length - 1]; + cur_stroke.points.push(point); + cur_stroke.boundingBox = _boundingBox(cur_stroke.points); + + var rect = Qt.rect(Math.floor(Math.min(point.x, prev_point.x) - cur_stroke.lineWidth/2), + Math.floor(Math.min(point.y, prev_point.y) - cur_stroke.lineWidth/2), + Math.ceil(Math.abs(point.x - prev_point.x) + cur_stroke.lineWidth), + Math.ceil(Math.abs(point.y - prev_point.y) + cur_stroke.lineWidth)); + + if (!cur_stroke.stylus) { + if (_isStylusOn()) { + cur_stroke.stylus = true; + cur_stroke.lineColor = stylusLineColor; + canvas.requestPaint(); + return; + } else if (_isEraserOn()) { + cur_stroke.stylus = true; + cur_stroke.eraser = true; + cur_stroke.lineColor = eraserLineColor; + canvas.requestPaint(); + return; + } + } + + canvas.markDirty(rect); + } + } +} diff --git a/qml/items/SketchView.qml b/qml/items/SketchView.qml new file mode 100644 index 0000000..8ded87a --- /dev/null +++ b/qml/items/SketchView.qml @@ -0,0 +1,80 @@ +import QtQuick 2.0 + +Item { + id: view + + property alias fillColor: rectangle.color + property alias border: rectangle.border + + property var strokes: [] + + property bool autoRepaint: true + property alias canvas: canvas + + function _drawStroke(ctx, stroke) { + var points = stroke.points; + ctx.save(); + ctx.lineWidth = stroke.lineWidth; + ctx.strokeStyle = stroke.lineColor; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + for (var i = 1; i < points.length; i++) { + ctx.lineTo(points[i].x, points[i].y); + } + ctx.stroke(); + ctx.restore(); + } + + function _intersect(r1, r2) { + if (!r1.width || !r2.width) return false; + if (!r1.height || !r2.height) return false; + + if (r1.x >= r2.x + r2.width) return false; + if (r1.y >= r2.y + r2.height) return false; + if (r2.x >= r1.x + r1.width) return false; + if (r2.y >= r1.y + r1.height) return false; + return true; + } + + Rectangle { + id: rectangle + anchors.fill: parent + + color: Qt.rgba(1.0, 1.0, 1.0, 0.3) + radius: 10.0 + } + + Canvas { + id: canvas + anchors.fill: parent + + renderTarget: Canvas.Image + renderStrategy: Canvas.Immediate + + onPaint: { + var ctx = canvas.getContext('2d'); + ctx.clearRect(region.x, region.y, region.width, region.height); + + ctx.save(); + ctx.beginPath(); + ctx.rect(region.x, region.y, region.width, region.height); + ctx.clip(); + + for (var i = 0; i < strokes.length; i++) { + if (_intersect(region, strokes[i].boundingBox)) { + _drawStroke(ctx, strokes[i]); + } + } + + ctx.restore(); + } + } + + onStrokesChanged: { + if (autoRepaint) { + canvas.requestPaint(); + } + } +} diff --git a/qml/pages/SketchPage.qml b/qml/pages/SketchPage.qml new file mode 100644 index 0000000..449b2aa --- /dev/null +++ b/qml/pages/SketchPage.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import "../items" + +Page { + id: sketchPage + + SketchArea { + id: area + anchors.fill: parent + } +} -- cgit v1.2.3