Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 6 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /html/canvas/offscreen/text/2d.text.measure.getActualBoundingBox.tentative.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<meta charset="UTF-8">
<title>OffscreenCanvas test: 2d.text.measure.getActualBoundingBox.tentative</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.getActualBoundingBox.tentative</h1>
<script>
promise_test(async t => {
const canvas = new OffscreenCanvas(800, 200);
const ctx = canvas.getContext('2d');
// Use measureText to create a rect for the whole text
function getFullTextBoundingBox(text) {
const tm = ctx.measureText(text);
return {
x: -tm.actualBoundingBoxLeft,
y: -tm.actualBoundingBoxAscent,
width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
};
}
// Returns a string a replaces the characters in text that are not in the
// range [start, end) with spaces.
function buildTestString(text, start, end) {
let ret = '';
for (let i = 0; i < text.length; ++i) {
if (start <= i && i < end)
ret += text[i];
else
ret += ' ';
}
return ret;
}
function checkRectsMatch(rect_a, rect_b, text, start, end) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
}
function testForSubstring(text, start, end) {
const textMetrics = ctx.measureText(text);
const rect_from_api = textMetrics.getActualBoundingBox(start, end);
const rect_from_full_bounds = getFullTextBoundingBox(
buildTestString(text, start, end));
checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
}
var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
f.load();
document.fonts.add(f);
await document.fonts.ready;
ctx.textAlign = 'left';
ctx.letterSpacing = '0px';
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
ctx.font = '50px CanvasTest';
const text = 'ABCDE';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
// Full string.
testForSubstring(text, 0, text.length);
// Intermediate string.
testForSubstring(text, 1, text.length - 1);
// First character.
testForSubstring(text, 0, 1);
// Intermediate character.
testForSubstring(text, 2, 3);
}
}
}, "Test TextMetrics::getActualBoundingBox(), with text align left , and 0px letter spacing.");
promise_test(async t => {
const canvas = new OffscreenCanvas(800, 200);
const ctx = canvas.getContext('2d');
// Use measureText to create a rect for the whole text
function getFullTextBoundingBox(text) {
const tm = ctx.measureText(text);
return {
x: -tm.actualBoundingBoxLeft,
y: -tm.actualBoundingBoxAscent,
width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
};
}
// Returns a string a replaces the characters in text that are not in the
// range [start, end) with spaces.
function buildTestString(text, start, end) {
let ret = '';
for (let i = 0; i < text.length; ++i) {
if (start <= i && i < end)
ret += text[i];
else
ret += ' ';
}
return ret;
}
function checkRectsMatch(rect_a, rect_b, text, start, end) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
}
function testForSubstring(text, start, end) {
const textMetrics = ctx.measureText(text);
const rect_from_api = textMetrics.getActualBoundingBox(start, end);
const rect_from_full_bounds = getFullTextBoundingBox(
buildTestString(text, start, end));
checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
}
var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
f.load();
document.fonts.add(f);
await document.fonts.ready;
ctx.textAlign = 'center';
ctx.letterSpacing = '0px';
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
ctx.font = '50px CanvasTest';
const text = 'ABCDE';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
// Full string.
testForSubstring(text, 0, text.length);
// Intermediate string.
testForSubstring(text, 1, text.length - 1);
// First character.
testForSubstring(text, 0, 1);
// Intermediate character.
testForSubstring(text, 2, 3);
}
}
}, "Test TextMetrics::getActualBoundingBox(), with text align center , and 0px letter spacing.");
promise_test(async t => {
const canvas = new OffscreenCanvas(800, 200);
const ctx = canvas.getContext('2d');
// Use measureText to create a rect for the whole text
function getFullTextBoundingBox(text) {
const tm = ctx.measureText(text);
return {
x: -tm.actualBoundingBoxLeft,
y: -tm.actualBoundingBoxAscent,
width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
};
}
// Returns a string a replaces the characters in text that are not in the
// range [start, end) with spaces.
function buildTestString(text, start, end) {
let ret = '';
for (let i = 0; i < text.length; ++i) {
if (start <= i && i < end)
ret += text[i];
else
ret += ' ';
}
return ret;
}
function checkRectsMatch(rect_a, rect_b, text, start, end) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
}
function testForSubstring(text, start, end) {
const textMetrics = ctx.measureText(text);
const rect_from_api = textMetrics.getActualBoundingBox(start, end);
const rect_from_full_bounds = getFullTextBoundingBox(
buildTestString(text, start, end));
checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
}
var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
f.load();
document.fonts.add(f);
await document.fonts.ready;
ctx.textAlign = 'right';
ctx.letterSpacing = '0px';
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
ctx.font = '50px CanvasTest';
const text = 'ABCDE';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
// Full string.
testForSubstring(text, 0, text.length);
// Intermediate string.
testForSubstring(text, 1, text.length - 1);
// First character.
testForSubstring(text, 0, 1);
// Intermediate character.
testForSubstring(text, 2, 3);
}
}
}, "Test TextMetrics::getActualBoundingBox(), with text align right , and 0px letter spacing.");
promise_test(async t => {
const canvas = new OffscreenCanvas(800, 200);
const ctx = canvas.getContext('2d');
// Use measureText to create a rect for the whole text
function getFullTextBoundingBox(text) {
const tm = ctx.measureText(text);
return {
x: -tm.actualBoundingBoxLeft,
y: -tm.actualBoundingBoxAscent,
width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
};
}
// Returns a string a replaces the characters in text that are not in the
// range [start, end) with spaces.
function buildTestString(text, start, end) {
let ret = '';
for (let i = 0; i < text.length; ++i) {
if (start <= i && i < end)
ret += text[i];
else
ret += ' ';
}
return ret;
}
function checkRectsMatch(rect_a, rect_b, text, start, end) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
}
function testForSubstring(text, start, end) {
const textMetrics = ctx.measureText(text);
const rect_from_api = textMetrics.getActualBoundingBox(start, end);
const rect_from_full_bounds = getFullTextBoundingBox(
buildTestString(text, start, end));
checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
}
var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
f.load();
document.fonts.add(f);
await document.fonts.ready;
ctx.textAlign = 'left';
ctx.letterSpacing = '10px';
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
ctx.font = '50px CanvasTest';
const text = 'ABCDE';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
// Full string.
testForSubstring(text, 0, text.length);
// Intermediate string.
testForSubstring(text, 1, text.length - 1);
// First character.
testForSubstring(text, 0, 1);
// Intermediate character.
testForSubstring(text, 2, 3);
}
}
}, "Test TextMetrics::getActualBoundingBox(), with text align left , and 10px letter spacing.");
promise_test(async t => {
const canvas = new OffscreenCanvas(800, 200);
const ctx = canvas.getContext('2d');
// Use measureText to create a rect for the whole text
function getFullTextBoundingBox(text) {
const tm = ctx.measureText(text);
return {
x: -tm.actualBoundingBoxLeft,
y: -tm.actualBoundingBoxAscent,
width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
};
}
// Returns a string a replaces the characters in text that are not in the
// range [start, end) with spaces.
function buildTestString(text, start, end) {
let ret = '';
for (let i = 0; i < text.length; ++i) {
if (start <= i && i < end)
ret += text[i];
else
ret += ' ';
}
return ret;
}
function checkRectsMatch(rect_a, rect_b, text, start, end) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
}
function testForSubstring(text, start, end) {
const textMetrics = ctx.measureText(text);
const rect_from_api = textMetrics.getActualBoundingBox(start, end);
const rect_from_full_bounds = getFullTextBoundingBox(
buildTestString(text, start, end));
checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
}
var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
f.load();
document.fonts.add(f);
await document.fonts.ready;
ctx.textAlign = 'center';
ctx.letterSpacing = '10px';
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
ctx.font = '50px CanvasTest';
const text = 'ABCDE';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
// Full string.
testForSubstring(text, 0, text.length);
// Intermediate string.
testForSubstring(text, 1, text.length - 1);
// First character.
testForSubstring(text, 0, 1);
// Intermediate character.
testForSubstring(text, 2, 3);
}
}
}, "Test TextMetrics::getActualBoundingBox(), with text align center , and 10px letter spacing.");
promise_test(async t => {
const canvas = new OffscreenCanvas(800, 200);
const ctx = canvas.getContext('2d');
// Use measureText to create a rect for the whole text
function getFullTextBoundingBox(text) {
const tm = ctx.measureText(text);
return {
x: -tm.actualBoundingBoxLeft,
y: -tm.actualBoundingBoxAscent,
width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
};
}
// Returns a string a replaces the characters in text that are not in the
// range [start, end) with spaces.
function buildTestString(text, start, end) {
let ret = '';
for (let i = 0; i < text.length; ++i) {
if (start <= i && i < end)
ret += text[i];
else
ret += ' ';
}
return ret;
}
function checkRectsMatch(rect_a, rect_b, text, start, end) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
}
function testForSubstring(text, start, end) {
const textMetrics = ctx.measureText(text);
const rect_from_api = textMetrics.getActualBoundingBox(start, end);
const rect_from_full_bounds = getFullTextBoundingBox(
buildTestString(text, start, end));
checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
}
var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
f.load();
document.fonts.add(f);
await document.fonts.ready;
ctx.textAlign = 'right';
ctx.letterSpacing = '10px';
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
ctx.font = '50px CanvasTest';
const text = 'ABCDE';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
// Full string.
testForSubstring(text, 0, text.length);
// Intermediate string.
testForSubstring(text, 1, text.length - 1);
// First character.
testForSubstring(text, 0, 1);
// Intermediate character.
testForSubstring(text, 2, 3);
}
}
}, "Test TextMetrics::getActualBoundingBox(), with text align right , and 10px letter spacing.");
</script>