Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 4 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /html/canvas/element/text/2d.text.measure.getActualBoundingBox-full-text.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>Canvas test: 2d.text.measure.getActualBoundingBox-full-text.tentative</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">
<h1>2d.text.measure.getActualBoundingBox-full-text.tentative</h1>
<script>
test(t => {
const canvas = document.createElement('canvas');
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
};
}
function checkRectsMatch(rect_a, rect_b) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0);
assert_approx_equals(rect_a.y, rect_b.y, 1.0);
assert_approx_equals(rect_a.width, rect_b.width, 1.0);
assert_approx_equals(rect_a.height, rect_b.height, 1.0);
}
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
const kTexts = [
'UNAVAILABLE',
'🏁🎶🏁',
')(あ)(',
'-abcd ',
'اين المكتبة؟',
'bidiالرياضيات'
]
ctx.font = '50px sans-serif';
ctx.direction = 'ltr';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
for (text of kTexts) {
const tm = ctx.measureText(text);
const rect_from_api = tm.getActualBoundingBox(0, text.length);
const rect_from_full_bounds = getFullTextBoundingBox(text);
checkRectsMatch(rect_from_api, rect_from_full_bounds)
}
}
}
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction ltr and no-directional-override");
test(t => {
const canvas = document.createElement('canvas');
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
};
}
function checkRectsMatch(rect_a, rect_b) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0);
assert_approx_equals(rect_a.y, rect_b.y, 1.0);
assert_approx_equals(rect_a.width, rect_b.width, 1.0);
assert_approx_equals(rect_a.height, rect_b.height, 1.0);
}
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
const kTexts = [
'UNAVAILABLE',
'🏁🎶🏁',
')(あ)(',
'-abcd ',
'اين المكتبة؟',
'bidiالرياضيات'
]
ctx.font = '50px sans-serif';
ctx.direction = 'rtl';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
for (text of kTexts) {
const tm = ctx.measureText(text);
const rect_from_api = tm.getActualBoundingBox(0, text.length);
const rect_from_full_bounds = getFullTextBoundingBox(text);
checkRectsMatch(rect_from_api, rect_from_full_bounds)
}
}
}
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction rtl and no-directional-override");
test(t => {
const canvas = document.createElement('canvas');
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
};
}
function checkRectsMatch(rect_a, rect_b) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0);
assert_approx_equals(rect_a.y, rect_b.y, 1.0);
assert_approx_equals(rect_a.width, rect_b.width, 1.0);
assert_approx_equals(rect_a.height, rect_b.height, 1.0);
}
function addDirectionalOverrideCharacters(text, direction_is_ltr) {
// source: www.w3.org/International/questions/qa-bidi-unicode-controls.en
const LTR_OVERRIDE = '\u202D';
const RTL_OVERRIDE = '\u202E';
const OVERRIDE_END = '\u202C';
if (direction_is_ltr) {
return LTR_OVERRIDE + text + OVERRIDE_END;
}
return RTL_OVERRIDE + text + OVERRIDE_END;
}
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
const kTexts = [
'UNAVAILABLE',
'🏁🎶🏁',
')(あ)(',
'-abcd ',
'اين المكتبة؟',
'bidiالرياضيات'
]
ctx.font = '50px sans-serif';
ctx.direction = 'ltr';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
for (text of kTexts) {
text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr');
const tm = ctx.measureText(text);
const rect_from_api = tm.getActualBoundingBox(0, text.length);
const rect_from_full_bounds = getFullTextBoundingBox(text);
checkRectsMatch(rect_from_api, rect_from_full_bounds)
}
}
}
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction ltr and directional-override");
test(t => {
const canvas = document.createElement('canvas');
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
};
}
function checkRectsMatch(rect_a, rect_b) {
assert_approx_equals(rect_a.x, rect_b.x, 1.0);
assert_approx_equals(rect_a.y, rect_b.y, 1.0);
assert_approx_equals(rect_a.width, rect_b.width, 1.0);
assert_approx_equals(rect_a.height, rect_b.height, 1.0);
}
function addDirectionalOverrideCharacters(text, direction_is_ltr) {
// source: www.w3.org/International/questions/qa-bidi-unicode-controls.en
const LTR_OVERRIDE = '\u202D';
const RTL_OVERRIDE = '\u202E';
const OVERRIDE_END = '\u202C';
if (direction_is_ltr) {
return LTR_OVERRIDE + text + OVERRIDE_END;
}
return RTL_OVERRIDE + text + OVERRIDE_END;
}
const kAligns = [
'left',
'center',
'right',
];
const kBaselines = [
'top',
'hanging',
'middle',
'alphabetic',
'ideographic',
'bottom',
];
const kTexts = [
'UNAVAILABLE',
'🏁🎶🏁',
')(あ)(',
'-abcd ',
'اين المكتبة؟',
'bidiالرياضيات'
]
ctx.font = '50px sans-serif';
ctx.direction = 'rtl';
for (const align of kAligns) {
for (const baseline of kBaselines) {
ctx.textAlign = align;
ctx.textBaseline = baseline;
for (text of kTexts) {
text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr');
const tm = ctx.measureText(text);
const rect_from_api = tm.getActualBoundingBox(0, text.length);
const rect_from_full_bounds = getFullTextBoundingBox(text);
checkRectsMatch(rect_from_api, rect_from_full_bounds)
}
}
}
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction rtl and directional-override");
</script>
</div>