Skip to content

Commit c4cc9fb

Browse files
committed
Add plumbing for safe printable inset to wptrunner and webdriver.
For print reftests, check <meta name="safe-printable-inset"> to simulate an unprintable region along the paper edges. The `content` attribute takes a non-negative number, which is the safe printable inset specified in centimeters. Only implemented for executorwebdriver. Spec discussion: w3c/csswg-drafts#11395 Spec change: w3c/csswg-drafts#13190 RFC: web-platform-tests/rfcs#233 For background, see https://drafts.csswg.org/css-page-3/#printable-area
1 parent 2e7eca1 commit c4cc9fb

11 files changed

Lines changed: 53 additions & 24 deletions

File tree

tools/manifest/item.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,16 @@ class PrintRefTest(RefTest):
293293
def page_ranges(self) -> PageRanges:
294294
return cast(PageRanges, self._extras.get("page_ranges", {}))
295295

296+
@property
297+
def safe_printable_inset(self) -> float:
298+
return self._extras.get("safe_printable_inset")
299+
296300
def to_json(self): # type: ignore
297301
rv = super().to_json()
298302
if self.page_ranges:
299303
rv[-1]["page_ranges"] = self.page_ranges
304+
if self.safe_printable_inset:
305+
rv[-1]["safe_printable_inset"] = self.safe_printable_inset
300306
return rv
301307

302308

tools/manifest/sourcefile.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,14 @@ def page_ranges(self) -> Dict[Text, List[List[Optional[int]]]]:
675675
rv[key].append(range_parts)
676676
return rv
677677

678+
@cached_property
679+
def safe_printable_inset(self) -> Optional[float]:
680+
"""The safe printable inset to simulate (in centimeters)"""
681+
for entry in self.root.findall(".//{http://www.w3.org/1999/xhtml}meta[@name='safe-printable-inset']"):
682+
key_data, value = self.parse_ref_keyed_meta(entry)
683+
return float(value)
684+
return None
685+
678686
@cached_property
679687
def testharness_nodes(self) -> List[ElementTree.Element]:
680688
"""List of ElementTree Elements corresponding to nodes representing a
@@ -1023,6 +1031,7 @@ def manifest_items(self) -> Tuple[Text, List[ManifestItem]]:
10231031
viewport_size=self.viewport_size,
10241032
fuzzy=self.fuzzy,
10251033
page_ranges=self.page_ranges,
1034+
safe_printable_inset=self.safe_printable_inset,
10261035
testdriver=self.has_testdriver,
10271036
)]
10281037

tools/webdriver/webdriver/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ def print(
791791
orientation=None,
792792
page=None,
793793
page_ranges=None,
794+
safe_printable_inset=None,
794795
scale=None,
795796
shrink_to_fit=None,
796797
):
@@ -801,6 +802,7 @@ def print(
801802
"orientation": orientation,
802803
"page": page,
803804
"pageRanges": page_ranges,
805+
"safePrintableInset": safe_printable_inset,
804806
"scale": scale,
805807
"shrinkToFit": shrink_to_fit,
806808
}.items():

tools/wptrunner/wptrunner/executors/base.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,11 @@ def teardown(self):
418418
def logger(self):
419419
return self.executor.logger
420420

421-
def get_hash(self, test, viewport_size, dpi, page_ranges):
421+
def get_hash(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
422422
key = (test.url, viewport_size, dpi)
423423

424424
if key not in self.screenshot_cache:
425-
success, data = self.get_screenshot_list(test, viewport_size, dpi, page_ranges)
425+
success, data = self.get_screenshot_list(test, viewport_size, dpi, page_ranges, safe_printable_inset)
426426

427427
if not success:
428428
return False, data
@@ -524,9 +524,9 @@ def run_test(self, test):
524524
viewport_size = test.viewport_size
525525
dpi = test.dpi
526526
page_ranges = test.page_ranges
527+
safe_printable_inset = test.safe_printable_inset
527528
self.message = []
528529

529-
530530
# Depth-first search of reference tree, with the goal
531531
# of reachings a leaf node with only pass results
532532

@@ -541,7 +541,7 @@ def run_test(self, test):
541541
fuzzy = self.get_fuzzy(test, nodes, relation)
542542

543543
for i, node in enumerate(nodes):
544-
success, data = self.get_hash(node, viewport_size, dpi, page_ranges)
544+
success, data = self.get_hash(node, viewport_size, dpi, page_ranges, safe_printable_inset)
545545
if success is False:
546546
return {"status": data[0], "message": data[1]}
547547

@@ -575,7 +575,7 @@ def run_test(self, test):
575575

576576
for i, (node, screenshot) in enumerate(zip(nodes, screenshots)):
577577
if screenshot is None:
578-
success, screenshot = self.retake_screenshot(node, viewport_size, dpi, page_ranges)
578+
success, screenshot = self.retake_screenshot(node, viewport_size, dpi, page_ranges, safe_printable_inset)
579579
if success:
580580
screenshots[i] = screenshot
581581

@@ -606,11 +606,12 @@ def get_fuzzy(self, root_test, test_nodes, relation):
606606
break
607607
return value
608608

609-
def retake_screenshot(self, node, viewport_size, dpi, page_ranges):
609+
def retake_screenshot(self, node, viewport_size, dpi, page_ranges, safe_printable_inset):
610610
success, data = self.get_screenshot_list(node,
611611
viewport_size,
612612
dpi,
613-
page_ranges)
613+
page_ranges,
614+
safe_printable_inset)
614615
if not success:
615616
return False, data
616617

@@ -641,8 +642,8 @@ def get_png_dimensions(
641642

642643
return struct.unpack(">LL", image_data[16:24])
643644

644-
def get_screenshot_list(self, node, viewport_size, dpi, page_ranges):
645-
success, data = self.executor.screenshot(node, viewport_size, dpi, page_ranges)
645+
def get_screenshot_list(self, node, viewport_size, dpi, page_ranges, safe_printable_inset):
646+
success, data = self.executor.screenshot(node, viewport_size, dpi, page_ranges, safe_printable_inset)
646647
viewport_size = (800, 600) if viewport_size is None else viewport_size
647648
dpi = 96 if dpi is None else dpi
648649
dpcm = dpi / 2.54

tools/wptrunner/wptrunner/executors/executoredge.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def setup(self, runner, protocol=None):
3535
with open(os.path.join(here, "reftest.js")) as f:
3636
self.script = f.read()
3737

38-
def screenshot(self, test, viewport_size, dpi, page_ranges):
38+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
3939
# https://github.com/web-platform-tests/wpt/issues/7140
4040
assert dpi is None
4141

@@ -62,7 +62,7 @@ def _render(self, protocol, url, timeout):
6262

6363
protocol.base.execute_script(self.wait_script, asynchronous=True)
6464

65-
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
65+
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size, self.safe_printable_inset)
6666
screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
6767
for i, screenshot in enumerate(screenshots):
6868
# strip off the data:img/png, part of the url

tools/wptrunner/wptrunner/executors/executormarionette.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ def load_runner(self):
683683
raise
684684
self.runner_handle = self.marionette.current_window_handle
685685

686-
def render_as_pdf(self, width, height):
686+
def render_as_pdf(self, width, height, safe_printable_inset):
687687
margin = 0.5 * 2.54
688688
body = {
689689
"page": {
@@ -701,7 +701,7 @@ def render_as_pdf(self, width, height):
701701
}
702702
return self.marionette._send_message("WebDriver:Print", body, key="value")
703703

704-
def pdf_to_png(self, pdf_base64, page_ranges):
704+
def pdf_to_png(self, pdf_base64, page_ranges, safe_printable_inset):
705705
handle = self.marionette.current_window_handle
706706
_switch_to_window(self.marionette, self.runner_handle)
707707
try:
@@ -1227,7 +1227,7 @@ def do_test(self, test):
12271227

12281228
return self.convert_result(test, result)
12291229

1230-
def screenshot(self, test, viewport_size, dpi, page_ranges):
1230+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
12311231
# https://github.com/web-platform-tests/wpt/issues/7135
12321232
assert viewport_size is None
12331233
assert dpi is None
@@ -1431,7 +1431,7 @@ def setup(self, runner, protocol=None):
14311431
if not isinstance(self.implementation, InternalRefTestImplementation):
14321432
self.protocol.pdf_print.load_runner()
14331433

1434-
def screenshot(self, test, viewport_size, dpi, page_ranges):
1434+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
14351435
# https://github.com/web-platform-tests/wpt/issues/7140
14361436
assert dpi is None
14371437

@@ -1453,7 +1453,7 @@ def _render(self, protocol, url, timeout):
14531453

14541454
protocol.base.execute_script(self.wait_script, asynchronous=True)
14551455

1456-
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
1456+
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size, self.safe_printable_inset)
14571457
screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
14581458
for i, screenshot in enumerate(screenshots):
14591459
# strip off the data:img/png, part of the url

tools/wptrunner/wptrunner/executors/executorselenium.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ def do_test(self, test):
442442

443443
return self.convert_result(test, result)
444444

445-
def screenshot(self, test, viewport_size, dpi, page_ranges):
445+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
446446
# https://github.com/web-platform-tests/wpt/issues/7135
447447
assert viewport_size is None
448448
assert dpi is None

tools/wptrunner/wptrunner/executors/executorservolegacy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ def teardown(self):
244244
os.rmdir(self.tempdir)
245245
super().teardown()
246246

247-
def screenshot(self, test, viewport_size, dpi, page_ranges):
247+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
248248
with TempFilename(self.tempdir) as output_path:
249249
extra_args = ["--exit",
250250
"--output=%s" % output_path,

tools/wptrunner/wptrunner/executors/executorwebdriver.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,14 +519,15 @@ def load_runner(self):
519519
raise
520520
self.runner_handle = self.webdriver.window_handle
521521

522-
def render_as_pdf(self, width, height):
522+
def render_as_pdf(self, width, height, safe_printable_inset_param):
523523
# All units passed to `print()` are in cm. See [0] for testing specifications.
524524
#
525525
# [0]: https://web-platform-tests.org/writing-tests/print-reftests.html
526526
margin = 0.5 * self.CM_PER_INCH
527527
pdf_base64 = self.webdriver.print(page={"width": width, "height": height},
528528
margin={"top": margin, "right": margin, "bottom": margin,
529529
"left": margin},
530+
safe_printable_inset=safe_printable_inset_param,
530531
background=True,
531532
shrink_to_fit=False)
532533
return pdf_base64
@@ -1383,7 +1384,7 @@ def do_test(self, test):
13831384

13841385
return self.convert_result(test, result)
13851386

1386-
def screenshot(self, test, viewport_size, dpi, page_ranges):
1387+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
13871388
# https://github.com/web-platform-tests/wpt/issues/7135
13881389
assert viewport_size is None
13891390
assert dpi is None
@@ -1423,7 +1424,7 @@ def setup(self, runner, protocol=None):
14231424
with open(os.path.join(here, "reftest.js")) as f:
14241425
self.script = f.read()
14251426

1426-
def screenshot(self, test, viewport_size, dpi, page_ranges):
1427+
def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
14271428
# https://github.com/web-platform-tests/wpt/issues/7140
14281429
assert dpi is None
14291430

@@ -1434,6 +1435,7 @@ def screenshot(self, test, viewport_size, dpi, page_ranges):
14341435

14351436
self.viewport_size = viewport_size
14361437
self.page_ranges = page_ranges.get(test.url)
1438+
self.safe_printable_inset = safe_printable_inset
14371439
timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
14381440
test_url = self.test_url(test)
14391441

@@ -1449,7 +1451,7 @@ def _render(self, protocol, url, timeout):
14491451
# return value.
14501452
protocol.testdriver.run(url, self.wait_script)
14511453

1452-
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
1454+
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size, self.safe_printable_inset)
14531455
screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
14541456
for i, screenshot in enumerate(screenshots):
14551457
# strip off the data:img/png, part of the url

tools/wptrunner/wptrunner/executors/protocol.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ class PrintProtocolPart(ProtocolPart):
11341134
name = "pdf_print"
11351135

11361136
@abstractmethod
1137-
def render_as_pdf(self, width, height):
1137+
def render_as_pdf(self, width, height, safe_printable_inset):
11381138
"""Output document as PDF"""
11391139
pass
11401140

0 commit comments

Comments
 (0)