Commit Graph

361 Commits

Author SHA1 Message Date
Andreas Kling
655d9d1462 LibWeb: Make CSSPixels and Length use 64-bit (double) floating point
This fixes a plethora of rounding problems on many websites.
In the future, we may want to replace this with fixed-point arithmetic
(bug #18566) for performance (and consistency with other engines),
but in the meantime this makes the web look a bit better. :^)

There's a lot more things that could be converted to doubles, which
would reduce the amount of casting necessary in this patch.
We can do that incrementally, however.
2023-05-24 14:40:35 +02:00
Andreas Kling
fe92b54137 LibWeb: Don't draw text fragments that would be clipped by the painter
This avoids a ton of work when painting large documents. Even though it
would eventually get clipped by the painter anyway, by bailing out
earlier, we avoid a lot more work (UTF-8 iteration, OpenType lookups,
etc).

It would be even nicer if we could skip entire line boxes, but we don't
have a fast way to get the bounding rect of a line box at the moment.
2023-05-23 14:38:45 +02:00
Jelle Raaijmakers
f391ccfe53 LibGfx+Everywhere: Change Gfx::Rect to be endpoint exclusive
Previously, calling `.right()` on a `Gfx::Rect` would return the last
column's coordinate still inside the rectangle, or `left + width - 1`.
This is called 'endpoint inclusive' and does not make a lot of sense for
`Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would
return 4 as its right side. This same problem exists for `.bottom()`.

This changes `Gfx::Rect` to be endpoint exclusive, which gives us the
nice property that `width = right - left` and `height = bottom - top`.
It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly
the same.

All users of `Gfx::Rect` have been updated accordingly.
2023-05-23 12:35:42 +02:00
MacDue
91d8665ab4 LibWeb: Tidy up apply_clip_overflow_rect() a little
Avoid possible null optional dereference when creating border radius
clipper, and avoid creating clipper if the clip rect is empty (which
prevents some debug spam). Also remove an unnecessary lambda.
2023-05-22 06:05:47 +02:00
Andreas Kling
e63f68661f LibWeb: Have ImageProvider bitmap getter take optional size argument
This allows the painting subsystem to request a bitmap with the exact
size needed for painting, instead of being limited to "just give me a
bitmap" (which was perfectly enough for raster images, but not for
vector graphics).
2023-05-21 07:44:29 +02:00
MacDue
00cda96e2d LibWeb: Implement SVG opacity properties
This implements the stop-opacity, fill-opacity, and stroke-opacity
properties (in CSS). This replaces the existing more ad-hoc
fill-opacity attribute handling.
2023-05-20 08:52:19 +02:00
Jelle Raaijmakers
7652dbd983 LibWeb: Use box sampling instead of bilinear scaling when downscaling
As a heuristic, either the width or height of the scaled image should
decrease for box sampling to be used. Otherwise, we use bilinear
scaling.
2023-05-19 18:36:36 +02:00
Andreas Kling
77db621be5 Revert "LibWeb: Use box sampling instead of bilinear scaling when downscaling"
This reverts commit b79fd3d1a9.
2023-05-19 13:33:52 +02:00
Jelle Raaijmakers
b79fd3d1a9 LibWeb: Use box sampling instead of bilinear scaling when downscaling
As a heuristic, either the width or height of the scaled image should
decrease for box sampling to be used. Otherwise, we use bilinear
scaling.
2023-05-19 06:16:14 +02:00
Timothy Flynn
5f473bcb5f LibWeb: Propagate non-primary mouse button clicks on video elements
Otherwise, returning "no" here will disallow the browser process from
showing a context menu, as the event handler will bail early.
2023-05-16 12:48:39 +02:00
Andreas Kling
990e7219d6 LibWeb: Fix iframes flickering on window resize
After finishing layout, iframe layout boxes (FrameBox) get notified
about their new size by LayoutState::commit(). This information is
forwarded to the nested browsing context, where it can be used for
layout of the nested document.

The problem here was that we notified the FrameBox twice. Once when
assigning the used offset to its paintable, and once when assigning its
size. Because the offset was assigned first, we ended up telling the
FrameBox "btw, your size is 0x0". This caused us to throw away all
the layout information we had for the nested document.

We'd then say "actually, your size is 300x200" (or something) but by
then it was already too late, and we had to do a full relayout.
This caused iframes to flicker as every time their containing document
was laid out, we'd nuke the iframe layout and redo it (on a zero timer).

The fix is pleasantly simple: we didn't need to inform the nested
document of its offset in the containing document's layout anyway. Only
its size is relevant. So we can simply remove the first call, which
removes the bogus 0x0 temporary size.

Note that iframes may still flicker if they change size in the
containing document. That's a separate issue that will require more
finesse to solve. However, this fixes a very noticeable common case.
2023-05-15 14:08:08 +02:00
Andreas Kling
c648e24cff LibWeb: Don't force HTMLImageElement to have a legacy ImageLoader
We achieve this by adding a new Layout::ImageProvider class and having
both HTMLImageElement and HTMLObjectElement inherit from it.

The HTML spec is vague on how object image loading should work, which
is why this first pass is focusing on image elements.
2023-05-13 09:08:42 +02:00
Andreas Kling
3cf73ca0b3 LibWeb: Implement enough of "update the image data" to load images
This first pass is enough to get us:
- Image loading via fetch
- Source selection via srcset and sizes attributes
2023-05-13 09:08:42 +02:00
Andreas Kling
dbe961ca02 LibWeb: Move image viewport awareness from ImageBox to ImagePaintable
Images being aware of being visible inside the viewport is a painting
concern, not a layout concern.
2023-05-09 09:48:49 +02:00
Andreas Kling
ca1fa5f748 LibWeb: Use the new to_px() helpers in CSS, SVG and layout code
There should be no behavior change from this, only slightly less
verbosity. :^)
2023-05-06 18:41:34 +02:00
Sam Atkins
d16600a48b LibWeb: Propagate errors from StyleValue construction
Turns out we create a lot of these, mostly from places that don't return
ErrorOr. The yak stack grows.
2023-05-06 08:07:28 +02:00
thankyouverycool
f7e034d4b2 LibGfx+Userland: Merge FrameShape and FrameShadow into FrameStyle
Previously, Frames could set both these properties along with a
thickness to confusing effect: Most shapes of the same shadowing only
differentiated at a thickness >= 2, and some not at all. This led
to a lot of creative but ultimately superfluous choices in the code.

Instead let's streamline our options, automate thickness, and get
the right look without so much guesswork.

Plain shadowing has been consolidated into a single Plain style,
and 0 thickness can be had by setting style to NoFrame.
2023-04-30 05:49:46 +02:00
MacDue
afd355c135 LibWeb: Resolve and paint SVG gradient fills
This bit is mostly ad-hoc for now. This simply turns fill: url(#grad1)
into document().get_element_by_id('grad1') then resolves the gradient.
This seems to do the trick for most use cases, but this is not
attempting to follow the spec yet to keep things simple.
2023-04-28 09:42:28 +02:00
Sigmund Lahn
f2f14ad9bd LibWeb+WebContent: Make document background and Viewport transparent
This means iframes are transparent by default (as in firefox/chrome).

Painting the outermost canvas background is moved to the PageHost.
2023-04-25 09:33:35 +02:00
Timothy Flynn
ab1244a160 LibWeb: Paint video timestamps using CSS/device pixel-aware scaled fonts
The timestamp text was very tiny on a HiDPI display.
2023-04-23 16:22:45 +02:00
Timothy Flynn
83bb24991b LibWeb: Implement HTMLVideoElement representation closer to the spec
The representation is used to indicate whether the layout node should
paint a video frame, the video's poster, or a "transparent black" box.
2023-04-21 07:54:36 +02:00
Timothy Flynn
dd188aafb9 LibWeb: Track decoded video frame positions along with the frame image
This will be needed by the layout node, which may change what is painted
when the position of the frame image is not the same as the element's
current time.
2023-04-21 07:54:36 +02:00
Aliaksandr Kalenik
46c98dbf43 LibWeb: Use device pixels to translate NestedBrowsingContextPaintable
Fix translation of iframes when pixel size is not 1.0.
2023-04-20 20:44:02 +02:00
Linus Groh
37c9dbe248 LibWeb/Painting: Move-assign value in set_containing_line_box_fragment
An Optional<Layout::LineBoxFragmentCoordinate> is 24 bytes, which isn't
small enough to pass by value and then copy.
2023-04-20 20:43:30 +02:00
Linus Groh
352da3623b LibWeb/Painting: Remove redundant 'Painting::' namespace prefixes 2023-04-20 20:43:30 +02:00
Linus Groh
36d35c9c82 LibWeb: Rename remaining paint_box variables to paintable_box
These don't match the type name, which is confusing.
2023-04-20 20:43:30 +02:00
Linus Groh
754e458d0a LibWeb/Layout: Rename Box::{paint => paintable}_box()
It returns a PaintableBox, not a 'PaintBox'.
2023-04-20 20:43:30 +02:00
Linus Groh
ec37b55777 LibWeb/Painting: Rename StackingContext::paintable{ => _box}()
It returns a PaintableBox, not any Paintable.
2023-04-20 20:43:30 +02:00
Andreas Kling
d8ccc2d54e LibWeb: Rename BrowsingContextContainer => NavigableContainer
The "browsing context container" concept in the HTML spec has been
replaced with "navigable container". Renaming this is the first step of
many towards implementing the new world.

Co-authored-by: Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
2023-04-19 18:26:45 +02:00
Andreas Kling
ec5d5918c4 LibWeb: Make SVG <g> elements generate a SVGGraphicsPaintable
...instead of defaulting to a PaintableBox. This way it gets the same
behavior as other SVG boxes during paint.
2023-04-19 07:52:26 +02:00
Timothy Flynn
6131e621d6 LibWeb: Render HTMLVideoElement controls when scripting is disabled
The spec recommends exposing the user agent interface when scripting is
disabled on the media element.
2023-04-18 16:30:02 +02:00
MacDue
5a12e9f222 LibWeb: Clip SVG content to parent <svg> element bounding box 2023-04-17 07:32:31 +02:00
Timothy Flynn
c403f8e92c LibWeb: Update the media playback time for clicks on the media timeline
When clicking on the media timeline, compute the percentage along the
timeline's width the user clicked, and set the playback time to the same
percentage of the video's duration.
2023-04-17 01:16:04 +02:00
Timothy Flynn
ad3c63684c LibWeb: Restrict toggling video playback to certain areas in a video
When the control bar is shown, do not toggle playback when clicking on
the control bar, unless the click target is the playback button. This
will let us implement clicking on the timeline to seek.

Note that this requires caching some layout rects on the video element.
We need to remember where the corresponding layout boxes are, and we
can't cache them on the layout box, as that may be destroyed any time.
2023-04-17 01:16:04 +02:00
Timothy Flynn
c4e3ba2dfb LibWeb: Implement converting a DevicePixelRect to a CSSPixelRect
Which also requires converting a DevicePixelSize to a CSSPixelSize.
2023-04-17 01:16:04 +02:00
MacDue
f9c61e3ba7 LibWeb: Scale SVG stroke-width based on viewbox
This fixes the clipping of strokes in quite a few cases and now fixes
the Gartic Phone logo :^)

(Layout test updated but no visible changes there)
2023-04-15 19:28:13 +02:00
MacDue
ba6272a0a0 LibWeb: Don't try to paint SVG elements transformed to zero size
Otherwise, the Gfx::Painter will get choked up on NaNs and start
infinitely splitting paths till it OOMs.
2023-04-12 07:40:22 +02:00
MacDue
809c15d1ee LibWeb: Use (transformed) path bounding quad for SVG path hit testing
This is needed for hit testing the directional arrows on the Street
View office tour, and generally makes SVG hit testing more precise.

Note: The rough bounding box is hit test first, so this should not
be a load more overhead.
2023-04-12 07:40:22 +02:00
MacDue
d0496ae9b8 LibWeb: Apply CSS scaling to SVG elements
Not sure why this was not done before, not now it works easily :^)
2023-04-12 07:40:22 +02:00
MacDue
cf23a2b82d LibWeb: Apply SVG transform to path when painting (SVG) elements
This also combines the viewbox mapping into the same transform and
reuses some code by using Path::copy_transformed() rather than manually
mapping each segment of the path.
2023-04-12 07:40:22 +02:00
MacDue
d2fc8efd9e LibWeb: Make SC hit testing more closely follow reverse paint order
Previously, we would hit test positioned elements, then stacking
contexts with z-index 0, as two seperate steps. This did not really
follow the reverse paint order, where positioned elements and stacking
contexts with z-index 0 are painted during the same tree transversal.

This commit updates
for_each_in_subtree_of_type_within_same_stacking_context_in_reverse()
to return the stacking contexts it comes across too, but not recurse
into them. This more closely follows the paint order.

This fixes examples such as:

<div id="a" style="width: 10px; height: 10px">
  <div id="b" style="position: absolute; width: 10px; height: 10px">
    <div
     style="position: absolute; width: 10px; height: 10px; z-index: 0"
    >
      <div id="c"
           style="width: 100%; height: 100%; background-color:red;"
           onclick="alert('You Win!')">
      </div>
    </div>
  </div>
</div>

Where previously the onclick on #c would never fire as hit testing
always stopped at #b. This is reduced from Google Street View,
which becomes interactable after this commit.
2023-04-12 07:40:22 +02:00
Timothy Flynn
fe66490399 LibWeb: Paint a media timeline on HTMLVideoElement layout nodes 2023-04-11 19:27:55 +02:00
Timothy Flynn
d5412f4e78 LibWeb: Move VideoPaintable's cached mouse position to HTMLVideoElement
The layout node, and therefore the painting box, is frequently destroyed
and recreated. This causes us to forget the cached mouse position we use
to highlight media controls. Move this cached position to the DOM node
instead, which survives relayout.
2023-04-11 19:27:55 +02:00
Timothy Flynn
cdf4c410bf LibWeb: Tweak the color used for hovered media controls
The link color is what closely resembled the color I was going for on
the machine I originally developed the controls on. But turns out this
is a very dark blue on most Serenity themes. Instead, hard-code the
original intended color, which is a lighter blue.
2023-04-11 19:27:55 +02:00
Timothy Flynn
d0e18b8a17 LibWeb: Convert video control dimensions from CSSPixels to DevicePixels
Rather than storing static DevicePixels dimensions, treat the desired
pixel sizes as CSSPixels and convert them to DevicePixels.

This was originally developed on a mac with a device-to-CSS-pixel ratio
of 2. Running it on another machine with a ratio of 1 made the controls
appear huge.
2023-04-10 10:15:48 -04:00
Timothy Flynn
4555e3b8d2 LibWeb: Begin painting video controls on HTMLVideoElement layout nodes
If the video element has a 'controls' attribute, we now paint some basic
video controls over the video element. If no frame has been decoded yet,
we paint a play button on the center of the element.

If a frame has been decoded, we paint that frame and paint a control bar
on the bottom of the frame. This control bar currently only contains a
play/pause button, depending on the video's playback state. We will only
paint the control bar if the video is paused or hovered.
2023-04-08 22:04:14 +02:00
Timothy Flynn
f156d3d5e5 LibWeb: Create a basic layout node for HTMLVideoElement 2023-04-07 16:02:22 +02:00
MacDue
f409f68a9a LibWeb: Use scaled font when painting list item markers
This now uses the current font (rather than the painter's default)
and scales it correctly. This is not perfect though as just naviely
doing .draw_text() here does not follow the proper text layout logic
so this is misaligned (by a pixel or two) with the text in the <li>.
2023-04-01 22:39:47 +01:00
MacDue
14f937b292 LibWeb: Use scaled font when painting text shadows
This fixes painting text shadows at non-100% zoom.
2023-04-01 22:39:47 +01:00
MacDue
7061a3d8e6 LibWeb: Add .scaled_font() helper to Layout::Node
This returns the font scaled for the current zoom level.
2023-04-01 22:39:47 +01:00