Commit graph

70 commits

Author SHA1 Message Date
Andreas Kling
884ae80699 LibHTML+Browser: Show target URL of hovered links in Browser statusbar
HtmlView will now invoke the on_link_hover hook when the cursor enters
or leaves a DOM node that has an enclosing link element.

This patch also updates the meaning of Node::enclosing_link_element()
to find the nearest HTMLAnchorElementAncestor *with an href attribute*.
2019-10-19 21:25:49 +02:00
Andreas Kling
73af2f8d02 LibHTML: DOM fixup should handle a completely empty document
We were forgetting to check if there was even a first child of the
root Document node.
2019-10-19 21:20:42 +02:00
Andreas Kling
f970578cd4 LibDraw: Rename ImageLoader => ImageDecoder
ImageLoader was not the right name for this, as there is no loading
happening, only decoding. :^)
2019-10-19 20:54:47 +02:00
Andreas Kling
025d3b49ab LibHTML: Make "display: inline-block" generate a LayoutBlock for now
We're gonna need some more smarts for this, but this at least gives
us something instead of an assertion.
2019-10-19 19:02:02 +02:00
Andreas Kling
96f34d26c9 LibHTML: Batch style updates and make them start from the root
Use a zero-timer to schedule a style update after invalidating style
on any node. Nodes now have a needs_style_update flag which helps us
batch and coalesce the work.

We also start style updates at the root and work our way through the
document, updating any node that has the needs_style_update flag set.
This is slower than what we were doing before, but far more correct.

There is a ton of room for improvement here. :^)
2019-10-19 19:00:31 +02:00
Andreas Kling
5a34225999 LibHTML: Implement basic tiled background image support
It's now possible to set a page background image via <body background>.
Also, HtmlView now officially handles rendering the body element's
background (color, image or both.) LayoutBox is responsible for all
other background rendering.

Note that it's not yet possible to use CSS background-image properties
directly, since we can't parse them yet. :^)
2019-10-19 11:49:46 +02:00
Andreas Kling
a5f3f332ed LibHTML: Ignore completed image loads for already-destroyed <img>'s
Capture a weak pointer to the element and pass that to the load finish
callback in HTMLImageElement::load_image(). This allows us to ignore
completed loads if the <img> element is no longer around.
2019-10-19 09:43:05 +02:00
Andreas Kling
6202a0ab32 LibHTML: Only accumulate Text children's content in inline stylesheets
Some inline stylesheets use HTML comments like "<!--blah blah-->".
The HTML parser currently generates a comment child node of the <style>
element whenever this happens, and we don't want the comment itself to
be interpreted as part of the stylesheet.
2019-10-17 23:54:27 +02:00
Andreas Kling
41896ff521 LibHTML: Add stub classes for basic table layout
This class introduces LayoutTable, LayoutTableRow and LayoutTableCell.
These are produced by "display" values table, table-row and table-cell
respectively.

Note that there's no layout happening yet, I'm just adding the classes.
2019-10-17 23:39:31 +02:00
Andreas Kling
18fa662eb2 LibHTML: Use ImageLoader for <img> elements to defer bitmap decoding
We now wait until the pixels are actually needed before fully decoding
images in <img> elements.

This needs some more work and is currently a bit memory-wasteful since
we'll hang on to the raw image data forever.
2019-10-15 21:53:08 +02:00
Andreas Kling
4814253589 LibHTML: Introduce LayoutBox and LayoutNodeWithStyleAndBoxModelMetrics
To streamline the layout tree and remove irrelevant data from classes
that don't need it, this patch adds two new LayoutNode subclasses.

LayoutNodeWithStyleAndBoxModelMetrics should be inherited by any layout
node that cares about box model metrics (margin, border, and padding.)
LayoutBox should be inherited by any layout node that can have a rect.

This makes LayoutText significantly smaller (from 140 to 40 bytes) and
clarifies a lot of things about the layout tree.

I'm also adding next_sibling() and previous_sibling() overloads to
LayoutBlock that return a LayoutBlock*. This is okay since blocks only
ever have block siblings.

Do also note that the semantics of is<T> slightly change in this patch:
is<T>(nullptr) now returns true, to facilitate allowing to<T>(nullptr).
2019-10-15 16:48:38 +02:00
Andreas Kling
f4f5ede10a LibHTML: Simplify Node::create_layout_node()
There's no need to pass the StyleResolver to this function. Nodes that
need it can just get it from the document.
2019-10-15 15:06:16 +02:00
Andreas Kling
f7cd5662ef LibHTML: Move layout tree building to a LayoutTreeBuilder class
Building a whole layout tree shouldn't be a concern of Node, so this
patch moves it to a separate class.
2019-10-15 14:24:26 +02:00
Andreas Kling
735f02900b LibHTML: Implement basic partial style invalidation
This patch makes it possible to call Node::invalidate_style() and have
that node and all of its ancestors recompute their style.

We then figure out if the new style is visually different from the old
style, and if so do a paint invalidation with set_needs_display().
Note that the "are they visually different" code is very incomplete!

Use this to make hover effects a lot more efficient. They no longer
cause a full relayout+repaint, but only a style invalidation.
Style invalidations are still quite heavy though, and there's a lot of
room for improvement there. :^)
2019-10-14 18:33:23 +02:00
Andreas Kling
667b31746a LibHTML: Rename Document's invalidate_{style,layout}() to update_foo() 2019-10-14 17:57:06 +02:00
Andreas Kling
61ef17b87a LibHTML: Implement basic :hover pseudo-class support
This is currently very aggressive. Whenever the Document's hovered node
changes, we invalidate all style and do a full relayout.

It does look cool though. So cool that I'm adding it to the default
stylesheet. :^)
2019-10-14 17:55:04 +02:00
Andreas Kling
2c035f5072 LibHTML: Split layout invalidation into style and layout invalidation
When style is invalidated (for example when an external stylesheet
finishes loading) we delete the whole layout tree and build a new one.
This is necessary since the new style information may result in a
different layout tree.

When layout is invalidated (window resized, image dimensions learned,
etc..) we keep the existing layout tree but run the layout algorithm
once again.

There's obviously lots of room for improvement here. :^)
2019-10-13 12:51:16 +02:00
Andreas Kling
49ac0c2e24 LibHTML: Move layout root from HtmlView to Document
The layout root is now kept alive via Document::m_layout_root.
This will allow us to do more layout-related things inside the inner
layer of LibHTML without reaching out to the HtmlView.

I'd like to keep HtmlView at a slightly higher level, to prevent it
from getting too complex.

This patch also fixes accidental disconnection of the layout tree from
the DOM after doing a layout tree rebuild. ~LayoutNode() now only
unsets the DOM node's layout_node() if it's itself.
2019-10-13 12:43:31 +02:00
Andreas Kling
b083a233d8 LibHTML: Add Comment and CharacterData nodes and improve HTML parsing
This patch adds the CharacterData subclass of Node, which is now the
parent class of Text and a new Comment class.

A Comment node is one of these in HTML: <!--hello friends-->
Since these occur somewhat frequently on the web, we need to be able
to parse them.

This patch also adds a child rejection mechanism to the DOM tree.
Nodes can now override is_child_allowed(Node) and return false if they
don't want a particular Node to become a child of theirs. This is used
to prevent Document from taking on unwanted children.
2019-10-12 23:34:05 +02:00
Andreas Kling
6242459c0f LibHTML: Implement the <br> element for line breaking
The <br> element will produce a special LayoutBreak node in the layout
tree, which forces a break in the line layout whenever encountered.

This patch also makes LayoutBlock use the current line-height as the
minimum effective height for each line box. This ensures that having
multiple <br> elements in a row doesn't create 0-height line boxes.
2019-10-12 13:47:49 +02:00
Andreas Kling
3cef6a5cac LibHTML: Make all element tag names lowercase for now
This is not the correct-est way of doing this, but it does make a bunch
of things simpler for now. We can revisit tag name case later on. :^)
2019-10-12 13:04:06 +02:00
Andreas Kling
35def88c8b LibHTML: Move Element construction to a separate file
We now have create_element(document, tag_name) in ElementFactory.
This will be useful for constructing new elements outside of parsing.
2019-10-12 13:02:38 +02:00
Andreas Kling
f5bf8f6380 LibHTML: Add LayoutNode classes for "display: list-item" and its marker
This patch removes the hard-coded hack for "display: list-item" from
LayoutBlock and adds LayoutListItem and LayoutListItemMarker.

Elements with "display: list-item" now generate a LayoutListItem, which
may then also generate a LayoutListItemMarker if appropriate. :^)
2019-10-11 23:16:53 +02:00
Andreas Kling
ebacef36ee LibHTML: Fix relative URL completion when document URL ends in a slash 2019-10-10 11:35:38 +02:00
Andreas Kling
a259832266 LibHTML: Document::detach_from_frame() should actually detach 2019-10-09 21:52:38 +02:00
Andreas Kling
fdbad6284c LibHTML: Implement the <blink> element
Just in time for Serenity's 1st birthday, here is the <blink> element!

This patch adds a bunch of different mechanisms to enable partial
repaints of the layout tree (LayoutNode::set_needs_display()))
It also adds LayoutNode::is_visible(), which can be toggled to prevent
a LayoutNode from rendering anything (it still takes up space though.)
2019-10-09 21:25:29 +02:00
Andreas Kling
fc53867937 LibHTML: Add basic <!DOCTYPE> parsing and a DocumentType class
Plus, Document::fixup() will now make sure that the document always
starts with a doctype node, followed by an <html> element.
2019-10-09 20:17:01 +02:00
Andreas Kling
850955053f LibHTML: Rename Document::normalize() to fixup() and always do it
Node.normalize() is a standard DOM API that coalesces Text nodes.
To avoid clashing with that, rename it to fixup().

This patch also makes it happen automagically as part of parsing.
2019-10-09 18:54:34 +02:00
Andreas Kling
475c6d7112 LibHTML: Use ResourceLoader in HTMLLinkElement
This makes loading external stylesheets from http:// URLs work. :^)
2019-10-09 10:39:28 +02:00
Andreas Kling
3be6d1aff0 LibHTML: Add ResourceLoader to support protocol-agnostic URL loading
We now support loading both file:// and http:// URLs. Feel free to
visit http://www.serenityos.org/ and enjoy the fancy good times. :^)
2019-10-08 19:37:15 +02:00
Andreas Kling
31ac19543a LibHTML: Use an enum for CSS property ID's
Instead of using string everywhere, have the CSS parser produce enum
values, since they are a lot nicer to work with.

In the future we should generate most of this code based on a list of
supported CSS properties.
2019-10-08 15:35:05 +02:00
Andreas Kling
edbf09ea29 LibHTML: Make the CSS and HTML parsers take StringViews
This allows us to avoid unnecessary making unnecessary String copies of
all the source text.
2019-10-07 19:11:33 +02:00
Andreas Kling
71e8ddcd1c LibHTML: Start adding support for <link rel="stylesheet">
This patch adds basic support for external stylesheets. It currently
only works with file:// URLs.

We do a synchronous full relayout after loading a stylesheet, which is
definitely on the aggressive side, but it gives us something to work
on improving. :^)
2019-10-07 19:06:47 +02:00
Andreas Kling
15f3e64862 LibHTML: Rename "style_properties" to "style" everywhere 2019-10-07 10:56:44 +02:00
Andreas Kling
a239ef34d5 LibHTML: Add Node::first_ancestor_of_type<T>()
Here's another helper for finding the first ancestor of a Node of a
specific type.
2019-10-06 21:07:36 +02:00
Andreas Kling
3bee9d3d3c LibHTML: Templatize Node::first_child_of_type<T>()
This is a lot nicer than first_child_with_tag_name(...).

The is<T>(Node) functions are obviously unoptimized at the moment,
and this is about establishing pleasant patterns right now. :^)
2019-10-06 20:47:57 +02:00
Andreas Kling
f52f2736e1 LibHTML: Add is<ElementType> and to<ElementType> helper functions
These will help us write node-type-aware template functions.
2019-10-06 20:38:26 +02:00
Andreas Kling
5a6c36dc91 LibHTML: Add Node::{next,previous}_element_sibling()
These helpers return the next/previous sibling Node that's actually an
element. This will be useful in the CSS engine since CSS doesn't care
about text nodes.
2019-10-06 19:54:50 +02:00
Conrad Pankoff
b240500107 LibHTML: Support width/height attributes on images 2019-10-06 14:33:00 +02:00
Conrad Pankoff
1ef53be2f3 LibHTML: Load image resource when src attribute is set 2019-10-06 14:33:00 +02:00
Conrad Pankoff
ef8b754a46 LibHTML: Add function for invalidating the document layout
This allows any external actor to signal that the document layout may be
stale. This can be used when loading resources, changing the size or
placement of an element, adding/removing nodes, or really any time.
2019-10-06 14:33:00 +02:00
Andreas Kling
83a6474d82 LibHTML: Parse link, alink and vlink in <body> and pass to Document
This patch adds HTMLBodyElement::parse_attribute() where we extract the
link colors and stash them away on Document.
2019-10-06 10:11:54 +02:00
Andreas Kling
772718b8d8 LibHTML: Add a per-attribute callback for Elements to parse attributes
Elements now have a virtual parse_attribute(name, value) callback that
gets invoked for each one of its attributes.
2019-10-06 10:09:55 +02:00
Andreas Kling
958b395418 LibHTML: Support rendering <img src> with file:// URLs
We can now show images loaded from local file:// URLs. Pretty neat :^)
2019-10-05 23:41:14 +02:00
Andreas Kling
ee567cdc3d LibHTML: Implement basic layout for inline <img alt>
LayoutReplaced objects can now participate in inline layout.

It's very hackish, but basically LayoutReplaced will just add itself to
the last line in the containing block.

This patch gets rid of the idea that only LayoutInline subclasses can
be split into lines, by moving the split_into_lines() virtual up to
LayoutNode and overriding it in LayoutReplaced.
2019-10-05 23:29:01 +02:00
Andreas Kling
f150134de9 LibHTML: Make Node::create_layout_node() virtual
Instead of branching on the Node type, let subclasses decide how their
layout nodes get constructed.

This will allow elements to create custom layout nodes if they want.
2019-10-05 23:29:01 +02:00
Andreas Kling
09dccb3224 LibHTML: Flesh out <img> element with LayoutImage and LayoutReplaced
This patch adds parsing of <img> into HTMLImageElement objects.
It also adds LayoutImage and its parent class LayoutReplaced, which is
going to represent CSS "replaced elements."
2019-10-05 23:29:01 +02:00
Andreas Kling
78d65c1c64 LibHTML: Add load(URL) and reload() functions to HtmlView
You can now pass a file:/// URL to HtmlView and it will take care of
the loading logic for you. Each Document remembers the URL it was
loaded from, which allows us to also have reload().

This patch also adds a very simple function for resolving relative
URL's into absolute ones.
2019-10-05 10:17:33 +02:00
Andreas Kling
8fb979148d LibHTML: Add support for <font color>
This was pleasantly trivial to implement with the new support for
presentational hints. :^)
2019-10-04 21:14:59 +02:00
Andreas Kling
9808d35554 LibHTML: Add support for <body bgcolor="#rrggbb" text="#rrggbb">
This patch implements basic support for presentational hints, which are
old-school HTML attributes that affect style.

You add support for a presentational hint attribute by overriding
Element::apply_presentational_hints(StyleProperties&) and setting all
of the corresponding CSS properties as appropriate.

To make the background color fill the entire document, not just the
bounds of the <body> element's LayoutNode, we special-case it in the
HtmlView::paint_event() code for now. I'm not entirely sure what the
nicest solution would be, but I'm sure we'll discover it eventually.
2019-10-04 21:05:52 +02:00