16f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.comvar MAX_SWAP_IMG_SIZE = 400; 2513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comvar MAGNIFIER_WIDTH = 200; 3513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comvar MAGNIFIER_HEIGHT = 200; 4513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comvar MAGNIFIER_HALF_WIDTH = MAGNIFIER_WIDTH * 0.5; 5513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comvar MAGNIFIER_HALF_HEIGHT = MAGNIFIER_HEIGHT * 0.5; 6513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com// TODO add support for a magnified scale factor 7513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comvar MAGNIFIER_SCALE_FACTOR = 2.0; 86f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com 91bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.comangular.module('diff_viewer', []). 10513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comdirective('imgCompare', function() { 11513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // Custom directive for comparing (3-way) images 12513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return { 13513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com restrict: 'E', // The directive can be used as an element name 14513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com replace: true, // The directive replaces itself with the template 15513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com template: '<canvas/>', 16513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope: true, 17513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com link: function(scope, elm, attrs, ctrl) { 18513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var image = new Image(); 19513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var canvas = elm[0]; 20513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var ctx = canvas.getContext('2d'); 21513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 22513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var magnifyContent = false; 232cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org var maskCanvas = false; 24513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 25513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // When the type attribute changes, load the image and then render 26513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com attrs.$observe('type', function(value) { 27513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com switch(value) { 28513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com case "alphaMask": 29513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com image.src = scope.record.differencePath; 302cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org maskCanvas = true; 31513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com break; 32513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com case "baseline": 33513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com image.src = scope.record.baselinePath; 34513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com magnifyContent = true; 35513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com break; 36513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com case "test": 37513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com image.src = scope.record.testPath; 38513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com magnifyContent = true; 39513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com break; 40513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com default: 41513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com console.log("Unknown type attribute on <img-compare>: " + value); 42513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return; 43513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 44513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 45513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com image.onload = function() { 46513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // compute the scaled image width/height for image and canvas 47513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var divisor = 1; 48513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // Make it so the maximum size of an image is MAX_SWAP_IMG_SIZE, 49513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // and the images are scaled down in halves. 50513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com while ((image.width / divisor) > MAX_SWAP_IMG_SIZE) { 51513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com divisor *= 2; 52513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 53513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 54513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.setImgScaleFactor(1 / divisor); 55513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 56513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // Set canvas to correct size 57513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com canvas.width = image.width * scope.imgScaleFactor; 58513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com canvas.height = image.height * scope.imgScaleFactor; 59513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 602cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org // update the size for non-alphaMask canvas when loading baseline image 612cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org if (!scope.maskSizeUpdated) { 622cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org if (!maskCanvas) { 632cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org scope.updateMaskCanvasSize({width: canvas.width, height: canvas.height}); 642cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org } 652cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org scope.maskCanvasSizeUpdated(true); 662cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org } 672cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org 68513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // render the image onto the canvas 69513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.renderImage(); 70513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 71513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }); 72513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 732cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org // when updatedMaskSize changes, update mask canvas size. 742cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org scope.$watch('updatedMaskSize', function(updatedSize) { 752cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org if (!maskCanvas) { 762cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org return; 772cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org } 782cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org 792cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org canvas.width = updatedSize.width; 802cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org canvas.height = updatedSize.height; 812cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org }); 822cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org 83513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // When the magnify attribute changes, render the magnified rect at 84513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // the default zoom level. 85513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.$watch('magnifyCenter', function(magCenter) { 86513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com if (!magnifyContent) { 87513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return; 88513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 89513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 90513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.renderImage(); 91513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 92513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com if (!magCenter) { 93513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return; 94513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 95513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 96513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var magX = magCenter.x - MAGNIFIER_HALF_WIDTH; 97513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var magY = magCenter.y - MAGNIFIER_HALF_HEIGHT; 98513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 99513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var magMaxX = canvas.width - MAGNIFIER_WIDTH; 100513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var magMaxY = canvas.height - MAGNIFIER_HEIGHT; 101513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 102513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var magRect = { x: Math.max(0, Math.min(magX, magMaxX)), 103513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com y: Math.max(0, Math.min(magY, magMaxY)), 104513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com width: MAGNIFIER_WIDTH, 105513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com height: MAGNIFIER_HEIGHT 106513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 107513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 108513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var imgRect = { x: (magCenter.x / scope.imgScaleFactor) - MAGNIFIER_HALF_WIDTH, 109513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com y: (magCenter.y / scope.imgScaleFactor) - MAGNIFIER_HALF_HEIGHT, 110513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com width: MAGNIFIER_WIDTH, 111513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com height: MAGNIFIER_HEIGHT 112513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 1131bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com 114513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // draw the magnified image 115513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.clearRect(magRect.x, magRect.y, magRect.width, magRect.height); 116513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.drawImage(image, imgRect.x, imgRect.y, imgRect.width, imgRect.height, 117513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com magRect.x, magRect.y, magRect.width, magRect.height); 118513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 119513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // draw the outline rect 120513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.beginPath(); 121513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.rect(magRect.x, magRect.y, magRect.width, magRect.height); 122513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.lineWidth = 2; 123513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.strokeStyle = 'red'; 124513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.stroke(); 125513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 126513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }); 127513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 128513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // render the image to the canvas. This is often done every frame prior 129513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // to any special effects (i.e. magnification). 130513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.renderImage = function() { 131513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.clearRect(0, 0, canvas.width, canvas.height); 132513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.drawImage(image, 0, 0, canvas.width, canvas.height); 133513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 134513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 135513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // compute a rect (x,y,width,height) that represents the bounding box for 136513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // the magnification effect 137513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.computeMagnifierOutline = function(event) { 138513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var scaledWidth = MAGNIFIER_WIDTH * scope.imgScaleFactor; 139513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var scaledHeight = MAGNIFIER_HEIGHT * scope.imgScaleFactor; 140513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return { 141513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com x: event.offsetX - (scaledWidth * 0.5), 142513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com y: event.offsetY - (scaledHeight * 0.5), 143513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com width: scaledWidth, 144513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com height: scaledHeight 1451bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com }; 146513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 147513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 148513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // event handler for mouse events that triggers the magnification 149513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // effect across the 3 images being compared. 150513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.MagnifyDraw = function(event, startMagnify) { 151513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com if (startMagnify) { 152513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.setMagnifierState(true); 153513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } else if (!scope.magnifierOn) { 154513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return; 155513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 156513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 157513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.renderImage(); 158513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 159513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // render the magnifier outline rect 160513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com var rect = scope.computeMagnifierOutline(event); 161513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.save(); 162513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.beginPath(); 163513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.rect(rect.x, rect.y, rect.width, rect.height); 164513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.lineWidth = 2; 165513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.strokeStyle = 'red'; 166513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.stroke(); 167513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com ctx.restore(); 168513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 169513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // update scope on baseline / test that will cause them to render 170513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.setMagnifyCenter({x: event.offsetX, y: event.offsetY}); 171513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 172513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 173513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // event handler that triggers the end of the magnification effect and 174513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // resets all the canvases to their original state. 175513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.MagnifyEnd = function(event) { 176513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.renderImage(); 177513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // update scope on baseline / test that will cause them to render 178513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.setMagnifierState(false); 179513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com scope.setMagnifyCenter(undefined); 180513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 181513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 182513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com }; 1831bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com}); 1841bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com 185513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comfunction ImageController($scope, $http, $location, $timeout, $parse) { 186513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.imgScaleFactor = 1.0; 187513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.magnifierOn = false; 188513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.magnifyCenter = undefined; 1892cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org $scope.updatedMaskSize = undefined; 1902cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org $scope.maskSizeUpdated = false; 191513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 192513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.setImgScaleFactor = function(scaleFactor) { 193513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.imgScaleFactor = scaleFactor; 194513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 195513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 196513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.setMagnifierState = function(magnifierOn) { 197513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.magnifierOn = magnifierOn; 198513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 199513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 200513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.setMagnifyCenter = function(magnifyCenter) { 201513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com $scope.magnifyCenter = magnifyCenter; 202513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 2032cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org 2042cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org $scope.updateMaskCanvasSize = function(updatedSize) { 2052cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org $scope.updatedMaskSize = updatedSize; 2062cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org } 2072cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org 2082cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org $scope.maskCanvasSizeUpdated = function(flag) { 2092cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org $scope.maskSizeUpdated = flag; 2102cce3df19adc4bbda837d30f7f533938f579b478commit-bot@chromium.org } 211513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com} 212513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 21374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.comfunction DiffListController($scope, $http, $location, $timeout, $parse) { 21474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // Detect if we are running the web server version of the viewer. If so, we set a flag and 21574c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // enable some extra functionality of the website for rebaselining. 21674c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.isDynamic = ($location.protocol() == "http" || $location.protocol() == "https"); 21774c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com 2181bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com // Label each kind of differ for the sort buttons. 2199432c0c2843112c293be2630421ddc52cbf62583zachr@google.com $scope.differs = [ 2209432c0c2843112c293be2630421ddc52cbf62583zachr@google.com { 2219432c0c2843112c293be2630421ddc52cbf62583zachr@google.com "title": "Different Pixels" 2229432c0c2843112c293be2630421ddc52cbf62583zachr@google.com }, 2239432c0c2843112c293be2630421ddc52cbf62583zachr@google.com { 2249432c0c2843112c293be2630421ddc52cbf62583zachr@google.com "title": "Perceptual Difference" 2259432c0c2843112c293be2630421ddc52cbf62583zachr@google.com } 2269432c0c2843112c293be2630421ddc52cbf62583zachr@google.com ]; 2271bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com 2281bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com // Puts the records within AngularJS scope 2299432c0c2843112c293be2630421ddc52cbf62583zachr@google.com $scope.records = SkPDiffRecords.records; 2301bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com 23174c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // Keep track of the index of the last record to change so that shift clicking knows what range 23274c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // of records to apply the action to. 23374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.lastSelectedIndex = undefined; 23474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com 2351bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com // Indicates which diff metric is used for sorting 2361bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com $scope.sortIndex = 1; 2371bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com 2381bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com // Called by the sort buttons to adjust the metric used for sorting 2391bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com $scope.setSortIndex = function(idx) { 2401bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com $scope.sortIndex = idx; 24174c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com 24274c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // Because the index of things has most likely changed, the ranges of shift clicking no 24374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // longer make sense from the user's point of view. We reset it to avoid confusion. 24474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.lastSelectedIndex = undefined; 2451bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com }; 2461bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com 2471bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com // A predicate for pulling out the number used for sorting 2481bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com $scope.sortingDiffer = function(record) { 2491bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com return record.diffs[$scope.sortIndex].result; 2501bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com }; 2516f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com 25274c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // Flash status indicator on the page, and then remove it so the style can potentially be 2536f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com // reapplied later. 25474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.flashStatus = function(success) { 2556f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com var flashStyle = success ? "success-flash" : "failure-flash"; 2566f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com var flashDurationMillis = success ? 500 : 800; 2576f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com 2586f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com // Store the style in the record. The row will pick up the style this way instead of through 2596f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com // index because index can change with sort order. 26074c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.statusClass = flashStyle; 2616f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com 2626f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com // The animation cannot be repeated unless the class is removed the element. 2636f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com $timeout(function() { 26474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.statusClass = ""; 2656f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com }, flashDurationMillis); 26674c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com }; 26774c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com 26874c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.selectedRebaseline = function(index, event) { 26974c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // Retrieve the records in the same order they are displayed. 27074c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com var recordsInOrder = $parse("records | orderBy:sortingDiffer")($scope); 27174c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com 27274c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // If the user is shift clicking, apply the last tick/untick to all elements in between this 27374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // record, and the last one they ticked/unticked. 27474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com if (event.shiftKey && $scope.lastSelectedIndex !== undefined) { 27574c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com var currentAction = recordsInOrder[index].isRebaselined; 27674c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com var smallerIndex = Math.min($scope.lastSelectedIndex, index); 27774c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com var largerIndex = Math.max($scope.lastSelectedIndex, index); 27874c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com for (var recordIndex = smallerIndex; recordIndex <= largerIndex; recordIndex++) { 27974c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com recordsInOrder[recordIndex].isRebaselined = currentAction; 28074c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com } 28174c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.lastSelectedIndex = index; 28274c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com } 28374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com else 28474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com { 28574c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.lastSelectedIndex = index; 28674c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com } 28774c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com 28874c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com }; 2896f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com 29074c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.commitRebaselines = function() { 29174c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com // Gather up all records that have the rebaseline set. 29274c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com var rebaselines = []; 29374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com for (var recordIndex = 0; recordIndex < $scope.records.length; recordIndex++) { 29474c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com if ($scope.records[recordIndex].isRebaselined) { 29574c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com rebaselines.push($scope.records[recordIndex].testPath); 29674c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com } 29774c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com } 29874c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $http.post("/commit_rebaselines", { 29974c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com "rebaselines": rebaselines 3006f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com }).success(function(data) { 30174c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.flashStatus(data.success); 3026f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com }).error(function() { 30374c5ab19fd69d3c030f53e5b64493d548b74f916zachr@google.com $scope.flashStatus(false); 3046f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com }); 3056f8e2c5e87bd6620ff5290a9a8b6d5b570366336zachr@google.com }; 3061bc995e68cac8621a7efce3c2ccac88da1b8d3c2zachr@google.com} 307