<commit_before>angular.module('super-micro-paint', ['touch-directives'])
    .controller('smpController', ['$scope', function ($scope) {
        $scope.numFrames = 4;
        $scope.height = 16;
        $scope.width = 32;
        $scope._ = _;
        $scope.activeTool = 'pencil';
        $scope.undoBuffers = _.range(0, $scope.numFrames)
            .map(function () {
                return [];
            });
        $scope.redoBuffers = _.range(0, $scope.numFrames)
            .map(function () {
                return [];
            });
        $scope.frames = _.range(0, $scope.numFrames)
            .map(function () {
                return new SuperPixelGrid($scope.width, $scope.height)
                    .fill(false);
            });
        $scope.currentFrameNum = 0;
        $scope.currentFrame = new SuperPixelGrid($scope.width, $scope.height)
            .fill(false);
        $scope.overlay = new SuperPixelGrid($scope.width, $scope.height)
            .fill(false);
        $scope.pen = {};
        $scope.pen.drawing = false;
        $scope.pen.mode = false;
        $scope.pen.start = undefined;
        $scope.pen.last = undefined;
        $scope.pen.finish = false;
        $scope.events = {};
        $scope.events.start = undefined;
        $scope.events.current = undefined;
        $scope.events.finish = undefined;
        $scope.mode = 'normal';
        $scope.range = function (n) {
            return new Array(n);
        };
        var switchToFrame = function (n) {
            copyFrame($scope.currentFrame, $scope.frames[$scope.currentFrameNum]);
            $scope.currentFrameNum = n;
            copyFrame($scope.frames[n], $scope.currentFrame);
        };
        var clearSelection = function () {
            var selection = ('getSelection' in window) ? window.getSelection() : ('selection' in document) ? document.selection : null;
            if ('removeAllRanges' in selection) {
                selection.removeAllRanges();
            } else if ('empty' in selection) {
                selection.empty();
            }
        };
        var setPixel = function (pixel, mode) {
            $scope.currentFrame.set(pixel.x, pixel.y, mode);
        };
        var setUndo = function (frame) {
            var f, frameToSave;
            if (frame === undefined) {
                f = $scope.currentFrameNum;
                frameToSave = $scope.currentFrame;
            } else {
                f = frame;
                frameToSave = $scope.frames[f];
            }
            $scope.undoBuffers[f].push(frameToSave.toString());
        };
        var setRedo = function () {
            var f = $scope.currentFrameNum;
            $scope.redoBuffers[f].push($scope.currentFrame.toString());
        };
        $scope.undo = function () {
            var f = $scope.currentFrameNum;
            if ($scope.undoBuffers[f].length > 0) {
                setRedo();
                $scope.currentFrame = $scope.currentFrame.fromString($scope.undoBuffers[f].pop());
                $scope.save();
            }
        };
        $scope.redo = function () {
            var f = $scope.currentFrameNum;
            if ($scope.redoBuffers[f].length > 0) {
                setUndo();
                $scope.currentFrame = $scope.currentFrame.fromString($scope.redoBuffers[f].pop());
                $scope.save();
            }
        };
        $scope.canUndo = function () {
            return $scope.undoBuffers[$scope.currentFrameNum].length > 0;
        };
        $scope.canRedo = function () {
            return $scope.redoBuffers[$scope.currentFrameNum].length > 0;
        };
        var getPixel = function (pixel) {
            return $scope.currentFrame.get(pixel.x, pixel.y);
        };
        $scope.getExportURL = function() {
            return "export/?smp=" + location.hash.slice(1);
        };
        var tools = {};
        var buildPointToPointDrawingTool = function (drawingFunction) {
            return {
                'start': function (pen) {
                    $scope.overlay.fill(false);
                },
                'finish': function (pen) {
                    setUndo();
                    $scope.currentFrame[drawingFunction](pen.start.x, pen.start.y, pen.finish.x, pen.finish.y, pen.mode);
                    $scope.overlay.fill(false);
                    $scope.save();
                    clearSelection();
                },
                'update': function (pen) {
                    $scope.overlay.fill(false)[drawingFunction](pen.start.x, pen.start.y, pen.current.x, pen.current.y, true);
                }
            };
        };
        tools.pencil = {
            'start': function (pen) {
                setUndo();
                setPixel(pen.start, pen.mode);
            },
            'finish': function (pen) {
                $scope.save();
                clearSelection();
            },
            'update': function (pen) {
                $scope.currentFrame.drawLine(pen.last.x, pen.last.y, pen.current.x, pen.current.y, pen.mode);
            }
        };
        tools.fill = {
            'start': function (pen) {
                setUndo();
                $scope.currentFrame.floodFill(pen.start.x, pen.start.y, pen.mode);
                $scope.save();
            }
        };
        tools.line = buildPointToPointDrawingTool('drawLine');
        tools.rectangle = buildPointToPointDrawingTool('drawRectangle');
        tools.ellipse = buildPointToPointDrawingTool('drawEllipse');
        var drawUpdate = function() {
            var pen = $scope.pen;
            var events = $scope.events;
            if (events.start) {
                pen.drawing = true;
                pen.start = pen.last = pointFromEvent(events.start);
                pen.mode = !getPixel(pen.start);
                events.start = undefined;
                if (tools[$scope.activeTool].start) {
                    tools[$scope.activeTool].start(pen);
                }
            } else if (pen.drawing === true && events.current && !events.finish) {
                pen.current = pointFromEvent(events.current);
                if (tools[$scope.activeTool].update && !(pen.current.x === pen.last.x && pen.current.y === pen.last.y)) {
                    tools[$scope.activeTool].update(pen);
                }
                pen.last = pen.current;
                events.current = undefined;
            } else if (pen.drawing === true && events.finish) {
                pen.drawing = false;
                if (events.finish === 'outside') {
                    pen.finish = pen.last;
                } else {
                    pen.finish = pointFromEvent(events.finish);
                }
                if (tools[$scope.activeTool].finish) {
                    tools[$scope.activeTool].finish(pen);
                }
                events.finish = events.current = undefined;
            }
            window.requestAnimationFrame(drawUpdate);
        };
        var timeStep = (1 / 60) * 1000;
        var currentTime = Date.now();
        var drawingLoop = function () {
            var newTime = Date.now();
            var frameTime = newTime - currentTime;
            var delta;
            currentTime = newTime;
            while (frameTime > 0) {
                delta = Math.min(frameTime, timeStep);
                frameTime -= delta;
            }
            drawUpdate();
            requestAnimationFrame(drawingLoop);
        };
        drawingLoop();
        $scope.save = function () {
            copyFrame($scope.currentFrame, $scope.frames[$scope.currentFrameNum]);
            location.hash = $scope.frames.map(function (frame) {
                    return frame.toUrlSafeBase64();
                })
                .reduce(function (a, b) {
                    return a + "." + b;
                });
        };
        $scope.doLifeStep = function () {
            setUndo();
            $scope.currentFrame = $scope.currentFrame.lifeStep();
            $scope.save();
        };
        $scope.clear = function () {
            setUndo();
            $scope.currentFrame.fill(false);
            $scope.save();
        };
        $scope.nudge = function (xOffset, yOffset) {
            setUndo();
            $scope.currentFrame.nudge(xOffset, yOffset);
            $scope.save();
        };
        $scope.invert = function (xOffset, yOffset) {
            setUndo();
            $scope.currentFrame.invert();
            $scope.save();
        };
        var pointFromEvent = function ($event) {
            var event = $event.originalEvent;
            var point = {};
            if (event instanceof MouseEvent) {
                point = $scope.getPointFromCoords(event.pageX, event.pageY);
            }
            if (('ontouchstart' in window || navigator.msMaxTouchPoints) && event instanceof TouchEvent) {
                var touch = event.changedTouches[0];
                point = $scope.getPointFromCoords(touch.pageX, touch.pageY);
            }
            return point;
        };
        $scope.penDown = function ($event) {
            $event.preventDefault();
            if ($scope.mode != 'copy') {
                $scope.events.start = $event;
            }
        };
        $scope.penOver = function ($event) {
            $event.preventDefault();
            if ($scope.mode != 'copy') {
                $scope.events.current = $event;
            }
        };
        $scope.penUp = function ($event) {
            if ($event === 'outside') {
                if ($scope.pen.drawing) {
                    $scope.events.finish = $event;
                }
            } else {
                $event.stopPropagation();
                $event.preventDefault();
                if ($scope.mode != 'copy') {
                    $scope.events.finish = $event;
                }
            }
        };
        var updatePreviews = function () {
            $scope.frames.map(function (frame, index) {
                var previewCanvas = document.getElementById('preview' + index);
                if (index === $scope.currentFrameNum) {
                    drawPreview($scope.currentFrame, previewCanvas);
                } else {
                    drawPreview(frame, previewCanvas);
                }
            });
        };

        var aniTimer = function () {
            var aniState = 0;
            var aniCanvas = document.getElementById('previewani');
            var animate = function () {<commit_msg>Handle mouseup outside of window also<commit_after>angular.module('super-micro-paint', ['touch-directives'])
    .controller('smpController', ['$scope', '$window', function ($scope, $window) {
        $scope.numFrames = 4;
        $scope.height = 16;
        $scope.width = 32;
        $scope._ = _;
        $scope.activeTool = 'pencil';
        $scope.undoBuffers = _.range(0, $scope.numFrames)
            .map(function () {
                return [];
            });
        $scope.redoBuffers = _.range(0, $scope.numFrames)
            .map(function () {
                return [];
            });
        $scope.frames = _.range(0, $scope.numFrames)
            .map(function () {
                return new SuperPixelGrid($scope.width, $scope.height)
                    .fill(false);
            });
        $scope.currentFrameNum = 0;
        $scope.currentFrame = new SuperPixelGrid($scope.width, $scope.height)
            .fill(false);
        $scope.overlay = new SuperPixelGrid($scope.width, $scope.height)
            .fill(false);
        $scope.pen = {};
        $scope.pen.drawing = false;
        $scope.pen.mode = false;
        $scope.pen.start = undefined;
        $scope.pen.last = undefined;
        $scope.pen.finish = false;
        $scope.events = {};
        $scope.events.start = undefined;
        $scope.events.current = undefined;
        $scope.events.finish = undefined;
        $scope.mode = 'normal';
        $scope.range = function (n) {
            return new Array(n);
        };
        var switchToFrame = function (n) {
            copyFrame($scope.currentFrame, $scope.frames[$scope.currentFrameNum]);
            $scope.currentFrameNum = n;
            copyFrame($scope.frames[n], $scope.currentFrame);
        };
        var clearSelection = function () {
            var selection = ('getSelection' in window) ? window.getSelection() : ('selection' in document) ? document.selection : null;
            if ('removeAllRanges' in selection) {
                selection.removeAllRanges();
            } else if ('empty' in selection) {
                selection.empty();
            }
        };
        var setPixel = function (pixel, mode) {
            $scope.currentFrame.set(pixel.x, pixel.y, mode);
        };
        var setUndo = function (frame) {
            var f, frameToSave;
            if (frame === undefined) {
                f = $scope.currentFrameNum;
                frameToSave = $scope.currentFrame;
            } else {
                f = frame;
                frameToSave = $scope.frames[f];
            }
            $scope.undoBuffers[f].push(frameToSave.toString());
        };
        var setRedo = function () {
            var f = $scope.currentFrameNum;
            $scope.redoBuffers[f].push($scope.currentFrame.toString());
        };
        $scope.undo = function () {
            var f = $scope.currentFrameNum;
            if ($scope.undoBuffers[f].length > 0) {
                setRedo();
                $scope.currentFrame = $scope.currentFrame.fromString($scope.undoBuffers[f].pop());
                $scope.save();
            }
        };
        $scope.redo = function () {
            var f = $scope.currentFrameNum;
            if ($scope.redoBuffers[f].length > 0) {
                setUndo();
                $scope.currentFrame = $scope.currentFrame.fromString($scope.redoBuffers[f].pop());
                $scope.save();
            }
        };
        $scope.canUndo = function () {
            return $scope.undoBuffers[$scope.currentFrameNum].length > 0;
        };
        $scope.canRedo = function () {
            return $scope.redoBuffers[$scope.currentFrameNum].length > 0;
        };
        var getPixel = function (pixel) {
            return $scope.currentFrame.get(pixel.x, pixel.y);
        };
        $scope.getExportURL = function() {
            return "export/?smp=" + location.hash.slice(1);
        };
        var tools = {};
        var buildPointToPointDrawingTool = function (drawingFunction) {
            return {
                'start': function (pen) {
                    $scope.overlay.fill(false);
                },
                'finish': function (pen) {
                    setUndo();
                    $scope.currentFrame[drawingFunction](pen.start.x, pen.start.y, pen.finish.x, pen.finish.y, pen.mode);
                    $scope.overlay.fill(false);
                    $scope.save();
                    clearSelection();
                },
                'update': function (pen) {
                    $scope.overlay.fill(false)[drawingFunction](pen.start.x, pen.start.y, pen.current.x, pen.current.y, true);
                }
            };
        };
        tools.pencil = {
            'start': function (pen) {
                setUndo();
                setPixel(pen.start, pen.mode);
            },
            'finish': function (pen) {
                $scope.save();
                clearSelection();
            },
            'update': function (pen) {
                $scope.currentFrame.drawLine(pen.last.x, pen.last.y, pen.current.x, pen.current.y, pen.mode);
            }
        };
        tools.fill = {
            'start': function (pen) {
                setUndo();
                $scope.currentFrame.floodFill(pen.start.x, pen.start.y, pen.mode);
                $scope.save();
            }
        };
        tools.line = buildPointToPointDrawingTool('drawLine');
        tools.rectangle = buildPointToPointDrawingTool('drawRectangle');
        tools.ellipse = buildPointToPointDrawingTool('drawEllipse');
        var drawUpdate = function() {
            var pen = $scope.pen;
            var events = $scope.events;
            if (events.start) {
                pen.drawing = true;
                pen.start = pen.last = pointFromEvent(events.start);
                pen.mode = !getPixel(pen.start);
                events.start = undefined;
                if (tools[$scope.activeTool].start) {
                    tools[$scope.activeTool].start(pen);
                }
            } else if (pen.drawing === true && events.current && !events.finish) {
                pen.current = pointFromEvent(events.current);
                if (tools[$scope.activeTool].update && !(pen.current.x === pen.last.x && pen.current.y === pen.last.y)) {
                    tools[$scope.activeTool].update(pen);
                }
                pen.last = pen.current;
                events.current = undefined;
            } else if (pen.drawing === true && events.finish) {
                pen.drawing = false;
                if (events.finish === 'outside') {
                    pen.finish = pen.last;
                } else {
                    pen.finish = pointFromEvent(events.finish);
                }
                if (tools[$scope.activeTool].finish) {
                    tools[$scope.activeTool].finish(pen);
                }
                events.finish = events.current = undefined;
            }
            window.requestAnimationFrame(drawUpdate);
        };
        var timeStep = (1 / 60) * 1000;
        var currentTime = Date.now();
        var drawingLoop = function () {
            var newTime = Date.now();
            var frameTime = newTime - currentTime;
            var delta;
            currentTime = newTime;
            while (frameTime > 0) {
                delta = Math.min(frameTime, timeStep);
                frameTime -= delta;
            }
            drawUpdate();
            requestAnimationFrame(drawingLoop);
        };
        drawingLoop();
        $scope.save = function () {
            copyFrame($scope.currentFrame, $scope.frames[$scope.currentFrameNum]);
            location.hash = $scope.frames.map(function (frame) {
                    return frame.toUrlSafeBase64();
                })
                .reduce(function (a, b) {
                    return a + "." + b;
                });
        };
        $scope.doLifeStep = function () {
            setUndo();
            $scope.currentFrame = $scope.currentFrame.lifeStep();
            $scope.save();
        };
        $scope.clear = function () {
            setUndo();
            $scope.currentFrame.fill(false);
            $scope.save();
        };
        $scope.nudge = function (xOffset, yOffset) {
            setUndo();
            $scope.currentFrame.nudge(xOffset, yOffset);
            $scope.save();
        };
        $scope.invert = function (xOffset, yOffset) {
            setUndo();
            $scope.currentFrame.invert();
            $scope.save();
        };
        var pointFromEvent = function ($event) {
            var event = $event.originalEvent;
            var point = {};
            if (event instanceof MouseEvent) {
                point = $scope.getPointFromCoords(event.pageX, event.pageY);
            }
            if (('ontouchstart' in window || navigator.msMaxTouchPoints) && event instanceof TouchEvent) {
                var touch = event.changedTouches[0];
                point = $scope.getPointFromCoords(touch.pageX, touch.pageY);
            }
            return point;
        };
        $scope.penDown = function ($event) {
            $event.preventDefault();
            if ($scope.mode != 'copy') {
                $scope.events.start = $event;
            }
        };
        $scope.penOver = function ($event) {
            $event.preventDefault();
            if ($scope.mode != 'copy') {
                $scope.events.current = $event;
            }
        };
        $scope.penUp = function ($event) {
            if ($event === 'outside') {
                if ($scope.pen.drawing) {
                    $scope.events.finish = $event;
                }
            } else {
                $event.stopPropagation();
                $event.preventDefault();
                if ($scope.mode != 'copy') {
                    $scope.events.finish = $event;
                }
            }
        };
        angular.element($window).bind('blur', function (){
          $scope.penUp('outside');
        });
        angular.element($window).bind('mouseup', function (){
          $scope.penUp('outside');
        });
        var updatePreviews = function () {
            $scope.frames.map(function (frame, index) {
                var previewCanvas = document.getElementById('preview' + index);
                if (index === $scope.currentFrameNum) {
                    drawPreview($scope.currentFrame, previewCanvas);
                } else {
                    drawPreview(frame, previewCanvas);
                }
            });
        };

        var aniTimer = function () {
            var aniState = 0;
            var aniCanvas = document.getElementById('previewani');
            var animate = function () {
{'fraction_non_alphanumeric': 0.13213495835490094, 'fraction_numerical': 0.0024469436732389065, 'mean_word_length': 1.4354801741920697, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1539219', 'n_tokens_mistral': 5755, 'n_tokens_neox': 5533, 'n_words': 993}