Fixes in selector rule parser.
Stub implementation for attributes filter in CSS.
Fixes in `background-position` and `background` shorthand parsers.
Added a few HTML elements tags.
Added body default left and right margin.
Part 1: CSS background properties (UINodeDrawable, LayerDrawable)
Add `BackgroundMode` (Native / Html) to `UINodeDrawable`. When Html mode
is active, background rendering follows CSS/HTML semantics (repeat defaults
to repeat, clip plane always enabled, etc.). Native mode preserves the
original eepp behavior (no-repeat by default, clip only when repeating).
Add per-layer `background-origin`, `background-clip`, `background-attachment`
with `fromText` parsers and CSS property registration. `background-origin`
controls the reference box for position/percentage resolution.
`background-clip` enables per-layer content-box clipping.
`background-attachment: fixed` anchors the background to the scene root;
`local` is stubbed (needs per-widget scroll offset plumbing).
Replace the single `Repeat` enum with `RepeatX` / `RepeatY` enums supporting
two-value repeat (e.g. "repeat no-repeat", "space round"). Implement space
and round repeat rendering in `LayerDrawable::draw()`.
Fix `background-size: contain` to scale up (not just down) like HTML.
Rewrite the comma-separated multi-layer `background` shorthand parser with
`/size` separator, box keyword disambiguation, and attachment keywords.
UINode::{getBackground} detects `UI_HTML_ELEMENT` flag and lazily sets
`BackgroundMode::Html`.
Add golden image test: 20-tile image atlas via
`background: url(bnp.png) pos / size no-repeat` with browser-comparable HTML.
Part 2: HTML whitespace collapsing (HTMLFormatter → UIRichText)
Move whitespace collapsing from parse time to layout time. Previously
`HTMLFormatter::collapseXmlWhitespace` ran on the pugixml DOM before
CSS was resolved, using tag-name heuristics for inline/block detection.
This caused whitespace between elements with `display: inline-block`
(via CSS) to be incorrectly stripped.
The new pipeline preserves raw whitespace in `UITextNode` widgets (after
internal whitespace collapsing via `UIRichText::collapseInternalWhitespace`)
and defers boundary stripping to `UIRichText::rebuildRichText`, where every
widget's computed `CSSDisplay` is available via `UIWidget::isInlineDisplay()`.
- `UIWidget::isInlineDisplay()` returns true for text nodes and widgets
with `CSSDisplay::Inline | InlineBlock`, used by boundary logic.
- `UITextNode::isWhitespaceOnly()` identifies collapsible text nodes.
- `findLogicalPrev/Next` walks up through inline ancestors to find the
correct boundary element, matching HTML's whitespace transparency rule.
- Boundary stripping: leading/trailing spaces removed at block edges,
preserved between inline-level siblings.
- Double-space prevention: when adding text that starts with a space,
peeks at the last `SpanBlock` in RichText if it ends with a space,
the leading space is stripped. This prevents consecutive spaces when
whitespace nodes are separated by empty inline elements.
- `UITextNode::mLayoutCharCount` syncs the character index between
`rebuildRichText` (where boundary-stripped text is added) and
`positionRichTextChildren` (where widgets are mapped to render spans),
fixing hitbox alignment for all text-bearing widgets.
Remove `HTMLFormatter::collapseXmlWhitespace`, `isInlineNode`,
`hasSignificantText`, `getLogicalPrev`, `getLogicalNext`, and the
`precomputeDisplayStyles` hack (~200 lines removed). `HTMLFormatter`
now only exposes `HTMLtoXML`.
Other fixes
- Remove `@import url(https://fonts.googleapis.com/css?family=Lato)`
from ensoft.css (async HTTP use-after-free in test suite).
- `BlockLayouter::positionRichTextChildren` skips whitespace-only text
nodes when advancing the character index.
- Fix in DrawableSearcher not finding already loaded textures.
Added cookies support (now it's possible to login in websites).
Improved redirect handling in HTTP client.
Fix in `Node::find*` and `UIWidget::find*` functions to ignore closing nodes.
Fix in Node min width and height handling with pixel scale different than 1.
In standard web browsers, a `Node` represents anything in the DOM (including text), whereas an `Element` represents an HTML tag. CSS selectors strictly filter by `Element`.
Currently, `eepp`'s CSS engine (`StyleSheetSpecification`) evaluates selectors directly against `Node` sibling counts (`getNodeIndex()`, `getChildCount()`). By distinguishing between "Widgets" (Elements) and "Text Nodes" at the node level, we updated these selectors to count only true structural elements, matching web standards with zero performance overhead.