about summary refs log tree commit diff stats
path: root/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/box.nim5
-rw-r--r--src/layout/engine.nim26
-rw-r--r--src/layout/renderdocument.nim39
3 files changed, 52 insertions, 18 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 79f927ef..40628204 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -1,5 +1,6 @@
 import css/stylednode
 import css/values
+import img/bitmap
 import layout/layoutunit
 
 type
@@ -12,7 +13,7 @@ type
     h*: LayoutUnit
 
   InlineAtomType* = enum
-    iatSpacing, iatWord, iatInlineBlock
+    iatSpacing, iatWord, iatInlineBlock, iatImage
 
   InlineAtom* = ref object
     offset*: Offset
@@ -24,6 +25,8 @@ type
       str*: string
     of iatInlineBlock:
       innerbox*: BlockBox
+    of iatImage:
+      bmp*: Bitmap
 
   RootInlineFragment* = ref object
     # offset relative to parent
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 99d205f5..30afb066 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -5,6 +5,7 @@ import std/unicode
 
 import css/stylednode
 import css/values
+import img/bitmap
 import layout/box
 import layout/layoutunit
 import types/winattrs
@@ -68,6 +69,7 @@ type
     text: seq[string]
     newline: bool
     splitType: set[SplitType]
+    bmp: Bitmap
 
   BlockBoxBuilder = ref object of BoxBuilder
     inlinelayout: bool
@@ -1500,8 +1502,20 @@ proc layoutInline(ictx: var InlineContext; box: InlineBoxBuilder):
   if ictx.firstTextFragment == nil:
     ictx.firstTextFragment = fragment
   ictx.lastTextFragment = fragment
-  ictx.layoutText(state, box.text)
-  ictx.layoutChildren(state, box.children)
+  if box.bmp != nil:
+    let iastate = InlineAtomState(
+      vertalign: state.computed{"vertical-align"},
+      baseline: ictx.cellheight
+    )
+    let atom = InlineAtom(
+      t: iatImage,
+      bmp: box.bmp,
+      size: Size(w: int(box.bmp.width), h: int(box.bmp.height)) #TODO overflow
+    )
+    discard ictx.addAtom(state, iastate, atom)
+  else:
+    ictx.layoutText(state, box.text)
+    ictx.layoutChildren(state, box.children)
   if stSplitEnd in box.splitType:
     let paddingRight = box.computed{"padding-right"}.px(lctx, ictx.space.w)
     ictx.currentLine.size.w += paddingRight
@@ -2856,10 +2870,10 @@ proc generateFromElem(ctx: var InnerBlockContext; styledNode: StyledNode) =
   of DisplayNone: discard
 
 proc generateAnonymousInlineText(ctx: var InnerBlockContext; text: string;
-    styledNode: StyledNode) =
+    styledNode: StyledNode; bmp: Bitmap = nil) =
   if ctx.iroot == nil:
     let computed = styledNode.computed.inheritProperties()
-    ctx.ibox = InlineBoxBuilder(computed: computed, node: styledNode)
+    ctx.ibox = InlineBoxBuilder(computed: computed, node: styledNode, bmp: bmp)
     if ctx.inlineStack.len > 0:
       let iparent = ctx.reconstructInlineParents()
       iparent.children.add(ctx.ibox)
@@ -2900,7 +2914,7 @@ proc generateReplacement(ctx: var InnerBlockContext;
     ctx.generateAnonymousInlineText(child.content.s, parent)
   of ContentImage:
     #TODO idk
-    ctx.generateAnonymousInlineText("[img]", parent)
+    ctx.generateAnonymousInlineText("[img]", parent, child.content.bmp)
   of ContentVideo:
     ctx.generateAnonymousInlineText("[video]", parent)
   of ContentAudio:
@@ -3116,7 +3130,7 @@ proc generateTableBox(styledNode: StyledNode; lctx: LayoutState;
   box.generateTableChildWrappers()
   return box
 
-proc renderLayout*(root: StyledNode; attrsp: ptr WindowAttributes): BlockBox =
+proc layout*(root: StyledNode; attrsp: ptr WindowAttributes): BlockBox =
   let space = AvailableSpace(
     w: stretch(attrsp[].width_px),
     h: stretch(attrsp[].height_px)
diff --git a/src/layout/renderdocument.nim b/src/layout/renderdocument.nim
index fe7b92cb..e57a6d2c 100644
--- a/src/layout/renderdocument.nim
+++ b/src/layout/renderdocument.nim
@@ -3,12 +3,13 @@ import std/unicode
 
 import css/stylednode
 import css/values
+import img/bitmap
 import layout/box
 import layout/engine
 import layout/layoutunit
-import types/winattrs
 import types/cell
 import types/color
+import types/winattrs
 import utils/strwidth
 
 type
@@ -208,12 +209,19 @@ proc setText(grid: var FlexibleGrid; linestr: string; x, y: int; format: Format;
   assert grid[y].formats[fi].pos <= nx
   # That's it!
 
-type RenderState = object
-  # Position of the absolute positioning containing block:
-  # https://drafts.csswg.org/css-position/#absolute-positioning-containing-block
-  absolutePos: seq[Offset]
-  bgcolor: CellColor
-  attrsp: ptr WindowAttributes
+type
+  PosBitmap* = ref object
+    x*: int
+    y*: int
+    bmp*: Bitmap
+
+  RenderState = object
+    # Position of the absolute positioning containing block:
+    # https://drafts.csswg.org/css-position/#absolute-positioning-containing-block
+    absolutePos: seq[Offset]
+    bgcolor: CellColor
+    attrsp: ptr WindowAttributes
+    images: seq[PosBitmap]
 
 template attrs(state: RenderState): WindowAttributes =
   state.attrsp[]
@@ -361,6 +369,15 @@ proc renderInlineFragment(grid: var FlexibleGrid; state: var RenderState;
         grid.setRowWord(state, atom, offset, format, fragment.node)
       of iatSpacing:
         grid.setSpacing(state, atom, offset, format, fragment.node)
+      of iatImage:
+        state.images.add(PosBitmap(
+          x: (offset.x div state.attrs.ppc).toInt,
+          y: (offset.y div state.attrs.ppl).toInt,
+          bmp: atom.bmp
+        ))
+  else:
+    for child in fragment.children:
+      grid.renderInlineFragment(state, child, offset)
   if fragment.computed{"position"} != PositionStatic:
     if fragment.splitType != {stSplitStart, stSplitEnd}:
       if stSplitStart in fragment.splitType:
@@ -370,8 +387,6 @@ proc renderInlineFragment(grid: var FlexibleGrid; state: var RenderState;
         ))
       if stSplitEnd in fragment.splitType:
         discard state.absolutePos.pop()
-  for child in fragment.children:
-    grid.renderInlineFragment(state, child, offset)
 
 proc renderRootInlineFragment(grid: var FlexibleGrid; state: var RenderState;
     root: RootInlineFragment; offset: Offset) =
@@ -440,7 +455,8 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
         stack.add((box.nested[i], offset))
 
 proc renderDocument*(grid: var FlexibleGrid; bgcolor: var CellColor;
-    styledRoot: StyledNode; attrsp: ptr WindowAttributes) =
+    styledRoot: StyledNode; attrsp: ptr WindowAttributes;
+    images: var seq[PosBitmap]) =
   grid.setLen(0)
   if styledRoot == nil:
     # no HTML element when we run cascade; just clear all lines.
@@ -449,8 +465,9 @@ proc renderDocument*(grid: var FlexibleGrid; bgcolor: var CellColor;
     absolutePos: @[Offset(x: 0, y: 0)],
     attrsp: attrsp
   )
-  let rootBox = renderLayout(styledRoot, attrsp)
+  let rootBox = styledRoot.layout(attrsp)
   grid.renderBlockBox(state, rootBox, Offset(x: 0, y: 0))
   if grid.len == 0:
     grid.addLines(1)
   bgcolor = state.bgcolor
+  images = state.images