| - 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 |
| t.done(); |
| |
| - name: 2d.text.font.parse.tiny |
| code: | |
| ctx.font = '1px sans-serif'; |
| @assert ctx.font === '1px sans-serif'; |
| t.done(); |
| |
| - 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); |
| t.done(); |
| |
| - 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'; |
| t.done(); |
| |
| - 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\\\\\\","'; |
| t.done(); |
| |
| # 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.system |
| desc: System fonts must be computed to explicit values |
| code: | |
| ctx.font = 'message-box'; |
| @assert ctx.font !== 'message-box'; |
| t.done(); |
| |
| - 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'; |
| t.done(); |
| |
| - name: 2d.text.font.default |
| code: | |
| @assert ctx.font === '10px sans-serif'; |
| t.done(); |
| |
| - name: 2d.text.font.relative_size |
| code: | |
| ctx.font = '1em sans-serif'; |
| @assert ctx.font === '10px sans-serif'; |
| t.done(); |
| |
| - 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'; |
| t.done(); |
| |
| - 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'; |
| t.done(); |
| |
| - name: 2d.text.align.default |
| code: | |
| @assert ctx.textAlign === 'start'; |
| t.done(); |
| |
| |
| - 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'; |
| t.done(); |
| |
| - 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'; |
| t.done(); |
| |
| - name: 2d.text.baseline.default |
| code: | |
| @assert ctx.textBaseline === 'alphabetic'; |
| t.done(); |
| |
| - 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); |
| t.done(); |
| 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; |
| t.done(); |
| 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); |
| t.done(); |
| 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); |
| t.done(); |
| 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); |
| t.done(); |
| 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); |
| t.done(); |
| expected: green |
| timeout: long |
| |
| - 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); |
| t.done(); |
| 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); |
| t.done(); |
| 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); |
| t.done(); |
| 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; |
| t.done(); |
| 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); |
| t.done(); |
| 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 |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.fill.maxWidth.bound |
| desc: fillText handles maxWidth based on line size, not bounding box size |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.fontface |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - 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.) |
| fonts: |
| - CanvasTest |
| fonthack: 0 |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.fillStyle = '#f00'; |
| ctx.fillRect(0, 0, 100, 50); |
| ctx.font = '67px CanvasTest'; |
| ctx.fillStyle = '#0f0'; |
| ctx.fillText('AA', 0, 50); |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.fontface.notinpage |
| desc: '@font-face fonts should work even if they are not used in the page' |
| fonts: |
| - CanvasTest |
| fonthack: 0 |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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 |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.baseline.top |
| desc: textBaseline top is the top of the em square (not the bounding box) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.baseline.bottom |
| desc: textBaseline bottom is the bottom of the em square (not the bounding box) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.baseline.middle |
| desc: textBaseline middle is the middle of the em square (not the bounding box) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.baseline.alphabetic |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.baseline.ideographic |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.fillStyle = '#f00'; |
| ctx.fillRect(0, 0, 100, 50); |
| ctx.fillStyle = '#0f0'; |
| ctx.textBaseline = 'ideographic'; |
| ctx.fillText('CC', 0, 81.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 |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.baseline.hanging |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.fillStyle = '#f00'; |
| ctx.fillRect(0, 0, 100, 50); |
| ctx.fillStyle = '#0f0'; |
| ctx.textBaseline = 'hanging'; |
| ctx.fillText('CC', 0, -30); |
| @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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.left |
| desc: textAlign left is the left of the first em square (not the bounding box) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.right |
| desc: textAlign right is the right of the last em square (not the bounding box) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.start.ltr |
| desc: textAlign start with ltr is the left edge |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'ltr'; |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.start.rtl |
| desc: textAlign start with rtl is the right edge |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'rtl'; |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.end.ltr |
| desc: textAlign end with ltr is the right edge |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'ltr'; |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.end.rtl |
| desc: textAlign end with rtl is the left edge |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'rtl'; |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.align.center |
| desc: textAlign center is the center of the em squares (not the bounding box) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| |
| - name: 2d.text.draw.space.basic |
| desc: U+0020 is rendered the correct size (1em wide) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.space.collapse.space |
| desc: Space characters are converted to U+0020, and collapsed (per CSS) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; @moz-todo |
| @assert pixel 75,25 ==~ 0,255,0,255; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.space.collapse.other |
| desc: Space characters are converted to U+0020, and collapsed (per CSS) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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', -100, 37.5); |
| @assert pixel 25,25 ==~ 0,255,0,255; @moz-todo |
| @assert pixel 75,25 ==~ 0,255,0,255; @moz-todo |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.space.collapse.nonspace |
| desc: Non-space characters are not converted to U+0020 and collapsed |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.space.collapse.start |
| desc: Space characters at the start of a line are collapsed (per CSS) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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 ==~ 0,255,0,255; @moz-todo |
| @assert pixel 75,25 ==~ 0,255,0,255; |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.draw.space.collapse.end |
| desc: Space characters at the end of a line are collapsed (per CSS) |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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 ==~ 0,255,0,255; @moz-todo |
| }).then(t_pass, t_fail); |
| expected: green |
| |
| - name: 2d.text.measure.width.basic |
| desc: The width of character is same as font used for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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; |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.measure.width.empty |
| desc: The empty string has zero width for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| @assert ctx.measureText("").width === 0; |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.measure.width.space |
| desc: Space characters are converted to U+0020 and collapsed (per CSS) for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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 === 150; @moz-todo |
| @assert ctx.measureText('A \x0b B').width >= 200; |
| |
| @assert ctx.measureText(' AB').width === 100; @moz-todo |
| @assert ctx.measureText('AB ').width === 100; @moz-todo |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.measure.advances |
| desc: Testing width advances for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| 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]; |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.measure.actualBoundingBox |
| desc: Testing actualBoundingBox for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'ltr'; |
| ctx.align = 'left' |
| ctx.baseline = 'alphabetic' |
| // Some platforms may return '-0'. |
| @assert Math.abs(ctx.measureText('A').actualBoundingBoxLeft) === 0; |
| // Different platforms may render text slightly different. |
| @assert ctx.measureText('A').actualBoundingBoxRight >= 50; |
| @assert ctx.measureText('A').actualBoundingBoxAscent >= 35; |
| @assert Math.abs(ctx.measureText('A').actualBoundingBoxDescent) === 0; |
| |
| @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) === 0; |
| @assert ctx.measureText('ABCD').actualBoundingBoxRight >= 200; |
| @assert ctx.measureText('ABCD').actualBoundingBoxAscent >= 85; |
| @assert ctx.measureText('ABCD').actualBoundingBoxDescent >= 37; |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.measure.fontBoundingBox |
| desc: Testing fontBoundingBox for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'ltr'; |
| ctx.align = 'left' |
| @assert ctx.measureText('A').fontBoundingBoxAscent === 85; |
| @assert ctx.measureText('A').fontBoundingBoxDescent === 39; |
| |
| @assert ctx.measureText('ABCD').fontBoundingBoxAscent === 85; |
| @assert ctx.measureText('ABCD').fontBoundingBoxDescent === 39; |
| }).then(t_pass, t_fail); |
| - name: 2d.text.measure.emHeights |
| desc: Testing emHeights for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'ltr'; |
| ctx.align = 'left' |
| @assert ctx.measureText('A').emHeightAscent === 37.5; |
| @assert ctx.measureText('A').emHeightDescent === 12.5; |
| @assert ctx.measureText('A').emHeightDescent + ctx.measureText('A').emHeightAscent === 50; |
| |
| @assert ctx.measureText('ABCD').emHeightAscent === 37.5; |
| @assert ctx.measureText('ABCD').emHeightDescent === 12.5; |
| @assert ctx.measureText('ABCD').emHeightDescent + ctx.measureText('ABCD').emHeightAscent === 50; |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.measure.baselines |
| desc: Testing baselines for OffscreenCanvas |
| fonts: |
| - CanvasTest |
| code: | |
| var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); |
| let fonts = (self.fonts ? self.fonts : document.fonts); |
| f.load(); |
| fonts.add(f); |
| fonts.ready.then(function() { |
| ctx.font = '50px CanvasTest'; |
| ctx.direction = 'ltr'; |
| ctx.align = 'left' |
| @assert Math.abs(ctx.measureText('A').getBaselines().alphabetic) === 0; |
| @assert ctx.measureText('A').getBaselines().ideographic === -39; |
| @assert ctx.measureText('A').getBaselines().hanging === 68; |
| |
| @assert Math.abs(ctx.measureText('ABCD').getBaselines().alphabetic) === 0; |
| @assert ctx.measureText('ABCD').getBaselines().ideographic === -39; |
| @assert ctx.measureText('ABCD').getBaselines().hanging === 68; |
| }).then(t_pass, t_fail); |
| |
| - name: 2d.text.drawing.style.spacing |
| desc: Testing letter spacing and word spacing |
| 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 = '1EM'; |
| @assert ctx.letterSpacing === '1px'; |
| @assert ctx.wordSpacing === '1em'; |
| t.done(); |
| |
| - 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>); |
| |
| t.done(); |
| |
| - 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'>); |
| |
| t.done(); |
| |
| - name: 2d.text.drawing.style.letterSpacing.measure.absolute |
| desc: Testing letter spacing with absolute length |
| 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], |
| ['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]); |
| } |
| t.done(); |
| |
| - name: 2d.text.drawing.style.letterSpacing.measure.relative |
| desc: Testing letter spacing with font-relative length |
| code: | |
| @assert ctx.letterSpacing === '0px'; |
| @assert ctx.wordSpacing === '0px'; |
| ctx.font = "10px monospace"; |
| var width_normal = ctx.measureText('Hello World').width; |
| var ch_width = width_normal / 11; |
| |
| 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. |
| test_cases = [['1em', 110, 0.1], |
| ['-0.1em', -11, 0.1], |
| ['1ch', 11 * ch_width, 0.1]] |
| |
| for (const test_case of test_cases) { |
| test_letter_spacing(test_case[0], test_case[1], test_case[2]); |
| } |
| t.done(); |
| |
| - name: 2d.text.drawing.style.wordSpacing.measure.absolute |
| desc: Testing if word spacing is working properly with absolute length |
| 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], |
| ['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]); |
| } |
| t.done(); |
| |
| - name: 2d.text.drawing.style.wordSpacing.measure.relative |
| desc: Testing if word spacing is working properly with font-relative length |
| code: | |
| @assert ctx.letterSpacing === '0px'; |
| @assert ctx.wordSpacing === '0px'; |
| ctx.font = "10px monospace"; |
| var width_normal = ctx.measureText('Hello World, again').width; |
| var ch_width = width_normal / 18; |
| |
| 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. |
| test_cases = [['1em', 20, 0.1], |
| ['-0.5em', -10, 0.1], |
| ['1ch', 2 * ch_width, 0.1]] |
| |
| for (const test_case of test_cases) { |
| test_word_spacing(test_case[0], test_case[1], test_case[2]); |
| } |
| t.done(); |
| |
| - 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 width_with_spacing === width_normal + 110; |
| |
| // 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 width_with_spacing === width_normal + 220; |
| t.done(); |
| |
| - 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; |
| t.done(); |
| |
| - 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; |
| t.done(); |
| |
| - 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"; |
| t.done(); |
| |
| - 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"; |
| t.done(); |
| |
| - name: 2d.text.drawing.style.textRendering.settings |
| desc: Testing basic functionalities of textRendering in Canvas |
| code: | |
| // Setting textRendering with lower cases |
| @assert ctx.textRendering === "auto"; |
| |
| ctx.textRendering = "auto"; |
| @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"; |
| |
| // Setting textRendering with lower cases and upper cases word. |
| ctx.textRendering = "aUto"; |
| @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"; |
| |
| // Setting textRendering with non-existing font variant. |
| ctx.textRendering = "abcd"; |
| @assert ctx.textRendering === "geometricPrecision"; |
| t.done(); |
| |
| - 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; |
| t.done(); |
| |
| - 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; |
| t.done(); |
| |
| - 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; |
| t.done(); |
| |
| # TODO: shadows, alpha, composite, clip |