Move xhtml rendering here
This commit is contained in:
parent
6ec86cfa27
commit
c9511f99db
|
@ -0,0 +1,101 @@
|
|||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import std/sequtils
|
||||
import pixie, pixie/systemtypefaces
|
||||
import svui
|
||||
|
||||
type Typesetting* = object
|
||||
h1, h2, h3, p: Font
|
||||
|
||||
proc newFont(typeface: Typeface, size: float32): Font =
|
||||
result = newFont(typeface)
|
||||
result.size = size
|
||||
|
||||
proc initTypesetting*(): Typesetting =
|
||||
let typeface = readTypeface findSystemTypeface(family = "Gentium Plus")
|
||||
result.h1 = newFont(typeface, 24)
|
||||
result.h2 = newFont(typeface, 20)
|
||||
result.h3 = newFont(typeface, 16)
|
||||
result.p = newFont(typeface, 12)
|
||||
|
||||
proc body(xhtml: Xhtml): XmlElement =
|
||||
for e in xhtml.elements:
|
||||
if e.orKind == XmlNodeKind.`XmlElement` and e.xmlElement.name == "body":
|
||||
return e.xmlElement
|
||||
raise newException(ValueError, "no body in XHTML document")
|
||||
|
||||
proc name(node: XmlNode): string = node.xmlElement.name
|
||||
|
||||
proc text(node: XmlNode): string =
|
||||
case node.orKind
|
||||
of XmlNodeKind.XmlElement:
|
||||
for e in node.xmlElement.elements:
|
||||
result.add e.text
|
||||
of XmlNodeKind.XmlText:
|
||||
result.add node.xmlText.data
|
||||
|
||||
func height(arr: Arrangement): float =
|
||||
if arr.positions.len > 0: result = arr.positions[arr.positions.high].y
|
||||
|
||||
proc add(result: var Arrangement; other: sink Arrangement) =
|
||||
if result.lines.len == 0:
|
||||
result = other
|
||||
else:
|
||||
let runeOff = result.runes.len
|
||||
add(result.lines, map(other.lines,
|
||||
proc (x: (int, int)): (int, int) = (x[0]+runeOff, x[1]+runeOff)))
|
||||
add(result.spans, map(other.spans,
|
||||
proc (x: (int, int)): (int, int) = (x[0]+runeOff, x[1]+runeOff)))
|
||||
add(result.fonts, other.fonts)
|
||||
add(result.runes, other.runes)
|
||||
let yOff = result.positions[result.positions.high].y
|
||||
add(result.positions,
|
||||
map(other.positions,
|
||||
proc(pos: Vec2): Vec2 = vec2(pos.x, pos.y + yOff)))
|
||||
add(result.selectionRects,
|
||||
map(other.selectionRects,
|
||||
proc(rect: Rect): Rect = rect(rect.x, rect.y + yOff, rect.w, rect.h)))
|
||||
|
||||
proc render*(ts: Typesetting; xhtml: Xhtml): Image =
|
||||
# TODO: render by font size, not by wh
|
||||
var wh = computeBounds(ts.p, "X")
|
||||
wh.x = wh.x * 80
|
||||
wh.y = wh.y * 50
|
||||
let margin = wh / 9.0
|
||||
var
|
||||
printSpace = wh * (7.0 / 9.0)
|
||||
pages = @[Arrangement()]
|
||||
|
||||
proc pageEnd(): float =
|
||||
let
|
||||
pi = pages.high
|
||||
li = pages[pi].lines.high
|
||||
ci = pages[pi].lines[li][1]
|
||||
pages[pi].positions[ci].y
|
||||
|
||||
proc append(span: Span) =
|
||||
var arr = typeset(@[span], printSpace)
|
||||
if pages[pages.high].height + arr.height < printSpace.y:
|
||||
pages[pages.high].add arr
|
||||
else:
|
||||
discard
|
||||
|
||||
for e in xhtml.body.elements:
|
||||
let tag = e.name
|
||||
case tag
|
||||
of "h1":
|
||||
append newSpan(e.text & "\n", ts.h1)
|
||||
of "h2":
|
||||
append newSpan("\n" & e.text & "\n", ts.h2)
|
||||
of "h3":
|
||||
append newSpan("\n" & e.text & "\n", ts.h3)
|
||||
of "p":
|
||||
append newSpan(" " & e.text & "\n\n", ts.p)
|
||||
else:
|
||||
discard
|
||||
# raise newException(ValueError, "unhandled element in XHTML :" & tag)
|
||||
|
||||
result = newImage(int wh.x, int wh.y)
|
||||
fill(result, rgba(255, 255, 255, 255))
|
||||
fillText(result, pages[0], translate(margin))
|
|
@ -11,8 +11,8 @@ import nimsvg
|
|||
import bumpy, pixie, pixie/fileformats/svg
|
||||
|
||||
import sdl2
|
||||
|
||||
import svui, svui/render/xhtml
|
||||
import svui
|
||||
import ./private/render/xhtml
|
||||
|
||||
type
|
||||
Svui = svui.Svui[Ref]
|
||||
|
|
Loading…
Reference in New Issue