aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorj-james2022-08-09 22:48:58 +0000
committerj-james2022-08-09 22:49:47 +0000
commit1118d87f2732a72294d043e18415609cd9f48853 (patch)
tree6a955e1d1f0df33e266db782645615d351e7d207
parent194e2e1b0f65e1c63fdf5c4702d454446785a9a9 (diff)
Complete layout tree generation
-rw-r--r--README.md4
-rw-r--r--src/layout.nim39
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.