灵符lingfu
H

horizon-browser

↓ 0 downloads

Horizon: a real box-model HTML/CSS layout engine with a Canvas 2D surface, no_std + alloc, zero dependencies -- LingOS's next-generation browser engine, sibling to bring-browser

Keywords browser, html, css, layout, canvas, no_std, lingos
lingfu install horizon-browser
LicenseMIT
AuthorsLing Lin <taellinglin@gmail.com>
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (9)

README.md
# horizon — a real browser engine for LingOS

`horizon` is LingOS's second web engine: a `no_std` + `alloc`, zero-dependency
HTML/CSS **box-model** layout library, sibling to
[`bring-browser`](../bring-browser). Where `bring` is a `links`/`lynx`-style
text-flow engine (fixed line buffers, no allocation, no real box model),
`horizon` builds an actual DOM tree, cascades CSS onto it, lays it out with
real block/inline boxes, and paints a **pixel display list** — including a
`<canvas>` element with a real 2D drawing surface. It is not a JS engine and
does not pretend to be WebKit/Gecko/Servo; see the roadmap below for what's
honestly in scope today.

The engine never touches a screen itself. Like `bring`, it hands a laid-out
`Page` (a display list of rects/text/canvas/image items, in pixels) to a thin
embedder — LingOS's desktop compositor (`ling-kernel/src/drivers/horizon.rs`)
walks that list with the kernel's existing `framebuffer` + `font8x8`
primitives, the same way `ling-kernel/src/drivers/browser.rs` already does
for `bring`.

## What renders today (v0.1)

- DOM: `html`, `head`, `body`, `div`, `span`, `p`, `h1`–`h6`, `a[href]`,
  `b`/`strong`, `i`/`em`, `br`, `ul`/`ol`/`li`, `img[src]`, `canvas[width][height][id]`,
  `pre`, `title`; `script`/`style` contents parsed for CSS only, never executed
  or rendered as text.
- CSS: inline `style=""` and `<style>` blocks, tag + `.class` + `#id`
  selectors, cascade by specificity + source order. Properties: `display`
  (`block`/`inline`/`none`), `color`, `background-color`, `width`, `height`,
  `margin`, `padding` (single value, uniform on all sides — shorthand
  per-side values are roadmap), `font-weight: bold`, `text-align`.
- Layout: real normal-flow box model. Block boxes stack vertically with
  margin/padding/explicit-or-auto width; inline content (text + inline
  elements) flows and wraps within the content box at the embedder's glyph
  metrics (monospace only — `horizon` takes a `char_w`/`line_h` in pixels,
  same spirit as `bring`'s `cols` parameter, so it stays font-agnostic).
  No floats, no flexbox, no grid, no absolute/relative positioning yet.
- Canvas: `<canvas>` allocates a real `CanvasSurface` (`Vec<u32>` pixel
  buffer) with a 2D drawing API — `fill_rect`, `stroke_rect`, `fill_circle`,
  `line`, `set_pixel`, `clear` — addressable by the embedder or host Rust
  code via `Page::canvas_mut(id)`. **Scripted** canvas (a page's own
  `<script>` calling `getContext("2d")`) is not implemented; there is no JS
  engine yet, so nothing drives the canvas except native code that already
  has a `&mut Page`. This is the same honest limitation `bring` states for
  scripting generally.
- Output: a flat `Vec<DisplayItem>` (`Rect`, `Text`, `Image`, `Canvas`) in
  paint order, plus link/image tables — the embedder walks it once per frame.

## Roadmap, honestly staged

1. **CSS box model completeness** (near): per-side margin/padding/border
   shorthand, `border` painting, `%`-relative widths, `position: relative`.
2. **Proportional text + inline-block** (mid): today's layout assumes a
   monospace glyph grid because that's what LingOS's `font8x8` gives it;
   real font metrics (variable glyph widths, LingOS's `font_unicode` table)
   need layout to measure text instead of counting characters.
3. **Flexbox subset** (mid-far): the single most-requested real-world layout
   primitive; a constrained one-axis flex (`display: flex`, `flex-direction`,
   `justify-content`, no wrapping) before anything fancier.
4. **Scripting** (far): if it lands, a small interpreted subset sharing
   LingOS's in-kernel VM work, the same stance `bring` takes — not a JS
   engine bolted onto a kernel. Until then, `<canvas>` is a real paintable
   surface that only native code can drive, and pages with script-driven
   behavior render their static markup only.

Each stage lands with host tests in this repo (`cargo test`, no kernel
required) before it's wired into `ling-kernel`.

← Back to index