Source code

Revision control

Copy as Markdown

Other Tools

- name: 2d.text.font.parse.basic
code: |
ctx.font = '20px serif';
@assert ctx.font === '20px serif';
ctx.font = '20PX SERIF';
@assert ctx.font === '20px serif'; @moz-todo
- name: 2d.text.font.parse.tiny
code: |
ctx.font = '1px sans-serif';
@assert ctx.font === '1px sans-serif';
- name: 2d.text.font.parse.complex
code: |
ctx.font = 'small-caps italic 400 12px/2 Unknown Font, sans-serif';
@assert ['italic small-caps 12px "Unknown Font", sans-serif', 'italic small-caps 12px Unknown Font, sans-serif'].includes(ctx.font);
- name: 2d.text.font.parse.complex2
code: |
ctx.font = 'small-caps italic 400 12px/2 "Unknown Font #2", sans-serif';
@assert ctx.font === 'italic small-caps 12px "Unknown Font #2", sans-serif';
- name: 2d.text.font.parse.family
code: |
ctx.font = '20px cursive,fantasy,monospace,sans-serif,serif,UnquotedFont,"QuotedFont\\\\\\","';
@assert ctx.font === '20px cursive, fantasy, monospace, sans-serif, serif, UnquotedFont, "QuotedFont\\\\\\","';
# TODO:
# 2d.text.font.parse.size.absolute
# xx-small x-small small medium large x-large xx-large
# 2d.text.font.parse.size.relative
# smaller larger
# 2d.text.font.parse.size.length.relative
# em ex px
# 2d.text.font.parse.size.length.absolute
# in cm mm pt pc
- name: 2d.text.font.parse.size.percentage
canvas: 'style="font-size: 144px"'
canvas_types: ['HtmlCanvas']
code: |
ctx.font = '50% serif';
@assert ctx.font === '72px serif'; @moz-todo
canvas.setAttribute('style', 'font-size: 100px');
@assert ctx.font === '72px serif'; @moz-todo
- name: 2d.text.font.parse.size.percentage.default
canvas_types: ['HtmlCanvas']
code: |
var canvas2 = document.createElement('canvas');
var ctx2 = canvas2.getContext('2d');
ctx2.font = '1000% serif';
@assert ctx2.font === '100px serif'; @moz-todo
- name: 2d.text.font.parse.system
desc: System fonts must be computed to explicit values
code: |
ctx.font = 'message-box';
@assert ctx.font !== 'message-box';
- name: 2d.text.font.parse.invalid
code: |
ctx.font = '20px serif';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = '';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = 'bogus';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = 'inherit';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = '10px {bogus}';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = '10px initial';
@assert ctx.font === '20px serif'; @moz-todo
ctx.font = '20px serif';
ctx.font = '10px default';
@assert ctx.font === '20px serif'; @moz-todo
ctx.font = '20px serif';
ctx.font = '10px inherit';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = '10px revert';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = 'var(--x)';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = 'var(--x, 10px serif)';
@assert ctx.font === '20px serif';
ctx.font = '20px serif';
ctx.font = '1em serif; background: green; margin: 10px';
@assert ctx.font === '20px serif';
- name: 2d.text.font.default
code: |
@assert ctx.font === '10px sans-serif';
- name: 2d.text.font.relative_size
canvas_types: ['HtmlCanvas']
code: |
var canvas2 = document.createElement('canvas');
var ctx2 = canvas2.getContext('2d');
ctx2.font = '1em sans-serif';
@assert ctx2.font === '10px sans-serif';
- name: 2d.text.font.relative_size
canvas_types: ['OffscreenCanvas', 'Worker']
code: |
ctx.font = '1em sans-serif';
@assert ctx.font === '10px sans-serif';
- name: 2d.text.font.weight
code: |
ctx.font = 'italic 400 12px serif';
@assert ctx.font === 'italic 12px serif';
ctx.font = 'italic 300 12px serif';
@assert ctx.font === 'italic 300 12px serif';
- name: 2d.text.align.valid
code: |
ctx.textAlign = 'start';
@assert ctx.textAlign === 'start';
ctx.textAlign = 'end';
@assert ctx.textAlign === 'end';
ctx.textAlign = 'left';
@assert ctx.textAlign === 'left';
ctx.textAlign = 'right';
@assert ctx.textAlign === 'right';
ctx.textAlign = 'center';
@assert ctx.textAlign === 'center';
- name: 2d.text.align.invalid
code: |
ctx.textAlign = 'start';
ctx.textAlign = 'bogus';
@assert ctx.textAlign === 'start';
ctx.textAlign = 'start';
ctx.textAlign = 'END';
@assert ctx.textAlign === 'start';
ctx.textAlign = 'start';
ctx.textAlign = 'end ';
@assert ctx.textAlign === 'start';
ctx.textAlign = 'start';
ctx.textAlign = 'end\0';
@assert ctx.textAlign === 'start';
- name: 2d.text.align.default
code: |
@assert ctx.textAlign === 'start';
- name: 2d.text.baseline.valid
code: |
ctx.textBaseline = 'top';
@assert ctx.textBaseline === 'top';
ctx.textBaseline = 'hanging';
@assert ctx.textBaseline === 'hanging';
ctx.textBaseline = 'middle';
@assert ctx.textBaseline === 'middle';
ctx.textBaseline = 'alphabetic';
@assert ctx.textBaseline === 'alphabetic';
ctx.textBaseline = 'ideographic';
@assert ctx.textBaseline === 'ideographic';
ctx.textBaseline = 'bottom';
@assert ctx.textBaseline === 'bottom';
- name: 2d.text.baseline.invalid
code: |
ctx.textBaseline = 'top';
ctx.textBaseline = 'bogus';
@assert ctx.textBaseline === 'top';
ctx.textBaseline = 'top';
ctx.textBaseline = 'MIDDLE';
@assert ctx.textBaseline === 'top';
ctx.textBaseline = 'top';
ctx.textBaseline = 'middle ';
@assert ctx.textBaseline === 'top';
ctx.textBaseline = 'top';
ctx.textBaseline = 'middle\0';
@assert ctx.textBaseline === 'top';
- name: 2d.text.baseline.default
code: |
@assert ctx.textBaseline === 'alphabetic';
- name: 2d.text.draw.baseline.top
desc: textBaseline top is the top of the em square (not the bounding box)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textBaseline = 'top';
ctx.fillText('CC', 0, 0);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: &load-font-variant-definition
- HtmlCanvas:
append_variants_to_name: false
canvas_types: ['HtmlCanvas']
load_font: |-
await document.fonts.ready;
OffscreenCanvas:
append_variants_to_name: false
canvas_types: ['OffscreenCanvas', 'Worker']
load_font: |-
var f = new FontFace("{{ fonts[0] }}", "url('/fonts/{{ fonts[0] }}.ttf')");
f.load();
{% set root = 'self' if canvas_type == 'Worker' else 'document' %}
{{ root }}.fonts.add(f);
await {{ root }}.fonts.ready;
- name: 2d.text.draw.baseline.bottom
desc: textBaseline bottom is the bottom of the em square (not the bounding box)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textBaseline = 'bottom';
ctx.fillText('CC', 0, 50);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.baseline.middle
desc: textBaseline middle is the middle of the em square (not the bounding box)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textBaseline = 'middle';
ctx.fillText('CC', 0, 25);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.baseline.alphabetic
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textBaseline = 'alphabetic';
ctx.fillText('CC', 0, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.baseline.ideographic
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textBaseline = 'ideographic';
ctx.fillText('CC', 0, 31.25);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255; @moz-todo
@assert pixel 95,45 ==~ 0,255,0,255; @moz-todo
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.baseline.hanging
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textBaseline = 'hanging';
ctx.fillText('CC', 0, 12.5);
@assert pixel 5,5 ==~ 0,255,0,255; @moz-todo
@assert pixel 95,5 ==~ 0,255,0,255; @moz-todo
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.space.collapse.space
desc: Space characters are converted to U+0020, and are NOT collapsed
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('E EE', 0, 37.5);
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 255,0,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.space.collapse.other
desc: Space characters are converted to U+0020, and are NOT collapsed
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('E \x09\x0a\x0c\x0d \x09\x0a\x0c\x0dEE', 0, 37.5);
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 255,0,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.space.collapse.start
desc: Space characters at the start of a line are NOT collapsed
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText(' EE', 0, 37.5);
@assert pixel 25,25 ==~ 255,0,0,255; @moz-todo
@assert pixel 75,25 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.space.collapse.end
desc: Space characters at the end of a line are NOT collapsed
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'right';
ctx.fillText('EE ', 100, 37.5);
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 255,0,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.measure.width.space
desc: Space characters are converted to U+0020 and NOT collapsed
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
@assert ctx.measureText('A B').width === 150;
@assert ctx.measureText('A B').width === 200;
@assert ctx.measureText('A \x09\x0a\x0c\x0d \x09\x0a\x0c\x0dB').width === 650;
@assert ctx.measureText('A \x0b B').width >= 200;
@assert ctx.measureText(' AB').width === 150;
@assert ctx.measureText('AB ').width === 150;
variants: *load-font-variant-definition
- name: 2d.text.drawing.style.measure.rtl.text
desc: Measurement should follow canvas direction instead text direction
code: |
metrics = ctx.measureText('اَلْعَرَبِيَّةُ');
@assert metrics.actualBoundingBoxLeft < metrics.actualBoundingBoxRight;
metrics = ctx.measureText('hello');
@assert metrics.actualBoundingBoxLeft < metrics.actualBoundingBoxRight;
- name: 2d.text.drawing.style.measure.textAlign
desc: Measurement should be related to textAlignment
code: |
ctx.textAlign = "right";
metrics = ctx.measureText('hello');
@assert metrics.actualBoundingBoxLeft > metrics.actualBoundingBoxRight;
ctx.textAlign = "left"
metrics = ctx.measureText('hello');
@assert metrics.actualBoundingBoxLeft < metrics.actualBoundingBoxRight;
- name: 2d.text.drawing.style.measure.direction
desc: Measurement should follow text direction
code: |
ctx.direction = "ltr";
metrics = ctx.measureText('hello');
@assert metrics.actualBoundingBoxLeft < metrics.actualBoundingBoxRight;
ctx.direction = "rtl";
metrics = ctx.measureText('hello');
@assert metrics.actualBoundingBoxLeft > metrics.actualBoundingBoxRight;
- name: 2d.text.draw.fill.basic
desc: fillText draws filled text
manual:
code: |
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.strokeStyle = '#f00';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('PASS', 5, 35);
expected: &passfill |
size 100 50
cr.set_source_rgb(0, 0, 0)
cr.rectangle(0, 0, 100, 50)
cr.fill()
cr.set_source_rgb(0, 1, 0)
cr.select_font_face("Arial")
cr.set_font_size(35)
cr.translate(5, 35)
cr.text_path("PASS")
cr.fill()
- name: 2d.text.draw.fill.unaffected
desc: fillText does not start a new path or subpath
code: |
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.moveTo(0, 0);
ctx.lineTo(100, 0);
ctx.font = '35px Arial, sans-serif';
ctx.fillText('FAIL', 5, 35);
ctx.lineTo(100, 50);
ctx.lineTo(0, 50);
ctx.fillStyle = '#0f0';
ctx.fill();
@assert pixel 50,25 == 0,255,0,255;
@assert pixel 5,45 == 0,255,0,255;
expected: green
- name: 2d.text.draw.fill.rtl
desc: fillText respects Right-To-Left Override characters
manual:
code: |
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.strokeStyle = '#f00';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('\u202eFAIL \xa0 \xa0 SSAP', 5, 35);
expected: *passfill
- name: 2d.text.draw.fill.maxWidth.large
desc: fillText handles maxWidth correctly
manual:
code: |
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('PASS', 5, 35, 200);
expected: *passfill
- name: 2d.text.draw.fill.maxWidth.small
desc: fillText handles maxWidth correctly
code: |
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#f00';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('fail fail fail fail fail', -100, 35, 90);
_assertGreen(ctx, 100, 50);
expected: green
- name: 2d.text.draw.fill.maxWidth.zero
desc: fillText handles maxWidth correctly
code: |
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#f00';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('fail fail fail fail fail', 5, 35, 0);
_assertGreen(ctx, 100, 50);
expected: green
- name: 2d.text.draw.fill.maxWidth.negative
desc: fillText handles maxWidth correctly
code: |
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#f00';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('fail fail fail fail fail', 5, 35, -1);
_assertGreen(ctx, 100, 50);
expected: green
- name: 2d.text.draw.fill.maxWidth.NaN
desc: fillText handles maxWidth correctly
code: |
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#f00';
ctx.font = '35px Arial, sans-serif';
ctx.fillText('fail fail fail fail fail', 5, 35, NaN);
_assertGreen(ctx, 100, 50);
expected: green
- name: 2d.text.draw.stroke.basic
desc: strokeText draws stroked text
manual:
code: |
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 100, 50);
ctx.strokeStyle = '#0f0';
ctx.fillStyle = '#f00';
ctx.lineWidth = 1;
ctx.font = '35px Arial, sans-serif';
ctx.strokeText('PASS', 5, 35);
expected: |
size 100 50
cr.set_source_rgb(0, 0, 0)
cr.rectangle(0, 0, 100, 50)
cr.fill()
cr.set_source_rgb(0, 1, 0)
cr.select_font_face("Arial")
cr.set_font_size(35)
cr.set_line_width(1)
cr.translate(5, 35)
cr.text_path("PASS")
cr.stroke()
- name: 2d.text.draw.stroke.unaffected
desc: strokeText does not start a new path or subpath
code: |
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.moveTo(0, 0);
ctx.lineTo(100, 0);
ctx.font = '35px Arial, sans-serif';
ctx.strokeStyle = '#f00';
ctx.strokeText('FAIL', 5, 35);
ctx.lineTo(100, 50);
ctx.lineTo(0, 50);
ctx.fillStyle = '#0f0';
ctx.fill();
@assert pixel 50,25 == 0,255,0,255;
@assert pixel 5,45 == 0,255,0,255;
expected: green
- name: 2d.text.draw.kern.consistent
desc: Stroked and filled text should have exactly the same kerning so it overlaps
manual:
code: |
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#f00';
ctx.strokeStyle = '#0f0';
ctx.lineWidth = 3;
ctx.font = '20px Arial, sans-serif';
ctx.fillText('VAVAVAVAVAVAVA', -50, 25);
ctx.fillText('ToToToToToToTo', -50, 45);
ctx.strokeText('VAVAVAVAVAVAVA', -50, 25);
ctx.strokeText('ToToToToToToTo', -50, 45);
expected: green
# CanvasTest is:
# A = (0, 0) to (1em, 0.75em) (above baseline)
# B = (0, 0) to (1em, -0.25em) (below baseline)
# C = (0, -0.25em) to (1em, 0.75em) (the em square) plus some Xs above and below
# D = (0, -0.25em) to (1em, 0.75em) (the em square) plus some Xs left and right
# E = (0, -0.25em) to (1em, 0.75em) (the em square)
# space = empty, 1em wide
#
# At 50px, "E" will fill the canvas vertically
# At 67px, "A" will fill the canvas vertically
#
# Ideographic baseline is 0.125em above alphabetic
# Mathematical baseline is 0.375em above alphabetic
# Hanging baseline is 0.500em above alphabetic
- name: 2d.text.draw.fill.maxWidth.fontface
desc: fillText works on @font-face fonts
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#f00';
ctx.fillText('EEEE', -50, 37.5, 40);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.fill.maxWidth.bound
desc: fillText handles maxWidth based on line size, not bounding box size
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('DD', 0, 37.5, 100);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.fontface
fonts:
- CanvasTest
test_type: promise
code: |
{{ load_font }}
ctx.font = '67px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('AA', 0, 50);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.fontface.repeat
desc: Draw with the font immediately, then wait a bit until and draw again. (This
crashes some version of WebKit.)
test_type: promise
fonts:
- CanvasTest
font_unused_in_dom: true
code: |
{{ load_font }}
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.font = '67px CanvasTest';
ctx.fillStyle = '#0f0';
ctx.fillText('AA', 0, 50);
await new Promise(resolve => t.step_timeout(resolve, 500));
ctx.fillText('AA', 0, 50);
_assertPixelApprox(canvas, 5,5, 0,255,0,255, 2);
_assertPixelApprox(canvas, 95,5, 0,255,0,255, 2);
_assertPixelApprox(canvas, 25,25, 0,255,0,255, 2);
_assertPixelApprox(canvas, 75,25, 0,255,0,255, 2);
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.fontface.notinpage
desc: '@font-face fonts should work even if they are not used in the page'
test_type: promise
fonts:
- CanvasTest
font_unused_in_dom: true
code: |
{{ load_font }}
ctx.font = '67px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('AA', 0, 50);
@assert pixel 5,5 ==~ 0,255,0,255; @moz-todo
@assert pixel 95,5 ==~ 0,255,0,255; @moz-todo
@assert pixel 25,25 ==~ 0,255,0,255; @moz-todo
@assert pixel 75,25 ==~ 0,255,0,255; @moz-todo
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.left
desc: textAlign left is the left of the first em square (not the bounding box)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'left';
ctx.fillText('DD', 0, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.right
desc: textAlign right is the right of the last em square (not the bounding box)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'right';
ctx.fillText('DD', 100, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.start.ltr
desc: textAlign start with ltr is the left edge
canvas: dir="ltr"
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
{% if canvas_type != 'HtmlCanvas' %}
ctx.direction = 'ltr';
{% endif %}
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'start';
ctx.fillText('DD', 0, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.start.rtl
desc: textAlign start with rtl is the right edge
canvas: dir="rtl"
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
{% if canvas_type != 'HtmlCanvas' %}
ctx.direction = 'rtl';
{% endif %}
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'start';
ctx.fillText('DD', 100, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.end.ltr
desc: textAlign end with ltr is the right edge
test_type: promise
canvas: dir="ltr"
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
{% if canvas_type != 'HtmlCanvas' %}
ctx.direction = 'ltr';
{% endif %}
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'end';
ctx.fillText('DD', 100, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.end.rtl
desc: textAlign end with rtl is the left edge
canvas: dir="rtl"
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
{% if canvas_type != 'HtmlCanvas' %}
ctx.direction = 'rtl';
{% endif %}
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'end';
ctx.fillText('DD', 0, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.align.center
desc: textAlign center is the center of the em squares (not the bounding box)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.textAlign = 'center';
ctx.fillText('DD', 50, 37.5);
@assert pixel 5,5 ==~ 0,255,0,255;
@assert pixel 95,5 ==~ 0,255,0,255;
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
@assert pixel 5,45 ==~ 0,255,0,255;
@assert pixel 95,45 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.space.basic
desc: U+0020 is rendered the correct size (1em wide)
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('E EE', -100, 37.5);
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.draw.space.collapse.nonspace
desc: Non-space characters are not converted to U+0020 and collapsed
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
ctx.fillStyle = '#0f0';
ctx.fillText('E\x0b EE', -150, 37.5);
@assert pixel 25,25 ==~ 0,255,0,255;
@assert pixel 75,25 ==~ 0,255,0,255;
expected: green
variants: *load-font-variant-definition
- name: 2d.text.measure.width.basic
desc: The width of character is same as font used
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
@assert ctx.measureText('A').width === 50;
@assert ctx.measureText('AA').width === 100;
@assert ctx.measureText('ABCD').width === 200;
ctx.font = '100px CanvasTest';
@assert ctx.measureText('A').width === 100;
variants: *load-font-variant-definition
- name: 2d.text.measure.width.empty
desc: The empty string has zero width
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
@assert ctx.measureText("").width === 0;
variants: *load-font-variant-definition
- name: 2d.text.measure.advances
desc: Testing width advances
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.direction = 'ltr';
ctx.align = 'left'
// Some platforms may return '-0'.
@assert Math.abs(ctx.measureText('Hello').advances[0]) === 0;
// Different platforms may render text slightly different.
@assert ctx.measureText('Hello').advances[1] >= 36;
@assert ctx.measureText('Hello').advances[2] >= 58;
@assert ctx.measureText('Hello').advances[3] >= 70;
@assert ctx.measureText('Hello').advances[4] >= 80;
var tm = ctx.measureText('Hello');
@assert ctx.measureText('Hello').advances[0] === tm.advances[0];
@assert ctx.measureText('Hello').advances[1] === tm.advances[1];
@assert ctx.measureText('Hello').advances[2] === tm.advances[2];
@assert ctx.measureText('Hello').advances[3] === tm.advances[3];
@assert ctx.measureText('Hello').advances[4] === tm.advances[4];
variants: *load-font-variant-definition
- name: 2d.text.measure.actualBoundingBox
desc: Testing actualBoundingBox
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.direction = 'ltr';
ctx.align = 'left'
ctx.baseline = 'alphabetic'
// Different platforms may render text slightly different.
// Values that are nominally expected to be zero might actually vary by a
// pixel or so if the UA accounts for antialiasing at glyph edges, so we
// allow a slight deviation.
@assert Math.abs(ctx.measureText('A').actualBoundingBoxLeft) <= 1;
@assert ctx.measureText('A').actualBoundingBoxRight >= 50;
@assert ctx.measureText('A').actualBoundingBoxAscent >= 35;
@assert Math.abs(ctx.measureText('A').actualBoundingBoxDescent) <= 1;
@assert ctx.measureText('D').actualBoundingBoxLeft >= 48;
@assert ctx.measureText('D').actualBoundingBoxLeft <= 52;
@assert ctx.measureText('D').actualBoundingBoxRight >= 75;
@assert ctx.measureText('D').actualBoundingBoxRight <= 80;
@assert ctx.measureText('D').actualBoundingBoxAscent >= 35;
@assert ctx.measureText('D').actualBoundingBoxAscent <= 40;
@assert ctx.measureText('D').actualBoundingBoxDescent >= 12;
@assert ctx.measureText('D').actualBoundingBoxDescent <= 15;
@assert Math.abs(ctx.measureText('ABCD').actualBoundingBoxLeft) <= 1;
@assert ctx.measureText('ABCD').actualBoundingBoxRight >= 200;
@assert ctx.measureText('ABCD').actualBoundingBoxAscent >= 85;
@assert ctx.measureText('ABCD').actualBoundingBoxDescent >= 37;
variants: *load-font-variant-definition
- name: 2d.text.measure.fontBoundingBox
desc: Testing fontBoundingBox measurements
test_type: promise
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '40px CanvasTest';
ctx.direction = 'ltr';
ctx.align = 'left'
@assert ctx.measureText('A').fontBoundingBoxAscent === 30;
@assert ctx.measureText('A').fontBoundingBoxDescent === 10;
@assert ctx.measureText('ABCD').fontBoundingBoxAscent === 30;
@assert ctx.measureText('ABCD').fontBoundingBoxDescent === 10;
variants: *load-font-variant-definition
- name: 2d.text.measure.fontBoundingBox.ahem
desc: Testing fontBoundingBox for font ahem
test_type: promise
fonts:
- Ahem
code: |
{{ load_font }}
ctx.font = '50px Ahem';
ctx.direction = 'ltr';
ctx.align = 'left'
@assert ctx.measureText('A').fontBoundingBoxAscent === 40;
@assert ctx.measureText('A').fontBoundingBoxDescent === 10;
@assert ctx.measureText('ABCD').fontBoundingBoxAscent === 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
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '40px CanvasTest';
ctx.direction = 'ltr';
ctx.align = 'left'
@assert ctx.measureText('A').emHeightAscent === 30;
@assert ctx.measureText('A').emHeightDescent === 10;
@assert ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent === 40;
@assert ctx.measureText('ABCD').emHeightAscent === 30;
@assert ctx.measureText('ABCD').emHeightDescent === 10;
@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
fonts:
- CanvasTest
code: |
{{ load_font }}
ctx.font = '50px CanvasTest';
ctx.direction = 'ltr';
ctx.align = 'left'
@assert Math.abs(ctx.measureText('A').alphabeticBaseline) === 0;
@assert ctx.measureText('A').ideographicBaseline === 6.25;
@assert ctx.measureText('A').hangingBaseline === 25;
@assert Math.abs(ctx.measureText('ABCD').alphabeticBaseline) === 0;
@assert ctx.measureText('ABCD').ideographicBaseline === 6.25;
@assert ctx.measureText('ABCD').hangingBaseline === 25;
variants: *load-font-variant-definition
- name: 2d.text.drawing.style.absolute.spacing
desc: Testing letter spacing and word spacing with absolute length
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
ctx.letterSpacing = '3px';
@assert ctx.letterSpacing === '3px';
@assert ctx.wordSpacing === '0px';
ctx.wordSpacing = '5px';
@assert ctx.letterSpacing === '3px';
@assert ctx.wordSpacing === '5px';
ctx.letterSpacing = '-1px';
ctx.wordSpacing = '-1px';
@assert ctx.letterSpacing === '-1px';
@assert ctx.wordSpacing === '-1px';
ctx.letterSpacing = '1PX';
ctx.wordSpacing = '10PX';
@assert ctx.letterSpacing === '1px';
@assert ctx.wordSpacing === '10px';
- name: 2d.text.drawing.style.font-relative.spacing
desc: Testing letter spacing and word spacing with font-relative length
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
ctx.letterSpacing = '1EX';
ctx.wordSpacing = '1EM';
@assert ctx.letterSpacing === '1ex';
@assert ctx.wordSpacing === '1em';
ctx.letterSpacing = '1ch';
ctx.wordSpacing = '1ic';
@assert ctx.letterSpacing === '1ch';
@assert ctx.wordSpacing === '1ic';
- name: 2d.text.drawing.style.nonfinite.spacing
desc: Testing letter spacing and word spacing with nonfinite inputs
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
function test_word_spacing(value) {
ctx.wordSpacing = value;
ctx.letterSpacing = value;
@assert ctx.wordSpacing === '0px';
@assert ctx.letterSpacing === '0px';
}
@nonfinite test_word_spacing(<0 NaN Infinity -Infinity>);
- name: 2d.text.drawing.style.invalid.spacing
desc: Testing letter spacing and word spacing with invalid units
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
function test_word_spacing(value) {
ctx.wordSpacing = value;
ctx.letterSpacing = value;
@assert ctx.wordSpacing === '0px';
@assert ctx.letterSpacing === '0px';
}
@nonfinite test_word_spacing(< '0s' '1min' '1deg' '1pp' 'initial' 'inherit' 'normal' 'none'>);
- name: 2d.text.drawing.style.letterSpacing.measure
desc: Testing letter spacing with different length units
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
var width_normal = ctx.measureText('Hello World').width;
function test_letter_spacing(value, difference_spacing, epsilon) {
ctx.letterSpacing = value;
@assert ctx.letterSpacing === value;
@assert ctx.wordSpacing === '0px';
width_with_letter_spacing = ctx.measureText('Hello World').width;
assert_approx_equals(width_with_letter_spacing, width_normal + difference_spacing, epsilon, "letter spacing doesn't work.");
}
// The first value is the letter Spacing to be set, the second value the
// change in length of string 'Hello World', note that there are 11 letters
// in 'hello world', so the length difference is always letterSpacing * 11.
// and the third value is the acceptable differencee for the length change,
// note that unit such as 1cm/1mm doesn't map to an exact pixel value.
test_cases = [['3px', 33, 0.1],
['5px', 55, 0.1],
['-2px', -22, 0.1],
['1em', 110, 0.1],
['-0.1em', -11, 0.1],
['1in', 1056, 0.1],
['-0.1cm', -41.65, 0.2],
['-0.6mm', -24,95, 0.2]]
for (const test_case of test_cases) {
test_letter_spacing(test_case[0], test_case[1], test_case[2]);
}
- name: 2d.text.drawing.style.wordSpacing.measure
desc: Testing word spacing with different length units
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
var width_normal = ctx.measureText('Hello World, again').width;
function test_word_spacing(value, difference_spacing, epsilon) {
ctx.wordSpacing = value;
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === value;
width_with_word_spacing = ctx.measureText('Hello World, again').width;
assert_approx_equals(width_with_word_spacing, width_normal + difference_spacing, epsilon, "word spacing doesn't work.");
}
// The first value is the word Spacing to be set, the second value the
// change in length of string 'Hello World', note that there are 2 words
// in 'Hello World, again', so the length difference is always wordSpacing * 2.
// and the third value is the acceptable differencee for the length change,
// note that unit such as 1cm/1mm doesn't map to an exact pixel value.
test_cases = [['3px', 6, 0.1],
['5px', 10, 0.1],
['-2px', -4, 0.1],
['1em', 20, 0.1],
['-0.5em', -10, 0.1],
['1in', 192, 0.1],
['-0.1cm', -7.57, 0.2],
['-0.6mm', -4.54, 0.2]]
for (const test_case of test_cases) {
test_word_spacing(test_case[0], test_case[1], test_case[2]);
}
- name: 2d.text.drawing.style.letterSpacing.change.font
desc: Set letter spacing and word spacing to font dependent value and verify it works after font change.
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
// Get the width for 'Hello World' at default size, 10px.
var width_normal = ctx.measureText('Hello World').width;
ctx.letterSpacing = '1em';
@assert ctx.letterSpacing === '1em';
// 1em = 10px. Add 10px after each letter in "Hello World",
// makes it 110px longer.
var width_with_spacing = ctx.measureText('Hello World').width;
assert_approx_equals(width_with_spacing, width_normal + 110, 0.1, "letter-spacing error");
// Changing font to 20px. Without resetting the spacing, 1em letterSpacing
// is now 20px, so it's suppose to be 220px longer without any letterSpacing set.
ctx.font = '20px serif';
width_with_spacing = ctx.measureText('Hello World').width;
// Now calculate the reference spacing for "Hello World" with no spacing.
ctx.letterSpacing = '0em';
width_normal = ctx.measureText('Hello World').width;
assert_approx_equals(width_with_spacing, width_normal + 220, 0.1, "letter-spacing error after font change");
- name: 2d.text.drawing.style.wordSpacing.change.font
desc: Set word spacing and word spacing to font dependent value and verify it works after font change.
code: |
@assert ctx.letterSpacing === '0px';
@assert ctx.wordSpacing === '0px';
// Get the width for 'Hello World, again' at default size, 10px.
var width_normal = ctx.measureText('Hello World, again').width;
ctx.wordSpacing = '1em';
@assert ctx.wordSpacing === '1em';
// 1em = 10px. Add 10px after each word in "Hello World, again",
// makes it 20px longer.
var width_with_spacing = ctx.measureText('Hello World, again').width;
@assert width_with_spacing === width_normal + 20;
// Changing font to 20px. Without resetting the spacing, 1em wordSpacing
// is now 20px, so it's suppose to be 40px longer without any wordSpacing set.
ctx.font = '20px serif';
width_with_spacing = ctx.measureText('Hello World, again').width;
// Now calculate the reference spacing for "Hello World, again" with no spacing.
ctx.wordSpacing = '0em';
width_normal = ctx.measureText('Hello World, again').width;
@assert width_with_spacing === width_normal + 40;
- name: 2d.text.drawing.style.fontKerning
desc: Testing basic functionalities of fontKerning for canvas
code: |
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "normal";
@assert ctx.fontKerning === "normal";
width_normal = ctx.measureText("TAWATAVA").width;
ctx.fontKerning = "none";
@assert ctx.fontKerning === "none";
width_none = ctx.measureText("TAWATAVA").width;
@assert width_normal < width_none;
- name: 2d.text.drawing.style.fontKerning.with.uppercase
desc: Testing basic functionalities of fontKerning for canvas
code: |
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "Normal";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "normal";
@assert ctx.fontKerning === "normal";
ctx.fontKerning = "Auto";
@assert ctx.fontKerning === "normal";
ctx.fontKerning = "auto";
ctx.fontKerning = "noRmal";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "auto";
ctx.fontKerning = "NoRMal";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "auto";
ctx.fontKerning = "NORMAL";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "None";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "none";
@assert ctx.fontKerning === "none";
ctx.fontKerning = "Auto";
@assert ctx.fontKerning === "none";
ctx.fontKerning = "auto";
ctx.fontKerning = "nOne";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "auto";
ctx.fontKerning = "nonE";
@assert ctx.fontKerning === "auto";
ctx.fontKerning = "auto";
ctx.fontKerning = "NONE";
@assert ctx.fontKerning === "auto";
- name: 2d.text.drawing.style.fontVariant.settings
desc: Testing basic functionalities of fontVariant for canvas
code: |
// Setting fontVariantCaps with lower cases
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "normal";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "small-caps";
@assert ctx.fontVariantCaps === "small-caps";
ctx.fontVariantCaps = "all-small-caps";
@assert ctx.fontVariantCaps === "all-small-caps";
ctx.fontVariantCaps = "petite-caps";
@assert ctx.fontVariantCaps === "petite-caps";
ctx.fontVariantCaps = "all-petite-caps";
@assert ctx.fontVariantCaps === "all-petite-caps";
ctx.fontVariantCaps = "unicase";
@assert ctx.fontVariantCaps === "unicase";
ctx.fontVariantCaps = "titling-caps";
@assert ctx.fontVariantCaps === "titling-caps";
// Setting fontVariantCaps with mixed-case values is not valid
ctx.fontVariantCaps = "nORmal";
@assert ctx.fontVariantCaps === "titling-caps";
ctx.fontVariantCaps = "normal";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "smaLL-caps";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "all-small-CAPS";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "pEtitE-caps";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "All-Petite-Caps";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "uNIcase";
@assert ctx.fontVariantCaps === "normal";
ctx.fontVariantCaps = "titling-CAPS";
@assert ctx.fontVariantCaps === "normal";
// Setting fontVariantCaps with non-existing font variant.
ctx.fontVariantCaps = "titling-caps";
ctx.fontVariantCaps = "abcd";
@assert ctx.fontVariantCaps === "titling-caps";
- name: 2d.text.drawing.style.textRendering.settings
desc: Testing basic functionalities of textRendering in Canvas
code: |
// Setting textRendering with correct case.
@assert ctx.textRendering === "auto";
ctx.textRendering = "optimizeSpeed";
@assert ctx.textRendering === "optimizeSpeed";
ctx.textRendering = "optimizeLegibility";
@assert ctx.textRendering === "optimizeLegibility";
ctx.textRendering = "geometricPrecision";
@assert ctx.textRendering === "geometricPrecision";
ctx.textRendering = "auto";
@assert ctx.textRendering === "auto";
// Setting textRendering with incorrect case is ignored.
ctx.textRendering = "OPtimizeSpeed";
@assert ctx.textRendering === "auto";
ctx.textRendering = "OPtimizELEgibility";
@assert ctx.textRendering === "auto";
ctx.textRendering = "GeometricPrecision";
@assert ctx.textRendering === "auto";
ctx.textRendering = "optimizespeed";
@assert ctx.textRendering === "auto";
ctx.textRendering = "optimizelegibility";
@assert ctx.textRendering === "auto";
ctx.textRendering = "geometricprecision";
@assert ctx.textRendering === "auto";
ctx.textRendering = "optimizeLegibility";
@assert ctx.textRendering === "optimizeLegibility";
ctx.textRendering = "AUTO";
@assert ctx.textRendering === "optimizeLegibility";
ctx.textRendering = "Auto";
@assert ctx.textRendering === "optimizeLegibility";
// Setting textRendering with non-existing font variant.
ctx.textRendering = "abcd";
@assert ctx.textRendering === "optimizeLegibility";
ctx.textRendering = "normal";
@assert ctx.textRendering === "optimizeLegibility";
ctx.textRendering = "";
@assert ctx.textRendering === "optimizeLegibility";
ctx.textRendering = "auto";
@assert ctx.textRendering === "auto";
- name: 2d.text.drawing.style.fontStretch.settings
desc: Testing value setting of fontStretch in Canvas
code: |
// Setting textRendering with lower cases
ctx.fontStretch = "ultra-condensed";
@assert ctx.fontStretch === "ultra-condensed";
ctx.fontStretch = "extra-condensed";
@assert ctx.fontStretch === "extra-condensed";
ctx.fontStretch = "condensed";
@assert ctx.fontStretch === "condensed";
ctx.fontStretch = "semi-condensed";
@assert ctx.fontStretch === "semi-condensed";
ctx.fontStretch = "normal";
@assert ctx.fontStretch === "normal";
ctx.fontStretch = "semi-expanded";
@assert ctx.fontStretch === "semi-expanded";
ctx.fontStretch = "expanded";
@assert ctx.fontStretch === "expanded";
ctx.fontStretch = "extra-expanded";
@assert ctx.fontStretch === "extra-expanded";
ctx.fontStretch = "ultra-expanded";
@assert ctx.fontStretch === "ultra-expanded";
// Setting fontStretch with lower cases and upper cases word,
// these values should be ignored.
ctx.fontStretch = "ulTra-condensed";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "Extra-condensed";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "cOndensed";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "Semi-Condensed";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "normaL";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "semi-Expanded";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "Expanded";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "eXtra-expanded";
@assert ctx.fontStretch === "ultra-expanded";
ctx.fontStretch = "abcd";
@assert ctx.fontStretch === "ultra-expanded";
- name: 2d.text.fontVariantCaps1
desc: Testing small caps setting in fontVariant
code: |
ctx.font = "32px serif";
ctx.fontVariantCaps = "small-caps";
// This should render the same as font = "small-caps 32px serif".
ctx.fillText("Hello World", 20, 100);
reference: |
ctx.font = "small-caps 32px serif";
ctx.fillText("Hello World", 20, 100);
- name: 2d.text.fontVariantCaps2
desc: Testing small caps setting in fontVariant
code: |
ctx.font = "small-caps 32px serif";
// "mismatch" test, to verify that small-caps does change the rendering.
smallCaps_len = ctx.measureText("Hello World").width;
ctx.font = "32px serif";
normalCaps_len = ctx.measureText("Hello World").width;
@assert smallCaps_len != normalCaps_len;
- name: 2d.text.fontVariantCaps3
desc: Testing small caps setting in fontVariant
code: |
ctx.font = "32px serif";
ctx.fontVariantCaps = "all-small-caps";
// This should render the same as using font = "small-caps 32px serif"
// with all the underlying text in lowercase.
ctx.fillText("Hello World", 20, 100);
reference: |
ctx.font = "small-caps 32px serif";
ctx.fillText("hello world", 20, 100);
- name: 2d.text.fontVariantCaps4
desc: Testing small caps setting in fontVariant
code: |
ctx.font = "small-caps 32px serif";
// fontVariantCaps overrides the small-caps setting from the font attribute
ctx.fontVariantCaps = "all-small-caps";
ctx.fillText("Hello World", 20, 100);
reference: |
ctx.font = "small-caps 32px serif";
ctx.fillText("hello world", 20, 100);
- name: 2d.text.fontVariantCaps5
desc: Testing small caps setting in fontVariant
code: |
ctx.font = "small-caps 32px serif";
// fontVariantCaps 'normal' does not override the setting from the font attribute.
ctx.fontVariantCaps = "normal";
ctx.fillText("Hello World", 20, 100);
reference: |
ctx.font = "small-caps 32px serif";
ctx.fillText("Hello World", 20, 100);
- name: 2d.text.fontVariantCaps6
desc: Testing small caps setting in fontVariant
code: |
// fontVariantCaps is reset when the font attribute is set.
ctx.fontVariantCaps = "all-small-caps";
ctx.font = "32px serif";
ctx.fillText("Hello World", 20, 100);
reference: |
ctx.font = "32px serif";
ctx.fillText("Hello World", 20, 100);
- name: 2d.text.setFont.mathFont
desc: crbug.com/1212190, make sure offscreencanvas doesn't crash with Math Font
code: |
ctx.font = "math serif";
# TODO: shadows, alpha, composite, clip