summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/Painting
AgeCommit message (Collapse)Author
2022-03-30LibWeb: Use more precise font metrics when doing inline layoutAndreas Kling
We now position inline-level boxes based on ascent and descent metrics from the font in use. This makes our basic text layouts look a lot more like those produced by other browsers. :^) I've tried to match the terminology used by the CSS Inline Layout spec. This will regress Acid2 a little bit, and probably various other sites, but on the whole it's the direction we should be heading, so let's go.
2022-03-30LibWeb: Draw inspector overlay label with default fontAndreas Kling
2022-03-30LibWeb: Use the new Gfx::Painter::draw_text_run() API for drawing textAndreas Kling
This avoids a bunch of unnecessary work in Painter which not only took time, but sometimes also led to alignment issues. draw_text_run() will draw the text where we tell it, and that's it.
2022-03-29LibWeb: Don't round numbers too early when painting backgroundsAndreas Kling
Preserve floating point precision and delay rounding until the last moment when figuring out where to paint background layers. This fixes an issue on Acid3 where a thin sliver of red was visible because the background X position was incorrectly rounded by 1px.
2022-03-29LibWeb: Use rounding instead of enclosing_int_rect() when paintingAndreas Kling
By using enclosing_int_rect(), borders and backgrounds of boxes were sometimes 1 pixel off, making things slightly larger than they should be. Fix this by using to_rounded() instead of enclosing_int_rect(). There's definitely more of these type of issues lurking in the code, and we'll get to them in time.
2022-03-27LibWeb: Stop allowing position:relative to affect layoutAndreas Kling
Relatively positioned boxes should not affect the *layout* of their siblings. So instead of applying relative inset as a layout-time translation on the box, we now perform the adjustment at the paintable level instead. This makes position:relative actually work as expected, and exposes some new bugs we need to take care of for Acid2. :^)
2022-03-27LibWeb: Use Gfx::Font::pixel_size() when we want pixel metricsAndreas Kling
This gives us consistent results with both bitmap and scalable fonts.
2022-03-26LibWeb: Preserve paint state when painting stacking contexts indirectlyAndreas Kling
For layers that require indirect painting (due to opacity, transform, etc.) we create a nested PaintContext. Until now, that PaintContext was created fresh without transferring all the state from the parent PaintContext.
2022-03-26LibWeb: Paint the focus outline using Painter::draw_focus_rect()Linus Groh
Now it actually looks like a classic focus outline and not some misplaced border :^)
2022-03-26LibWeb: Paint the focus outline actually *outside* the elementLinus Groh
Instead of using the absolute_rect(), use absolute_border_box_rect() - at least for PaintableBox - and inflate it by 2px on each side. This looks much nicer for text input elements, especially when they have padding, which would be applied outside the focus rect previously.
2022-03-25LibWeb: When painting, reduce computation cost by using the reciprocalJames Bellamy
Rather than dividing the rect width and high by the border lengths, this change multiples those lengths by the reciprocal of the width and height because this is a faster operation. When mousing around on the html spec website, the profile showed that inline painting went from ~15% to ~3%
2022-03-25LibWeb: Attach BackgroundAttachment::Fixed to the window view portTimothy Flynn
This fixes the placement of several background images on Acid2, most notably the background of the eyes and the red rectangle near the bottom of the head.
2022-03-24LibWeb: Align text shadows the same way we align textSam Atkins
This makes the shadow line-up correctly on Acid3. :^)
2022-03-24LibWeb: Treate SVG paintable coordinates as relative to <svg> elementAndreas Kling
Normally, paintable coordinates are relative to the nearest containing block, but in the SVG case, since <svg> doesn't form a containing block, we have to specialize the computation of SVGPaintable::absolute_rect().
2022-03-24LibWeb: Implement text-shadow paintingSam Atkins
We don't yet take the spread-distance parameter into account, since we don't have a way to "inflate" the text shadow. Also, I'm not sure if we need to inflate the shadow slightly anyway. Blurred shadows of our pixel fonts seem very faint. Part of this is that a blur of < 3px does nothing, see #13231, but even so we might want to inflate it a little.
2022-03-24LbWeb: Rename BoxShadowFoo => ShadowFooSam Atkins
The `text-shadow` property is almost identical to `box-shadow`: > Values are interpreted as for box-shadow [CSS-BACKGROUNDS-3]. > (But note that the inset keyword are not allowed.) So, let's use the same data structures and parsing code for both. :^)
2022-03-23LibGfx: Implement `Rect::to_rounded<U>()`Jelle Raaijmakers
This replaces the usage of `rounded_int_rect`, whose name did not accurately reflect the rounding operation happening. For example, the position of the rect was not rounded but floored, and the size was pulled through `roundf` before casting to `int` which could result in inadvertent flooring if the resulting floating point could not exactly represent the rounded value.
2022-03-22LibWeb: Support `transform: translate(...)` by percentageSimon Wanner
2022-03-22LibWeb: Apply the CSS transform-origin propertySimon Wanner
We don't have transform-box yet, so this applies to the border-box for now. This also makes us pass a couple Web Platform Tests as well :^) For example: https://wpt.live/css/css-transforms/css3-transform-scale-002.html
2022-03-21LibWeb: Ignore invisible boxes and stacking contexts during hit testingAndreas Kling
2022-03-21LibWeb: Remove now-unused PaintableBox::for_each_child_in_paint_order()Andreas Kling
2022-03-21LibWeb: Don't compute fragment absolute rect twice while hit testingAndreas Kling
2022-03-21LibWeb: Fix O(n^2) traversal in hit testingAndreas Kling
We already walk the entire paint tree within each stacking context in the main hit testing function (StackingContext::hit_test()), so there's no need for each individual paintable to walk its own children again. By not doing that, we remove a source of O(n^2) traversal which made hit testing on deeply nested web pages unbearably slow.
2022-03-21LibWeb: Add Paintable::dom_node() convenience accessorAndreas Kling
2022-03-21LibWeb: Add Painting::HitTestResult::dom_node()Andreas Kling
This is a convenience accessor to avoid having to say this everywhere: result.paintable->layout_node().dom_node() Instead, you can now do: result.dom_node()
2022-03-21LibWeb: Make hit testing functions return Optional<HitTestResult>Andreas Kling
Using "HitTestResult with null paintable" as a way to signal misses was unnecessarily confusing. Let's use Optional instead. :^)
2022-03-21LibWeb: Build stacking context tree lazilyAndreas Kling
There's no actual need to build the stacking context tree before performing layout. Instead, make it lazy and build the tree when it's actually needed for something. This avoids a bunch of work in situations where multiple synchronous layouts are forced (typically by JavaScript) without painting or hit testing taking place in between. It also opens up for style invalidations that only target the stacking context tree.
2022-03-20LibWeb: Always call Layout::Box::did_set_rect()Andreas Kling
Since paintables have a default content size of 0x0, we were neglecting to notify the corresponding layout node about size changes, if the used content size came out to 0x0. This fixes an issue where resizing an iframe to 0x0 didn't take effect.
2022-03-20LibWeb: Include entire border box when painting stacking context layerAndreas Kling
For stacking contexts that have opacity between 0 and 1, and also contexts with a 2D transform, we first paint them into a temporary layer buffer. Then we blend that buffer with the contents in one go. Before this patch, we were only drawing the content box of the stacking context into this layer buffer, which led to padding and borders missing from elements painted this way.
2022-03-19LibWeb: Make SVG <svg> elements behave as CSS replaced elementsAndreas Kling
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.
2022-03-19LibWeb: Make Paintable::hit_test() return nothingAndreas Kling
For paintables that don't know how to hit test themselves, let's just return nothing instead of crashing.
2022-03-18LibWeb: Update hit_test for CSS TransformsSimon Wanner
This now also takes a FloatPoint instead of an IntPoint to avoid excessive rounding when multiple transforms apply on top of each other.
2022-03-18LibWeb: Implement CSS transforms on stacking contextsSimon Wanner
Since there is currently no easy way to handle rotations and skews with LibGfx this only implements translation and scaling by first constructing a general 4x4 transformation matrix like outlined in the css-transforms-1 specification. This is then downgraded to a Gfx::AffineTransform in order to transform the destination rectangle used with draw_scaled_bitmap() While rotation would be nice this already looks pretty good :^)
2022-03-18LibWeb: Make PaintableBox::enclosing_stacking_context() cheaperAndreas Kling
No need to call the expensive establishes_stacking_context() here, as we've already built the stacking context tree and can simply test for the presence of existing stacking contexts.
2022-03-16LibWeb: Move text fragment painting to PaintableWithLinesAndreas Kling
All the other painting code has moved to paintables already.
2022-03-16LibWeb: Don't call establishes_stacking_context() during paintingAndreas Kling
By the time we're painting, we've already built the stacking context tree. So instead of asking if a box establishes a stacking context, we can ask if its paintable *has* a stacking context. This was taking up ~6% of the profile when mousing around on the HTML specification. With this change, it disappears completely. :^)
2022-03-16LibWeb: Refactor all LabelableNode subclasses + input event handling :^)sin-ack
This commit is messy due to the Paintable and Layout classes being tangled together. The RadioButton, CheckBox and ButtonBox classes are now subclasses of FormAssociatedLabelableNode. This subclass separates these layout nodes from LabelableNode, which is also the superclass of non-form associated labelable nodes (Progress). ButtonPaintable, CheckBoxPaintable and RadioButtonPaintable no longer call events on DOM nodes directly from their mouse event handlers; instead, all the functionality is now directly in EventHandler, which dispatches the related events. handle_mousedown and related methods return a bool indicating whether the event handling should proceed. Paintable classes can now return an alternative DOM::Node which should be the target of the mouse event. Labels use this to indicate that the labeled control should be the target of the mouse events. HTMLInputElement put its activation behavior on run_activation_behavior, which wasn't actually called anywhere and had to be manually called by other places. We now use activation_behavior which is used by EventDispatcher. This commit also brings HTMLInputElement closer to spec by removing the did_foo functions that did ad-hoc event dispatching and unifies the behavior under run_input_activation_behavior.
2022-03-13LibWeb: Sort stacking context tree once, after fully building itAndreas Kling
Instead of calling quick_sort() every time a StackingContext child is added to a parent, we now do a single pass of sorting work after the full StackingContext tree has been built. Before this change, the quick_sort() was ~13.5% of the profile while hovering links on GitHub in the Browser. After the change, it's down to ~0.6%. Pretty good! :^)
2022-03-13LibWeb: Make Layout::SVGBox a BlockContainer againAndreas Kling
This wasn't worth the headache of trying to make SVG boxes work together with BFC right now. Let's just make it a block container once again, and have its corresponding SVGPaintable inherit from PaintableWithLines. We'll have to revisit this as SVG support improves.
2022-03-12LibWeb: Keep SVG elliptical arc shape when applying viewboxSimon Danner
When doing viewbox transforms, elliptical always had large arc and sweep flag set to false. Preserve these flags so they can be set correctly when applying viewbox transformations.
2022-03-12LibWeb: Let paintables cache their containing block and absolute rectAndreas Kling
The absolute rect of a paintable is somewhat expensive to compute. This is because all coordinates are relative to the nearest containing block, so we have to traverse the containing block chain and apply each offset to get the final rect. Paintables will never move between containing blocks, nor will their absolute rect change. If anything changes, we'll simpl make a new paintable and replace the old one. Take advantage of this by caching the containing block and absolute rect after first access.
2022-03-11LibWeb: Move hit testing to the painting treeAndreas Kling
2022-03-11LibWeb: Move PaintingBox to its own .cpp and .h filesAndreas Kling
2022-03-11LibWeb: Make hit testing return a { paintable, offset }Andreas Kling
Everything related to hit testing is better off using the painting tree. The thing being mousemoved over is a paintable, so let's hand that out directly instead of the corresponding layout node.
2022-03-11LibWeb: Move mouse event and label logic from layout to painting treeAndreas Kling
Input events have nothing to do with layout, so let's not send them to layout nodes. The job of Paintable starts to become clear. It represents a paintable item that can be rendered into the viewport, which means it can also be targeted by the mouse cursor.
2022-03-11LibWeb: Make Paintable ref-countedAndreas Kling
This will allow us to use a protective NonnullRefPtr to keep paintables alive while running arbitrary JavaScript in response to events.
2022-03-11LibWeb: Generate a TextPaintable for every Layout::TextNodeAndreas Kling
This is prep work for moving event handling over to the painting tree.
2022-03-11LibWeb: Port inline elements to the new Paintable systemAndreas Kling
This patch adds InlinePaintable which corresponds to Layout::InlineNode.
2022-03-11LibWeb: Split Paintable into Paintable and PaintableBoxAndreas Kling
To prepare for paintable inline content, we take the basic painting functionality and hoist it into a base class.
2022-03-11LibWeb: Add Paintable::layout_box() accessorAndreas Kling
Let's move away from accessing the m_layout_box member directly.