Uups, forgot to remove files.
This commit is contained in:
		
							parent
							
								
									af932a9911
								
							
						
					
					
						commit
						b6fc04a411
					
				@ -1,13 +0,0 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
https://mattdesl.svbtle.com/drawing-lines-is-hard
 | 
			
		||||
http://perfectionkills.com/exploring-canvas-drawing-techniques/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
https://github.com/mattdesl/polyline-normals
 | 
			
		||||
 | 
			
		||||
var path = [ [0, 122], [0, 190], [90, 190] ]
 | 
			
		||||
 | 
			
		||||
//get the normals as a closed loop
 | 
			
		||||
var normals = getNormals(path, true)
 | 
			
		||||
@ -1,73 +0,0 @@
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="utf-8" />
 | 
			
		||||
 | 
			
		||||
  <!-- disable zooming -->
 | 
			
		||||
  <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1" />
 | 
			
		||||
  <title>Stylus Functional Tests</title>
 | 
			
		||||
  <style media="screen">
 | 
			
		||||
 | 
			
		||||
    html, body {
 | 
			
		||||
        margin:0;
 | 
			
		||||
        padding:0;
 | 
			
		||||
 | 
			
		||||
        height:100%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        /* See http://stackoverflow.com/questions/9280258/prevent-body-scrolling-but-allow-overlay-scrolling */
 | 
			
		||||
        position:fixed;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        font-size: 18px;
 | 
			
		||||
        background:gray;
 | 
			
		||||
        font-family:arial,sans-serif;
 | 
			
		||||
        color:#FFF;
 | 
			
		||||
        -webkit-user-select: none;
 | 
			
		||||
        -khtml-user-select: none;
 | 
			
		||||
        -moz-user-select: none;
 | 
			
		||||
        -ms-user-select: none;
 | 
			
		||||
        -webkit-overflow-scrolling: auto;
 | 
			
		||||
        user-select: none;
 | 
			
		||||
        touch-action: manipulation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .site {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        min-height: 100%;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
    .interactive {
 | 
			
		||||
        -ms-content-zooming: none;
 | 
			
		||||
        touch-action: none;
 | 
			
		||||
    }
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    main {
 | 
			
		||||
        flex-grow: 1;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        position:relative
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .container {
 | 
			
		||||
        position:absolute;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        min-height: 100%;
 | 
			
		||||
    }
 | 
			
		||||
    </style>
 | 
			
		||||
 | 
			
		||||
    <script src=".././3rdparty/all.js"></script>
 | 
			
		||||
	<script src="../../lib/bootstrap.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body class="site" oncontextmenu="return false" >
 | 
			
		||||
<main id="main" class="container">
 | 
			
		||||
    <canvas id="canvas" width="100%" height="100%" style="position: absolute; z-index:10000; user-select: none;">
 | 
			
		||||
	    Get a better browser, bro.
 | 
			
		||||
    </canvas>
 | 
			
		||||
</main>
 | 
			
		||||
<script>
 | 
			
		||||
    Bootstrap.import('./main.js')
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@ -1,90 +0,0 @@
 | 
			
		||||
import PIXIApp from '../../lib/pixi/app.js'
 | 
			
		||||
import Button from '../../lib/pixi/button.js'
 | 
			
		||||
import ButtonGroup from '../../lib/pixi/buttongroup.js'
 | 
			
		||||
import Stylus from './stylus.js'
 | 
			
		||||
 | 
			
		||||
class StylusApp extends PIXIApp {
 | 
			
		||||
 | 
			
		||||
    sceneFactory() {
 | 
			
		||||
        return new Stylus(this.renderer)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setup() {
 | 
			
		||||
        let buttonColor = 0x666666
 | 
			
		||||
        super.setup()
 | 
			
		||||
 | 
			
		||||
        this.tools = new ButtonGroup({
 | 
			
		||||
            type: 'checkbox',
 | 
			
		||||
            margin: 0,
 | 
			
		||||
            x: 16,
 | 
			
		||||
            y: 16,
 | 
			
		||||
            fill: buttonColor,
 | 
			
		||||
            buttons: [{icon: 'edit',
 | 
			
		||||
                        iconColorActive: 0xFFFF00,
 | 
			
		||||
                        action: (event, button) => this.toggleEditMode() },
 | 
			
		||||
               {icon: 'undo',
 | 
			
		||||
                        action: (event, button) => this.undo(button) },
 | 
			
		||||
               {icon: 'redo',
 | 
			
		||||
                        action: (event, button) => this.redo(button) },
 | 
			
		||||
               {icon: 'delete',
 | 
			
		||||
                        action: (event, button) => this.clear(button) }
 | 
			
		||||
            ]
 | 
			
		||||
        })
 | 
			
		||||
        this.scene.addChild(this.tools)
 | 
			
		||||
 | 
			
		||||
        let defaults = { icon: 'brightness_1',
 | 
			
		||||
                    action: (event, button) => this.selectColor(button),
 | 
			
		||||
                    fillAlpha: 0,
 | 
			
		||||
                    strokeAlpha: 0,
 | 
			
		||||
                    fillActiveAlpha: 0,
 | 
			
		||||
                    strokeActiveAlpha: 0}
 | 
			
		||||
 | 
			
		||||
        this.palette = new ButtonGroup( {
 | 
			
		||||
            type: "radio",
 | 
			
		||||
            x: 200,
 | 
			
		||||
            y: 16,
 | 
			
		||||
            margin: 0,
 | 
			
		||||
            strokeAlpha: 0,
 | 
			
		||||
            fill: buttonColor,
 | 
			
		||||
            buttons: [
 | 
			
		||||
                Object.assign({}, defaults, { iconColor: 0x111111,
 | 
			
		||||
                                                iconColorActive: 0x111111}),     // tooltip: "Black",
 | 
			
		||||
                Object.assign({}, defaults, { iconColor: 0xFFFF00,
 | 
			
		||||
                                                iconColorActive: 0xFFFF00}),     // tooltip: "Yellow",
 | 
			
		||||
                Object.assign({}, defaults, { iconColor: 0x00FF00,
 | 
			
		||||
                                                iconColorActive:0x00FF00}),          // tooltip: "Green",
 | 
			
		||||
                Object.assign({}, defaults, { iconColor: 0xFF00FF,
 | 
			
		||||
                                                iconColorActive:0xFF00FF})     // tooltip: "Violet",
 | 
			
		||||
            ]
 | 
			
		||||
        })
 | 
			
		||||
        this.scene.addChild(this.palette)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    selectColor(button) {
 | 
			
		||||
        this.scene.color = button.opts.iconColor
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    undo(button) {
 | 
			
		||||
        this.scene.undo()
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            button.active = false}, 200)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    redo(button) {
 | 
			
		||||
        this.scene.redo()
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            button.active = false}, 200)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clear(button) {
 | 
			
		||||
        this.scene.clearAll()
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            button.active = false}, 200)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const app = new StylusApp({ view: canvas })
 | 
			
		||||
window.app = app
 | 
			
		||||
app.setup()
 | 
			
		||||
app.run()
 | 
			
		||||
 | 
			
		||||
@ -1,398 +0,0 @@
 | 
			
		||||
import Events from '../events.js'
 | 
			
		||||
import { Angle } from '../utils.js'
 | 
			
		||||
 | 
			
		||||
class StylusCommand extends Object {
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    do(stylus) {
 | 
			
		||||
        stylus.commandStack.push(this)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    undo(stylus) {
 | 
			
		||||
        stylus.undoCommandStack.push(this)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    redo(stylus) {
 | 
			
		||||
        this.do(stylus)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class StrokeCommand extends StylusCommand {
 | 
			
		||||
 | 
			
		||||
    constructor(stroke) {
 | 
			
		||||
        super()
 | 
			
		||||
        this.stroke = stroke
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    do(stylus) {
 | 
			
		||||
        if (this.stroke.length > 0) {
 | 
			
		||||
            super.do(stylus)
 | 
			
		||||
            stylus.stroke = []
 | 
			
		||||
            stylus.strokes.push(this.stroke)
 | 
			
		||||
            stylus.redraw()
 | 
			
		||||
            stylus.changed()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    undo(stylus) {
 | 
			
		||||
        if (this.stroke.length > 0) {
 | 
			
		||||
            super.undo(stylus)
 | 
			
		||||
            stylus.strokes.pop()
 | 
			
		||||
            stylus.redraw()
 | 
			
		||||
            stylus.changed()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ClearCommand extends StylusCommand {
 | 
			
		||||
 | 
			
		||||
    do(stylus) {
 | 
			
		||||
        // Clears the command stack
 | 
			
		||||
        stylus.commandStack = []
 | 
			
		||||
        super.do(stylus)
 | 
			
		||||
        this.strokes = stylus.strokes
 | 
			
		||||
        stylus.stroke = []
 | 
			
		||||
        stylus.strokes = []
 | 
			
		||||
        stylus.redraw()
 | 
			
		||||
        stylus.changed()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    undo(stylus) {
 | 
			
		||||
        //super.undo(stylus) // Clear all is not redoable
 | 
			
		||||
        stylus.stroke = []
 | 
			
		||||
        stylus.strokes = this.strokes
 | 
			
		||||
        stylus.redraw()
 | 
			
		||||
        stylus.changed()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default class Stylus extends PIXI.Graphics {
 | 
			
		||||
 | 
			
		||||
    constructor({ width = window.innerWidth,
 | 
			
		||||
        height = window.innerHeight,
 | 
			
		||||
        interactive = true,
 | 
			
		||||
        color = 0x000000,
 | 
			
		||||
        tiltX = 0,
 | 
			
		||||
        tiltY = 0,
 | 
			
		||||
        backgroundAlpha = 1,
 | 
			
		||||
        backgroundFill = 0xFFFFFF,
 | 
			
		||||
        colorAlpha = 1,
 | 
			
		||||
        captureEvents = true,
 | 
			
		||||
        acceptMouseEvents = true } = {}) {
 | 
			
		||||
        super()
 | 
			
		||||
        this.wantedWidth = width
 | 
			
		||||
        this.wantedHeight = height
 | 
			
		||||
        this.backgroundAlpha = backgroundAlpha
 | 
			
		||||
        this.backgroundFill = backgroundFill
 | 
			
		||||
        this.colorAlpha = colorAlpha
 | 
			
		||||
        this.color = color
 | 
			
		||||
        this.interactive = interactive
 | 
			
		||||
        this.debug = false
 | 
			
		||||
        this.tiltX = tiltX  // degrees -90 ... 90
 | 
			
		||||
        this.tiltY = tiltY  // degrees -90 ... 90
 | 
			
		||||
        this.captureEvents = captureEvents
 | 
			
		||||
        this.commandStack = []
 | 
			
		||||
        this.undoCommandStack = []
 | 
			
		||||
        this.strokes = []
 | 
			
		||||
        this.stroke = []
 | 
			
		||||
        if (captureEvents)
 | 
			
		||||
            this.registerEventHandler(acceptMouseEvents)
 | 
			
		||||
        this.drawBackground()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    drawBackground() {
 | 
			
		||||
        this.clear()
 | 
			
		||||
        this.beginFill(this.backgroundFill, this.backgroundAlpha)
 | 
			
		||||
        this.drawRect(0, 0, this.wantedWidth, this.wantedHeight)
 | 
			
		||||
        this.endFill()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    touchToPoint(t) {
 | 
			
		||||
        return { x: t.clientX, y: t.clientY }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isStylusPointer(event) {
 | 
			
		||||
        let identifier = event.data.identifier
 | 
			
		||||
        if (typeof (event.data.originalEvent.changedTouches) !== 'undefined') {
 | 
			
		||||
            for (let touch of event.data.originalEvent.changedTouches) {
 | 
			
		||||
                if (touch.identifier === identifier && touch.touchType === 'stylus') {
 | 
			
		||||
                    this.tiltX = Angle.radian2degree(touch.azimuthAngle)
 | 
			
		||||
                    this.tiltY = 90.0 - Angle.radian2degree(touch.altitudeAngle)
 | 
			
		||||
                    return true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // UO: Not tested since the Sprot delivered "mouse" events to Chrome
 | 
			
		||||
        if (event.data.originalEvent.pointerType === 'pen') {
 | 
			
		||||
            this.tiltX = event.data.originalEvent.tiltX
 | 
			
		||||
            this.tiltY = event.data.originalEvent.tiltY
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isStylusTouch(event) {
 | 
			
		||||
        let identifier = event.data.identifier
 | 
			
		||||
        if (typeof (event.data.originalEvent.changedTouches) !== 'undefined') {
 | 
			
		||||
            for (let touch of event.data.originalEvent.changedTouches) {
 | 
			
		||||
                if (touch.identifier === identifier && touch.pointerType === 'touch') {
 | 
			
		||||
                    return true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getPointerID(event) {
 | 
			
		||||
        let identifier = event.data.identifier
 | 
			
		||||
        for (let touch of event.data.originalEvent.changedTouches) {
 | 
			
		||||
            if (touch.identifier === identifier) {
 | 
			
		||||
                return touch.pointerId
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registerEventHandler() {
 | 
			
		||||
        window.addEventListener('keydown', (e) => {
 | 
			
		||||
            switch (e.keyCode) {
 | 
			
		||||
                case 38:  // up arrow
 | 
			
		||||
                    this.tiltX += 5
 | 
			
		||||
                    break
 | 
			
		||||
                case 40:  // down arrow
 | 
			
		||||
                    this.tiltX -= 5
 | 
			
		||||
                    break
 | 
			
		||||
                case 37:  // left arrow
 | 
			
		||||
                    this.tiltY -= 5
 | 
			
		||||
                    break
 | 
			
		||||
                case 39:  // right arrow
 | 
			
		||||
                    this.tiltY += 5
 | 
			
		||||
                    break
 | 
			
		||||
            }
 | 
			
		||||
            if (this.debug) console.log("keydown", e.keyCode, this.tiltX, this.tiltY)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        this.on('pointerdown', (e) => {
 | 
			
		||||
            if (this.debug) console.log("pointerdown", e)
 | 
			
		||||
            if (this.eventInside(e))
 | 
			
		||||
                this.startStroke(this.toStroke(e))
 | 
			
		||||
        })
 | 
			
		||||
        this.on('pointermove', (e) => {
 | 
			
		||||
            if (Events.isPointerDown(e.data.originalEvent) || this.isStylusPointer(e) || this.isStylusTouch(e)) {
 | 
			
		||||
                if (this.debug) console.log("pointermove", e, this.eventInside(e))
 | 
			
		||||
                if (this.eventInside(e))
 | 
			
		||||
                    this.moveStroke(this.toStroke(e))
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        this.on('pointerup', (e) => {
 | 
			
		||||
            if (this.debug) console.log("pointerup", e)
 | 
			
		||||
            if (this.eventInside(e))
 | 
			
		||||
                this.endStroke(this.toStroke(e))
 | 
			
		||||
        })
 | 
			
		||||
        this.on('pointerleave', (e) => {
 | 
			
		||||
            this.endStroke(this.toStroke(e))
 | 
			
		||||
        })
 | 
			
		||||
        this.on('pointercancel', (e) => {
 | 
			
		||||
            this.endStroke(this.toStroke(e))
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    undoable() {
 | 
			
		||||
        return this.commandStack.length > 0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    redoable() {
 | 
			
		||||
        return this.undoCommandStack.length > 0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    undo() {
 | 
			
		||||
        if (this.undoable()) {
 | 
			
		||||
            let cmd = this.commandStack.pop()
 | 
			
		||||
            cmd.undo(this)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    redo() {
 | 
			
		||||
        if (this.redoable()) {
 | 
			
		||||
            let cmd = this.undoCommandStack.pop()
 | 
			
		||||
            cmd.redo(this)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    eventInside(event) {
 | 
			
		||||
 | 
			
		||||
        let local = this.toLocal(event.data.global)
 | 
			
		||||
        for (let child of this.children) {
 | 
			
		||||
            let r = child.getBounds()
 | 
			
		||||
            if (r.contains(local.x, local.y)) {
 | 
			
		||||
                console.log("Child touched")
 | 
			
		||||
                return false
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (local.x < 0 || local.x > this.wantedWidth)
 | 
			
		||||
            return false
 | 
			
		||||
        if (local.y < 0 || local.y > this.wantedHeight)
 | 
			
		||||
            return false
 | 
			
		||||
        event.stopPropagation()
 | 
			
		||||
        if (this.debug) console.log("stopPropagation", event)
 | 
			
		||||
        if (event.data.originalEvent.claimedByScatter) {
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toLocalPoint(event) {
 | 
			
		||||
        return this.toLocal(event.data.global)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toStroke(event) {
 | 
			
		||||
        let local = this.toLocalPoint(event)
 | 
			
		||||
        let x = Math.max(0, Math.min(local.x, this.wantedWidth))
 | 
			
		||||
        let y = Math.max(0, Math.min(local.y, this.wantedHeight))
 | 
			
		||||
        let desc = {
 | 
			
		||||
            x, y,
 | 
			
		||||
            pressure: event.pressure || null,
 | 
			
		||||
            tiltX: this.tiltX, tiltY: this.tiltY,
 | 
			
		||||
            color: this.color
 | 
			
		||||
        }
 | 
			
		||||
        return desc
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    startStroke(info) {
 | 
			
		||||
        this.stroke = [info]
 | 
			
		||||
        this.redraw()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    moveStroke(info) {
 | 
			
		||||
        this.stroke.push(info)
 | 
			
		||||
        this.redraw()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    endStroke(info) {
 | 
			
		||||
        if (this.stroke.length > 1) {
 | 
			
		||||
            let cmd = new StrokeCommand(this.stroke)
 | 
			
		||||
            cmd.do(this)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tiltToLineWidth(value) {
 | 
			
		||||
        return Math.round(Math.abs(value / 10) + 1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    drawStroke(stroke) {
 | 
			
		||||
        if (stroke.length) {
 | 
			
		||||
            let start = stroke[0]
 | 
			
		||||
            this.beginFill(0, 0)
 | 
			
		||||
            this.moveTo(start.x, start.y)
 | 
			
		||||
            for (let i = 1; i < stroke.length; i++) {
 | 
			
		||||
                let info = stroke[i]
 | 
			
		||||
                this.lineStyle(this.tiltToLineWidth(info.tiltY),
 | 
			
		||||
                    info.color, this.colorAlpha)
 | 
			
		||||
                this.lineTo(info.x, info.y)
 | 
			
		||||
            }
 | 
			
		||||
            this.endFill()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    drawTouch(point) {
 | 
			
		||||
        this.beginFill(0, 0)
 | 
			
		||||
        this.drawCircle(point.x, point.y, 22)
 | 
			
		||||
        this.endFill()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    drawStrokes() {
 | 
			
		||||
        this.drawBackground()
 | 
			
		||||
        this.lineStyle(1.0, 0xFF0000, 1)
 | 
			
		||||
        for (let stroke of this.iterStrokes()) {
 | 
			
		||||
            this.drawStroke(stroke)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    redraw() {
 | 
			
		||||
        this.drawStrokes()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Can be overwritten if different levels of strokes are necessary
 | 
			
		||||
    *iterStrokes() {
 | 
			
		||||
        for (let stroke of this.strokes) {
 | 
			
		||||
            yield stroke
 | 
			
		||||
        }
 | 
			
		||||
        yield this.stroke
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    changed() {
 | 
			
		||||
        // Can be overwritten
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clearAll() {
 | 
			
		||||
        let cmd = new ClearCommand()
 | 
			
		||||
        cmd.do(this)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    normalizeInfo(info) {
 | 
			
		||||
        let { x, y, pressure, tiltX, tiltY, color } = info
 | 
			
		||||
        x /= this.wantedWidth
 | 
			
		||||
        y /= this.wantedHeight
 | 
			
		||||
        return { x, y, pressure, tiltX, tiltY, color }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    denormalizeInfo(info) {
 | 
			
		||||
        let { x, y, pressure, tiltX, tiltY, color } = info
 | 
			
		||||
        x = x * this.wantedWidth
 | 
			
		||||
        y = y * this.wantedHeight
 | 
			
		||||
        return { x, y, pressure, tiltX, tiltY, color }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Convert strokes into an object that can be stored in an Indexed DB.
 | 
			
		||||
    // Returns normalized strokes
 | 
			
		||||
    toObject() {
 | 
			
		||||
        let result = []
 | 
			
		||||
        for (let stroke of this.strokes) {
 | 
			
		||||
            let normalized = []
 | 
			
		||||
            for (let info of stroke) {
 | 
			
		||||
                normalized.push(this.normalizeInfo(info))
 | 
			
		||||
            }
 | 
			
		||||
            result.push(normalized)
 | 
			
		||||
        }
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Read normalized strokes from an object from an Indexed DB.
 | 
			
		||||
    fromObject(normalizedStrokes) {
 | 
			
		||||
        this.strokes = []
 | 
			
		||||
        for (let stroke of normalizedStrokes) {
 | 
			
		||||
            let denormalized = []
 | 
			
		||||
            for (let info of stroke) {
 | 
			
		||||
                denormalized.push(this.denormalizeInfo(info))
 | 
			
		||||
            }
 | 
			
		||||
            this.strokes.push(denormalized)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Convert strokes into a JSON object that can be stored in an Indexed DB
 | 
			
		||||
    toJSON() {
 | 
			
		||||
        return JSON.stringify(this.toObject())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Convert strokes from a JSON
 | 
			
		||||
    fromJSON(json) {
 | 
			
		||||
        this.fromObject(JSON.parse(json))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Returns a set of used colors
 | 
			
		||||
    usedColors() {
 | 
			
		||||
        let used = new Set()
 | 
			
		||||
        for (let info of this.stroke) {
 | 
			
		||||
            used.add(info.color)
 | 
			
		||||
        }
 | 
			
		||||
        for (let stroke of this.strokes) {
 | 
			
		||||
            for (let info of stroke) {
 | 
			
		||||
                used.add(info.color)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return used.values()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 6.7 KiB  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user