Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
skdiff_html.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
11
12/// Make layout more consistent by scaling image to 240 height, 360 width,
13/// or natural size, whichever is smallest.
14static int compute_image_height(int height, int width) {
15 int retval = 240;
16 if (height < retval) {
17 retval = height;
18 }
19 float scale = (float) retval / height;
20 if (width * scale > 360) {
21 scale = (float) 360 / width;
22 retval = static_cast<int>(height * scale);
23 }
24 return retval;
25}
26
28 const int matchCount,
29 const int colorThreshold,
30 const RecordArray& differences,
31 const SkString &baseDir,
32 const SkString &comparisonDir) {
33 stream->writeText("<table>\n");
34 stream->writeText("<tr><th>");
35 stream->writeText("select image</th>\n<th>");
36 stream->writeDecAsText(matchCount);
37 stream->writeText(" of ");
38 stream->writeDecAsText(differences.size());
39 stream->writeText(" diffs matched ");
40 if (colorThreshold == 0) {
41 stream->writeText("exactly");
42 } else {
43 stream->writeText("within ");
44 stream->writeDecAsText(colorThreshold);
45 stream->writeText(" color units per component");
46 }
47 stream->writeText(".<br>");
48 stream->writeText("</th>\n<th>");
49 stream->writeText("every different pixel shown in white");
50 stream->writeText("</th>\n<th>");
51 stream->writeText("color difference at each pixel");
52 stream->writeText("</th>\n<th>baseDir: ");
53 stream->writeText(baseDir.c_str());
54 stream->writeText("</th>\n<th>comparisonDir: ");
55 stream->writeText(comparisonDir.c_str());
56 stream->writeText("</th>\n");
57 stream->writeText("</tr>\n");
58}
59
60static void print_pixel_count(SkFILEWStream* stream, const DiffRecord& diff) {
61 stream->writeText("<br>(");
62 stream->writeDecAsText(static_cast<int>(diff.fFractionDifference *
63 diff.fBase.fBitmap.width() *
64 diff.fBase.fBitmap.height()));
65 stream->writeText(" pixels)");
66/*
67 stream->writeDecAsText(diff.fWeightedFraction *
68 diff.fBaseWidth *
69 diff.fBaseHeight);
70 stream->writeText(" weighted pixels)");
71*/
72}
73
74static void print_checkbox_cell(SkFILEWStream* stream, const DiffRecord& diff) {
75 stream->writeText("<td><input type=\"checkbox\" name=\"");
76 stream->writeText(diff.fBase.fFilename.c_str());
77 stream->writeText("\" checked=\"yes\"></td>");
78}
79
80static void print_label_cell(SkFILEWStream* stream, const DiffRecord& diff) {
81 char metricBuf [20];
82
83 stream->writeText("<td><b>");
84 stream->writeText(diff.fBase.fFilename.c_str());
85 stream->writeText("</b><br>");
86 switch (diff.fResult) {
88 SkDEBUGFAIL("should not encounter DiffRecord with kEqualBits here");
89 return;
91 SkDEBUGFAIL("should not encounter DiffRecord with kEqualPixels here");
92 return;
94 stream->writeText("Image sizes differ</td>");
95 return;
97 sprintf(metricBuf, "%.4f%%", 100 * diff.fFractionDifference);
98 stream->writeText(metricBuf);
99 stream->writeText(" of pixels differ");
100 stream->writeText("\n (");
101 sprintf(metricBuf, "%.4f%%", 100 * diff.fWeightedFraction);
102 stream->writeText(metricBuf);
103 stream->writeText(" weighted)");
104 // Write the actual number of pixels that differ if it's < 1%
105 if (diff.fFractionDifference < 0.01) {
106 print_pixel_count(stream, diff);
107 }
108 stream->writeText("<br>");
110 stream->writeText("<br>Average alpha channel mismatch ");
111 stream->writeDecAsText(SkScalarRoundToInt(diff.fAverageMismatchA));
112 }
113
114 stream->writeText("<br>Max alpha channel mismatch ");
115 stream->writeDecAsText(SkScalarRoundToInt(diff.fMaxMismatchA));
116
117 stream->writeText("<br>Total alpha channel mismatch ");
118 stream->writeDecAsText(static_cast<int>(diff.fTotalMismatchA));
119
120 stream->writeText("<br>");
121 stream->writeText("<br>Average color mismatch ");
122 stream->writeDecAsText(SkScalarRoundToInt(MAX3(diff.fAverageMismatchR,
124 diff.fAverageMismatchB)));
125 stream->writeText("<br>Max color mismatch ");
126 stream->writeDecAsText(MAX3(diff.fMaxMismatchR,
127 diff.fMaxMismatchG,
128 diff.fMaxMismatchB));
129 stream->writeText("</td>");
130 break;
132 stream->writeText("Could not compare.<br>base: ");
133 stream->writeText(DiffResource::getStatusDescription(diff.fBase.fStatus));
134 stream->writeText("<br>comparison: ");
136 stream->writeText("</td>");
137 return;
138 default:
139 SkDEBUGFAIL("encountered DiffRecord with unknown result type");
140 return;
141 }
142}
143
144static void print_image_cell(SkFILEWStream* stream, const SkString& path, int height) {
145 stream->writeText("<td><a href=\"");
146 stream->writeText(path.c_str());
147 stream->writeText("\"><img src=\"");
148 stream->writeText(path.c_str());
149 stream->writeText("\" height=\"");
150 stream->writeDecAsText(height);
151 stream->writeText("px\"></a></td>");
152}
153
154static void print_link_cell(SkFILEWStream* stream, const SkString& path, const char* text) {
155 stream->writeText("<td><a href=\"");
156 stream->writeText(path.c_str());
157 stream->writeText("\">");
158 stream->writeText(text);
159 stream->writeText("</a></td>");
160}
161
162static void print_diff_resource_cell(SkFILEWStream* stream, const DiffResource& resource,
163 const SkString& relativePath, bool local) {
164 SkString fullPath = resource.fFullPath;
165 if (resource.fBitmap.empty()) {
167 if (local && !resource.fFilename.isEmpty()) {
168 print_link_cell(stream, resource.fFilename, "N/A");
169 return;
170 }
171 if (!fullPath.isEmpty()) {
172 if (!fullPath.startsWith(PATH_DIV_STR)) {
173 fullPath.prepend(relativePath);
174 }
175 print_link_cell(stream, fullPath, "N/A");
176 return;
177 }
178 }
179 stream->writeText("<td>N/A</td>");
180 return;
181 }
182
183 int height = compute_image_height(resource.fBitmap.height(), resource.fBitmap.width());
184 if (local) {
185 print_image_cell(stream, resource.fFilename, height);
186 return;
187 }
188 if (!fullPath.startsWith(PATH_DIV_STR)) {
189 fullPath.prepend(relativePath);
190 }
191 print_image_cell(stream, fullPath, height);
192}
193
194static void print_diff_row(SkFILEWStream* stream, const DiffRecord& diff, const SkString& relativePath) {
195 stream->writeText("<tr>\n");
196 print_checkbox_cell(stream, diff);
197 print_label_cell(stream, diff);
198 print_diff_resource_cell(stream, diff.fWhite, relativePath, true);
199 print_diff_resource_cell(stream, diff.fDifference, relativePath, true);
200 print_diff_resource_cell(stream, diff.fBase, relativePath, false);
201 print_diff_resource_cell(stream, diff.fComparison, relativePath, false);
202 stream->writeText("</tr>\n");
203 stream->flush();
204}
205
206void print_diff_page(const int matchCount,
207 const int colorThreshold,
208 const RecordArray& differences,
209 const SkString& baseDir,
210 const SkString& comparisonDir,
211 const SkString& outputDir) {
212
213 SkASSERT(!baseDir.isEmpty());
214 SkASSERT(!comparisonDir.isEmpty());
215 SkASSERT(!outputDir.isEmpty());
216
217 SkString outputPath(outputDir);
218 outputPath.append("index.html");
219 //SkFILEWStream outputStream ("index.html");
220 SkFILEWStream outputStream(outputPath.c_str());
221
222 // Need to convert paths from relative-to-cwd to relative-to-outputDir
223 // FIXME this doesn't work if there are '..' inside the outputDir
224
225 bool isPathAbsolute = false;
226 // On Windows or Linux, a path starting with PATH_DIV_CHAR is absolute.
227 if (outputDir.size() > 0 && PATH_DIV_CHAR == outputDir[0]) {
228 isPathAbsolute = true;
229 }
230#ifdef SK_BUILD_FOR_WIN
231 // On Windows, absolute paths can also start with "x:", where x is any
232 // drive letter.
233 if (outputDir.size() > 1 && ':' == outputDir[1]) {
234 isPathAbsolute = true;
235 }
236#endif
237
238 SkString relativePath;
239 if (!isPathAbsolute) {
240 unsigned int ui;
241 for (ui = 0; ui < outputDir.size(); ui++) {
242 if (outputDir[ui] == PATH_DIV_CHAR) {
243 relativePath.append(".." PATH_DIV_STR);
244 }
245 }
246 }
247
248 outputStream.writeText(
249 "<html>\n<head>\n"
250 "<script type=\"text/javascript\">\n"
251 "function generateCheckedList() {\n"
252 " const boxes = document.querySelectorAll('input[type=checkbox]:checked');\n"
253 " let fileCmdLineString = '';\n"
254 " let fileMultiLineString = '';\n"
255 " for (let i = 0; i < boxes.length; i++) {\n"
256 " fileMultiLineString += boxes[i].name + '<br>';\n"
257 " fileCmdLineString += boxes[i].name + '&nbsp;';\n"
258 " }\n"
259 " const checkedList = document.querySelector('#checkedList');\n"
260 " checkedList.innerHTML = fileCmdLineString + '<br><br>' + fileMultiLineString;\n"
261 "}\n"
262 "</script>\n</head>\n<body>\n");
263 print_table_header(&outputStream, matchCount, colorThreshold, differences,
264 baseDir, comparisonDir);
265 int i;
266 for (i = 0; i < differences.size(); i++) {
267 const DiffRecord& diff = differences[i];
268
269 switch (diff.fResult) {
270 // Cases in which there is no diff to report.
273 continue;
274 // Cases in which we want a detailed pixel diff.
278 print_diff_row(&outputStream, diff, relativePath);
279 continue;
280 default:
281 SkDEBUGFAIL("encountered DiffRecord with unknown result type");
282 continue;
283 }
284 }
285 outputStream.writeText(
286 "</table>\n"
287 "<input type=\"button\" "
288 "onclick=\"generateCheckedList()\" "
289 "value=\"Create Rebaseline List\">\n"
290 "<div id=\"checkedList\"></div>\n"
291 "</body>\n</html>\n");
292 outputStream.flush();
293}
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkScalarRoundToInt(x)
Definition SkScalar.h:37
bool empty() const
Definition SkBitmap.h:210
int width() const
Definition SkBitmap.h:149
int height() const
Definition SkBitmap.h:158
void flush() override
Definition SkStream.cpp:442
bool startsWith(const char prefixStr[]) const
Definition SkString.h:140
size_t size() const
Definition SkString.h:131
bool isEmpty() const
Definition SkString.h:130
void append(const char text[])
Definition SkString.h:203
void prepend(const char text[])
Definition SkString.h:215
const char * c_str() const
Definition SkString.h:133
bool writeText(const char text[])
Definition SkStream.h:247
int size() const
Definition SkTArray.h:416
std::u16string text
int32_t height
int32_t width
#define MAX3(a, b, c)
Definition skdiff.h:26
#define PATH_DIV_STR
Definition skdiff.h:21
#define PATH_DIV_CHAR
Definition skdiff.h:22
void print_diff_page(const int matchCount, const int colorThreshold, const RecordArray &differences, const SkString &baseDir, const SkString &comparisonDir, const SkString &outputDir)
static void print_link_cell(SkFILEWStream *stream, const SkString &path, const char *text)
static void print_pixel_count(SkFILEWStream *stream, const DiffRecord &diff)
static void print_label_cell(SkFILEWStream *stream, const DiffRecord &diff)
static void print_diff_row(SkFILEWStream *stream, const DiffRecord &diff, const SkString &relativePath)
static void print_table_header(SkFILEWStream *stream, const int matchCount, const int colorThreshold, const RecordArray &differences, const SkString &baseDir, const SkString &comparisonDir)
static void print_image_cell(SkFILEWStream *stream, const SkString &path, int height)
static int compute_image_height(int height, int width)
static void print_diff_resource_cell(SkFILEWStream *stream, const DiffResource &resource, const SkString &relativePath, bool local)
static void print_checkbox_cell(SkFILEWStream *stream, const DiffRecord &diff)
const Scalar scale
DiffResource fDifference
Definition skdiff.h:132
DiffResource fComparison
Definition skdiff.h:131
float fAverageMismatchG
Definition skdiff.h:143
Result fResult
Which category of diff result.
Definition skdiff.h:154
@ kEqualBits_Result
Definition skdiff.h:92
@ kCouldNotCompare_Result
Definition skdiff.h:96
@ kDifferentSizes_Result
Definition skdiff.h:95
@ kDifferentPixels_Result
Definition skdiff.h:94
@ kEqualPixels_Result
Definition skdiff.h:93
DiffResource fBase
Definition skdiff.h:130
float fAverageMismatchA
Definition skdiff.h:141
uint32_t fMaxMismatchB
Definition skdiff.h:151
uint32_t fMaxMismatchR
Definition skdiff.h:149
float fFractionDifference
Definition skdiff.h:138
uint32_t fMaxMismatchG
Definition skdiff.h:150
float fAverageMismatchB
Definition skdiff.h:144
float fWeightedFraction
Definition skdiff.h:139
uint32_t fMaxMismatchA
Definition skdiff.h:148
float fAverageMismatchR
Definition skdiff.h:142
uint32_t fTotalMismatchA
Definition skdiff.h:146
DiffResource fWhite
Definition skdiff.h:133
SkString fFullPath
Definition skdiff.h:81
SkBitmap fBitmap
Definition skdiff.h:83
static const char * getStatusDescription(Status status)
Definition skdiff.cpp:86
@ kCouldNotDecode_Status
Definition skdiff.h:34
Status fStatus
Definition skdiff.h:84
SkString fFilename
Definition skdiff.h:79