about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css/cssparser.nim7
-rw-r--r--src/css/values.nim45
-rw-r--r--src/render/renderdocument.nim48
3 files changed, 68 insertions, 32 deletions
diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim
index 864119ea..9c8328de 100644
--- a/src/css/cssparser.nim
+++ b/src/css/cssparser.nim
@@ -81,8 +81,10 @@ proc `$`*(c: CSSParsedItem): string =
   if c of CSSToken:
     let c = CSSToken(c)
     case c.tokenType:
-    of CSS_FUNCTION_TOKEN, CSS_AT_KEYWORD_TOKEN, CSS_URL_TOKEN:
+    of CSS_FUNCTION_TOKEN, CSS_AT_KEYWORD_TOKEN:
       result &= $c.tokenType & c.value & '\n'
+    of CSS_URL_TOKEN:
+      result &= "url(" & c.value & ")"
     of CSS_HASH_TOKEN:
       result &= '#' & c.value
     of CSS_IDENT_TOKEN:
@@ -372,7 +374,8 @@ proc consumeIdentLikeToken(state: var CSSTokenizerState): CSSToken =
     discard state.consume()
     while state.has(1) and state.peek().isWhitespace() and state.peek(1).isWhitespace():
       discard state.consume()
-    if state.has(1) and state.peek() in {'"', '\''} + AsciiWhitespace and state.peek(1) in {'"', '\''}:
+    if state.has() and state.peek() in {'"', '\''} or
+        state.has(1) and state.peek() in {'"', '\''} + AsciiWhitespace and state.peek(1) in {'"', '\''}:
       return CSSToken(tokenType: CSS_FUNCTION_TOKEN, value: s)
     else:
       return state.consumeURL()
diff --git a/src/css/values.nim b/src/css/values.nim
index 5e5d807c..5916bc89 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -335,6 +335,11 @@ func `$`*(val: CSSComputedValue): string =
   case val.v
   of VALUE_COLOR:
     result &= $val.color
+  of VALUE_IMAGE:
+    if val.image.s != "":
+      result &= "url(" & val.image.s & ")"
+    else:
+      result &= "none"
   else: discard
 
 macro `{}`*(vals: CSSComputedValues, s: string): untyped =
@@ -868,12 +873,36 @@ func cssMaxMinSize(cval: CSSComponentValue): CSSLength =
     else: discard
   raise newException(CSSValueError, "Invalid min/max-size")
 
-#TODO this should be a separate type
+#TODO should be URL (parsed with baseurl of document...)
+func cssURL(cval: CSSComponentValue): Option[string] =
+  if isToken(cval):
+    let tok = getToken(cval)
+    if tok == CSS_URL_TOKEN:
+      return some(tok.value)
+  elif cval of CSSFunction:
+    let fun = CSSFunction(cval)
+    if fun.name == "url" or fun.name == "src":
+      for x in fun.value:
+        if not isToken(x):
+          break
+        let x = getToken(x)
+        if x == CSS_WHITESPACE_TOKEN:
+          discard
+        elif x == CSS_STRING_TOKEN:
+          return some(x.value)
+        else:
+          break
+
+#TODO this should be bg-image, add gradient, etc etc
 func cssImage(cval: CSSComponentValue): CSSContent =
   if isToken(cval):
+    #TODO bg-image only
     let tok = getToken(cval)
-    if tok.tokenType == CSS_URL_TOKEN or tok.tokenType == CSS_BAD_URL_TOKEN:
-      return CSSContent(t: CONTENT_IMAGE, s: "[img]")
+    if tok.tokenType == CSS_IDENT_TOKEN and tok.value == "none":
+      return CSSContent(t: CONTENT_IMAGE, s: "")
+  let url = cssURL(cval)
+  if url.isSome:
+    return CSSContent(t: CONTENT_IMAGE, s: url.get)
   raise newException(CSSValueError, "Invalid image")
 
 func cssInteger(cval: CSSComponentValue, range: Slice[int]): int =
@@ -939,7 +968,7 @@ proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueT
       val.length2.b = cssAbsoluteLength(cval)
   of VALUE_QUOTES: val.quotes = cssQuotes(d)
   of VALUE_COUNTER_RESET: val.counterreset = cssCounterReset(d)
-  of VALUE_IMAGE: val.image = cssImage(d)
+  of VALUE_IMAGE: val.image = cssImage(cval)
   of VALUE_NONE: discard
 
 func getInitialColor(t: CSSPropertyType): RGBAColor =
@@ -1100,12 +1129,16 @@ proc getComputedValues(d: CSSDeclaration): seq[(CSSComputedValue, CSSGlobalValue
     let bgimageval = CSSComputedValue(t: bgimageptype, v: valueType(bgimageptype))
     if global == VALUE_NOGLOBAL:
       for tok in d.value:
+        if tok == CSS_WHITESPACE_TOKEN:
+          continue
         try:
-          bgimageval.image = cssImage(tok)
+          let img = cssImage(tok)
+          bgimageval.image = img
           result.add((bgimageval, global))
         except CSSValueError:
           try:
-            bgcolorval.color = cssColor(tok)
+            let color = cssColor(tok)
+            bgcolorval.color = color
             result.add((bgcolorval, global))
           except CSSValueError:
             discard
diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim
index e2aa1b0e..1d4c28f1 100644
--- a/src/render/renderdocument.nim
+++ b/src/render/renderdocument.nim
@@ -278,7 +278,7 @@ func calculateErrorY(ctx: InlineContext, window: WindowAttributes): int =
       error += dy - (dy div window.ppl) * window.ppl
   return error div (ctx.lines.len - 1)
 
-proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockBox, x, y: int, window: WindowAttributes)
+proc renderBlockBox(grid: var FlexibleGrid, box: BlockBox, x, y: int, window: WindowAttributes)
 
 proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int, window: WindowAttributes) =
   let x = x + ctx.offset.x
@@ -297,7 +297,7 @@ proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int,
     for atom in line.atoms:
       if atom of InlineBlockBox:
         let iblock = InlineBlockBox(atom)
-        grid.renderBlockContext(iblock.innerbox, x + iblock.offset.x, y + iblock.offset.y, window)
+        grid.renderBlockBox(iblock.innerbox, x + iblock.offset.x, y + iblock.offset.y, window)
       elif atom of InlineWord:
         let word = InlineWord(atom)
         grid.setRowWord(word, x, y, window)
@@ -306,42 +306,42 @@ proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int,
         grid.setSpacing(spacing, x, y, window)
     inc i
 
-proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockBox, x, y: int, window: WindowAttributes) =
+proc renderBlockBox(grid: var FlexibleGrid, box: BlockBox, x, y: int, window: WindowAttributes) =
   var stack = newSeqOfCap[(BlockBox, int, int)](100)
-  stack.add((ctx, x, y))
+  stack.add((box, x, y))
 
   while stack.len > 0:
-    var (ctx, x, y) = stack.pop()
-    x += ctx.offset.x
-    y += ctx.offset.y
+    var (box, x, y) = stack.pop()
+    x += box.offset.x
+    y += box.offset.y
 
-    if ctx.computed{"background-color"}.a != 0: #TODO color blending
-      grid.paintBackground(ctx.computed{"background-color"}, x, y, x + ctx.width, y + ctx.height, ctx.node, window)
-    if ctx.computed{"background-image"}.t == CONTENT_IMAGE:
+    if box.computed{"background-color"}.a != 0: #TODO color blending
+      grid.paintBackground(box.computed{"background-color"}, x, y, x + box.width, y + box.height, box.node, window)
+    if box.computed{"background-image"}.t == CONTENT_IMAGE and box.computed{"background-image"}.s != "":
       # ugly hack for background-image display... TODO actually display images
-      let s = ctx.computed{"background-image"}.s # [img]
+      let s = "[img]"
       let w = s.len * window.ppc
       var x = x
-      if ctx.width < w:
+      if box.width < w:
         # text is larger than image; center it to minimize error
         x -= w div 2
-        x += ctx.width div 2
+        x += box.width div 2
       x = x div window.ppc
       y = y div window.ppl
       if y >= 0 and x + w >= 0:
-        grid.setText(s, ComputedFormat(node: ctx.node), x, y)
+        grid.setText(s, ComputedFormat(node: box.node), x, y)
 
-    if ctx of ListItemBox:
-      let ctx = ListItemBox(ctx)
-      if ctx.marker != nil:
-        grid.renderInlineContext(ctx.marker, x - ctx.marker.width, y, window)
+    if box of ListItemBox:
+      let box = ListItemBox(box)
+      if box.marker != nil:
+        grid.renderInlineContext(box.marker, x - box.marker.width, y, window)
 
-    if ctx.inline != nil:
-      assert ctx.nested.len == 0
-      grid.renderInlineContext(ctx.inline, x, y, window)
+    if box.inline != nil:
+      assert box.nested.len == 0
+      grid.renderInlineContext(box.inline, x, y, window)
     else:
-      for i in countdown(ctx.nested.high, 0):
-        stack.add((ctx.nested[i], x, y))
+      for i in countdown(box.nested.high, 0):
+        stack.add((box.nested[i], x, y))
 
 const css = staticRead"res/ua.css"
 let uastyle = css.parseStylesheet()
@@ -356,6 +356,6 @@ proc renderDocument*(document: Document, window: WindowAttributes, userstyle: CS
   layout.renderLayout(styledNode)
   result[0].setLen(0)
   for root in layout.root:
-    result[0].renderBlockContext(root, 0, 0, window)
+    result[0].renderBlockBox(root, 0, 0, window)
   if result[0].len == 0:
     result[0].addLine()