Although DistinctNumeric, which is supposed to abstract the underlying
type, was used to represent CSSPixels, we have a whole bunch of places
in the layout code that assume CSSPixels::value() returns a
floating-point type. This assumption makes it difficult to replace the
underlying type in CSSPixels with a non-floating type.
To make it easier to transition CSSPixels to fixed-point math, one step
we can take is to prevent access to the underlying type using value()
and instead use explicit conversions with the to_float(), to_double(),
and to_int() methods.
Having this here instead of in ReplacedBox means we can access it when
figuring out what the "preferred aspect ratio" is.
There's some inconsistency between specs about what this is called, but
they're moving towards referring to this as "natural width/height/
aspect-ratio", so let's copy that terminology.
There are a couple of things that went into this:
- We now calculate the intrinsic width/height and aspect ratio of <svg>
elements based on the spec algorithm instead of our previous ad-hoc
guesswork solution.
- Replaced elements with automatic size and intrinsic aspect ratio but
no intrinsic dimensions are now sized with the stretch-fit width
formula.
- We take care to assign both used width and used height to <svg>
elements before running their SVG formatting contexts. This ensures
that the inside SVG content is laid out with knowledge of its
viewport geometry.
- We avoid infinite recursion in tentative_height_for_replaced_element()
by using the already-calculated used width instead of calling the
function that calculates the used width (since that may call us right
back again).
Previously we were using the HTML parse_dimension_value method for the
height and width attributes of an SVG element. These attributes should
however be treated as css properties instead and thus also support
calc() and absolute units so we use the css parser for this instead.
This simplifies the ownership model between DOM/layout/paint nodes
immensely by deferring to the garbage collector for figuring out what's
live and what's not.
If the `width` and `height` attributes are provided, we derive the
intrinsic size and ratio from them.
Otherwise, we trace a rectangle around the geometry elements inside
the SVG and use the size of that as the intrinsic size.
This is definitely far from correct, but is still a much better guess
at the intrinsic size than nothing.
This makes SVG-in-HTML behave quite a bit better by following general
replaced layout rules. It also turns <svg> elements into inline-level
boxes instead of block-level boxes.
This patch adds a bunch of Paintable subclasses, each corresponding to
the Layout::Node subclasses that had a paint() override. All painting
logic is moved from layout nodes into their corresponding paintables.
Paintables are now created by asking a Layout::Box to produce one:
static NonnullOwnPtr<Paintable> Layout::Box::create_paintable()
Note that inline nodes still have their painting logic. Since they
are not boxes, and all paintables have a corresponding box, we'll need
to come up with some other solution for them.
The "paintable" state in Layout::Box was actually not safe to access
until after layout had been performed.
As a first step towards making this harder to mess up accidentally,
this patch moves painting information from Layout::Box to a new class:
Painting::Box. Every layout can have a corresponding paint box, and
it holds the final used metrics determined by layout.
The paint box is created and populated by FormattingState::commit().
I've also added DOM::Node::paint_box() as a convenient way to access
the paint box (if available) of a given DOM node.
Going forward, I believe this will allow us to better separate data
that belongs to layout vs painting, and also open up opportunities
for naturally invalidating caches in the paint box (since it's
reconstituted by every layout.)
This makes the selected-in-the-inspector outline appear in the right
place. We take the stroke-width into account when producing the
bounding box, which makes the fit nice and snug. :^)
Instead of trying to layout SVG boxes as if they are regular CSS boxes,
let's invent an "SVG formatting context" and let it manage SVG boxes.
To facilitate this, Layout::SVGBox no longer inherits from ReplacedBox,
and is instead a simple, "inline-block" style BlockBox.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.
See: https://spdx.dev/resources/use/#identifiers
This was done with the `ambr` search and replace tool.
ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *