about summary refs log tree commit diff stats
path: root/src/layout/engine.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-01-23 13:42:24 +0100
committerbptato <nincsnevem662@gmail.com>2022-01-23 13:42:24 +0100
commitd97776fb627720bc4bd5841ffffcd8c9af712f3c (patch)
treefde0f696f78fa4cb197edcee7308403d1d6d22b6 /src/layout/engine.nim
parent0b19885b33c53e2250a3a91326e5f146ccfa1492 (diff)
downloadchawan-d97776fb627720bc4bd5841ffffcd8c9af712f3c.tar.gz
Use pixels as the base unit for the layout
Diffstat (limited to 'src/layout/engine.nim')
-rw-r--r--src/layout/engine.nim78
1 files changed, 49 insertions, 29 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 3f16c8ac..eba40f7c 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -20,6 +20,9 @@ func cells_h(l: CSSLength, state: Viewport, p: Option[int]): int =
 func cells_h(l: CSSLength, state: Viewport, p: int): int =
   return l.cells_in(state, state.term.ppl, p.some, false)
 
+func px(l: CSSLength, state: Viewport, p = 0): int {.inline.} =
+  return px(l, state.term, p)
+
 type InlineState = object
   ictx: InlineContext
   skip: bool
@@ -28,6 +31,27 @@ type InlineState = object
   maxwidth: int
   specified: CSSSpecifiedValues
 
+func whitespacepre(specified: CSSSpecifiedValues): bool {.inline.} =
+  specified{"white-space"} in {WHITESPACE_PRE, WHITESPACE_PRE_WRAP}
+
+func cellwidth(ictx: InlineContext): int {.inline.} =
+  ictx.viewport.term.ppc
+
+func cellheight(ictx: InlineContext): int {.inline.} =
+  ictx.viewport.term.ppl
+
+# Whitespace between words
+func computeShift(ictx: InlineContext, specified: CSSSpecifiedValues): int =
+  if ictx.whitespace:
+    if ictx.thisrow.atoms.len > 0 or specified.whitespacepre:
+      let spacing = specified{"word-spacing"}
+      if spacing.auto:
+        return ictx.cellwidth
+      #return spacing.cells_w(ictx.viewport, 0)
+      return spacing.px(ictx.viewport)
+    ictx.whitespace = false
+  return 0
+
 proc newWord(state: var InlineState) =
   let word = InlineWord()
   let specified = state.specified
@@ -46,20 +70,6 @@ proc finishRow(ictx: InlineContext) =
     ictx.width = max(ictx.width, oldrow.width)
     ictx.thisrow = InlineRow(rely: oldrow.rely + oldrow.height)
 
-func whitespacepre(specified: CSSSpecifiedValues): bool {.inline.} =
-  specified{"white-space"} in {WHITESPACE_PRE, WHITESPACE_PRE_WRAP}
-
-# Whitespace between words
-func computeShift(ictx: InlineContext, specified: CSSSpecifiedValues): int =
-  if ictx.whitespace:
-    if ictx.thisrow.atoms.len > 0 or specified.whitespacepre:
-      let spacing = specified{"word-spacing"}
-      if spacing.auto:
-        return 1
-      return spacing.cells_w(ictx.viewport, 0)
-    ictx.whitespace = false
-  return 0
-
 proc addAtom(ictx: InlineContext, atom: InlineAtom, maxwidth: int, specified: CSSSpecifiedValues) =
   var shift = ictx.computeShift(specified)
   # Line wrapping
@@ -81,13 +91,13 @@ proc addWord(state: var InlineState) =
   if state.word.str != "":
     let row = state.ictx.thisrow
     var word = state.word
-    word.height = 1
+    word.height = state.ictx.cellheight
     state.ictx.addAtom(word, state.maxwidth, state.specified)
     state.newWord()
 
 # Start a new line, even if the previous one is empty
 proc flushLine(ictx: InlineContext) =
-  ictx.thisrow.height = max(ictx.thisrow.height, 1)
+  ictx.thisrow.height = max(ictx.thisrow.height, ictx.cellheight)
   ictx.finishRow()
 
 proc checkWrap(state: var InlineState, r: Rune) =
@@ -96,11 +106,11 @@ proc checkWrap(state: var InlineState, r: Rune) =
   let shift = state.ictx.computeShift(state.specified)
   case state.specified{"word-break"}
   of WORD_BREAK_BREAK_ALL:
-    if state.ictx.thisrow.width + state.word.width + shift + r.width() > state.maxwidth:
+    if state.ictx.thisrow.width + state.word.width + shift + r.width() * state.ictx.cellwidth > state.maxwidth:
       state.addWord()
       state.ictx.finishRow()
   of WORD_BREAK_KEEP_ALL:
-    if state.ictx.thisrow.width + state.word.width + shift + r.width() > state.maxwidth:
+    if state.ictx.thisrow.width + state.word.width + shift + r.width() * state.ictx.cellwidth > state.maxwidth:
       state.ictx.finishRow()
   else: discard
 
@@ -135,7 +145,7 @@ proc renderText*(ictx: InlineContext, str: string, maxwidth: int, specified: CSS
       fastRuneAt(str, i, r)
       state.checkWrap(r)
       state.word.str &= r
-      state.word.width += r.width()
+      state.word.width += r.width() * state.ictx.cellwidth
 
   state.addWord()
 
@@ -147,18 +157,24 @@ proc computedDimensions(bctx: BlockContext, width: int, height: Option[int]) =
   if pwidth.auto:
     bctx.compwidth = width
   else:
-    bctx.compwidth = pwidth.cells_w(bctx.viewport, width)
+    #bctx.compwidth = pwidth.cells_w(bctx.viewport, width)
+    bctx.compwidth = pwidth.px(bctx.viewport, width)
 
-  let mlef = bctx.specified{"margin-left"}.cells_w(bctx.viewport, width)
-  let mrig = bctx.specified{"margin-right"}.cells_w(bctx.viewport, width)
+  #let mlef = bctx.specified{"margin-left"}.cells_w(bctx.viewport, width)
+  #let mrig = bctx.specified{"margin-right"}.cells_w(bctx.viewport, width)
+  let mlef = bctx.specified{"margin-left"}.px(bctx.viewport, width)
+  let mrig = bctx.specified{"margin-right"}.px(bctx.viewport, width)
   bctx.relx = mlef
   bctx.compwidth -= mlef
   bctx.compwidth -= mrig
 
   let pheight = bctx.specified{"height"}
   if not pheight.auto:
-    if pheight.unit != UNIT_PERC or height.issome:
-      bctx.compheight = pheight.cells_h(bctx.viewport, height).some
+    #bctx.compheight = pheight.cells_h(bctx.viewport, height).some
+    if pheight.unit != UNIT_PERC:
+      bctx.compheight = pheight.px(bctx.viewport).some
+    elif height.issome:
+      bctx.compheight = pheight.px(bctx.viewport, height.get).some
 
 proc newBlockContext_common(parent: BlockContext, box: CSSBox): BlockContext {.inline.} =
   new(result)
@@ -185,7 +201,7 @@ proc newBlockContext(viewport: Viewport): BlockContext =
   new(result)
   result.specified = rootProperties()
   result.viewport = viewport
-  result.computedDimensions(viewport.term.width, none(int))
+  result.computedDimensions(viewport.term.width_px, none(int))
 
 proc newInlineContext(bctx: BlockContext): InlineContext =
   new(result)
@@ -211,7 +227,8 @@ proc arrangeBlocks(bctx: BlockContext) =
     let child = bctx.nested[i]
 
     bctx.margin_top = child.margin_top
-    let mtop = bctx.specified{"margin-top"}.cells_h(bctx.viewport, bctx.compwidth)
+    #let mtop = bctx.specified{"margin-top"}.cells_h(bctx.viewport, bctx.compwidth)
+    let mtop = bctx.specified{"margin-top"}.px(bctx.viewport, bctx.compwidth)
     if mtop > bctx.margin_top or mtop < 0:
       bctx.margin_top = mtop - bctx.margin_top
 
@@ -230,7 +247,8 @@ proc arrangeBlocks(bctx: BlockContext) =
     inc i
 
   bctx.margin_bottom = margin_todo
-  let mbot = bctx.specified{"margin-bottom"}.cells_h(bctx.viewport, bctx.compwidth)
+  #let mbot = bctx.specified{"margin-bottom"}.cells_h(bctx.viewport, bctx.compwidth)
+  let mbot = bctx.specified{"margin-bottom"}.px(bctx.viewport, bctx.compwidth)
   if mbot > bctx.margin_bottom or mbot < 0:
     bctx.margin_bottom = mbot - bctx.margin_bottom
 
@@ -295,8 +313,10 @@ proc alignInlines(bctx: BlockContext, inlines: seq[CSSBox]) =
   if bctx.compheight.issome:
     bctx.height = bctx.compheight.get
   bctx.width = max(ictx.width, ictx.width)
-  bctx.margin_top = bctx.specified{"margin-top"}.cells_h(bctx.viewport, bctx.compwidth)
-  bctx.margin_bottom = bctx.specified{"margin-bottom"}.cells_h(bctx.viewport, bctx.compwidth)
+  #bctx.margin_top = bctx.specified{"margin-top"}.cells_h(bctx.viewport, bctx.compwidth)
+  #bctx.margin_bottom = bctx.specified{"margin-bottom"}.cells_h(bctx.viewport, bctx.compwidth)
+  bctx.margin_top = bctx.specified{"margin-top"}.px(bctx.viewport, bctx.compwidth)
+  bctx.margin_bottom = bctx.specified{"margin-bottom"}.px(bctx.viewport, bctx.compwidth)
 
 proc alignBlocks(bctx: BlockContext, blocks: seq[CSSBox]) =
   # Box contains block boxes.