Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions | Variables
pdf-comparison Namespace Reference

Functions

 test_exe (cmd)
 
 print_cmd (cmd, o)
 
 check_call (cmd, **kwargs)
 
 check_output (cmd, **kwargs)
 
 remove (*paths)
 
 timeout (deadline, cmd)
 
 is_same (path1, path2)
 
 getfilesoftype (directory, ending)
 
 get_common_paths (dirs, ext)
 
 printable_path (d)
 
 spawn (cmd)
 
 sysopen (arg)
 
 shard (fn, arglist)
 
 shardsum (fn, arglist)
 
 checkout_worktree (checkoutable)
 
 build_skia (directory, executable)
 
 build_and_run_dm (directory, data_dir)
 
 rasterize (path)
 
 main (control_commitish)
 

Variables

 EXTRA_GN_ARGS = os.environ.get('PDF_COMPARISON_GN_ARGS', '')
 
str REFERENCE_BACKEND = 'gl' if 'PDF_COMPARISON_NOGPU' not in os.environ else '8888'
 
 DPI = float(os.environ.get('PDF_COMPARISON_DPI', 72))
 
str PDF_CONFIG = 'pdf' if 'PDF_COMPARISON_300DPI' not in os.environ else 'pdf300'
 
list BAD_TESTS
 
str NINJA = 'ninja'
 
str PDFIUM_TEST = 'pdfium_test'
 
 NUM_THREADS = int(os.environ.get('PDF_COMPARISON_THREADS', 40))
 
list SOURCES = ['gm']
 
str HTML_HEAD
 
str HTML_TAIL
 
tuple USAGE
 

Function Documentation

◆ build_and_run_dm()

pdf-comparison.build_and_run_dm (   directory,
  data_dir 
)

Definition at line 227 of file pdf-comparison.py.

227def build_and_run_dm(directory, data_dir):
228 dm = build_skia(directory, 'dm')
229 for source in SOURCES:
230 os.makedirs(os.path.join(data_dir, PDF_CONFIG, source))
231 dm_args = [dm, '--src'] + SOURCES + ['--config', PDF_CONFIG, '-w', data_dir]
232 if BAD_TESTS:
233 dm_args += ['-m'] + ['~^%s$' % x for x in BAD_TESTS]
234 check_call(dm_args, cwd=directory)
235 return dm
236

◆ build_skia()

pdf-comparison.build_skia (   directory,
  executable 
)

Definition at line 213 of file pdf-comparison.py.

213def build_skia(directory, executable):
214 args = ('--args=is_debug=false'
215 ' extra_cflags=["-DSK_PDF_LESS_COMPRESSION",'
216 ' "-DSK_PDF_BASE85_BINARY"] ')
217 if test_exe('ccache'):
218 args += ' cc_wrapper="ccache"'
219 args += EXTRA_GN_ARGS
220 build_dir = directory + '/out/pdftest'
221 check_call([sys.executable, 'bin/sync'], cwd=directory)
222 check_call([directory + '/bin/gn', 'gen', 'out/pdftest', args],
223 cwd=directory)
224 check_call([NINJA, executable], cwd=build_dir)
225 return os.path.join(build_dir, executable)
226

◆ check_call()

pdf-comparison.check_call (   cmd,
**  kwargs 
)

Definition at line 72 of file pdf-comparison.py.

72def check_call(cmd, **kwargs):
73 print_cmd(cmd, sys.stdout)
74 return subprocess.check_call(cmd, **kwargs)
75

◆ check_output()

pdf-comparison.check_output (   cmd,
**  kwargs 
)

Definition at line 76 of file pdf-comparison.py.

76def check_output(cmd, **kwargs):
77 print_cmd(cmd, sys.stdout)
78 return subprocess.check_output(cmd, **kwargs)
79

◆ checkout_worktree()

pdf-comparison.checkout_worktree (   checkoutable)

Definition at line 201 of file pdf-comparison.py.

201def checkout_worktree(checkoutable):
202 directory = os.path.join(tempfile.gettempdir(), 'skpdf_control_tree')
203 commit = check_output(['git', 'rev-parse', checkoutable]).strip()
204 if os.path.isdir(directory):
205 try:
206 check_call(['git', 'checkout', commit], cwd=directory)
207 return directory
208 except subprocess.CalledProcessError:
209 shutil.rmtree(directory)
210 check_call(['git', 'worktree', 'add', '-f', directory, commit])
211 return directory
212

◆ get_common_paths()

pdf-comparison.get_common_paths (   dirs,
  ext 
)

Definition at line 114 of file pdf-comparison.py.

114def get_common_paths(dirs, ext):
115 return sorted(list(
116 set.intersection(*(set(getfilesoftype(d, ext)) for d in dirs))))
117

◆ getfilesoftype()

pdf-comparison.getfilesoftype (   directory,
  ending 
)

Definition at line 107 of file pdf-comparison.py.

107def getfilesoftype(directory, ending):
108 for dirpath, _, filenames in os.walk(directory):
109 rp = os.path.normpath(os.path.relpath(dirpath, directory))
110 for f in filenames:
111 if f.endswith(ending):
112 yield os.path.join(rp, f)
113

◆ is_same()

pdf-comparison.is_same (   path1,
  path2 
)

Definition at line 94 of file pdf-comparison.py.

94def is_same(path1, path2):
95 if not os.path.isfile(path1) or not os.path.isfile(path2):
96 return os.path.isfile(path1) == os.path.isfile(path2)
97 with open(path1, 'rb') as f1:
98 with open(path2, 'rb') as f2:
99 while True:
100 c1, c2 = f1.read(4096), f2.read(4096)
101 if c1 != c2:
102 return False
103 if not c1:
104 return True
105
106

◆ main()

pdf-comparison.main (   control_commitish)

Definition at line 245 of file pdf-comparison.py.

245def main(control_commitish):
246 assert os.pardir == '..' and '/' in [os.sep, os.altsep]
247 assert test_exe(NINJA)
248 assert test_exe(PDFIUM_TEST)
249 os.chdir(os.path.dirname(__file__) + '/../..')
250 control_worktree = checkout_worktree(control_commitish)
251 tmpdir = tempfile.mkdtemp(prefix='skpdf_')
252 exp = tmpdir + '/experim'
253 con = tmpdir + '/control'
254 build_and_run_dm(os.curdir, exp)
255 dm = build_and_run_dm(control_worktree, con)
256 image_diff_metric = build_skia(control_worktree, 'image_diff_metric')
257
258 out = sys.stdout
259 common_paths = get_common_paths([con, exp], '.pdf')
260 out.write('\nNumber of PDFs: %d\n\n' % len(common_paths))
261 def compare_identical(path):
262 cpath, epath = (os.path.join(x, path) for x in (con, exp))
263 if is_same(cpath, epath):
264 remove(cpath, epath)
265 return True
266 return False
267 identical_count = shardsum(compare_identical, common_paths)
268 out.write('Number of identical PDFs: %d\n\n' % identical_count)
269
270 differing_paths = get_common_paths([con, exp], '.pdf')
271 if not differing_paths:
272 out.write('All PDFs are the same!\n')
273 sys.exit(0)
274 out.write('Number of differing PDFs: %d\n' % len(differing_paths))
275 for p in differing_paths:
276 out.write(' %s\n' % printable_path(tmpdir + '/*/' + p))
277 out.write('\n')
278 shard(rasterize,
279 [os.path.join(x, p) for p in differing_paths for x in [con, exp]])
280
281 common_pngs = get_common_paths([con, exp], '.pdf.0.png')
282 identical_count = shardsum(compare_identical, common_pngs)
283 out.write('Number of PDFs that rasterize the same: %d\n\n'
284 % identical_count)
285
286 differing_pngs = get_common_paths([con, exp], '.pdf.0.png')
287 if not differing_pngs:
288 out.write('All PDFs rasterize the same!\n')
289 sys.exit(0)
290 out.write('Number of PDFs that rasterize differently: %d\n'
291 % len(differing_pngs))
292 for p in differing_pngs:
293 out.write(' %s\n' % printable_path(tmpdir + '/*/' + p))
294 out.write('\n')
295
296 scores = dict()
297 def compare_differing_pngs(path):
298 cpath, epath = (os.path.join(x, path) for x in (con, exp))
299 s = float(subprocess.check_output([image_diff_metric, cpath, epath]))
300 indicator = '.' if s < 0.001 else ':' if s < 0.01 else '!'
301 sys.stdout.write(indicator)
302 sys.stdout.flush()
303 scores[path] = s
304 shard(compare_differing_pngs, differing_pngs)
305 paths = sorted(scores.iterkeys(), key=lambda p: -scores[p])
306 out.write('\n\n')
307 for p in paths:
308 pdfpath = printable_path(tmpdir + '/*/' + p.replace('.0.png', ''))
309 out.write(' %6.4f %s\n' % (scores[p], pdfpath))
310 out.write('\n')
311
312 errors = []
313 rc = re.compile('^' + PDF_CONFIG + r'/([^/]*)/([^/]*)\.pdf\.0\.png$')
314 for p in paths:
315 m = rc.match(p)
316 assert(m)
317 source, name = m.groups()
318 errors.append((source, name, scores[p]))
319
320 for source in SOURCES:
321 os.makedirs(os.path.join(con, REFERENCE_BACKEND, source))
322 dm_args = [dm, '--src'] + SOURCES + [
323 '--config', REFERENCE_BACKEND, '-w', con, '-m'] + [
324 '^%s$' % name for _, name, _ in errors]
325 check_call(dm_args, cwd=control_worktree)
326
327 report = tmpdir + '/report.html'
328 with open(report, 'w') as o:
329 o.write(HTML_HEAD)
330 o.write('c="%s/";\n' % os.path.relpath(con, tmpdir))
331 o.write('e="%s/";\n' % os.path.relpath(exp, tmpdir))
332 o.write('z=[\n')
333 for source, name, score in errors:
334 gt = REFERENCE_BACKEND + '/' + source + '/' + name + '.png'
335 p = '%s/%s/%s.pdf.0.png' % (PDF_CONFIG, source, name)
336 desc = '%s | %s | %g' % (source, name, score)
337 o.write('["%s","%s","%s"],\n' % (p, gt, desc))
338 o.write(HTML_TAIL)
339 out.write(printable_path(report) + '\n')
340 sysopen(report)
341
Definition main.py:1

◆ print_cmd()

pdf-comparison.print_cmd (   cmd,
  o 
)

Definition at line 61 of file pdf-comparison.py.

61def print_cmd(cmd, o):
62 m = re.compile('[^A-Za-z0-9_./-]')
63 o.write('+ ')
64 for c in cmd:
65 if m.search(c) is not None:
66 o.write(repr(c) + ' ')
67 else:
68 o.write(c + ' ')
69 o.write('\n')
70 o.flush()
71

◆ printable_path()

pdf-comparison.printable_path (   d)

Definition at line 118 of file pdf-comparison.py.

118def printable_path(d):
119 if 'TMPDIR' in os.environ:
120 return d.replace(os.path.normpath(os.environ['TMPDIR']) + '/', '$TMPDIR/')
121 return d
122

◆ rasterize()

pdf-comparison.rasterize (   path)

Definition at line 237 of file pdf-comparison.py.

237def rasterize(path):
238 ret = timeout(30, [PDFIUM_TEST, '--png', '--scale=%g' % (DPI / 72.0), path])
239 if ret != 0:
240 sys.stdout.write(
241 '\nTIMEOUT OR ERROR [%d] "%s"\n' % (ret, printable_path(path)))
242 return
243 assert os.path.isfile(path + '.0.png')
244

◆ remove()

pdf-comparison.remove ( paths)

Definition at line 80 of file pdf-comparison.py.

80def remove(*paths):
81 for path in paths:
82 os.remove(path)
83

◆ shard()

pdf-comparison.shard (   fn,
  arglist 
)

Definition at line 181 of file pdf-comparison.py.

181def shard(fn, arglist):
182 jobs = [[arg for j, arg in enumerate(arglist) if j % NUM_THREADS == i]
183 for i in range(NUM_THREADS)]
184 results = []
185 def do_shard(*args):
186 for arg in args:
187 results.append(fn(arg))
188 thread_list = []
189 for job in jobs:
190 t = threading.Thread(target=do_shard, args=job)
191 t.start()
192 thread_list += [t]
193 for t in thread_list:
194 t.join()
195 return results
196

◆ shardsum()

pdf-comparison.shardsum (   fn,
  arglist 
)

Definition at line 197 of file pdf-comparison.py.

197def shardsum(fn, arglist):
198 'return the number of True results returned by fn(arg) for arg in arglist.'
199 return sum(1 for result in shard(fn, arglist) if result)
200

◆ spawn()

pdf-comparison.spawn (   cmd)

Definition at line 123 of file pdf-comparison.py.

123def spawn(cmd):
124 with open(os.devnull, 'w') as o:
125 subprocess.Popen(cmd, stdout=o, stderr=o)
126

◆ sysopen()

pdf-comparison.sysopen (   arg)

Definition at line 127 of file pdf-comparison.py.

127def sysopen(arg):
128 plat = sys.platform
129 if plat.startswith('darwin'):
130 spawn(["open", arg])
131 elif plat.startswith('win'):
132 # pylint: disable=no-member
133 os.startfile(arg)
134 else:
135 spawn(["xdg-open", arg])
136

◆ test_exe()

pdf-comparison.test_exe (   cmd)

Definition at line 53 of file pdf-comparison.py.

53def test_exe(cmd):
54 with open(os.devnull, 'w') as o:
55 try:
56 subprocess.call([cmd], stdout=o, stderr=o)
57 except OSError:
58 return False
59 return True
60

◆ timeout()

pdf-comparison.timeout (   deadline,
  cmd 
)

Definition at line 84 of file pdf-comparison.py.

84def timeout(deadline, cmd):
85 #print_cmd(cmd, sys.stdout)
86 with open(os.devnull, 'w') as o:
87 proc = subprocess.Popen(cmd, stdout=o, stderr=subprocess.STDOUT)
88 timer = threading.Timer(deadline, proc.terminate)
89 timer.start()
90 proc.wait()
91 timer.cancel()
92 return proc.returncode
93

Variable Documentation

◆ BAD_TESTS

list pdf-comparison.BAD_TESTS
Initial value:
1= [
2 'image-cacherator-from-picture',
3 'image-cacherator-from-raster',
4 'mixershader',
5 'shadermaskfilter_image',
6 'tilemode_decal',
7]

Definition at line 37 of file pdf-comparison.py.

◆ DPI

pdf-comparison.DPI = float(os.environ.get('PDF_COMPARISON_DPI', 72))

Definition at line 33 of file pdf-comparison.py.

◆ EXTRA_GN_ARGS

pdf-comparison.EXTRA_GN_ARGS = os.environ.get('PDF_COMPARISON_GN_ARGS', '')

Definition at line 29 of file pdf-comparison.py.

◆ HTML_HEAD

str pdf-comparison.HTML_HEAD

Definition at line 137 of file pdf-comparison.py.

◆ HTML_TAIL

str pdf-comparison.HTML_TAIL
Initial value:
1= '''];
2for(i=0;i<z.length;i++){
3r(c+z[i][0],e+z[i][0],z[i][2],c+z[i][1]);}},false);
4</script></head><body><table id="t">
5<tr><th>BEFORE-AFTER DIFF</th>
6<th>BEFORE</th><th>AFTER</th>
7<th>REFERENCE</th></tr>
8</table></body></html>'''

Definition at line 172 of file pdf-comparison.py.

◆ NINJA

str pdf-comparison.NINJA = 'ninja'

Definition at line 45 of file pdf-comparison.py.

◆ NUM_THREADS

pdf-comparison.NUM_THREADS = int(os.environ.get('PDF_COMPARISON_THREADS', 40))

Definition at line 49 of file pdf-comparison.py.

◆ PDF_CONFIG

str pdf-comparison.PDF_CONFIG = 'pdf' if 'PDF_COMPARISON_300DPI' not in os.environ else 'pdf300'

Definition at line 35 of file pdf-comparison.py.

◆ PDFIUM_TEST

str pdf-comparison.PDFIUM_TEST = 'pdfium_test'

Definition at line 47 of file pdf-comparison.py.

◆ REFERENCE_BACKEND

str pdf-comparison.REFERENCE_BACKEND = 'gl' if 'PDF_COMPARISON_NOGPU' not in os.environ else '8888'

Definition at line 31 of file pdf-comparison.py.

◆ SOURCES

list pdf-comparison.SOURCES = ['gm']

Definition at line 51 of file pdf-comparison.py.

◆ USAGE

tuple pdf-comparison.USAGE
Initial value:
1= ('\nusage:\n {0} COMMIT_OR_BRANCH_TO_COMPARE_TO\n\n'
2 'e.g.:\n {0} HEAD\nor\n {0} HEAD~1\n\n')

Definition at line 344 of file pdf-comparison.py.