moebius-web

web based ansi art editor

tools/ellipse.js


function ellipseTool(editor) {
    "use strict";
    var canvas, ctx, fromBlock, oldTo, currentColor, filledEllipse;

    canvas = ElementHelper.create("canvas", {"width": 80 * editor.codepage.fontWidth, "height": editor.height * editor.codepage.fontHeight});
    ctx = canvas.getContext("2d");

    function translateCoords(fromBlockX, fromBlockY, toBlockX, toBlockY) {
        return {
            "blockX": fromBlockX,
            "blockY": fromBlockY,
            "width": Math.abs(fromBlockX - toBlockX) + 1,
            "height": Math.abs(fromBlockY - toBlockY) + 1
        };
    }

    function canvasDown(evt) {
        fromBlock = evt.detail;
        filledEllipse = evt.detail.shiftKey;
    }

    function clearEllipse() {
        var coords;
        if (oldTo) {
            coords = translateCoords(fromBlock.blockX, fromBlock.blockY, oldTo.blockX, oldTo.blockY);
            ctx.clearRect((coords.blockX - (coords.width + 1)) * editor.codepage.fontWidth, (coords.blockY - (coords.height + 1)) * (editor.codepage.fontHeight / 2), (coords.width + 2) * 2 * editor.codepage.fontWidth, (coords.height + 2) * 2 * (editor.codepage.fontHeight / 2));
        }
    }

    function drawEllipse(x0, y0, width, height, setPixel, setLine) {
        var a2, b2, fa2, fb2, x, y, sigma;
        a2 = width * width;
        b2 = height * height;
        fa2 = 4 * a2;
        fb2 = 4 * b2;

        for (x = 0, y = height, sigma = 2 * b2 + a2 * (1 - 2 * height); b2 * x <= a2 * y; ++x) {
            if (filledEllipse) {
                setLine(x0 - x, x * 2, y0 + y);
                setLine(x0 - x, x * 2, y0 - y);
            } else {
                setPixel(x0 + x, y0 + y);
                setPixel(x0 - x, y0 + y);
                setPixel(x0 + x, y0 - y);
                setPixel(x0 - x, y0 - y);
            }
            if (sigma >= 0) {
                sigma += fa2 * (1 - y);
                --y;
            }
            sigma += b2 * ((4 * x) + 6);
        }

        for (x = width, y = 0, sigma = 2 * a2 + b2 * (1 - 2 * width); a2 * y <= b2 * x; ++y) {
            if (filledEllipse) {
                setLine(x0 - x, x * 2, y0 + y);
                setLine(x0 - x, x * 2, y0 - y);
            } else {
                setPixel(x0 + x, y0 + y);
                setPixel(x0 - x, y0 + y);
                setPixel(x0 + x, y0 - y);
                setPixel(x0 - x, y0 - y);
            }
            if (sigma >= 0) {
                sigma += fb2 * (1 - x);
                --x;
            }
            sigma += a2 * ((4 * y) + 6);
        }
    }

    function canvasDrag(evt) {
        var coords;

        function setPixel(px, py) {
            ctx.fillRect(px * editor.codepage.fontWidth, py * (editor.codepage.fontHeight / 2), editor.codepage.fontWidth, (editor.codepage.fontHeight / 2));
        }

        function setLine(fromX, lineWidth, py) {
            ctx.fillRect(fromX * editor.codepage.fontWidth, py * (editor.codepage.fontHeight / 2), lineWidth * editor.codepage.fontWidth, (editor.codepage.fontHeight / 2));
        }

        clearEllipse();
        ctx.fillStyle = editor.palette.styleRGBA(editor.palette.getCurrentColor(), 1);
        coords = translateCoords(fromBlock.blockX, fromBlock.blockY, evt.detail.blockX, evt.detail.blockY);
        drawEllipse(coords.blockX, coords.blockY, coords.width, coords.height, setPixel, setLine);
        oldTo = evt.detail;
    }

    function canvasUp(evt) {
        clearEllipse();
        editor.takeUndoSnapshot();
        editor.setBlocks(!evt.detail.altKey, currentColor, function (setBlock) {
            var coords, px, block;

            function setPixel(px, py) {
                if (px >= 0 && px < 80 && py >= 0 && py < (editor.height * 2)) {
                    block = editor.getBlock(px, py);
                    setBlock(block, currentColor);
                }
            }

            function setLine(fromX, lineWidth, py) {
                for (px = fromX; px < fromX + lineWidth; ++px) {
                    setPixel(px, py);
                }
            }

            coords = translateCoords(fromBlock.blockX, fromBlock.blockY, oldTo.blockX, oldTo.blockY);
            drawEllipse(coords.blockX, coords.blockY, coords.width, coords.height, setPixel, setLine);
        });
    }

    function canvasOut() {
        clearEllipse();
    }

    function colorChange(evt) {
        currentColor = evt.detail;
    }

    function init() {
        editor.canvas.addEventListener("canvasDown", canvasDown, false);
        editor.canvas.addEventListener("canvasDrag", canvasDrag, false);
        editor.canvas.addEventListener("canvasUp", canvasUp, false);
        editor.canvas.addEventListener("canvasOut", canvasOut, false);
        editor.canvas.addEventListener("colorChange", colorChange, false);
        currentColor = editor.palette.getCurrentColor();
        editor.addOverlay(canvas, "ellipse");
        return true;
    }

    function remove() {
        editor.canvas.removeEventListener("canvasDown", canvasDown);
        editor.canvas.removeEventListener("canvasDrag", canvasDrag);
        editor.canvas.removeEventListener("canvasUp", canvasUp);
        editor.canvas.removeEventListener("canvasOut", canvasOut);
        editor.canvas.removeEventListener("colorChange", colorChange);
        editor.removeOverlay("ellipse");
    }

    function toString() {
        return "Ellipse";
    }

    return {
        "init": init,
        "remove": remove,
        "toString": toString,
        "uid": "ellispe"
    };
}

AnsiEditController.addTool(ellipseTool, "tools-right", 105);

Download

raw zip tar