From 1118d87f2732a72294d043e18415609cd9f48853 Mon Sep 17 00:00:00 2001 From: j-james Date: Tue, 9 Aug 2022 15:48:58 -0700 Subject: Complete layout tree generation --- README.md | 4 ++-- src/layout.nim | 39 +++++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 23d5fac..c80e145 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # bamboo -A lightweight and flexible web browser built from scratch. +A lightweight and flexible web browser built from scratch. Loosely based on [browser.engineering](https://browser.engineering). -This project currently includes an implementation of most of HTTP, a (fragile) HTML parser, an OpenGL-based renderer, and a basic style engine. This is planned to include the rest of HTTP, an implementation of HTML5, an implementation of CSS3, a JavaScript compilation target (to run in the browser), and JavaScript support through an embedded external library. +This project currently includes an implementation of most of HTTP, a (fragile) HTML parser, an OpenGL-based renderer, and a basic style engine. This is planned to include the rest of HTTP, an implementation of HTML5, an implementation of CSS3, and JavaScript support through an embedded external library. This does not implement TCP or UDP, and instead relies on Nim's [`std/net`](https://nim-lang.org/docs/net.html) to provide a cross-platform implementation of Berkeley Sockets. This also relies on [`treeform/[windy,`](https://github.com/treeform/windy)[`boxy]`](https://github.com/treeform/boxy) for a cross-platform windowing API, and [`treeform/pixie`](https://github.com/treeform/pixie) for a Skia-like graphics engine. diff --git a/src/layout.nim b/src/layout.nim index cfec966..2be0610 100644 --- a/src/layout.nim +++ b/src/layout.nim @@ -8,6 +8,12 @@ import print # Note that Nim's UFCS means that typically calls to get() look like value.get(T()). # (T() is an object constructor, and [] are both openarray accesses and generic brackets) +const + window_width = 500 + window_height = 500 + hstep = 13 + vstep = 18 + # const inline_elements = [] const block_elements = [ @@ -23,7 +29,7 @@ const block_elements = [ # The Document layout is included because pages can # have multiple Documents through the use of iframes. type LayoutKind = enum - Inline, Block, Document + Document, Block, Inline # Improve error messages: suggest a ref object when failing from recursion type Layout = ref object @@ -34,12 +40,13 @@ type Layout = ref object x, y, width, height: float cursorX, cursorY: float case kind: LayoutKind: - of Inline: - weight: int - of Block: - discard of Document: discard + of Block: + discard + of Inline: + cx, cy: float # cursor + weight: int # The layout tree is constructed in a two-part process: # 1. We iterate through the node tree to create a simple layout tree. @@ -79,34 +86,38 @@ func get(self: Option[Layout]): auto = func calculate_position(self: Layout) = case self.kind: of Document: - self.x = 1 - self.y = 1 - self.width = 500 - self.height = 500 - of Inline: + self.width = window_width - 2*hstep + self.x = hstep + self.y = vstep + of Block: self.x = self.parent.get.x # every object starts at its parent's left edge... self.y = # if there is no previous sibiling, they start at their parent's top edge... if self.previous.isSome(): self.previous.get.y + self.previous.get.height else: self.parent.get.y self.width = self.parent.get.width # by default, objects are greedy and take up all the space they can get... - of Block: + of Inline: self.x = self.parent.get.x self.y = if self.previous.isSome(): self.previous.get.y + self.previous.get.height else: self.parent.get.y self.width = self.parent.get.width + self.cx = self.x + self.cy = self.y for child in self.children: calculate_position(child) case self.kind: - of Inline: - self.height = 0 + of Document: + self.height = + if self.children.len != 0: self.children.map(x => x.height).foldl(a + b) + 2*vstep + else: 2*vstep of Block: self.height = # height calculation must come after the recursive call if self.children.len != 0: self.children.map(x => x.height).foldl(a + b) else: 0 - else: discard # the Document layout doesn't matter + of Inline: + self.height = self.cy - self.y # These implicitly-mutating parameters are a bit gross, but # really seem like the best way to build this layout tree. -- cgit v1.2.3-70-g09d2