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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
import css/cssvalues
import css/stylednode
import types/bitmap
import layout/layoutunit
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
RootInlineFragmentState* = object
# offset relative to parent
offset*: Offset
# padding size
size*: Size
# overflow relative to offset
overflow*: Overflow
# minimum content width
xminwidth*: LayoutUnit
# baseline of the first line box
firstBaseline*: LayoutUnit
# baseline of the last line box
baseline*: LayoutUnit
RootInlineFragment* = ref object
fragment*: InlineFragment # root fragment
state*: RootInlineFragmentState
SplitType* = enum
stSplitStart, stSplitEnd
Area* = object
offset*: Offset
size*: Size
InlineFragmentState* = object
startOffset*: Offset # offset of the first word, for position: absolute
areas*: seq[Area] # background that should be painted by fragment
atoms*: seq[InlineAtom]
InlineFragmentType* = enum
iftParent, iftText, iftNewline, iftBitmap, iftBox
InlineFragment* = ref object
state*: InlineFragmentState
computed*: CSSComputedValues
node*: StyledNode
splitType*: set[SplitType]
case t*: InlineFragmentType
of iftParent:
children*: seq[InlineFragment]
of iftText:
text*: StyledNode # note: this has no parent.
of iftNewline:
discard
of iftBitmap:
bmp*: NetworkBitmap
of iftBox:
box*: BlockBox
Span* = object
start*: LayoutUnit
send*: LayoutUnit
RelativeRect* = array[DimensionType, Span]
BlockBoxLayoutState* = object
# offset relative to parent
offset*: Offset
# padding size
size*: Size
margin*: RelativeRect #TODO get rid of this?
positioned*: RelativeRect #TODO ditto
# overflow relative to offset
overflow*: Overflow
# minimum content width (usually shortest word)
xminwidth*: LayoutUnit
# baseline of the first line box of all descendants
firstBaseline*: LayoutUnit
# baseline of the last line box of all descendants
baseline*: LayoutUnit
BlockBox* = ref object
state*: BlockBoxLayoutState
computed*: CSSComputedValues
node*: StyledNode
inline*: RootInlineFragment
nested*: 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
|