diff options
author | bptato <nincsnevem662@gmail.com> | 2022-12-27 23:36:13 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-12-27 23:42:28 +0100 |
commit | b5cffb3d805714767f2568b09fe86bb3a83d10b7 (patch) | |
tree | d9106729545b5b3915bfd3a97cf08f8da0d82619 /src | |
parent | 65b0b48f445b6c56016a3c842089ef117a9298bc (diff) | |
download | chawan-b5cffb3d805714767f2568b09fe86bb3a83d10b7.tar.gz |
layout/engine: get rid of dom dependency
Layout should only depend on cascading.
Diffstat (limited to 'src')
-rw-r--r-- | src/css/cascade.nim | 57 | ||||
-rw-r--r-- | src/css/selectorparser.nim | 2 | ||||
-rw-r--r-- | src/css/values.nim | 37 | ||||
-rw-r--r-- | src/layout/box.nim | 1 | ||||
-rw-r--r-- | src/layout/engine.nim | 53 | ||||
-rw-r--r-- | src/render/renderdocument.nim | 2 |
6 files changed, 96 insertions, 56 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim index 1207444d..633bf0f5 100644 --- a/src/css/cascade.nim +++ b/src/css/cascade.nim @@ -74,49 +74,61 @@ func calcRules(styledNode: StyledNode, sheet: CSSStylesheet): DeclarationList = dl func calcPresentationalHints(element: Element): CSSComputedValues = - template set_cv(a, b, c: untyped) = + template set_cv(a, b: untyped) = if result == nil: new(result) - result[a] = CSSComputedValue(t: a, v: ValueTypes[a], b: c) + result{a} = b template map_width = let s = parseDimensionValues(element.attr("width")) if s.isSome: - set_cv(PROPERTY_WIDTH, length, s.get) + set_cv "width", s.get template map_height = let s = parseDimensionValues(element.attr("height")) if s.isSome: - set_cv(PROPERTY_HEIGHT, length, s.get) + set_cv "height", s.get template map_width_nozero = let s = parseDimensionValues(element.attr("width")) if s.isSome and s.get.num != 0: - set_cv(PROPERTY_WIDTH, length, s.get) + set_cv "width", s.get template map_height_nozero = let s = parseDimensionValues(element.attr("height")) if s.isSome and s.get.num != 0: - set_cv(PROPERTY_HEIGHT, length, s.get) + set_cv "height", s.get template map_bgcolor = let c = parseLegacyColor(element.attr("bgcolor")) if c.isSome: - set_cv(PROPERTY_BACKGROUND_COLOR, color, c.get) + set_cv "background-color", c.get template map_valign = case element.attr("valign").toLowerAscii() - of "top": set_cv(PROPERTY_VERTICAL_ALIGN, verticalalign, CSSVerticalAlign(keyword: VERTICAL_ALIGN_TOP)) - of "middle": set_cv(PROPERTY_VERTICAL_ALIGN, verticalalign, CSSVerticalAlign(keyword: VERTICAL_ALIGN_MIDDLE)) - of "bottom": set_cv(PROPERTY_VERTICAL_ALIGN, verticalalign, CSSVerticalAlign(keyword: VERTICAL_ALIGN_BOTTOM)) - of "baseline": set_cv(PROPERTY_VERTICAL_ALIGN, verticalalign, CSSVerticalAlign(keyword: VERTICAL_ALIGN_BASELINE)) + of "top": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_TOP) + of "middle": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_MIDDLE) + of "bottom": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_BOTTOM) + of "baseline": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_BASELINE) template map_align = case element.attr("align").toLowerAscii() - of "center", "middle": set_cv(PROPERTY_TEXT_ALIGN, textalign, TEXT_ALIGN_CHA_CENTER) - of "left": set_cv(PROPERTY_TEXT_ALIGN, textalign, TEXT_ALIGN_CHA_LEFT) - of "right": set_cv(PROPERTY_TEXT_ALIGN, textalign, TEXT_ALIGN_CHA_RIGHT) + of "center", "middle": set_cv "text-align", TEXT_ALIGN_CHA_CENTER + of "left": set_cv "text-align", TEXT_ALIGN_CHA_LEFT + of "right": set_cv "text-align", TEXT_ALIGN_CHA_RIGHT template map_text = let c = parseLegacyColor(element.attr("text")) if c.isSome: - set_cv(PROPERTY_COLOR, color, c.get) + set_cv "color", c.get template map_color = let c = parseLegacyColor(element.attr("color")) if c.isSome: - set_cv(PROPERTY_COLOR, color, c.get) + set_cv "color", c.get + template map_colspan = + let colspan = element.attrigz("colspan") + if colspan.isSome: + let i = colspan.get + if i <= 1000: + set_cv "-cha-colspan", i + template map_rowspan = + let rowspan = element.attrigez("rowspan") + if rowspan.isSome: + let i = rowspan.get + if i <= 65534: + set_cv "-cha-rowspan", i case element.tagType of TAG_DIV: @@ -131,6 +143,8 @@ func calcPresentationalHints(element: Element): CSSComputedValues = map_bgcolor map_valign map_align + map_colspan + map_rowspan of TAG_THEAD, TAG_TBODY, TAG_TFOOT, TAG_TR: map_height map_bgcolor @@ -146,8 +160,8 @@ func calcPresentationalHints(element: Element): CSSComputedValues = map_text of TAG_TEXTAREA: let textarea = HTMLTextAreaElement(element) - set_cv(PROPERTY_WIDTH, length, CSSLength(unit: UNIT_CH, num: float64(textarea.cols))) - set_cv(PROPERTY_HEIGHT, length, CSSLength(unit: UNIT_EM, num: float64(textarea.rows))) + set_cv "width", CSSLength(unit: UNIT_CH, num: float64(textarea.cols)) + set_cv "height", CSSLength(unit: UNIT_EM, num: float64(textarea.rows)) of TAG_FONT: map_color else: discard @@ -286,6 +300,11 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN let styledText = styledParent.newStyledReplacement(content) styledText.pseudo = pseudo styledParent.children.add(styledText) + of PSEUDO_NEWLINE: + let content = CSSContent(t: CONTENT_NEWLINE) + let styledText = styledParent.newStyledReplacement(content) + styledText.pseudo = pseudo + styledParent.children.add(styledText) of PSEUDO_NONE: discard else: assert child != nil @@ -364,6 +383,8 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN stack_append styledChild, PSEUDO_TEXTAREA_TEXT elif elem.tagType == TAG_IMG or elem.tagType == TAG_IMAGE: stack_append styledChild, PSEUDO_IMAGE + elif elem.tagType == TAG_BR: + stack_append styledChild, PSEUDO_NEWLINE else: for i in countdown(elem.childList.high, 0): if elem.childList[i].nodeType in {ELEMENT_NODE, TEXT_NODE}: diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim index 8a38292b..2c6ab659 100644 --- a/src/css/selectorparser.nim +++ b/src/css/selectorparser.nim @@ -19,7 +19,7 @@ type PseudoElem* = enum PSEUDO_NONE, PSEUDO_BEFORE, PSEUDO_AFTER, # internal - PSEUDO_INPUT_TEXT, PSEUDO_TEXTAREA_TEXT, PSEUDO_IMAGE + PSEUDO_INPUT_TEXT, PSEUDO_TEXTAREA_TEXT, PSEUDO_IMAGE, PSEUDO_NEWLINE PseudoClass* = enum PSEUDO_FIRST_CHILD, PSEUDO_LAST_CHILD, PSEUDO_ONLY_CHILD, PSEUDO_HOVER, diff --git a/src/css/values.nim b/src/css/values.nim index 874d82a0..f847b72b 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -35,7 +35,8 @@ type PROPERTY_RIGHT, PROPERTY_TOP, PROPERTY_BOTTOM, PROPERTY_CAPTION_SIDE, PROPERTY_BORDER_SPACING, PROPERTY_BORDER_COLLAPSE, PROPERTY_QUOTES, PROPERTY_COUNTER_RESET, PROPERTY_MAX_WIDTH, PROPERTY_MAX_HEIGHT, - PROPERTY_MIN_WIDTH, PROPERTY_MIN_HEIGHT, PROPERTY_BACKGROUND_IMAGE + PROPERTY_MIN_WIDTH, PROPERTY_MIN_HEIGHT, PROPERTY_BACKGROUND_IMAGE, + PROPERTY_CHA_COLSPAN, PROPERTY_CHA_ROWSPAN CSSValueType* = enum VALUE_NONE, VALUE_LENGTH, VALUE_COLOR, VALUE_CONTENT, VALUE_DISPLAY, @@ -102,7 +103,8 @@ type CSSContentType* = enum CONTENT_STRING, CONTENT_OPEN_QUOTE, CONTENT_CLOSE_QUOTE, - CONTENT_NO_OPEN_QUOTE, CONTENT_NO_CLOSE_QUOTE, CONTENT_IMAGE + CONTENT_NO_OPEN_QUOTE, CONTENT_NO_CLOSE_QUOTE, CONTENT_IMAGE, + CONTENT_NEWLINE const RowGroupBox* = {DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP, DISPLAY_TABLE_FOOTER_GROUP} @@ -250,7 +252,9 @@ const PropertyNames = { "max-height": PROPERTY_MAX_HEIGHT, "min-width": PROPERTY_MIN_WIDTH, "min-height": PROPERTY_MIN_HEIGHT, - "background-image": PROPERTY_BACKGROUND_IMAGE + "background-image": PROPERTY_BACKGROUND_IMAGE, + "-cha-colspan": PROPERTY_CHA_COLSPAN, + "-cha-rowspan": PROPERTY_CHA_ROWSPAN }.toTable() const ValueTypes* = [ @@ -294,7 +298,9 @@ const ValueTypes* = [ PROPERTY_MAX_HEIGHT: VALUE_LENGTH, PROPERTY_MIN_WIDTH: VALUE_LENGTH, PROPERTY_MIN_HEIGHT: VALUE_LENGTH, - PROPERTY_BACKGROUND_IMAGE: VALUE_IMAGE + PROPERTY_BACKGROUND_IMAGE: VALUE_IMAGE, + PROPERTY_CHA_COLSPAN: VALUE_INTEGER, + PROPERTY_CHA_ROWSPAN: VALUE_INTEGER ] const InheritedProperties = { @@ -856,6 +862,15 @@ func cssImage(cval: CSSComponentValue): Option[CSSContent] = if tok.tokenType == CSS_URL_TOKEN or tok.tokenType == CSS_BAD_URL_TOKEN: return some(CSSContent(t: CONTENT_IMAGE, s: "[img]")) +func cssInteger(cval: CSSComponentValue, range: Slice[int]): int = + if isToken(cval): + let tok = getToken(cval) + if tok.tokenType == CSS_NUMBER_TOKEN: + let i = int(tok.nvalue) + if float64(i) == tok.nvalue and i in range: + return i + raise newException(CSSValueError, "Invalid integer") + proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueType, ptype: CSSPropertyType) = var i = 0 d.value.skipWhitespace(i) @@ -891,6 +906,10 @@ proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueT of VALUE_INTEGER: if ptype == PROPERTY_FONT_WEIGHT: val.integer = cssFontWeight(cval) + elif ptype == PROPERTY_CHA_COLSPAN: + val.integer = cssInteger(cval, 1 .. 1000) + elif ptype == PROPERTY_CHA_ROWSPAN: + val.integer = cssInteger(cval, 0 .. 65534) of VALUE_TEXT_DECORATION: val.textdecoration = cssTextDecoration(d) of VALUE_WORD_BREAK: val.wordbreak = cssWordBreak(cval) of VALUE_LIST_STYLE_TYPE: val.liststyletype = cssListStyleType(cval) @@ -947,6 +966,14 @@ func getInitialLength(t: CSSPropertyType): CSSLength = else: return CSSLength(auto: false, unit: UNIT_PX, num: 0) +func getInitialInteger(t: CSSPropertyType): int = + case t + of PROPERTY_CHA_COLSPAN, PROPERTY_CHA_ROWSPAN: + return 1 + of PROPERTY_FONT_WEIGHT: + return 400 # normal + else: discard + func calcInitial(t: CSSPropertyType): CSSComputedValue = let v = valueType(t) var nv: CSSComputedValue @@ -959,6 +986,8 @@ func calcInitial(t: CSSPropertyType): CSSComputedValue = nv = CSSComputedValue(t: t, v: v, wordbreak: WORD_BREAK_NORMAL) of VALUE_LENGTH: nv = CSSComputedValue(t: t, v: v, length: getInitialLength(t)) + of VALUE_INTEGER: + nv = CSSComputedValue(t: t, v: v, integer: getInitialInteger(t)) of VALUE_QUOTES: nv = CSSComputedValue(t: t, v: v, quotes: CSSQuotes(auto: true)) else: diff --git a/src/layout/box.nim b/src/layout/box.nim index a436cfae..05df1ae6 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -50,7 +50,6 @@ type TableRowBoxBuilder* = ref object of BlockBoxBuilder TableCellBoxBuilder* = ref object of BlockBoxBuilder - colspan*: int TableBoxBuilder* = ref object of BlockBoxBuilder rowgroups*: seq[TableRowGroupBoxBuilder] diff --git a/src/layout/engine.nim b/src/layout/engine.nim index b26e0ebe..97b19f2b 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -6,8 +6,6 @@ import unicode import css/stylednode import css/values -import html/tags -import html/dom import io/window import layout/box import utils/twtstr @@ -844,15 +842,16 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B for child in box.children: assert child.computed{"display"} == DISPLAY_TABLE_CELL let cellbuilder = TableCellBoxBuilder(child) + let colspan = cellbuilder.computed{"-cha-colspan"} let cell = parent.viewport.buildTableCell(cellbuilder, parent.contentWidth, parent.contentHeight) - ctx.cells[i] = CellWrapper(box: cell, builder: cellbuilder, colspan: cellbuilder.colspan) - if pctx.cols.len < n + cellbuilder.colspan: - pctx.cols.setLen(n + cellbuilder.colspan) - if ctx.reflow.len < n + cellbuilder.colspan: - ctx.reflow.setLen(n + cellbuilder.colspan) - let minw = cell.xminwidth div cellbuilder.colspan - let w = cell.width div cellbuilder.colspan - for i in n ..< n + cellbuilder.colspan: + ctx.cells[i] = CellWrapper(box: cell, builder: cellbuilder, colspan: colspan) + if pctx.cols.len < n + colspan: + pctx.cols.setLen(n + colspan) + if ctx.reflow.len < n + colspan: + ctx.reflow.setLen(n + colspan) + let minw = cell.xminwidth div colspan + let w = cell.width div colspan + for i in n ..< n + colspan: ctx.width += pctx.inlinespacing pctx.cols[i].maxwidth = w if pctx.cols[i].width < w: @@ -878,7 +877,7 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B ctx.reflow[i] = true ctx.width += pctx.cols[i].width ctx.width += pctx.inlinespacing - n += cellbuilder.colspan + n += colspan inc i ctx.ncols = n return ctx @@ -1122,13 +1121,7 @@ proc buildRootBlock(viewport: Viewport, builder: BlockBoxBuilder) = # Returns a block box, disregarding the computed value of display proc getBlockBox(computed: CSSComputedValues): BlockBoxBuilder = new(result) - result.computed = computed.copyProperties() - result.computed{"display"} = DISPLAY_BLOCK - -proc getTextBox(box: BoxBuilder): InlineBoxBuilder = - new(result) - result.inlinelayout = true - result.computed = box.computed.inheritProperties() + result.computed = computed proc getTextBox(computed: CSSComputedValues): InlineBoxBuilder = new(result) @@ -1164,7 +1157,6 @@ proc getTableRowBox(computed: CSSComputedValues): TableRowBoxBuilder = proc getTableCellBox(computed: CSSComputedValues): TableCellBoxBuilder = new(result) result.computed = computed - result.colspan = 1 proc getTableCaptionBox(computed: CSSComputedValues): TableCaptionBoxBuilder = new(result) @@ -1193,7 +1185,9 @@ proc add(blockgroup: var BlockGroup, box: BoxBuilder) {.inline.} = proc flush(blockgroup: var BlockGroup) {.inline.} = if blockgroup.boxes.len > 0: assert blockgroup.parent.computed{"display"} != DISPLAY_INLINE - let bbox = getBlockBox(blockgroup.parent.computed.inheritProperties()) + let computed = blockgroup.parent.computed.inheritProperties() + computed{"display"} = DISPLAY_BLOCK + let bbox = getBlockBox(computed) bbox.inlinelayout = true bbox.children = blockgroup.boxes blockgroup.parent.children.add(bbox) @@ -1264,13 +1258,6 @@ proc flush(ctx: var InnerBlockContext) = proc generateFromElem(ctx: var InnerBlockContext, styledNode: StyledNode) = let box = ctx.blockgroup.parent - if styledNode.node != nil: - let elem = Element(styledNode.node) - if elem.tagType == TAG_BR: - ctx.iflush() - ctx.ibox = box.getTextBox() - ctx.ibox.newline = true - ctx.iflush() case styledNode.computed{"display"} of DISPLAY_BLOCK: @@ -1287,6 +1274,8 @@ proc generateFromElem(ctx: var InnerBlockContext, styledNode: StyledNode) = childbox.marker = nil else: childbox.content = ctx.generateBlockBox(styledNode) + childbox.content.computed = childbox.content.computed.copyProperties() + childbox.content.computed{"display"} = DISPLAY_BLOCK box.children.add(childbox) of DISPLAY_INLINE: ctx.iflush() @@ -1294,7 +1283,6 @@ proc generateFromElem(ctx: var InnerBlockContext, styledNode: StyledNode) = of DISPLAY_INLINE_BLOCK: ctx.iflush() let childbox = ctx.generateBlockBox(styledNode) - childbox.computed{"display"} = DISPLAY_INLINE_BLOCK ctx.blockgroup.add(childbox) of DISPLAY_TABLE: ctx.flush() @@ -1396,6 +1384,11 @@ proc generateReplacement(ctx: var InnerBlockContext, child, parent: StyledNode) of CONTENT_IMAGE: #TODO idk ctx.generateInlineText(child.content.s, parent) + of CONTENT_NEWLINE: + ctx.iflush() + ctx.ibox = parent.computed.getTextBox() + ctx.ibox.newline = true + ctx.iflush() proc generateInlineBoxes(ctx: var InnerBlockContext, styledNode: StyledNode) = for child in styledNode.children: @@ -1466,8 +1459,6 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none( proc generateTableCellBox(styledNode: StyledNode, viewport: Viewport, parent: var InnerBlockContext): TableCellBoxBuilder = let box = getTableCellBox(styledNode.computed) - if styledNode.node != nil and styledNode.node.nodeType == ELEMENT_NODE: - box.colspan = Element(styledNode.node).attri("colspan").get(1) var ctx = newInnerBlockContext(styledNode, box, viewport, addr parent) ctx.generateInnerBlockBox() ctx.flush() @@ -1545,7 +1536,7 @@ proc generateTableBox(styledNode: StyledNode, viewport: Viewport, parent: var In box.generateTableChildWrappers() return box -proc renderLayout*(viewport: var Viewport, document: Document, root: StyledNode) = +proc renderLayout*(viewport: var Viewport, root: StyledNode) = viewport.root.setLen(0) viewport.absolutes.setLen(0) let builder = root.generateBlockBox(viewport) diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim index a988cca7..cd6d7a0e 100644 --- a/src/render/renderdocument.nim +++ b/src/render/renderdocument.nim @@ -335,7 +335,7 @@ proc renderDocument*(document: Document, window: WindowAttributes, userstyle: CS uastyle = quirkstyle let styledNode = document.applyStylesheets(uastyle, userstyle, previousStyled) result[1] = styledNode - layout.renderLayout(document, styledNode) + layout.renderLayout(styledNode) result[0].setLen(0) for root in layout.root: result[0].renderBlockContext(root, 0, 0, window) |