aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/skpdiff/diff_viewer.js
blob: e7156b359f4596d5e2cc7773e4f145ee263a4bd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
var MAX_SWAP_IMG_SIZE = 400;

angular.module('diff_viewer', []).
config(['$routeProvider', function($routeProvider) {
    // Show the list of differences by default
    $routeProvider.
    otherwise({ templateUrl: '/diff_list.html', controller: DiffListController});
}]).
directive('swapImg', function() {
    // Custom directive for showing an image that gets swapped my mouseover.
    return {
        restrict: 'E', // The directive can be used as an element name
        replace: true, // The directive replaces itself with the template
        template: '<canvas ng-mouseenter="swap()" ng-mouseleave="swap()"></canvas>',
        scope: { // The attributes below are bound to the scope
            leftSrc: '@',
            rightSrc: '@',
            side: '@'
        },
        link: function(scope, elm, attrs, ctrl) {
            var leftImage = new Image();
            var rightImage = new Image();
            var ctx = elm[0].getContext('2d');

            scope.render = function() {
                var image;
                if (scope.side == "left") {
                    image = leftImage;
                } else {
                    image = rightImage;
                }

                // Make it so the maximum size of an image is MAX_SWAP_IMG_SIZE, and the images are
                // scaled down in halves.
                var divisor = 1;
                while ((image.width / divisor) > MAX_SWAP_IMG_SIZE) {
                    divisor *= 2;
                }

                // Set canvas to correct size and draw the image into it
                elm[0].width = image.width / divisor;
                elm[0].height = image.height / divisor;
                ctx.drawImage(image, 0, 0, elm[0].width, elm[0].height);
            };

            // When the leftSrc attribute changes, load the image and then rerender
            attrs.$observe('leftSrc', function(value) {
                leftImage.src = value;
                leftImage.onload = function() {
                    if (scope.side == "left") {
                        scope.render();
                    }
                };
            });

            // When the rightSrc attribute changes, load the image and then rerender
            attrs.$observe('rightSrc', function(value) {
                rightImage.src = value;
                rightImage.onload = function() {
                    if (scope.side == "right") {
                        scope.render();
                    }
                };
            });

            // Swap which side to draw onto the canvas and then rerender
            scope.swap = function() {
                if (scope.side == "left") {
                    scope.side = "right";
                } else {
                    scope.side = "left";
                }
                scope.render();
            };
        }
    };
});

function DiffListController($scope, $http, $timeout) {
    // Label each kind of differ for the sort buttons.
    $scope.differs = [
        {
            "title": "Different Pixels"
        },
        {
            "title": "Perceptual Difference"
        }
    ];

    // Puts the records within AngularJS scope
    $scope.records = SkPDiffRecords.records;

    // Indicates which diff metric is used for sorting
    $scope.sortIndex = 1;

    // Called by the sort buttons to adjust the metric used for sorting
    $scope.setSortIndex = function(idx) {
        $scope.sortIndex = idx;
    };

    // A predicate for pulling out the number used for sorting
    $scope.sortingDiffer = function(record) {
        return record.diffs[$scope.sortIndex].result;
    };

    // Flash status indicators on the rows, and then remove them so the style can potentially be
    // reapplied later.
    $scope.flashRowStatus = function(success, record) {
        var flashStyle = success ? "success-flash" : "failure-flash";
        var flashDurationMillis = success ? 500 : 800;

        // Store the style in the record. The row will pick up the style this way instead of through
        // index because index can change with sort order.
        record.cssClasses = flashStyle;

        // The animation cannot be repeated unless the class is removed the element.
        $timeout(function() {
            record.cssClasses = "";
        }, flashDurationMillis);
    }

    $scope.setHashOf = function(imagePath, record) {
        $http.post("/set_hash", {
            "path": imagePath
        }).success(function(data) {
            $scope.flashRowStatus(data.success, record);
        }).error(function() {
            $scope.flashRowStatus(false, record);
        });

    };
}