diff options
-rw-r--r-- | src/css/values.nim | 6 | ||||
-rw-r--r-- | src/layout/box.nim | 9 | ||||
-rw-r--r-- | src/layout/engine.nim | 103 |
3 files changed, 79 insertions, 39 deletions
diff --git a/src/css/values.nim b/src/css/values.nim index a30c79a4..82b82588 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -530,10 +530,10 @@ func cssDisplay(d: CSSDeclaration): CSSDisplay = of "block": return DISPLAY_BLOCK of "inline": return DISPLAY_INLINE of "list-item": return DISPLAY_LIST_ITEM - of "table": return DISPLAY_TABLE of "inline-block": return DISPLAY_INLINE_BLOCK - of "table-row": return DISPLAY_TABLE_ROW - of "table-cell": return DISPLAY_TABLE_CELL + # of "table": return DISPLAY_TABLE + # of "table-row": return DISPLAY_TABLE_ROW + # of "table-cell": return DISPLAY_TABLE_CELL # of "table-column": return DISPLAY_TABLE_COLUMN # of "table-row-group": return DISPLAY_TABLE_ROW_GROUP # of "table-header-group": return DISPLAY_TABLE_HEADER_GROUP diff --git a/src/layout/box.nim b/src/layout/box.nim index d2546a85..20885849 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -23,7 +23,6 @@ type cssvalues*: CSSComputedValues node*: Node - #TODO move fromy InlineContext* = ref object fromx*: int fromy*: int @@ -55,9 +54,9 @@ type str*: string nodes*: seq[Node] - CSSInlineBox* = ref CSSInlineBoxObj - CSSInlineBoxObj = object of CSSBox + CSSInlineBox* = ref object of CSSBox content*: seq[CSSRowBox] - CSSBlockBox* = ref CSSBlockBoxObj - CSSBlockBoxObj = object of CSSBox + CSSBlockBox* = ref object of CSSBox + + CSSInlineBlockBox* = ref object of CSSBox diff --git a/src/layout/engine.nim b/src/layout/engine.nim index b2dfe8dd..70914251 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -28,16 +28,23 @@ func newInlineContext*(box: CSSBox): InlineContext = func newBlockContext(): BlockContext = new(result) -proc flushLines(box: CSSBox) = - if box.icontext.conty: - inc box.icontext.fromy - inc box.bcontext.fromy - inc box.height - box.icontext.conty = false +proc flushConty(box: CSSBox) = + inc box.icontext.fromy + inc box.bcontext.fromy + box.icontext.conty = false + box.icontext.whitespace = true + box.icontext.ws_initial = true + +proc flushMargins(box: CSSBox) = box.icontext.fromy += box.bcontext.margin_todo box.bcontext.margin_done += box.bcontext.margin_todo box.bcontext.margin_todo = 0 +proc flushLines(box: CSSBox) = + if box.icontext.conty: + box.flushConty() + box.flushMargins() + func newBlockBox(state: var LayoutState, parent: CSSBox, vals: CSSComputedValues): CSSBlockBox = new(result) result.x = parent.x @@ -83,6 +90,39 @@ func newInlineBox*(state: LayoutState, parent: CSSBox, vals: CSSComputedValues): result.cssvalues = vals result.icontext.fromx += vals[PROPERTY_MARGIN_LEFT].length.cells_w(state, parent.bcontext.width) +func newInlineBlockBox*(state: LayoutState, parent: CSSBox, vals: CSSComputedValues): CSSInlineBlockBox = + assert parent != nil + new(result) + result.x = parent.icontext.fromx + result.x += vals[PROPERTY_MARGIN_LEFT].length.cells_w(state, parent.bcontext.width) + result.bcontext = newBlockContext() + + let mtop = vals[PROPERTY_MARGIN_TOP].length.cells_h(state, parent.bcontext.width) + if mtop > parent.bcontext.margin_done or mtop < 0: + let diff = mtop - parent.bcontext.margin_done + parent.icontext.fromy += diff + parent.bcontext.margin_done += diff + + result.y = parent.icontext.fromy + + result.bcontext.margin_done = parent.bcontext.margin_done + + let pwidth = vals[PROPERTY_WIDTH].length + if pwidth.auto: + result.bcontext.width = parent.bcontext.width + else: + result.bcontext.width = pwidth.cells_w(state, parent.bcontext.width) + + let pheight = vals[PROPERTY_HEIGHT].length + if not pheight.auto: + if pheight.unit != UNIT_PERC or parent.bcontext.height.issome: + result.bcontext.height = pheight.cells_h(state, parent.bcontext.height).some + + result.icontext = newInlineContext(parent) + result.icontext.fromy = result.y + result.icontext.fromx = result.x + result.cssvalues = vals + type InlineState = object ibox: CSSInlineBox rowi: int @@ -183,25 +223,10 @@ proc preWrap(state: var InlineState) = state.ibox.icontext.ws_initial = true state.skip = true -proc processInlineBox(lstate: var LayoutState, parent: CSSBox, str: string): CSSBox = - if str.len > 0: - parent.icontext.fromy += parent.bcontext.margin_todo - parent.bcontext.margin_done += parent.bcontext.margin_todo - parent.bcontext.margin_todo = 0 - +proc processInlineText(lstate: var LayoutState, ibox: CSSInlineBox, str: string) = var state: InlineState state.nodes = lstate.nodes - var use_parent = false - if parent of CSSInlineBox: - state.ibox = CSSInlineBox(parent) - use_parent = true - else: - # TODO TODO TODO I highly doubt this is correct but it's the only way it - # makes sense... - state.ibox = lstate.newInlineBox(parent, parent.cssvalues.inheritProperties()) - - if str.len == 0: - return + state.ibox = ibox var i = 0 state.newRowBox() @@ -268,9 +293,25 @@ proc processInlineBox(lstate: var LayoutState, parent: CSSBox, str: string): CSS state.ibox.bcontext.margin_todo = 0 state.ibox.bcontext.margin_done = 0 state.ibox.icontext.fromy += state.rowi - if use_parent: + +proc processInlineBox(lstate: var LayoutState, parent: CSSBox, str: string): CSSBox = + #TODO this doesn't really belong in here + if str.len > 0: + parent.icontext.fromy += parent.bcontext.margin_todo + parent.bcontext.margin_done += parent.bcontext.margin_todo + parent.bcontext.margin_todo = 0 + + if str.len == 0: + return nil + + if parent of CSSInlineBox: + let ibox = CSSInlineBox(parent) + lstate.processInlineText(ibox, str) return nil - return state.ibox + + let ibox = lstate.newInlineBox(parent, parent.cssvalues.inheritProperties()) + lstate.processInlineText(ibox, str) + return ibox proc add(state: var LayoutState, parent: CSSBox, box: CSSBox) = if box == nil: @@ -296,6 +337,9 @@ proc add(state: var LayoutState, parent: CSSBox, box: CSSBox) = elif box of CSSInlineBox: parent.icontext.fromx += box.cssvalues[PROPERTY_MARGIN_RIGHT].length.cells_w(state, parent.bcontext.width) parent.icontext.fromy = box.icontext.fromy + elif box of CSSInlineBlockBox: + parent.icontext.fromx += box.cssvalues[PROPERTY_MARGIN_RIGHT].length.cells_w(state, parent.bcontext.width) + parent.icontext.fromy = box.icontext.fromy parent.height += box.height @@ -306,7 +350,7 @@ proc processComputedValueBox(state: var LayoutState, parent: CSSBox, values: CSS of DISPLAY_BLOCK: result = state.newBlockBox(parent, values) of DISPLAY_INLINE_BLOCK: - result = state.newInlineBox(parent, values) + result = state.newInlineBlockBox(parent, values) of DISPLAY_INLINE: result = state.newInlineBox(parent, values) of DISPLAY_LIST_ITEM: @@ -325,13 +369,10 @@ proc processComputedValueBox(state: var LayoutState, parent: CSSBox, values: CSS proc processBr(state: var LayoutState, parent: CSSBox, vals: CSSComputedValues) = if vals[PROPERTY_DISPLAY].display == DISPLAY_INLINE: if parent.icontext.conty: - inc parent.height - inc parent.icontext.fromy - parent.icontext.conty = false + parent.flushConty() else: + inc parent.bcontext.fromy inc parent.icontext.fromy - parent.icontext.whitespace = true - parent.icontext.ws_initial = true parent.icontext.fromx = parent.x proc processElemBox(state: var LayoutState, parent: CSSBox, elem: Element): CSSBox = |