@@ -40,10 +40,28 @@ const CAPTURE_PROGRESS_STEPS = 20;
4040const BAKE_SCALES = [ 0.25 , 0.5 , 0.75 , 1 ] ;
4141// A remembered frame holds its body markup, so a window bounds the memory. 300 frames covers a 10 s loop at 30 fps.
4242const REPEAT_WINDOW_FRAMES = 300 ;
43+ // Part of every bake's cache key, so raising it redraws every cached bake.
44+ const FRAME_DRAWING_VERSION = 1 ;
4345const ANIMATION_OVERRIDE = `<style>*,*::before,*::after{animation:none!important;transition:none!important}</style>` ;
4446
47+ // A base64 bitmap in a frame's markup: a CSS url(), an <img> source, or a canvas painted as a background.
48+ const NESTED_BITMAP = / d a t a : i m a g e \/ (? ! s v g ) [ \w . + - ] + ; b a s e 6 4 , [ A - Z a - z 0 - 9 + / = ] + / g;
49+
50+ // WebKit lays an SVG image out as offscreen, so a large bitmap inside one decodes asynchronously and a draw before
51+ // the decode lands leaves it out. Nothing signals that decode, but an <img decoding="sync"> decodes synchronously, so
52+ // one per bitmap, painted ahead of the page, has every bitmap ready within the same draw. opacity:0 would skip its paint.
4553function foreignObjectSvg ( width : number , height : number , styles : string , body : string ) : string {
46- return `<svg xmlns="http://www.w3.org/2000/svg" width="${ width } " height="${ height } "><foreignObject width="${ width } " height="${ height } ">${ styles } ${ ANIMATION_OVERRIDE } ${ body } </foreignObject></svg>` ;
54+ const decoders = [ ...new Set ( `${ styles } ${ body } ` . match ( NESTED_BITMAP ) ) ]
55+ . map (
56+ src =>
57+ `<img xmlns="http://www.w3.org/1999/xhtml" decoding="sync" src="${ src } " style="position:absolute;left:0;top:0;width:1px;height:1px;filter:opacity(0)!important"/>`
58+ )
59+ . join ( "" ) ;
60+ return (
61+ `<svg xmlns="http://www.w3.org/2000/svg" width="${ width } " height="${ height } ">` +
62+ `${ decoders && `<foreignObject width="1" height="1">${ decoders } </foreignObject>` } ` +
63+ `<foreignObject width="${ width } " height="${ height } ">${ styles } ${ ANIMATION_OVERRIDE } ${ body } </foreignObject></svg>`
64+ ) ;
4765}
4866
4967function forceLayout ( el : HTMLElement ) : void {
@@ -207,7 +225,7 @@ export class Html5Player extends Player {
207225 width : this . renderedWidth ,
208226 height : this . renderedHeight
209227 } ) ;
210- return `${ content } :${ frameCount } @${ captureFps } ` ;
228+ return `${ content } :${ frameCount } @${ captureFps } :v ${ FRAME_DRAWING_VERSION } ` ;
211229 }
212230
213231 // Canvas pixels per clip pixel: a bake at this scale or above looks as sharp as a full-size one.
0 commit comments