patch 5 - Add testcases for emHeights and fontBoundingBox where the font's typographic ascent+descent does not equal the em size.

Depends on D184608

Differential Revision: https://phabricator.services.mozilla.com/D184609

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1841692
gecko-commit: 90b19e0d07e5d2cd137f135b860f0357df90e338
gecko-reviewers: gfx-reviewers, lsalzman
diff --git a/fonts/CanvasTest-ascent256.ttf b/fonts/CanvasTest-ascent256.ttf
new file mode 100644
index 0000000..d5924fc
--- /dev/null
+++ b/fonts/CanvasTest-ascent256.ttf
Binary files differ
diff --git a/fonts/CanvasTest-descent0.ttf b/fonts/CanvasTest-descent0.ttf
new file mode 100644
index 0000000..5887c0d
--- /dev/null
+++ b/fonts/CanvasTest-descent0.ttf
Binary files differ
diff --git a/html/canvas/element/text/2d.text.measure.emHeights-low-ascent.html b/html/canvas/element/text/2d.text.measure.emHeights-low-ascent.html
new file mode 100644
index 0000000..7b6874d
--- /dev/null
+++ b/html/canvas/element/text/2d.text.measure.emHeights-low-ascent.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.emHeights-low-ascent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<style>
+@font-face {
+  font-family: CanvasTest-ascent256;
+  src: url("/fonts/CanvasTest-ascent256.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.emHeights-low-ascent</h1>
+<p class="desc">Testing emHeights with reduced ascent metric</p>
+
+
+<span style="font-family: CanvasTest-ascent256; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+promise_test(async t => {
+
+  var canvas = document.getElementById('c');
+  var ctx = canvas.getContext('2d');
+
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-ascent256';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').emHeightAscent, 20, "ctx.measureText('A').emHeightAscent", "20");
+  _assertSame(ctx.measureText('A').emHeightDescent, 20, "ctx.measureText('A').emHeightDescent", "20");
+  _assertSame(ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent", "40");
+
+  _assertSame(ctx.measureText('ABCD').emHeightAscent, 20, "ctx.measureText('ABCD').emHeightAscent", "20");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent, 20, "ctx.measureText('ABCD').emHeightDescent", "20");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent", "40");
+
+}, "Testing emHeights with reduced ascent metric");
+</script>
+
diff --git a/html/canvas/element/text/2d.text.measure.emHeights-zero-descent.html b/html/canvas/element/text/2d.text.measure.emHeights-zero-descent.html
new file mode 100644
index 0000000..c3ce994
--- /dev/null
+++ b/html/canvas/element/text/2d.text.measure.emHeights-zero-descent.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.emHeights-zero-descent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<style>
+@font-face {
+  font-family: CanvasTest-descent0;
+  src: url("/fonts/CanvasTest-descent0.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.emHeights-zero-descent</h1>
+<p class="desc">Testing emHeights with zero descent metric</p>
+
+
+<span style="font-family: CanvasTest-descent0; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+promise_test(async t => {
+
+  var canvas = document.getElementById('c');
+  var ctx = canvas.getContext('2d');
+
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-descent0';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightAscent", "40");
+  _assertSame(ctx.measureText('A').emHeightDescent, 0, "ctx.measureText('A').emHeightDescent", "0");
+  _assertSame(ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent", "40");
+
+  _assertSame(ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightAscent", "40");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent, 0, "ctx.measureText('ABCD').emHeightDescent", "0");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent", "40");
+
+}, "Testing emHeights with zero descent metric");
+</script>
+
diff --git a/html/canvas/element/text/2d.text.measure.fontBoundingBox-reduced-ascent.html b/html/canvas/element/text/2d.text.measure.fontBoundingBox-reduced-ascent.html
new file mode 100644
index 0000000..653d26d
--- /dev/null
+++ b/html/canvas/element/text/2d.text.measure.fontBoundingBox-reduced-ascent.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.fontBoundingBox-reduced-ascent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<style>
+@font-face {
+  font-family: CanvasTest-ascent256;
+  src: url("/fonts/CanvasTest-ascent256.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.fontBoundingBox-reduced-ascent</h1>
+<p class="desc">Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric</p>
+
+
+<span style="font-family: CanvasTest-ascent256; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+promise_test(async t => {
+
+  var canvas = document.getElementById('c');
+  var ctx = canvas.getContext('2d');
+
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-ascent256';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 10, "ctx.measureText('A').fontBoundingBoxAscent", "10");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 10, "ctx.measureText('A').fontBoundingBoxDescent", "10");
+
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 10, "ctx.measureText('ABCD').fontBoundingBoxAscent", "10");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 10, "ctx.measureText('ABCD').fontBoundingBoxDescent", "10");
+
+}, "Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric");
+</script>
+
diff --git a/html/canvas/element/text/2d.text.measure.fontBoundingBox-zero-descent.html b/html/canvas/element/text/2d.text.measure.fontBoundingBox-zero-descent.html
new file mode 100644
index 0000000..785c0bc
--- /dev/null
+++ b/html/canvas/element/text/2d.text.measure.fontBoundingBox-zero-descent.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.fontBoundingBox-zero-descent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<style>
+@font-face {
+  font-family: CanvasTest-descent0;
+  src: url("/fonts/CanvasTest-descent0.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.fontBoundingBox-zero-descent</h1>
+<p class="desc">Testing fontBoundingBox for OffscreenCanvas with zero descent metric</p>
+
+
+<span style="font-family: CanvasTest-descent0; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+promise_test(async t => {
+
+  var canvas = document.getElementById('c');
+  var ctx = canvas.getContext('2d');
+
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-descent0';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 30, "ctx.measureText('A').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 0, "ctx.measureText('A').fontBoundingBoxDescent", "0");
+
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 30, "ctx.measureText('ABCD').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 0, "ctx.measureText('ABCD').fontBoundingBoxDescent", "0");
+
+}, "Testing fontBoundingBox for OffscreenCanvas with zero descent metric");
+</script>
+
diff --git a/html/canvas/element/text/2d.text.measure.fontBoundingBox.html b/html/canvas/element/text/2d.text.measure.fontBoundingBox.html
index 90781bd..9e7e190 100644
--- a/html/canvas/element/text/2d.text.measure.fontBoundingBox.html
+++ b/html/canvas/element/text/2d.text.measure.fontBoundingBox.html
@@ -29,15 +29,14 @@
   var ctx = canvas.getContext('2d');
 
   await document.fonts.ready;
-  ctx.font = '50px CanvasTest';
+  ctx.font = '40px CanvasTest';
   ctx.direction = 'ltr';
   ctx.align = 'left'
-  // approx_equals because font metrics may be rounded slightly differently by different platforms/browsers.
-  assert_approx_equals(ctx.measureText('A').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-  assert_approx_equals(ctx.measureText('A').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 30, "ctx.measureText('A').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 10, "ctx.measureText('A').fontBoundingBoxDescent", "10");
 
-  assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-  assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 30, "ctx.measureText('ABCD').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 10, "ctx.measureText('ABCD').fontBoundingBoxDescent", "10");
 
 }, "Testing fontBoundingBox measurements");
 </script>
diff --git a/html/canvas/offscreen/text/2d.text.measure.emHeights-low-ascent.html b/html/canvas/offscreen/text/2d.text.measure.emHeights-low-ascent.html
new file mode 100644
index 0000000..2e2e5dd
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.emHeights-low-ascent.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.text.measure.emHeights-low-ascent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.text.measure.emHeights-low-ascent</h1>
+<p class="desc">Testing emHeights with reduced ascent metric</p>
+
+
+<script>
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-ascent256", "url('/fonts/CanvasTest-ascent256.ttf')");
+  f.load();
+  document.fonts.add(f);
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-ascent256';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').emHeightAscent, 20, "ctx.measureText('A').emHeightAscent", "20");
+  _assertSame(ctx.measureText('A').emHeightDescent, 20, "ctx.measureText('A').emHeightDescent", "20");
+  _assertSame(ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent", "40");
+
+  _assertSame(ctx.measureText('ABCD').emHeightAscent, 20, "ctx.measureText('ABCD').emHeightAscent", "20");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent, 20, "ctx.measureText('ABCD').emHeightDescent", "20");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent", "40");
+
+}, "Testing emHeights with reduced ascent metric");
+</script>
diff --git a/html/canvas/offscreen/text/2d.text.measure.emHeights-low-ascent.worker.js b/html/canvas/offscreen/text/2d.text.measure.emHeights-low-ascent.worker.js
new file mode 100644
index 0000000..09ee787
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.emHeights-low-ascent.worker.js
@@ -0,0 +1,30 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.text.measure.emHeights-low-ascent
+// Description:Testing emHeights with reduced ascent metric
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-ascent256", "url('/fonts/CanvasTest-ascent256.ttf')");
+  f.load();
+  self.fonts.add(f);
+  await self.fonts.ready;
+  ctx.font = '40px CanvasTest-ascent256';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').emHeightAscent, 20, "ctx.measureText('A').emHeightAscent", "20");
+  _assertSame(ctx.measureText('A').emHeightDescent, 20, "ctx.measureText('A').emHeightDescent", "20");
+  _assertSame(ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent", "40");
+
+  _assertSame(ctx.measureText('ABCD').emHeightAscent, 20, "ctx.measureText('ABCD').emHeightAscent", "20");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent, 20, "ctx.measureText('ABCD').emHeightDescent", "20");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent", "40");
+  t.done();
+}, "Testing emHeights with reduced ascent metric");
+done();
diff --git a/html/canvas/offscreen/text/2d.text.measure.emHeights-zero-descent.html b/html/canvas/offscreen/text/2d.text.measure.emHeights-zero-descent.html
new file mode 100644
index 0000000..e39c08c
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.emHeights-zero-descent.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.text.measure.emHeights-zero-descent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.text.measure.emHeights-zero-descent</h1>
+<p class="desc">Testing emHeights with zero descent metric</p>
+
+
+<script>
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-descent0", "url('/fonts/CanvasTest-descent0.ttf')");
+  f.load();
+  document.fonts.add(f);
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-descent0';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightAscent", "40");
+  _assertSame(ctx.measureText('A').emHeightDescent, 0, "ctx.measureText('A').emHeightDescent", "0");
+  _assertSame(ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent", "40");
+
+  _assertSame(ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightAscent", "40");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent, 0, "ctx.measureText('ABCD').emHeightDescent", "0");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent", "40");
+
+}, "Testing emHeights with zero descent metric");
+</script>
diff --git a/html/canvas/offscreen/text/2d.text.measure.emHeights-zero-descent.worker.js b/html/canvas/offscreen/text/2d.text.measure.emHeights-zero-descent.worker.js
new file mode 100644
index 0000000..a2f0978
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.emHeights-zero-descent.worker.js
@@ -0,0 +1,30 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.text.measure.emHeights-zero-descent
+// Description:Testing emHeights with zero descent metric
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-descent0", "url('/fonts/CanvasTest-descent0.ttf')");
+  f.load();
+  self.fonts.add(f);
+  await self.fonts.ready;
+  ctx.font = '40px CanvasTest-descent0';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightAscent", "40");
+  _assertSame(ctx.measureText('A').emHeightDescent, 0, "ctx.measureText('A').emHeightDescent", "0");
+  _assertSame(ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent, 40, "ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent", "40");
+
+  _assertSame(ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightAscent", "40");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent, 0, "ctx.measureText('ABCD').emHeightDescent", "0");
+  _assertSame(ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent, 40, "ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent", "40");
+  t.done();
+}, "Testing emHeights with zero descent metric");
+done();
diff --git a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-reduced-ascent.html b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-reduced-ascent.html
new file mode 100644
index 0000000..51eb2c8
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-reduced-ascent.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.text.measure.fontBoundingBox-reduced-ascent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.text.measure.fontBoundingBox-reduced-ascent</h1>
+<p class="desc">Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric</p>
+
+
+<script>
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-ascent256", "url('/fonts/CanvasTest-ascent256.ttf')");
+  f.load();
+  document.fonts.add(f);
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-ascent256';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 10, "ctx.measureText('A').fontBoundingBoxAscent", "10");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 10, "ctx.measureText('A').fontBoundingBoxDescent", "10");
+
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 10, "ctx.measureText('ABCD').fontBoundingBoxAscent", "10");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 10, "ctx.measureText('ABCD').fontBoundingBoxDescent", "10");
+
+}, "Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric");
+</script>
diff --git a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-reduced-ascent.worker.js b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-reduced-ascent.worker.js
new file mode 100644
index 0000000..dea67ff
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-reduced-ascent.worker.js
@@ -0,0 +1,28 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.text.measure.fontBoundingBox-reduced-ascent
+// Description:Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-ascent256", "url('/fonts/CanvasTest-ascent256.ttf')");
+  f.load();
+  self.fonts.add(f);
+  await self.fonts.ready;
+  ctx.font = '40px CanvasTest-ascent256';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 10, "ctx.measureText('A').fontBoundingBoxAscent", "10");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 10, "ctx.measureText('A').fontBoundingBoxDescent", "10");
+
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 10, "ctx.measureText('ABCD').fontBoundingBoxAscent", "10");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 10, "ctx.measureText('ABCD').fontBoundingBoxDescent", "10");
+  t.done();
+}, "Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric");
+done();
diff --git a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-zero-descent.html b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-zero-descent.html
new file mode 100644
index 0000000..ea65e58
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-zero-descent.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>OffscreenCanvas test: 2d.text.measure.fontBoundingBox-zero-descent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+
+<h1>2d.text.measure.fontBoundingBox-zero-descent</h1>
+<p class="desc">Testing fontBoundingBox for OffscreenCanvas with zero descent metric</p>
+
+
+<script>
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-descent0", "url('/fonts/CanvasTest-descent0.ttf')");
+  f.load();
+  document.fonts.add(f);
+  await document.fonts.ready;
+  ctx.font = '40px CanvasTest-descent0';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 30, "ctx.measureText('A').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 0, "ctx.measureText('A').fontBoundingBoxDescent", "0");
+
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 30, "ctx.measureText('ABCD').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 0, "ctx.measureText('ABCD').fontBoundingBoxDescent", "0");
+
+}, "Testing fontBoundingBox for OffscreenCanvas with zero descent metric");
+</script>
diff --git a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-zero-descent.worker.js b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-zero-descent.worker.js
new file mode 100644
index 0000000..99a886d
--- /dev/null
+++ b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox-zero-descent.worker.js
@@ -0,0 +1,28 @@
+// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
+// OffscreenCanvas test in a worker:2d.text.measure.fontBoundingBox-zero-descent
+// Description:Testing fontBoundingBox for OffscreenCanvas with zero descent metric
+// Note:
+
+importScripts("/resources/testharness.js");
+importScripts("/html/canvas/resources/canvas-tests.js");
+
+promise_test(async t => {
+
+  var canvas = new OffscreenCanvas(100, 50);
+  var ctx = canvas.getContext('2d');
+
+  var f = new FontFace("CanvasTest-descent0", "url('/fonts/CanvasTest-descent0.ttf')");
+  f.load();
+  self.fonts.add(f);
+  await self.fonts.ready;
+  ctx.font = '40px CanvasTest-descent0';
+  ctx.direction = 'ltr';
+  ctx.align = 'left'
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 30, "ctx.measureText('A').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 0, "ctx.measureText('A').fontBoundingBoxDescent", "0");
+
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 30, "ctx.measureText('ABCD').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 0, "ctx.measureText('ABCD').fontBoundingBoxDescent", "0");
+  t.done();
+}, "Testing fontBoundingBox for OffscreenCanvas with zero descent metric");
+done();
diff --git a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.html b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.html
index 439c96c..36b11f3 100644
--- a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.html
+++ b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.html
@@ -19,15 +19,14 @@
   f.load();
   document.fonts.add(f);
   await document.fonts.ready;
-  ctx.font = '50px CanvasTest';
+  ctx.font = '40px CanvasTest';
   ctx.direction = 'ltr';
   ctx.align = 'left'
-  // approx_equals because font metrics may be rounded slightly differently by different platforms/browsers.
-  assert_approx_equals(ctx.measureText('A').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-  assert_approx_equals(ctx.measureText('A').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 30, "ctx.measureText('A').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 10, "ctx.measureText('A').fontBoundingBoxDescent", "10");
 
-  assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-  assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 30, "ctx.measureText('ABCD').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 10, "ctx.measureText('ABCD').fontBoundingBoxDescent", "10");
 
 }, "Testing fontBoundingBox measurements");
 </script>
diff --git a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.worker.js b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.worker.js
index 463bc21..b2cde04 100644
--- a/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.worker.js
+++ b/html/canvas/offscreen/text/2d.text.measure.fontBoundingBox.worker.js
@@ -15,15 +15,14 @@
   f.load();
   self.fonts.add(f);
   await self.fonts.ready;
-  ctx.font = '50px CanvasTest';
+  ctx.font = '40px CanvasTest';
   ctx.direction = 'ltr';
   ctx.align = 'left'
-  // approx_equals because font metrics may be rounded slightly differently by different platforms/browsers.
-  assert_approx_equals(ctx.measureText('A').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-  assert_approx_equals(ctx.measureText('A').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+  _assertSame(ctx.measureText('A').fontBoundingBoxAscent, 30, "ctx.measureText('A').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('A').fontBoundingBoxDescent, 10, "ctx.measureText('A').fontBoundingBoxDescent", "10");
 
-  assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-  assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxAscent, 30, "ctx.measureText('ABCD').fontBoundingBoxAscent", "30");
+  _assertSame(ctx.measureText('ABCD').fontBoundingBoxDescent, 10, "ctx.measureText('ABCD').fontBoundingBoxDescent", "10");
   t.done();
 }, "Testing fontBoundingBox measurements");
 done();
diff --git a/html/canvas/tools/yaml-new/text.yaml b/html/canvas/tools/yaml-new/text.yaml
index ffdc240..93c86b8 100644
--- a/html/canvas/tools/yaml-new/text.yaml
+++ b/html/canvas/tools/yaml-new/text.yaml
@@ -1060,15 +1060,14 @@
   - CanvasTest
   code: |
     {{ load_font }}
-    ctx.font = '50px CanvasTest';
+    ctx.font = '40px CanvasTest';
     ctx.direction = 'ltr';
     ctx.align = 'left'
-    // approx_equals because font metrics may be rounded slightly differently by different platforms/browsers.
-    assert_approx_equals(ctx.measureText('A').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-    assert_approx_equals(ctx.measureText('A').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+    @assert ctx.measureText('A').fontBoundingBoxAscent === 30;
+    @assert ctx.measureText('A').fontBoundingBoxDescent === 10;
 
-    assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxAscent, 50 * 768 / 1024, 1, "unexpected fontBoundingBoxAscent");
-    assert_approx_equals(ctx.measureText('ABCD').fontBoundingBoxDescent, 50 * 256 / 1024, 1, "unexpected fontBoundingBoxDescent");
+    @assert ctx.measureText('ABCD').fontBoundingBoxAscent === 30;
+    @assert ctx.measureText('ABCD').fontBoundingBoxDescent === 10;
   variants: *load-font-variant-definition
 
 - name: 2d.text.measure.fontBoundingBox.ahem
@@ -1087,6 +1086,40 @@
     @assert ctx.measureText('ABCD').fontBoundingBoxDescent === 10;
   variants: *load-font-variant-definition
 
+- name: 2d.text.measure.fontBoundingBox-reduced-ascent
+  desc: Testing fontBoundingBox for OffscreenCanvas with reduced ascent metric
+  test_type: promise
+  fonts:
+  - CanvasTest-ascent256
+  code: |
+    {{ load_font }}
+    ctx.font = '40px CanvasTest-ascent256';
+    ctx.direction = 'ltr';
+    ctx.align = 'left'
+    @assert ctx.measureText('A').fontBoundingBoxAscent === 10;
+    @assert ctx.measureText('A').fontBoundingBoxDescent === 10;
+
+    @assert ctx.measureText('ABCD').fontBoundingBoxAscent === 10;
+    @assert ctx.measureText('ABCD').fontBoundingBoxDescent === 10;
+  variants: *load-font-variant-definition
+
+- name: 2d.text.measure.fontBoundingBox-zero-descent
+  desc: Testing fontBoundingBox for OffscreenCanvas with zero descent metric
+  test_type: promise
+  fonts:
+  - CanvasTest-descent0
+  code: |
+    {{ load_font }}
+    ctx.font = '40px CanvasTest-descent0';
+    ctx.direction = 'ltr';
+    ctx.align = 'left'
+    @assert ctx.measureText('A').fontBoundingBoxAscent === 30;
+    @assert ctx.measureText('A').fontBoundingBoxDescent === 0;
+
+    @assert ctx.measureText('ABCD').fontBoundingBoxAscent === 30;
+    @assert ctx.measureText('ABCD').fontBoundingBoxDescent === 0;
+  variants: *load-font-variant-definition
+
 - name: 2d.text.measure.emHeights
   desc: Testing emHeights
   test_type: promise
@@ -1106,6 +1139,44 @@
     @assert ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent === 40;
   variants: *load-font-variant-definition
 
+- name: 2d.text.measure.emHeights-low-ascent
+  desc: Testing emHeights with reduced ascent metric
+  test_type: promise
+  fonts:
+  - CanvasTest-ascent256
+  code: |
+    {{ load_font }}
+    ctx.font = '40px CanvasTest-ascent256';
+    ctx.direction = 'ltr';
+    ctx.align = 'left'
+    @assert ctx.measureText('A').emHeightAscent === 20;
+    @assert ctx.measureText('A').emHeightDescent === 20;
+    @assert ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent === 40;
+
+    @assert ctx.measureText('ABCD').emHeightAscent === 20;
+    @assert ctx.measureText('ABCD').emHeightDescent === 20;
+    @assert ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent === 40;
+  variants: *load-font-variant-definition
+
+- name: 2d.text.measure.emHeights-zero-descent
+  desc: Testing emHeights with zero descent metric
+  test_type: promise
+  fonts:
+  - CanvasTest-descent0
+  code: |
+    {{ load_font }}
+    ctx.font = '40px CanvasTest-descent0';
+    ctx.direction = 'ltr';
+    ctx.align = 'left'
+    @assert ctx.measureText('A').emHeightAscent === 40;
+    @assert ctx.measureText('A').emHeightDescent === 0;
+    @assert ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent === 40;
+
+    @assert ctx.measureText('ABCD').emHeightAscent === 40;
+    @assert ctx.measureText('ABCD').emHeightDescent === 0;
+    @assert ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent === 40;
+  variants: *load-font-variant-definition
+
 - name: 2d.text.measure.baselines
   desc: Testing baselines
   test_type: promise