/* symbols.js graphical GUI-symbols for for morphic.js and Snap! written by Jens Mönig jens@moenig.org Copyright (C) 2019 by Jens Mönig This file is part of Snap!. Snap! is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . prerequisites: -------------- needs morphic.js prerequisites: -------------- additional symbols have been contributed by members of the Snap! open-source community, especially by Bernat Romagosa */ /*global modules, Morph, Point, newCanvas, Costume, radians, Color*/ // Global stuff //////////////////////////////////////////////////////// modules.symbols = '2019-February-07'; var SymbolMorph; /* WorldMorph.prototype.customMorphs = function () { // add examples to the world's demo menu return [ new SymbolMorph( 'globe', 50, new Color(250, 250, 250), new Point(-1, -1), new Color(20, 20, 20) ) ]; }; */ // SymbolMorph ////////////////////////////////////////////////////////// /* I display graphical symbols, such as special letters. I have been called into existence out of frustration about not being able to consistently use Unicode characters to the same ends. Symbols can also display costumes, if one is specified in lieu of a name property, although this feature is currently not being used because of asynchronous image loading issues. */ // SymbolMorph inherits from Morph: SymbolMorph.prototype = new Morph(); SymbolMorph.prototype.constructor = SymbolMorph; SymbolMorph.uber = Morph.prototype; // SymbolMorph available symbols: SymbolMorph.prototype.names = [ 'square', 'pointRight', 'stepForward', 'gears', 'file', 'fullScreen', 'normalScreen', 'smallStage', 'normalStage', 'turtle', 'stage', 'turtleOutline', 'pause', 'flag', 'octagon', 'cloud', 'cloudOutline', 'cloudGradient', 'turnRight', 'turnLeft', 'storage', 'poster', 'flash', 'brush', 'rectangle', 'rectangleSolid', 'circle', 'circleSolid', 'ellipse', 'line', 'cross', 'crosshairs', 'paintbucket', 'eraser', 'pipette', 'speechBubble', 'speechBubbleOutline', 'loop', 'turnBack', 'turnForward', 'arrowUp', 'arrowUpOutline', 'arrowLeft', 'arrowLeftOutline', 'arrowDown', 'arrowDownOutline', 'arrowRight', 'arrowRightOutline', 'robot', 'magnifyingGlass', 'magnifierOutline', 'selection', 'polygon', 'closedBrush', 'notes', 'camera', 'location', 'footprints', 'keyboard', 'keyboardFilled', 'globe' ]; // SymbolMorph instance creation: function SymbolMorph(name, size, color, shadowOffset, shadowColor) { this.init(name, size, color, shadowOffset, shadowColor); } SymbolMorph.prototype.init = function ( name, // or costume size, color, shadowOffset, shadowColor ) { this.isProtectedLabel = false; // participate in zebraing this.isReadOnly = true; this.name = name || 'square'; // can also be a costume this.size = size || ((size === 0) ? 0 : 50); this.shadowOffset = shadowOffset || new Point(0, 0); this.shadowColor = shadowColor || null; SymbolMorph.uber.init.call(this, true); // silently this.color = color || new Color(0, 0, 0); this.drawNew(); }; // SymbolMorph zebra coloring: SymbolMorph.prototype.setLabelColor = function ( textColor, shadowColor, shadowOffset ) { this.shadowOffset = shadowOffset || new Point(); this.shadowColor = shadowColor; this.setColor(textColor); }; // SymbolMorph displaying: SymbolMorph.prototype.drawNew = function () { var ctx, x, y, sx, sy; this.image = newCanvas(new Point( this.symbolWidth() + Math.abs(this.shadowOffset.x), this.size + Math.abs(this.shadowOffset.y) )); this.silentSetWidth(this.image.width); this.silentSetHeight(this.image.height); ctx = this.image.getContext('2d'); sx = this.shadowOffset.x < 0 ? 0 : this.shadowOffset.x; sy = this.shadowOffset.y < 0 ? 0 : this.shadowOffset.y; x = this.shadowOffset.x < 0 ? Math.abs(this.shadowOffset.x) : 0; y = this.shadowOffset.y < 0 ? Math.abs(this.shadowOffset.y) : 0; if (this.shadowColor) { ctx.drawImage( this.symbolCanvasColored(this.shadowColor), sx, sy ); } ctx.drawImage( this.symbolCanvasColored(this.color), x, y ); }; SymbolMorph.prototype.symbolCanvasColored = function (aColor) { // private if (this.name instanceof Costume) { return this.name.thumbnail(new Point(this.symbolWidth(), this.size)); } var canvas = newCanvas(new Point(this.symbolWidth(), this.size)); switch (this.name) { case 'square': return this.drawSymbolStop(canvas, aColor); case 'pointRight': return this.drawSymbolPointRight(canvas, aColor); case 'stepForward': return this.drawSymbolStepForward(canvas, aColor); case 'gears': return this.drawSymbolGears(canvas, aColor); case 'file': return this.drawSymbolFile(canvas, aColor); case 'fullScreen': return this.drawSymbolFullScreen(canvas, aColor); case 'normalScreen': return this.drawSymbolNormalScreen(canvas, aColor); case 'smallStage': return this.drawSymbolSmallStage(canvas, aColor); case 'normalStage': return this.drawSymbolNormalStage(canvas, aColor); case 'turtle': return this.drawSymbolTurtle(canvas, aColor); case 'stage': return this.drawSymbolStop(canvas, aColor); case 'turtleOutline': return this.drawSymbolTurtleOutline(canvas, aColor); case 'pause': return this.drawSymbolPause(canvas, aColor); case 'flag': return this.drawSymbolFlag(canvas, aColor); case 'octagon': return this.drawSymbolOctagon(canvas, aColor); case 'cloud': return this.drawSymbolCloud(canvas, aColor); case 'cloudOutline': return this.drawSymbolCloudOutline(canvas, aColor); case 'cloudGradient': return this.drawSymbolCloudGradient(canvas, aColor); case 'turnRight': return this.drawSymbolTurnRight(canvas, aColor); case 'turnLeft': return this.drawSymbolTurnLeft(canvas, aColor); case 'storage': return this.drawSymbolStorage(canvas, aColor); case 'poster': return this.drawSymbolPoster(canvas, aColor); case 'flash': return this.drawSymbolFlash(canvas, aColor); case 'brush': return this.drawSymbolBrush(canvas, aColor); case 'rectangle': return this.drawSymbolRectangle(canvas, aColor); case 'rectangleSolid': return this.drawSymbolRectangleSolid(canvas, aColor); case 'circle': return this.drawSymbolCircle(canvas, aColor); case 'circleSolid': return this.drawSymbolCircleSolid(canvas, aColor); case 'ellipse': return this.drawSymbolCircle(canvas, aColor); case 'line': return this.drawSymbolLine(canvas, aColor); case 'cross': return this.drawSymbolCross(canvas, aColor); case 'crosshairs': return this.drawSymbolCrosshairs(canvas, aColor); case 'paintbucket': return this.drawSymbolPaintbucket(canvas, aColor); case 'eraser': return this.drawSymbolEraser(canvas, aColor); case 'pipette': return this.drawSymbolPipette(canvas, aColor); case 'speechBubble': return this.drawSymbolSpeechBubble(canvas, aColor); case 'speechBubbleOutline': return this.drawSymbolSpeechBubbleOutline(canvas, aColor); case 'loop': return this.drawSymbolLoop(canvas, aColor); case 'turnBack': return this.drawSymbolTurnBack(canvas, aColor); case 'turnForward': return this.drawSymbolTurnForward(canvas, aColor); case 'arrowUp': return this.drawSymbolArrowUp(canvas, aColor); case 'arrowUpOutline': return this.drawSymbolArrowUpOutline(canvas, aColor); case 'arrowLeft': return this.drawSymbolArrowLeft(canvas, aColor); case 'arrowLeftOutline': return this.drawSymbolArrowLeftOutline(canvas, aColor); case 'arrowDown': return this.drawSymbolArrowDown(canvas, aColor); case 'arrowDownOutline': return this.drawSymbolArrowDownOutline(canvas, aColor); case 'arrowRight': return this.drawSymbolArrowRight(canvas, aColor); case 'arrowRightOutline': return this.drawSymbolArrowRightOutline(canvas, aColor); case 'robot': return this.drawSymbolRobot(canvas, aColor); case 'magnifyingGlass': return this.drawSymbolMagnifyingGlass(canvas, aColor); case 'magnifierOutline': return this.drawSymbolMagnifierOutline(canvas, aColor); case 'selection': return this.drawSymbolSelection(canvas, aColor); case 'polygon': return this.drawSymbolOctagonOutline(canvas, aColor); case 'closedBrush': return this.drawSymbolClosedBrushPath(canvas, aColor); case 'notes': return this.drawSymbolNotes(canvas, aColor); case 'camera': return this.drawSymbolCamera(canvas, aColor); case 'location': return this.drawSymbolLocation(canvas, aColor); case 'footprints': return this.drawSymbolFootprints(canvas, aColor); case 'keyboard': return this.drawSymbolKeyboard(canvas, aColor); case 'keyboardFilled': return this.drawSymbolKeyboardFilled(canvas, aColor); case 'globe': return this.drawSymbolGlobe(canvas, aColor); default: return canvas; } }; SymbolMorph.prototype.symbolWidth = function () { // private var size = this.size; if (this.name instanceof Costume) { return (size / this.name.height()) * this.name.width(); } switch (this.name) { case 'pointRight': return Math.sqrt(size * size - Math.pow(size / 2, 2)); case 'location': return size * 0.6; case 'flash': case 'file': return size * 0.8; case 'smallStage': case 'normalStage': return size * 1.2; case 'turtle': case 'turtleOutline': case 'stage': return size * 1.3; case 'cloud': case 'cloudGradient': case 'cloudOutline': case 'turnBack': case 'turnForward': case 'keyboard': case 'keyboardFilled': return size * 1.6; case 'turnRight': case 'turnLeft': return size / 3 * 2; case 'loop': return size * 2; default: return size; } }; SymbolMorph.prototype.drawSymbolStop = function (canvas, color) { // answer a canvas showing a vertically centered square var ctx = canvas.getContext('2d'); ctx.fillStyle = color.toString(); ctx.fillRect(0, 0, canvas.width, canvas.height); return canvas; }; SymbolMorph.prototype.drawSymbolPointRight = function (canvas, color) { // answer a canvas showing a right-pointing, equilateral triangle var ctx = canvas.getContext('2d'); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(canvas.width, Math.round(canvas.height / 2)); ctx.lineTo(0, canvas.height); ctx.lineTo(0, 0); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolStepForward = function (canvas, color) { // answer a canvas showing a right-pointing triangle // followed by a vertical bar var ctx = canvas.getContext('2d'); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(canvas.width * 0.75, Math.round(canvas.height / 2)); ctx.lineTo(0, canvas.height); ctx.lineTo(0, 0); ctx.closePath(); ctx.fill(); ctx.fillRect( canvas.width * 0.75, 0, canvas.width * 0.25, canvas.height ); return canvas; }; SymbolMorph.prototype.drawSymbolGears = function (canvas, color) { // answer a canvas showing gears var ctx = canvas.getContext('2d'), w = canvas.width, r = w / 2, e = w / 6; ctx.strokeStyle = color.toString(); ctx.lineWidth = canvas.width / 7; ctx.beginPath(); ctx.arc(r, r, w, radians(0), radians(360), true); ctx.arc(r, r, e * 1.5, radians(0), radians(360), false); ctx.closePath(); ctx.clip(); ctx.moveTo(0, r); ctx.lineTo(w, r); ctx.stroke(); ctx.moveTo(r, 0); ctx.lineTo(r, w); ctx.stroke(); ctx.moveTo(e, e); ctx.lineTo(w - e, w - e); ctx.stroke(); ctx.moveTo(w - e, e); ctx.lineTo(e, w - e); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolFile = function (canvas, color) { // answer a canvas showing a page symbol var ctx = canvas.getContext('2d'), w = Math.min(canvas.width, canvas.height) / 2; ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(w, 0); ctx.lineTo(w, w); ctx.lineTo(canvas.width, w); ctx.lineTo(canvas.width, canvas.height); ctx.lineTo(0, canvas.height); ctx.closePath(); ctx.fill(); ctx.fillStyle = color.darker(25).toString(); ctx.beginPath(); ctx.moveTo(w, 0); ctx.lineTo(canvas.width, w); ctx.lineTo(w, w); ctx.lineTo(w, 0); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolFullScreen = function (canvas, color) { // answer a canvas showing two arrows pointing diagonally outwards var ctx = canvas.getContext('2d'), h = canvas.height, c = canvas.width / 2, off = canvas.width / 20, w = canvas.width / 2; ctx.strokeStyle = color.toString(); ctx.lineWidth = canvas.width / 5; ctx.moveTo(c - off, c + off); ctx.lineTo(0, h); ctx.stroke(); ctx.strokeStyle = color.toString(); ctx.lineWidth = canvas.width / 5; ctx.moveTo(c + off, c - off); ctx.lineTo(h, 0); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, h); ctx.lineTo(0, h - w); ctx.lineTo(w, h); ctx.closePath(); ctx.fill(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(h, 0); ctx.lineTo(h - w, 0); ctx.lineTo(h, w); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolNormalScreen = function (canvas, color) { // answer a canvas showing two arrows pointing diagonally inwards var ctx = canvas.getContext('2d'), h = canvas.height, c = canvas.width / 2, off = canvas.width / 20, w = canvas.width; ctx.strokeStyle = color.toString(); ctx.lineWidth = canvas.width / 5; ctx.moveTo(c - off * 3, c + off * 3); ctx.lineTo(0, h); ctx.stroke(); ctx.strokeStyle = color.toString(); ctx.lineWidth = canvas.width / 5; ctx.moveTo(c + off * 3, c - off * 3); ctx.lineTo(h, 0); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(c + off, c - off); ctx.lineTo(w, c - off); ctx.lineTo(c + off, 0); ctx.closePath(); ctx.fill(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(c - off, c + off); ctx.lineTo(0, c + off); ctx.lineTo(c - off, w); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolSmallStage = function (canvas, color) { // answer a canvas showing a stage toggling symbol var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, w2 = w / 2, h2 = h / 2; ctx.fillStyle = color.darker(40).toString(); ctx.fillRect(0, 0, w, h); ctx.fillStyle = color.toString(); ctx.fillRect(w2, 0, w2, h2); return canvas; }; SymbolMorph.prototype.drawSymbolNormalStage = function (canvas, color) { // answer a canvas showing a stage toggling symbol var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, w2 = w / 2, h2 = h / 2; ctx.fillStyle = color.toString(); ctx.fillRect(0, 0, w, h); ctx.fillStyle = color.darker(25).toString(); ctx.fillRect(w2, 0, w2, h2); return canvas; }; SymbolMorph.prototype.drawSymbolTurtle = function (canvas, color) { // answer a canvas showing a turtle var ctx = canvas.getContext('2d'); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(canvas.width, canvas.height / 2); ctx.lineTo(0, canvas.height); ctx.lineTo(canvas.height / 2, canvas.height / 2); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolTurtleOutline = function (canvas, color) { // answer a canvas showing a turtle var ctx = canvas.getContext('2d'); ctx.strokeStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(canvas.width, canvas.height / 2); ctx.lineTo(0, canvas.height); ctx.lineTo(canvas.height / 2, canvas.height / 2); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolPause = function (canvas, color) { // answer a canvas showing two parallel rectangles var ctx = canvas.getContext('2d'), w = canvas.width / 5; ctx.fillStyle = color.toString(); ctx.fillRect(0, 0, w * 2, canvas.height); ctx.fillRect(w * 3, 0, w * 2, canvas.height); return canvas; }; SymbolMorph.prototype.drawSymbolFlag = function (canvas, color) { // answer a canvas showing a flag var ctx = canvas.getContext('2d'), w = canvas.width, l = Math.max(w / 12, 1), h = canvas.height; ctx.lineWidth = l; ctx.strokeStyle = color.toString(); ctx.beginPath(); ctx.moveTo(l / 2, 0); ctx.lineTo(l / 2, canvas.height); ctx.stroke(); ctx.lineWidth = h / 2; ctx.beginPath(); ctx.moveTo(0, h / 4); ctx.bezierCurveTo( w * 0.8, h / 4, w * 0.1, h * 0.5, w, h * 0.5 ); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolOctagon = function (canvas, color) { // answer a canvas showing an octagon var ctx = canvas.getContext('2d'), side = canvas.width, vert = (side - (side * 0.383)) / 2; ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(vert, 0); ctx.lineTo(side - vert, 0); ctx.lineTo(side, vert); ctx.lineTo(side, side - vert); ctx.lineTo(side - vert, side); ctx.lineTo(vert, side); ctx.lineTo(0, side - vert); ctx.lineTo(0, vert); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolCloud = function (canvas, color) { // answer a canvas showing an cloud var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, r1 = h * 2 / 5, r2 = h / 4, r3 = h * 3 / 10, r4 = h / 5; ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.arc(r2, h - r2, r2, radians(90), radians(259), false); ctx.arc(w / 20 * 5, h / 9 * 4, r4, radians(165), radians(300), false); ctx.arc(w / 20 * 11, r1, r1, radians(200), radians(357), false); ctx.arc(w - r3, h - r3, r3, radians(269), radians(90), false); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolCloudGradient = function (canvas, color) { // answer a canvas showing an cloud var ctx = canvas.getContext('2d'), gradient, w = canvas.width, h = canvas.height, r1 = h * 2 / 5, r2 = h / 4, r3 = h * 3 / 10, r4 = h / 5; gradient = ctx.createRadialGradient( 0, 0, 0, 0, 0, w ); gradient.addColorStop(0, color.lighter(25).toString()); gradient.addColorStop(1, color.darker(25).toString()); ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(r2, h - r2, r2, radians(90), radians(259), false); ctx.arc(w / 20 * 5, h / 9 * 4, r4, radians(165), radians(300), false); ctx.arc(w / 20 * 11, r1, r1, radians(200), radians(357), false); ctx.arc(w - r3, h - r3, r3, radians(269), radians(90), false); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolCloudOutline = function (canvas, color) { // answer a canvas showing an cloud var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, r1 = h * 2 / 5, r2 = h / 4, r3 = h * 3 / 10, r4 = h / 5; ctx.strokeStyle = color.toString(); ctx.beginPath(); ctx.arc(r2 + 1, h - r2 - 1, r2, radians(90), radians(259), false); ctx.arc(w / 20 * 5, h / 9 * 4, r4, radians(165), radians(300), false); ctx.arc(w / 20 * 11, r1 + 1, r1, radians(200), radians(357), false); ctx.arc(w - r3 - 1, h - r3 - 1, r3, radians(269), radians(90), false); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolTurnRight = function (canvas, color) { // answer a canvas showing a right-turning arrow var ctx = canvas.getContext('2d'), w = canvas.width, l = Math.max(w / 10, 1), r = w / 2; ctx.lineWidth = l; ctx.strokeStyle = color.toString(); ctx.beginPath(); ctx.arc(r, r * 2, r - l / 2, radians(0), radians(-90), false); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(w, r); ctx.lineTo(r, 0); ctx.lineTo(r, r * 2); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolTurnLeft = function (canvas, color) { // answer a canvas showing a left-turning arrow var ctx = canvas.getContext('2d'), w = canvas.width, l = Math.max(w / 10, 1), r = w / 2; ctx.lineWidth = l; ctx.strokeStyle = color.toString(); ctx.beginPath(); ctx.arc(r, r * 2, r - l / 2, radians(180), radians(-90), true); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, r); ctx.lineTo(r, 0); ctx.lineTo(r, r * 2); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolStorage = function (canvas, color) { // answer a canvas showing a stack of three disks var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, r = canvas.height, unit = canvas.height / 11; function drawDisk(bottom, fillTop) { ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.arc(w / 2, bottom - h, r, radians(60), radians(120), false); ctx.lineTo(0, bottom - unit * 2); ctx.arc( w / 2, bottom - h - unit * 2, r, radians(120), radians(60), true ); ctx.closePath(); ctx.fill(); ctx.fillStyle = color.darker(25).toString(); ctx.beginPath(); if (fillTop) { ctx.arc( w / 2, bottom - h - unit * 2, r, radians(120), radians(60), true ); } ctx.arc( w / 2, bottom + unit * 6 + 1, r, radians(60), radians(120), true ); ctx.closePath(); if (fillTop) { ctx.fill(); } else { ctx.stroke(); } } ctx.strokeStyle = color.toString(); drawDisk(h); drawDisk(h - unit * 3); drawDisk(h - unit * 6, false); return canvas; }; SymbolMorph.prototype.drawSymbolPoster = function (canvas, color) { // answer a canvas showing a poster stand var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, bottom = h * 0.75, edge = canvas.height / 5; ctx.fillStyle = color.toString(); ctx.strokeStyle = color.toString(); ctx.lineWidth = w / 15; ctx.moveTo(w / 2, h / 3); ctx.lineTo(w / 6, h); ctx.stroke(); ctx.moveTo(w / 2, h / 3); ctx.lineTo(w / 2, h); ctx.stroke(); ctx.moveTo(w / 2, h / 3); ctx.lineTo(w * 5 / 6, h); ctx.stroke(); ctx.fillRect(0, 0, w, bottom); ctx.clearRect(0, bottom, w, w / 20); ctx.clearRect(w - edge, bottom - edge, edge + 1, edge + 1); ctx.fillStyle = color.darker(25).toString(); ctx.beginPath(); ctx.moveTo(w, bottom - edge); ctx.lineTo(w - edge, bottom - edge); ctx.lineTo(w - edge, bottom); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolFlash = function (canvas, color) { // answer a canvas showing a flash var ctx = canvas.getContext('2d'), w = canvas.width, w3 = w / 3, h = canvas.height, h3 = h / 3, off = h3 / 3; ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(w3, 0); ctx.lineTo(0, h3); ctx.lineTo(w3, h3); ctx.lineTo(0, h3 * 2); ctx.lineTo(w3, h3 * 2); ctx.lineTo(0, h); ctx.lineTo(w, h3 * 2 - off); ctx.lineTo(w3 * 2, h3 * 2 - off); ctx.lineTo(w, h3 - off); ctx.lineTo(w3 * 2, h3 - off); ctx.lineTo(w, 0); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolBrush = function (canvas, color) { // answer a canvas showing a paintbrush var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, l = Math.max(w / 30, 0.5); ctx.fillStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(w / 8 * 3, h / 2); ctx.quadraticCurveTo(0, h / 2, l, h - l); ctx.quadraticCurveTo(w / 2, h, w / 2, h / 8 * 5); ctx.closePath(); ctx.fill(); ctx.lineJoin = 'round'; ctx.lineCap = 'round'; ctx.strokeStyle = color.toString(); ctx.moveTo(w / 8 * 3, h / 2); ctx.lineTo(w * 0.75, l); ctx.quadraticCurveTo(w, 0, w - l, h * 0.25); ctx.stroke(); ctx.moveTo(w / 2, h / 8 * 5); ctx.lineTo(w - l, h * 0.25); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolRectangle = function (canvas, color) { // answer a canvas showing a rectangle var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.width, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(l, l); ctx.lineTo(w - l, l); ctx.lineTo(w - l, h - l); ctx.lineTo(l, h - l); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolRectangleSolid = function (canvas, color) { // answer a canvas showing a solid rectangle var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.width; ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(w, 0); ctx.lineTo(w, h); ctx.lineTo(0, h); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolCircle = function (canvas, color) { // answer a canvas showing a circle var ctx = canvas.getContext('2d'), w = canvas.width, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.arc(w / 2, w / 2, w / 2 - l, radians(0), radians(360), false); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolCircleSolid = function (canvas, color) { // answer a canvas showing a solid circle var ctx = canvas.getContext('2d'), w = canvas.width; ctx.fillStyle = color.toString(); ctx.arc(w / 2, w / 2, w / 2, radians(0), radians(360), false); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolLine = function (canvas, color) { // answer a canvas showing a plus sign cross var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.lineCap = 'round'; ctx.moveTo(l, l); ctx.lineTo(w - l, h - l); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolCross = function (canvas, color) { // answer a canvas showing a diagonal line var ctx = canvas.getContext('2d'), w = canvas.width, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.lineCap = 'round'; ctx.moveTo(l, w / 2); ctx.lineTo(w - l, w / 2); ctx.stroke(); ctx.moveTo(w / 2, l); ctx.lineTo(w / 2, w - l); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolCrosshairs = function (canvas, color) { // answer a canvas showing a crosshairs var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, l = 0.5; ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.moveTo(l, h / 2); ctx.lineTo(w - l, h / 2); ctx.stroke(); ctx.moveTo(w / 2, l); ctx.lineTo(w / 2, h - l); ctx.stroke(); ctx.moveTo(w / 2, h / 2); ctx.arc(w / 2, w / 2, w / 3 - l, radians(0), radians(360), false); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolPaintbucket = function (canvas, color) { // answer a canvas showing a paint bucket var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 5, l = Math.max(w / 30, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(n * 2, n); ctx.lineTo(n * 4, n * 3); ctx.lineTo(n * 3, n * 4); ctx.quadraticCurveTo(n * 2, h, n, n * 4); ctx.quadraticCurveTo(0, n * 3, n, n * 2); ctx.closePath(); ctx.stroke(); ctx.lineWidth = l; ctx.moveTo(n * 2, n * 2.5); ctx.arc(n * 2, n * 2.5, l, radians(0), radians(360), false); ctx.stroke(); ctx.moveTo(n * 2, n * 2.5); ctx.lineTo(n * 2, n / 2 + l); ctx.stroke(); ctx.arc(n * 1.5, n / 2 + l, n / 2, radians(0), radians(180), true); ctx.stroke(); ctx.moveTo(n, n / 2 + l); ctx.lineTo(n, n * 2); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(n * 3.5, n * 3.5); ctx.quadraticCurveTo(w, n * 3.5, w - l, h); ctx.lineTo(w, h); ctx.quadraticCurveTo(w, n * 2, n * 2.5, n * 1.5); ctx.lineTo(n * 4, n * 3); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolEraser = function (canvas, color) { // answer a canvas showing an eraser var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 4, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(n * 3, l); ctx.lineTo(l, n * 3); ctx.quadraticCurveTo(n, h, n * 2, n * 3); ctx.lineTo(w - l, n); ctx.closePath(); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(n * 3, 0); ctx.lineTo(n * 1.5, n * 1.5); ctx.lineTo(n * 2.5, n * 2.5); ctx.lineTo(w, n); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolPipette = function (canvas, color) { // answer a canvas showing an eyedropper var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 4, n2 = n / 2, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(l, h - l); ctx.quadraticCurveTo(n2, h - n2, n2, h - n); ctx.lineTo(n * 2, n * 1.5); ctx.stroke(); ctx.beginPath(); ctx.moveTo(l, h - l); ctx.quadraticCurveTo(n2, h - n2, n, h - n2); ctx.lineTo(n * 2.5, n * 2); ctx.stroke(); ctx.fillStyle = color.toString(); ctx.arc(n * 3, n, n - l, radians(0), radians(360), false); ctx.fill(); ctx.beginPath(); ctx.moveTo(n * 2, n); ctx.lineTo(n * 3, n * 2); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolSpeechBubble = function (canvas, color) { // answer a canvas showing a speech bubble var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 3, l = Math.max(w / 20, 0.5); ctx.fillStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(n, n * 2); ctx.quadraticCurveTo(l, n * 2, l, n); ctx.quadraticCurveTo(l, l, n, l); ctx.lineTo(n * 2, l); ctx.quadraticCurveTo(w - l, l, w - l, n); ctx.quadraticCurveTo(w - l, n * 2, n * 2, n * 2); ctx.lineTo(n / 2, h - l); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolSpeechBubbleOutline = function ( canvas, color ) { // answer a canvas showing a speech bubble var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 3, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(n, n * 2); ctx.quadraticCurveTo(l, n * 2, l, n); ctx.quadraticCurveTo(l, l, n, l); ctx.lineTo(n * 2, l); ctx.quadraticCurveTo(w - l, l, w - l, n); ctx.quadraticCurveTo(w - l, n * 2, n * 2, n * 2); ctx.lineTo(n / 2, h - l); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolLoop = function (canvas, aColor) { var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, w2 = canvas.width / 2, w4 = w2 / 2, h2 = canvas.height / 2, l = Math.max(h / 10, 0.5); ctx.lineWidth = l * 2; ctx.strokeStyle = aColor.toString(); ctx.beginPath(); ctx.moveTo(0, h - l); ctx.lineTo(w2, h - l); ctx.arc(w2, h2, h2 - l, radians(90), radians(0), true); ctx.stroke(); ctx.fillStyle = aColor.toString(); ctx.beginPath(); ctx.moveTo(w4 * 3 - l, 0); ctx.lineTo(w2 - l, h2); ctx.lineTo(w, h2); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolTurnBack = function (canvas, aColor) { var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, w2 = canvas.width / 2, h2 = canvas.height / 2, l = Math.max(w / 20, 0.5); ctx.fillStyle = aColor.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(0, h2); ctx.lineTo(w2, 0); ctx.lineTo(w2, h); ctx.closePath(); ctx.fill(); ctx.lineWidth = l * 3; ctx.strokeStyle = aColor.toString(); ctx.beginPath(); ctx.arc(w2, h, h2, radians(0), radians(-90), true); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolTurnForward = function (canvas, aColor) { var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, w2 = canvas.width / 2, h2 = canvas.height / 2, l = Math.max(w / 20, 0.5); ctx.fillStyle = aColor.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(w, h2); ctx.lineTo(w2, 0); ctx.lineTo(w2, h); ctx.closePath(); ctx.fill(); ctx.lineWidth = l * 3; ctx.strokeStyle = aColor.toString(); ctx.beginPath(); ctx.arc(w2, h, h2, radians(-180), radians(-90), false); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowUp = function (canvas, color) { // answer a canvas showing an up arrow var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 2, l = Math.max(w / 20, 0.5); ctx.fillStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(l, n); ctx.lineTo(n, l); ctx.lineTo(w - l, n); ctx.lineTo(w * 0.65, n); ctx.lineTo(w * 0.65, h - l); ctx.lineTo(w * 0.35, h - l); ctx.lineTo(w * 0.35, n); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowUpOutline = function (canvas, color) { // answer a canvas showing an up arrow var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 2, l = Math.max(w / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(l, n); ctx.lineTo(n, l); ctx.lineTo(w - l, n); ctx.lineTo(w * 0.65, n); ctx.lineTo(w * 0.65, h - l); ctx.lineTo(w * 0.35, h - l); ctx.lineTo(w * 0.35, n); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowDown = function (canvas, color) { // answer a canvas showing a down arrow var ctx = canvas.getContext('2d'), w = canvas.width; ctx.save(); ctx.translate(w, w); ctx.rotate(radians(180)); this.drawSymbolArrowUp(canvas, color); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowDownOutline = function (canvas, color) { // answer a canvas showing a down arrow var ctx = canvas.getContext('2d'), w = canvas.width; ctx.save(); ctx.translate(w, w); ctx.rotate(radians(180)); this.drawSymbolArrowUpOutline(canvas, color); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowLeft = function (canvas, color) { // answer a canvas showing a left arrow var ctx = canvas.getContext('2d'), w = canvas.width; ctx.save(); ctx.translate(0, w); ctx.rotate(radians(-90)); this.drawSymbolArrowUp(canvas, color); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowLeftOutline = function (canvas, color) { // answer a canvas showing a left arrow var ctx = canvas.getContext('2d'), w = canvas.width; ctx.save(); ctx.translate(0, w); ctx.rotate(radians(-90)); this.drawSymbolArrowUpOutline(canvas, color); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowRight = function (canvas, color) { // answer a canvas showing a right arrow var ctx = canvas.getContext('2d'), w = canvas.width; ctx.save(); ctx.translate(w, 0); ctx.rotate(radians(90)); this.drawSymbolArrowUp(canvas, color); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolArrowRightOutline = function (canvas, color) { // answer a canvas showing a right arrow var ctx = canvas.getContext('2d'), w = canvas.width; ctx.save(); ctx.translate(w, 0); ctx.rotate(radians(90)); this.drawSymbolArrowUpOutline(canvas, color); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolRobot = function (canvas, color) { // answer a canvas showing a humanoid robot var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, n = canvas.width / 6, n2 = n / 2, l = Math.max(w / 20, 0.5); ctx.fillStyle = color.toString(); //ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(n + l, n); ctx.lineTo(n * 2, n); ctx.lineTo(n * 2.5, n * 1.5); ctx.lineTo(n * 3.5, n * 1.5); ctx.lineTo(n * 4, n); ctx.lineTo(n * 5 - l, n); ctx.lineTo(n * 4, n * 3); ctx.lineTo(n * 4, n * 4 - l); ctx.lineTo(n * 2, n * 4 - l); ctx.lineTo(n * 2, n * 3); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(n * 2.75, n + l); ctx.lineTo(n * 2.4, n); ctx.lineTo(n * 2.2, 0); ctx.lineTo(n * 3.8, 0); ctx.lineTo(n * 3.6, n); ctx.lineTo(n * 3.25, n + l); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(n * 2.5, n * 4); ctx.lineTo(n, n * 4); ctx.lineTo(n2 + l, h); ctx.lineTo(n * 2, h); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(n * 3.5, n * 4); ctx.lineTo(n * 5, n * 4); ctx.lineTo(w - (n2 + l), h); ctx.lineTo(n * 4, h); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(n, n); ctx.lineTo(l, n * 1.5); ctx.lineTo(l, n * 3.25); ctx.lineTo(n * 1.5, n * 3.5); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(n * 5, n); ctx.lineTo(w - l, n * 1.5); ctx.lineTo(w - l, n * 3.25); ctx.lineTo(n * 4.5, n * 3.5); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolMagnifyingGlass = function (canvas, color) { // answer a canvas showing a magnifying glass var ctx = canvas.getContext('2d'), gradient, w = canvas.width, h = canvas.height, r = w * 0.3, x = w * 2 / 3 - Math.sqrt(r), y = h / 3 + Math.sqrt(r), l = Math.max(w / 5, 0.5); ctx.strokeStyle = color.toString(); gradient = ctx.createRadialGradient( x, y, 0, x + r, y + r, w ); gradient.addColorStop(0, color.inverted().lighter(50).toString()); gradient.addColorStop(1, color.inverted().darker(25).toString()); ctx.fillStyle = gradient; ctx.arc(x, y, r, radians(0), radians(360), false); ctx.fill(); ctx.lineWidth = l / 2; ctx.arc(x, y, r, radians(0), radians(360), false); ctx.stroke(); ctx.lineWidth = l; ctx.beginPath(); ctx.moveTo(l / 2, h - l / 2); ctx.lineTo(x - Math.sqrt(r + l), y + Math.sqrt(r + l)); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolMagnifierOutline = function (canvas, color) { // answer a canvas showing a magnifying glass var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, r = w * 0.3, x = w * 2 / 3 - Math.sqrt(r), y = h / 3 + Math.sqrt(r), l = Math.max(w / 5, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 0.5; ctx.arc(x, y, r, radians(0), radians(360), false); ctx.stroke(); ctx.lineWidth = l; ctx.beginPath(); ctx.moveTo(l / 2, h - l / 2); ctx.lineTo(x - Math.sqrt(r + l), y + Math.sqrt(r + l)); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolSelection = function (canvas, color) { // answer a canvas showing a filled arrow and a dashed rectangle var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height; ctx.save(); ctx.setLineDash([3]); this.drawSymbolRectangle(canvas, color); ctx.restore(); ctx.save(); ctx.fillStyle = color.toString(); ctx.translate(0.7 * w, 0.4 * h); ctx.scale(0.5, 0.5); ctx.rotate(radians(135)); this.drawSymbolArrowDownOutline(canvas, color); ctx.fill(); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolOctagonOutline = function (canvas, color) { // answer a canvas showing an octagon var ctx = canvas.getContext('2d'), side = canvas.width, vert = (side - (side * 0.383)) / 2, l = Math.max(side / 20, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.beginPath(); ctx.moveTo(vert, l); ctx.lineTo(side - vert, l); ctx.lineTo(side - l, vert); ctx.lineTo(side - l, side - vert); ctx.lineTo(side - vert, side - l); ctx.lineTo(vert, side - l); ctx.lineTo(l, side - vert); ctx.lineTo(l, vert); ctx.closePath(); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolClosedBrushPath = SymbolMorph.prototype.drawSymbolCloudOutline; SymbolMorph.prototype.drawSymbolNotes = function (canvas, color) { // answer a canvas showing two musical notes var ctx = canvas.getContext('2d'), size = canvas.width, r = size / 6, l = Math.max(r / 3, 1); ctx.strokeStyle = color.toString(); ctx.fillStyle = color.toString(); ctx.arc(r, size - r, r, radians(0), radians(360), false); ctx.fill(); ctx.arc(size - r, size - (r * 2), r, radians(0), radians(360), false); ctx.fill(); ctx.beginPath(); ctx.moveTo(r * 2 - l, r); ctx.lineTo(size, 0); ctx.lineTo(size, r); ctx.lineTo(r * 2 - l, r * 2); ctx.closePath(); ctx.fill(); ctx.lineWidth = l; ctx.beginPath(); ctx.moveTo(r * 2 - (l / 2), size - r); ctx.lineTo(r * 2 - (l / 2), r + l); ctx.stroke(); ctx.beginPath(); ctx.moveTo(size - (l / 2), size - (r * 2)); ctx.lineTo(size - (l / 2), l); ctx.stroke(); return canvas; }; SymbolMorph.prototype.drawSymbolCamera = function (canvas, color) { // answer a canvas showing a camera var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.width, r = w * 0.16, l = Math.max(w / 20, 0.5); ctx.lineWidth = l * 2; // camera body ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.moveTo(l, h * 5 / 6); ctx.lineTo(w - l, h * 5 / 6); ctx.lineTo(w - l, h / 4); ctx.lineTo(w * 3 / 4 , h / 4); ctx.lineTo(w * 5 / 8 , l); ctx.lineTo(w * 3 / 8 , l); ctx.lineTo(w / 4 , h / 4); ctx.lineTo(l , h / 4); ctx.closePath(); ctx.fill(); // camera lens ctx.save(); ctx.globalCompositeOperation = 'destination-out'; ctx.beginPath(); ctx.arc(w / 2, h / 2, r, radians(0), radians(360), false); ctx.fill(); ctx.restore(); return canvas; }; SymbolMorph.prototype.drawSymbolLocation = function (canvas, color) { // answer a canvas showing a map pin var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, r = w / 2; // pin ctx.fillStyle = color.toString(); ctx.beginPath(); ctx.arc(r, r, r, radians(-210), radians(30), false); ctx.lineTo(r, h); ctx.closePath(); ctx.fill(); // hole ctx.globalCompositeOperation = 'destination-out'; ctx.beginPath(); ctx.arc(r, r, r * 0.5, radians(0), radians(360), false); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolFootprints = function (canvas, color) { // answer a canvas showing a pair of (shoe) footprints var ctx = canvas.getContext('2d'), w = canvas.width, u = w / 10, r = u * 1.5; ctx.fillStyle = color.toString(); // left shoe // tip ctx.beginPath(); ctx.arc(r, r, r, radians(-200), radians(0), false); ctx.lineTo(r * 2, u * 5.5); ctx.lineTo(u, u * 6); ctx.closePath(); ctx.fill(); // heel ctx.beginPath(); ctx.arc(u * 2.25, u * 6.75, u , radians(-40), radians(-170), false); ctx.closePath(); ctx.fill(); // right shoe // tip ctx.beginPath(); ctx.arc(w - r, u * 4.5, r, radians(-180), radians(20), false); ctx.lineTo(w - u, u * 8.5); ctx.lineTo(w - (r * 2), u * 8); ctx.closePath(); ctx.fill(); // heel ctx.beginPath(); ctx.arc(w - (u * 2.25), u * 9, u, radians(0), radians(-150), false); ctx.closePath(); ctx.fill(); return canvas; }; SymbolMorph.prototype.drawSymbolKeyboard = function (canvas, color) { // answer a canvas showing a typing keyboard var ctx = canvas.getContext('2d'), h = canvas.height, u = h / 10, k = h / 5, row, col; ctx.fillStyle = color.toString(); for (row = 0; row < 2; row += 1) { for (col = 0; col < 5; col += 1) { ctx.fillRect( ((u + k) * col) + u, ((u + k) * row) + u, k, k ); } } ctx.fillRect(u * 4, u * 7, k * 4, k); return canvas; }; SymbolMorph.prototype.drawSymbolKeyboardFilled = function (canvas, color) { // answer a canvas showing a typing keyboard var ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, u = h / 10, k = h / 5, row, col; ctx.fillStyle = color.toString(); ctx.fillRect(0, 0, w, h); ctx.globalCompositeOperation = 'destination-out'; for (row = 0; row < 2; row += 1) { for (col = 0; col < 5; col += 1) { ctx.fillRect( ((u + k) * col) + u, ((u + k) * row) + u, k, k ); } } ctx.fillRect(u * 4, u * 7, k * 4, k); return canvas; }; SymbolMorph.prototype.drawSymbolGlobe = function (canvas, color) { // answer a canvas showing a circle var ctx = canvas.getContext('2d'), w = canvas.width, l = Math.max(w / 30, 0.5); ctx.strokeStyle = color.toString(); ctx.lineWidth = l * 2; ctx.arc(w / 2, w / 2, w / 2 - l, radians(0), radians(360), false); ctx.stroke(); /* // more detailed version, commmented out ctx.moveTo(l, w / 3); ctx.lineTo(w - l, w / 3); ctx.stroke(); ctx.moveTo(l, 2 * w / 3); ctx.lineTo(w - l, 2 * w / 3); ctx.stroke(); */ // single line version, looks better when small: ctx.moveTo(l, w / 2); ctx.lineTo(w - l, w / 2); ctx.stroke(); ctx.moveTo(w / 2, 0); ctx.arcTo(0, w / 2, w / 2, w, w * 0.75); ctx.stroke(); ctx.moveTo(w / 2, 0); ctx.arcTo(w, w / 2, w / 2, w, w * 0.75); ctx.stroke(); return canvas; };