WICG / canvas-formatted-text

Other
80 stars 17 forks source link

Constraint-only changes #45

Open travisleithead opened 2 years ago

travisleithead commented 2 years ago

From comment raised by @yjbanov in PR #39:

Have the implementors evaluated the performance implications of this API for the case when the text contents remain the same while the constraints change rapidly? In this case the application would be passing the same array of text runs but pass a new width/height. If caching could provide performance benefits, then the text engine would also have to perform the following extra computation to produce a cache hit:

  • Make a defensive copy of the previously formatted text.
  • Fully traverse the newly input and compare to the previous snapshot.

The engine has to do these things because the text is expressed using plain mutable JavaScript objects (arrays, dictionaries). It's not possible to tell if something inside changed without the extra work.

A common use-case is resizing a window, which transitively resizes text inside. While all the strings and styles remain the same the value of width would change on every frame for multiple paragraphs of text in the UI. Some apps support resizing within the app, such as columns and rows of a spreadsheet.

And my comment in reply:

This is a very good use case to consider and to test for. My expectation at this early stage is that this case would be sub-optimal and that no caching/comparing of deltas between iterations of format are maintained.

These were all good reasons to have a retained data model supported by the platform--changes to the data model could trigger invalidation (or not) and make formatting faster. However, we're making the trade-off with this new approach to remove any retained platform data model and rely on JS strings, and as a consequence, this issue is now very much a potential concern.

There may be an opportunity for a new feature here: given an existing retained metrics object, allow it to be "re-calculated" based only on changing the constraints--no changes to style or text content. Since no new input is needed except for the new constraint it seems possible to make a fast adjustment to the existing formatted metrics and output (or in-place update) new metrics.

let width = 5;
let renderMe = FormattedText.format( "some content...", null, { width: width } );
function renderLoop() {
   if ( width < 100 ) {
      canvasCtx.drawFormattedText( renderMe, 50, 50 );
      width += 5;
      renderMe = renderMe.reflow( { width: width } ); // New API to take the existing rendered content and re-flow it given new constraints
      requestAnimationFrame( renderLoop );
   }
}
requestAnimationFrame( renderLoop );
travisleithead commented 2 years ago

.reflow!

Came to a similar naming convention for an in-progress design on #46, which I believe will subsume this use case too!

travisleithead commented 2 years ago

Well, #46 took a different turn, but having a reflow is still a good idea worth adding IMO.