1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import re 6 7 8def result_contains_repaint_rects(text): 9 return isinstance(text, str) and ( 10 re.search('"repaintRects": \[$', text, re.MULTILINE) != None or 11 text.find('Minimum repaint:') != -1) 12 13 14def extract_layer_tree(input_str): 15 if not isinstance(input_str, str): 16 return '{}' 17 18 if input_str[0:2] == '{\n': 19 start = 0 20 else: 21 start = input_str.find('\n{\n') 22 if start == -1: 23 return '{}' 24 25 end = input_str.find('\n}\n', start) 26 if end == -1: 27 return '{}' 28 29 # FIXME: There may be multiple layer trees in the result. 30 return input_str[start:end + 3] 31 32 33def generate_repaint_overlay_html(test_name, actual_text, expected_text): 34 if not result_contains_repaint_rects(actual_text) and not result_contains_repaint_rects(expected_text): 35 return '' 36 37 expected_layer_tree = extract_layer_tree(expected_text) 38 actual_layer_tree = extract_layer_tree(actual_text) 39 40 minimum_repaint = '[]' 41 minimum_repaint_match = re.search('Minimum repaint:\n(\[.*\n\])', actual_text, re.DOTALL) 42 if minimum_repaint_match: 43 minimum_repaint = minimum_repaint_match.group(1) 44 45 return """<!DOCTYPE HTML> 46<html> 47<head> 48<title>%(title)s</title> 49<style> 50 body { 51 margin: 0; 52 padding: 0; 53 } 54 iframe { 55 position: absolute; 56 top: 80px; 57 left: 0; 58 border: 0; 59 z-index: -1; 60 } 61 canvas { 62 position: absolute; 63 top: 80px; 64 left: 0; 65 z-index: 1; 66 } 67 #actual, #minimum-repaint { 68 display: none; 69 } 70</style> 71</head> 72<body> 73<a href="http://crbug.com/381221">Known issues</a><br> 74<label><input id="show-test" type="checkbox" checked onchange="toggle_test(this.checked)">Show test</label> 75<label title="See fast/repaint/resources/text-based-repaint.js for how this works"> 76 <input id="show-minimum-repaint" type="checkbox" onchange="toggle_minimum_repaint(this.checked)">Minimum repaint 77</label> 78<label><input id="use-solid-colors" type="checkbox" onchange="toggle_solid_color(this.checked)">Use solid colors</label> 79<br> 80<button title="See fast/repaint/resources/text-based-repaint.js for how this works" onclick="highlight_under_repaint()"> 81 Highlight under-repaint 82</button> 83<br> 84<span id='type'>Expected Invalidations</span> 85<div id=overlay> 86 <canvas id='minimum-repaint' width='2000' height='2000'></canvas> 87 <canvas id='expected' width='2000' height='2000'></canvas> 88 <canvas id='actual' width='2000' height='2000'></canvas> 89</div> 90<script> 91var overlay_opacity = 0.25; 92 93function toggle_test(show_test) { 94 iframe.style.display = show_test ? 'block' : 'none'; 95} 96 97function toggle_minimum_repaint(show_minimum_repaint) { 98 document.getElementById('minimum-repaint').style.display = show_minimum_repaint ? 'block' : 'none'; 99} 100 101function toggle_solid_color(use_solid_color) { 102 overlay_opacity = use_solid_color ? 1 : 0.25; 103 draw_repaint_rects(); 104 draw_minimum_repaint(); 105} 106 107function highlight_under_repaint() { 108 document.getElementById('show-test').checked = false; 109 toggle_test(false); 110 document.getElementById('show-minimum-repaint').checked = true; 111 toggle_minimum_repaint(true); 112 document.getElementById('use-solid-colors').checked = true; 113 toggle_solid_color(true); 114} 115 116var expected = %(expected)s; 117var actual = %(actual)s; 118var minimum_repaint = %(minimum_repaint)s; 119 120function rectsEqual(rect1, rect2) { 121 return rect1[0] == rect2[0] && rect1[1] == rect2[1] && rect1[2] == rect2[2] && rect1[3] == rect2[3]; 122} 123 124function draw_rects(context, rects) { 125 for (var i = 0; i < rects.length; ++i) { 126 var rect = rects[i]; 127 context.fillRect(rect[0], rect[1], rect[2], rect[3]); 128 } 129} 130 131function draw_layer_rects(context, result) { 132 context.save(); 133 if (result.position) 134 context.translate(result.position[0], result.position[1]); 135 var t = result.transform; 136 if (t) { 137 var origin = result.transformOrigin || [result.bounds[0] / 2, result.bounds[1] / 2]; 138 context.translate(origin[0], origin[1]); 139 context.transform(t[0][0], t[0][1], t[1][0], t[1][1], t[3][0], t[3][1]); 140 context.translate(-origin[0], -origin[1]); 141 } 142 if (result.repaintRects) 143 draw_rects(context, result.repaintRects); 144 if (result.children) { 145 for (var i = 0; i < result.children.length; ++i) 146 draw_layer_rects(context, result.children[i]); 147 } 148 context.restore(); 149} 150 151var expected_canvas = document.getElementById('expected'); 152var actual_canvas = document.getElementById('actual'); 153var minimum_repaint_canvas = document.getElementById('minimum-repaint'); 154 155function draw_repaint_rects() { 156 var expected_ctx = expected_canvas.getContext("2d"); 157 expected_ctx.clearRect(0, 0, 2000, 2000); 158 expected_ctx.fillStyle = 'rgba(255, 0, 0, ' + overlay_opacity + ')'; 159 draw_layer_rects(expected_ctx, expected); 160 161 var actual_ctx = actual_canvas.getContext("2d"); 162 actual_ctx.clearRect(0, 0, 2000, 2000); 163 actual_ctx.fillStyle = 'rgba(0, 255, 0, ' + overlay_opacity + ')'; 164 draw_layer_rects(actual_ctx, actual); 165} 166 167function draw_minimum_repaint() { 168 var context = minimum_repaint_canvas.getContext("2d"); 169 context.fillStyle = 'rgba(0, 0, 0, 1)'; 170 draw_rects(context, minimum_repaint); 171} 172 173draw_repaint_rects(); 174draw_minimum_repaint(); 175 176var path = decodeURIComponent(location.search).substr(1); 177var iframe = document.createElement('iframe'); 178iframe.id = 'test-frame'; 179iframe.width = 800; 180iframe.height = 600; 181iframe.src = path; 182 183var overlay = document.getElementById('overlay'); 184overlay.appendChild(iframe); 185 186var type = document.getElementById('type'); 187var expected_showing = true; 188function flip() { 189 if (expected_showing) { 190 type.textContent = 'Actual Invalidations'; 191 expected_canvas.style.display = 'none'; 192 actual_canvas.style.display = 'block'; 193 } else { 194 type.textContent = 'Expected Invalidations'; 195 actual_canvas.style.display = 'none'; 196 expected_canvas.style.display = 'block'; 197 } 198 expected_showing = !expected_showing 199} 200setInterval(flip, 3000); 201</script> 202</body> 203</html> 204""" % { 205 'title': test_name, 206 'expected': expected_layer_tree, 207 'actual': actual_layer_tree, 208 'minimum_repaint': minimum_repaint, 209 } 210