canvas-formatted-text icon indicating copy to clipboard operation
canvas-formatted-text copied to clipboard

Canvas Formatted Text should be harmonized with CSS Houdini, consider past SVG work

Open tantek opened this issue 5 years ago • 2 comments
trafficstars

High level feedback on Canvas Formatted Text: Please harmonize this work with the CSS Houdini effort. In addition you may want to take a look at some of the prior work in: SVG2 Chapter 11: Text.

(Originally published at: https://tantek.com/2020/290/b1/)

tantek avatar Oct 16 '20 21:10 tantek

Took a deep-dive into SVG text and CSS Houdini and came to several conclusions that I plan to address in a coming update:

  • Why intermediate line objects? Outside of the constrained worklet environment for Houdini's Layout API, there is no retained platform object that represents a position-able line. I think there are good reasons for that. One expectation we were thinking about in the current design was allowing authors to retain line objects for re-rendering. This puts the responsibility of caching lines on the author, who then must do the work to figure out which lines have changed (and which haven't) given a content change. This is non-trivial work; the native platform is already doing this internally, and authors will invariably get it wrong--if they bother doing it at all. Best to avoid this author foot-gun.
  • Alternative (existing) way of handling advanced line wrapping. Advanced scenarios involving positioning of lines around shapes/boundaries are handled quite eloquently with declarative syntax in both CSS and SVG (see shape-inside property of SVG, and the 'shape-outside' of CSS Shapes L1, and coming up 'shape-inside' from CSS Shapes L2). Given potential convergence with CSS/SVG and a nice symmetry with Path2D, advanced line-wrapping scenarios via declarative syntax is easier to read and understand, leverages existing CSS and SVG patterns, and makes some "simpler" advanced scenarios possible without having to resort to full manual-positioning of each line.
  • The problem of reinventing the wheel. Many of the desired Canvas Formatting Text line formatting features are already handled very well in CSS. Many unique SVG line layout options are slowly converging into CSS. It seems counter-productive to continue to extend the CanvasRenderingContext2D with new APIs that are just a different syntax for accomplishing what CSS can do today and will do in the future. (Plus implementation wise-we want to leverage the native CSS layout engine anyway.) It seems like we need to have better integration with CSS in a way that still allows the Canvas Formatted Text to operate in non-DOM environments, but not reinvent new syntax for all the things that CSS can do for inline level layout and formatting.
  • Improved design for retained source text. The current data model for the Canvas Formatted Text's text runs is JS objects. This is convenient until you consider that the data model is likely to be tweaked and changed over time, especially in editing-style scenarios (inserting characters/words and/or adjusting formatting). Given the current JS-object based model, the text runs must be re-submitted to the parent Canvas Formatted Text object in order for the platform to notice any changes. In other words, because the JS objects are not retained by the platform internals, and are "passed by value," changes to their data cannot be recognized by the platform without "passing the object back-in" (by value). That is not a convenient usage pattern when making small updates to the text, and is not consistent with HTML/SVG. In HTML and SVG text, platform objects (not JS objects) hold the text data; they are "retained." To change one span of text, the author only need update the text data's value, not re-append the node into the parent container! Thus, it will be a good idea to make text run objects into retained objects by converting them into interfaces.
  • Advanced scenarios can be "additive" on top of simple scenarios. The above considerations allow the API's "simple" scenarios to naturally be extended to "advanced" scenarios without needing a duplicate API or interaction model. For example, a simple scenario involving rendering multiple lines of text within a constrained inline-size can be enhanced by declaring a 'shape-inside' value that the line wrapping should conform to (as would be done in SVG). If there is a need for additional line-placement logic perhaps a Houdini-like callback could be added, or better yet: leverage Houdini natively via a 'display: layout()' CSS value on the formatted text object (a possibility with CSS integration).
  • Decoupled measurement from rendering scenarios. By dropping intermediate line objects and decoupling the advanced scenario of iteratively measuring-then-rendering lines, it becomes possible to more cleanly separate the measurement scenarios for the Canvas Formatted Text data model from the simple act of rendering that model. This has positive impact on the potential progression of standardization of the feature. Our exploration into SVG text uncovered a variety of interesting potential measurement scenarios (that already exist) and may inspire a more feature-filled set of measurement APIs that can be developed separately and in parallel.

Some potential positive outcomes from these proposed changes include:

  • Clear path forward for supporting vertical text (using exiting CSS) see https://github.com/WICG/canvas-formatted-text/issues/4
  • Clear path forward for whitespace handling (using existing CSS) see https://github.com/WICG/canvas-formatted-text/issues/5
  • Clear path forward for other justification/hyphenation features (using existing CSS) see https://github.com/WICG/canvas-formatted-text/issues/7
  • Possible path to Ruby annotation support in Canvas.

With greater integration of CSS, the interaction layer between Canvas drawing state, where that state is overlapping or conflicting with CSS-specified values in the Canvas Formatted Text must be clearly and logically clarified. At present, we do not desire to continue adding more text-formatting properties that are redundant with CSS to the Canvas drawing state when they can be specified using the Canvas Formatted Text object, which offers a clearer path forward for aligning many other relevant CSS line-formatting features.

travisleithead avatar Jan 09 '21 02:01 travisleithead

Hi @tantek. The CG met today to talk over the updated documents, including the Formatted Text Metrics proposal. I specifically called out some ways in which this feature can be harmonized with CSS Houdini and DOM in this section: https://github.com/WICG/canvas-formatted-text/blob/main/explainer-metrics.md#thinking-ahead-future-integration-into-dom-or-houdini-layout-api

travisleithead avatar Aug 19 '21 01:08 travisleithead