Commit graph

122 commits

Author SHA1 Message Date
Sergey Bugaev
0f42908073 LibHTML: Respect the system theme
LibHTML will now use the palette colors for the default document background and
the text. As always, a page can override this default styling with CSS if it
really wants a specific color or style.

Fixes https://github.com/SerenityOS/serenity/issues/963
2020-01-05 10:21:15 +01:00
Andreas Kling
a79bac428b LibGUI+LibDraw: Add "Palette" concept for scoped color theming
GApplication now has a palette. This palette contains all the system
theme colors by default, and is inherited by a new top-level GWidget.
New child widgets inherit their parents palette.

It is possible to override the GApplication palette, and the palette
of any GWidget.

The Palette object contains a bunch of colors, each corresponding to
a ColorRole. Each role has a convenience getter as well.

Each GWidget now has a background_role() and foreground_role(), which
are then looked up in their current palette when painting. This means
that you no longer alter the background color of a widget by setting
it directly, rather you alter either its background role, or the
widget's palette.
2019-12-24 21:27:16 +01:00
Andreas Kling
1aea8f116b LibHTML: Add TreeNode::for_each_in_subtree_of_type<T>()
This allows you to iterate a subtree and get a callback for every node
where is<T>(node) == true. This makes for quite pleasant DOM traversal.
2019-12-18 21:34:03 +01:00
Andreas Kling
54bd322881 LibHTML: Mark image bitmaps outside the visible viewport as volatile
When the visible viewport rect changes, we walk the layout tree and
check where each LayoutImage is in relation to the viewport rect.
Images outside have their bitmaps marked as volatile.

Note that the bitmaps are managed by ImageDecoder objects. If a bitmap
is purged by the kernel while volatile, we construct a new ImageDecoder
next time we need pixels for the image.
2019-12-18 21:19:04 +01:00
Andreas Kling
85ac9705ba LibHTML: Add LayoutNode::is_image() and is<LayoutImage> helper 2019-12-18 20:52:36 +01:00
Andreas Kling
0d6f186397 LibHTML: Insert a new linebox for every newline in "white-space: pre" 2019-12-18 12:44:16 +01:00
Andreas Kling
4d81bc20d8 LibHTML: Don't insert line breaks between multiple <pre>'s on a line
When iterating lines for "white-space: pre", we should only break when
there is an actual line break character.
2019-12-18 12:44:09 +01:00
Andreas Kling
6f4c380d95 AK: Use size_t for the length of strings
Using int was a mistake. This patch changes String, StringImpl,
StringView and StringBuilder to use size_t instead of int for lengths.
Obviously a lot of code needs to change as a result of this.
2019-12-09 17:51:21 +01:00
Andreas Kling
70fadbad37 LibHTML: Respect "border-style: dotted"
Dotted borders are now painted correctly (as long as they are 1px wide)
which is yet another little improvement to my Apache2 default page :^)
2019-11-27 20:53:28 +01:00
Andreas Kling
6d1c4ae5a9 LibHTML: Implement basic <form> and <input> element support
This patch adds "submit" inputs and default (text box) inputs, as well
as form elements that can be submitted.

Layout of input elements is implemented via a new LayoutWidget class
that allows you to put an arbitrary GWidget in the layout tree.
At the moment, the DOM node sets the initial size of the LayoutWidget,
and then the positioning is done by the normal layout algorithm.

We also now support submitting a <form method="GET">, which does a full
replacing load with a URL based on the form's action + a query string
built from the name/value of input elements within the submitted form.

This is pretty neat! :^)
2019-11-25 21:21:55 +01:00
Andreas Kling
847b232680 LibHTML: Divide the "line spacing" evenly between lines of text
Before this patch, all of the excess spacing caused by line-height was
"padding" the line boxes below the text.

To fix this, we make line box fragments use the font height as their
height, and then let the inline layout algorithm adjust the Y positions
to distribute the vertical space.
2019-11-25 18:14:52 +01:00
Andreas Kling
320c79cb48 LibHTML: Join border edges nicely when painting boxes
Always paint border edges so they join nicely with their buddy edges.
This makes borders look nice even if all sides have different widths.

Also switch the border code to using floating point numbers since
otherwise things get very ugly very fast.
2019-11-25 14:37:04 +01:00
Andreas Kling
05b1ecf1b1 LibHTML: Draw each CSS border edge separately with their own style
The borders still look very wrong with any border-width other than 1,
but at least we can see that they have the right color, and end up in
mostly the right place :^)
2019-11-25 13:17:14 +01:00
Andreas Kling
9f0ca1bfb0 LibHTML: Paint text background color before the underline decoration 2019-11-21 13:15:11 +01:00
Andreas Kling
9a6388f718 LibHTML: Render a background-color behind line box fragments if needed 2019-11-19 19:23:14 +01:00
Andreas Kling
5a04472470 LibHTML: Fix bug in removal of trailing whitespace from line boxes
This code was using the text from the DOM as a reference for how much
whitespace to remove from the end of a line box.

Since the DOM may contain uncollapsed whitespace, it would sometimes
be out of sync with the collapsed text used by the rest of the layout
system.
2019-11-19 19:21:47 +01:00
Andreas Kling
1fe2cca439 LibHTML: Use LayoutText::text_for_rendering() in layout tree dumps
This way the fragment offsets make a lot more sense, since they assume
whitespace has already been collapsed.
2019-11-19 18:36:33 +01:00
Andreas Kling
a12292bd03 LibHTML: LayoutImage should not dereference a null bitmap
This was happening when trying to render a bitmap that we couldn't
decode properly.
2019-11-18 20:26:32 +01:00
Andreas Kling
c628ebda0f LibHTML: Use floating point numbers throughout the layout tree 2019-11-18 16:30:18 +01:00
Andreas Kling
b08de46480 LibHTML: Implement basic 'max-width' and 'min-width' support
These CSS properties constrain the computed width of a block-level box
to a maximum, followed by a minimum value.

This makes the "better mother fricken website" look more like it's
intended to (which helps makes the author's point, I suppose.)
2019-11-18 12:26:08 +01:00
Andreas Kling
70a4678d77 LibHTML: Paint a magenta rectangle around the currently inspected node
Document now tracks one "inspected" node, set by set_inspected_node()
which is called by Browser's DOM inspector view on_selection callback.
2019-11-09 11:58:50 +01:00
Andreas Kling
71f249fd2c LibHTML: Draw box borders even if we don't have a border-color
In those cases we should fall back to currentColor, which is hackishly
implemented by falling back to "color" for now.
2019-11-07 21:36:32 +01:00
Andreas Kling
f3f0b08d43 LibHTML: Build some foundation for text selection
Add LayoutPosition and LayoutRange classes. The layout tree root node
now has a selection() LayoutRange. It's essentially a start and end
LayoutPosition.

A LayoutPosition is a LayoutNode, and an optional index into that node.
The index is only relevant for text nodes, where it's the character
index into the rendered text.

HtmlView now updates the selection start/end of the LayoutDocument when
clicking and dragging with the left mouse button.

We don't paint the selection yet, and there's no way to copy what's
selected. It only exists as a LayoutRange.
2019-11-05 22:13:26 +01:00
Andreas Kling
715d7a8532 LibHTML: Add a convenient way to get from any layout node to the root 2019-11-04 20:45:47 +01:00
Andreas Kling
3bd29ad98c LibHTML: Remove trailing whitespace in line boxes
After the splitting-into-lines pass, remove any trailing whitespace
from all of a block's line boxes.

This improves the appearance of text-align: justify/right :^)
2019-10-20 17:20:20 +02:00
Andreas Kling
eb77e680ed LibHTML: Implement "text-align: justify"
In order for this to work nicely, I made the line box classes use float
instead of int for its geometry information.

Justification works by distributing all of the whitespace on the line
(including the trailing whitespace before the line break) evenly across
the spaces in-between words.

We should probably use floating point (or maybe fixed point?) for all
the layout metrics stuff. But one thing at a time. :^)
2019-10-20 12:55:55 +02:00
Andreas Kling
457e49f528 LibHTML: Rename HTMLImageElement::m_image_loader => m_image_decoder
This matches the new class name, ImageDecoder.
2019-10-20 12:55:55 +02:00
Andreas Kling
c41bae3d54 LibHTML+Browser: Support scrolling to anchor with <a href="#foo">
This patch implements basic support for <a href="#foo"> fragment links.

To figure out where we actually want to scroll to, we have to do
something different based on the layout node's box type. So if it's a
regular LayoutBox we can just use the LayoutBox::position().

However, if it's an inline layout node, we use the position of the
first line box fragment in the containing block contributed by this
layout node or one of its descendants.
2019-10-20 10:07:26 +02:00
Andreas Kling
8b07025145 LibHTML: Don't insert unnecessary line breaks at start of text lines
Basically the same exact fix as I did for replaced elements. There's no
point in inserting a line break at the start of a line if all you're
trying to achieve is make more horizontal space for something.
2019-10-19 21:34:15 +02:00
Andreas Kling
6cbf8a3426 LibHTML: Use the correct inherited color for LayoutListItemMarker 2019-10-19 11:54:28 +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
762f20944c LibHTML: Replaced elements should not break lines at start of line
If the current line box already has zero width, there's no point in
inserting a line break to make space, since we'll just be at x=0 after
breaking as well.

This removes an ugly unnecessary line break before images wider than
their containing block. :^)
2019-10-19 09:44:40 +02:00
Andreas Kling
07cbe2daa4 LibHTML: Preserve UTF-8 codepoints when collapsing whitespace
This is extremely awkward and I'm sure there are many better ways to
achieve this..
2019-10-18 22:50:44 +02:00
Andreas Kling
2305dee455 LibHTML: Add LayoutNode::first_ancestor_of_type<T>() 2019-10-18 10:16:33 +02:00
Andreas Kling
65ad6c35f0 LibHTML: Add typed child/sibling traversal helpers for LayoutNode
Also add some special variants for the table classes, to make it a bit
more pleasant to write table code. :^)
2019-10-18 09:38:12 +02:00
Andreas Kling
6c22b46b37 LibHTML: Hard-code LayoutTable to never have inline children
This is a total hack to get around the auto-detection mechanism for
whether a block has inline or block children. We'll say that tables
never have inline children for now, and then anything that actually
turns out to be an inline child will just be ignored by layout.
2019-10-17 23:39:31 +02:00
Andreas Kling
b4c2621ed7 LibHTML: Add is<T> helpers for the table-related LayoutNode subclasses 2019-10-17 23:39:31 +02:00
Andreas Kling
5e29238a49 LibHTML: Make "children are inline" flag imperative
Instead of computing whether a block's children are inline based on the
first child, make it an imperatively-set flag.

This gives us some flexibility to ignore things like text nodes inside
a <table>, for example. I'm still unsure what the "correct" way to deal
with those will be. We'll find out sooner or later. :^)
2019-10-17 23:39:31 +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
14f380f87a LibHTML: Use is_inline() instead of !is_block() when building tree 2019-10-17 23:39:31 +02:00
Andreas Kling
6dbba6ad85 LibHTML: Implement CSS text-align: left/center/right
This was easier than I imagined; we just shift each line box to the
left based on the alignment and the remaining space on each line. :^)
2019-10-16 20:32:17 +02:00
Andreas Kling
38b55ee067 LibHTML: LayoutBlock::hit_test() was calling the wrong parent class
Oops, we now need to call LayoutBox instead of LayoutNode for blocks
with non-inline children.
2019-10-15 22:02:58 +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
5c2b21705a LibHTML: LayoutNode::set_needs_display() needs to invalidate fragments
If a LayoutNode is split into line box fragments, we need to walk our
fragments and invalidate them. It was not enough to do this only for
LayoutBox nodes.
2019-10-15 20:45:52 +02:00
Andreas Kling
110b2d52f2 LibHTML: Fix missing backgrounds an borders after LayoutBox refactoring
The render() implementation in both LayoutBlock and LayoutBox need to
be calling the immediate parent class. :^)
2019-10-15 19:12:56 +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
d14b60533f LibHTML: Add is<T> and to<T> helpers for LayoutNode class family 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