1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
import css/cssvalues
import css/lunit
import css/stylednode
import types/bitmap
type
DimensionType* = enum
dtHorizontal, dtVertical
Offset* = array[DimensionType, LayoutUnit]
Size* = array[DimensionType, LayoutUnit]
Overflow* = array[DimensionType, Span]
InlineAtomType* = enum
iatWord, iatInlineBlock, iatImage
InlineAtom* = ref object
offset*: Offset
size*: Size
case t*: InlineAtomType
of iatWord:
str*: string
of iatInlineBlock:
innerbox*: BlockBox
of iatImage:
bmp*: NetworkBitmap
BoxLayoutState* = object
# offset relative to parent
offset*: Offset
# padding size
size*: Size
# overflow relative to offset
overflow*: Overflow
# intrinsic minimum size (e.g. longest word)
intr*: Size
# baseline of the first line box of all descendants
firstBaseline*: LayoutUnit
# baseline of the last line box of all descendants
baseline*: LayoutUnit
SplitType* = enum
stSplitStart, stSplitEnd
Area* = object
offset*: Offset
size*: Size
InlineBoxState* = object
startOffset*: Offset # offset of the first word, for position: absolute
areas*: seq[Area] # background that should be painted by box
atoms*: seq[InlineAtom]
InlineBoxType* = enum
ibtParent, ibtText, ibtNewline, ibtBitmap, ibtBox
InlineBox* = ref object
state*: InlineBoxState
render*: BoxRenderState
computed*: CSSValues
node*: StyledNode
splitType*: set[SplitType]
case t*: InlineBoxType
of ibtParent:
children*: seq[InlineBox]
of ibtText:
text*: StyledNode # note: this has no parent.
of ibtNewline:
discard
of ibtBitmap:
bmp*: NetworkBitmap
of ibtBox:
box*: BlockBox
Span* = object
start*: LayoutUnit
send*: LayoutUnit
RelativeRect* = array[DimensionType, Span]
BoxRenderState* = object
offset*: Offset
BlockBox* = ref object
state*: BoxLayoutState
render*: BoxRenderState
computed*: CSSValues
node*: StyledNode
inline*: InlineBox
children*: seq[BlockBox]
func offset*(x, y: LayoutUnit): Offset =
return [dtHorizontal: x, dtVertical: y]
func x*(offset: Offset): LayoutUnit {.inline.} =
return offset[dtHorizontal]
func x*(offset: var Offset): var LayoutUnit {.inline.} =
return offset[dtHorizontal]
func `x=`*(offset: var Offset; x: LayoutUnit) {.inline.} =
offset[dtHorizontal] = x
func y*(offset: Offset): LayoutUnit {.inline.} =
return offset[dtVertical]
func y*(offset: var Offset): var LayoutUnit {.inline.} =
return offset[dtVertical]
func `y=`*(offset: var Offset; y: LayoutUnit) {.inline.} =
offset[dtVertical] = y
func size*(w, h: LayoutUnit): Size =
return [dtHorizontal: w, dtVertical: h]
func w*(size: Size): LayoutUnit {.inline.} =
return size[dtHorizontal]
func w*(size: var Size): var LayoutUnit {.inline.} =
return size[dtHorizontal]
func `w=`*(size: var Size; w: LayoutUnit) {.inline.} =
size[dtHorizontal] = w
func h*(size: Size): LayoutUnit {.inline.} =
return size[dtVertical]
func h*(size: var Size): var LayoutUnit {.inline.} =
return size[dtVertical]
func `h=`*(size: var Size; h: LayoutUnit) {.inline.} =
size[dtVertical] = h
func `+`*(a, b: Offset): Offset =
return offset(x = a.x + b.x, y = a.y + b.y)
func `-`*(a, b: Offset): Offset =
return offset(x = a.x - b.x, y = a.y - b.y)
proc `+=`*(a: var Offset; b: Offset) =
a.x += b.x
a.y += b.y
proc `-=`*(a: var Offset; b: Offset) =
a.x -= b.x
a.y -= b.y
func left*(s: RelativeRect): LayoutUnit =
return s[dtHorizontal].start
func right*(s: RelativeRect): LayoutUnit =
return s[dtHorizontal].send
func top*(s: RelativeRect): LayoutUnit =
return s[dtVertical].start
func bottom*(s: RelativeRect): LayoutUnit =
return s[dtVertical].send
proc `+=`*(span: var Span; u: LayoutUnit) =
span.start += u
span.send += u
|