Age | Commit message (Collapse) | Author |
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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).
|
|
This implements the stop-opacity, fill-opacity, and stroke-opacity
properties (in CSS). This replaces the existing more ad-hoc
fill-opacity attribute handling.
|
|
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.
|
|
This reverts commit b79fd3d1a90f959d71e8d1b56ad9f8c088681e78.
|
|
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.
|
|
Otherwise, returning "no" here will disallow the browser process from
showing a context menu, as the event handler will bail early.
|
|
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.
|
|
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.
|
|
This first pass is enough to get us:
- Image loading via fetch
- Source selection via srcset and sizes attributes
|
|
Images being aware of being visible inside the viewport is a painting
concern, not a layout concern.
|
|
There should be no behavior change from this, only slightly less
verbosity. :^)
|
|
Turns out we create a lot of these, mostly from places that don't return
ErrorOr. The yak stack grows.
|
|
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.
|
|
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.
|
|
This means iframes are transparent by default (as in firefox/chrome).
Painting the outermost canvas background is moved to the PageHost.
|
|
The timestamp text was very tiny on a HiDPI display.
|
|
The representation is used to indicate whether the layout node should
paint a video frame, the video's poster, or a "transparent black" box.
|
|
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.
|
|
Fix translation of iframes when pixel size is not 1.0.
|
|
An Optional<Layout::LineBoxFragmentCoordinate> is 24 bytes, which isn't
small enough to pass by value and then copy.
|
|
|
|
These don't match the type name, which is confusing.
|
|
It returns a PaintableBox, not a 'PaintBox'.
|
|
It returns a PaintableBox, not any Paintable.
|
|
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>
|
|
...instead of defaulting to a PaintableBox. This way it gets the same
behavior as other SVG boxes during paint.
|
|
The spec recommends exposing the user agent interface when scripting is
disabled on the media element.
|
|
|
|
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.
|
|
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.
|
|
Which also requires converting a DevicePixelSize to a CSSPixelSize.
|
|
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)
|
|
Otherwise, the Gfx::Painter will get choked up on NaNs and start
infinitely splitting paths till it OOMs.
|
|
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.
|
|
Not sure why this was not done before, not now it works easily :^)
|
|
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.
|
|
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.
|
|
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
|
|
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>.
|
|
This fixes painting text shadows at non-100% zoom.
|
|
This returns the font scaled for the current zoom level.
|