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
module Data.Text.ParagraphLayout.Internal.BoxOptions
( BoxCollapse (..)
, BoxOptions (..)
, BoxSpacing (..)
, activateBoxSpacing
, defaultBoxOptions
)
where
import Data.Int (Int32)
-- | Style options to be applied to an inline box.
--
-- This record type is likely to be extended in the future.
-- Use `defaultBoxOptions` and update it with specific record selectors
-- instead of constructing `BoxOptions` directly.
data BoxOptions = BoxOptions
{ boxSpacing :: BoxSpacing
-- ^ Determines amount of empty space to add before the first fragment
-- and/or after the last fragment of this box.
--
-- This can be used to reserve space for a left margin, border,
-- and/or padding.
--
-- In order to get CSS-compliant behaviour, consider using
-- `activateBoxSpacing` instead.
, boxCollapse :: BoxCollapse
-- ^ Determines how this box affects the height of a line that would
-- otherwise be empty.
-- TODO: textVerticalAlign
}
deriving (Eq)
-- | Determines the amount of empty space to add around a box.
data BoxSpacing
-- | Specification using absolute directions, unaffected by text direction.
--
-- (However, text direction is still used in case of fragmentation,
-- to determine how to map the first (last) fragment to left (right).)
= BoxSpacingLeftRight
Int32
-- ^ Amount of empty space to add to the left side of the
-- first fragment (for LTR text) or last fragment (for RTL text)
-- created from this box.
Int32
-- ^ Amount of empty space to add to the right side of the
-- first fragment (for RTL text) or last fragment (for LTR text)
-- created from this box.
deriving (Eq, Show, Read)
-- | Determines how an inline box affects the height of a line that would
-- otherwise be empty.
--
-- Note that for this setting to have any effect, the box must be the ancestor
-- of at least one (possibly empty) text sequence, so that it can generate
-- a `Data.Text.ParagraphLayout.Rich.Fragment`.
--
-- For CSS-compliant behaviour:
--
-- - Ensure that empty boxes contain empty text sequences as mentioned above.
-- This can be achieved using the `Data.Text.ParagraphLayout.Rich.strut`
-- function.
--
-- - Set `AllowBoxCollapse` for boxes with zero margins, padding,
-- and borders.
--
-- - Set `AvoidBoxCollapse` for boxes with non-zero margins, padding,
-- or borders.
--
-- Note that `BoxSpacing` may contain zero values even when calculated from
-- non-zero CSS values, because of rounding to integer values and/or because
-- of adding together positive and negative values that cancel out. You should
-- therefore compare the individual computed values for margins, padding, and
-- borders with zero, and set `boxCollapse` to `AllowBoxCollapse` if and only
-- if all these values are equal to zero.
data BoxCollapse
= AllowBoxCollapse
-- ^ The box should disappear when possible to make empty lines invisible.
| AvoidBoxCollapse
-- ^ The box should be preserved when possible, making lines visible
-- even when they would otherwise be empty.
deriving (Eq, Read, Show)
-- | `BoxOptions` with default values.
defaultBoxOptions :: BoxOptions
defaultBoxOptions = BoxOptions
{ boxSpacing = BoxSpacingLeftRight 0 0
, boxCollapse = AllowBoxCollapse
}
-- | Shorthand for updating `boxSpacing` and setting `boxCollapse`
-- to `AvoidBoxCollapse`.
--
-- Can be used to activate CSS-compliant rendering of empty boxes whose
-- spacing is calculated from non-zero values.
activateBoxSpacing :: BoxSpacing -> BoxOptions -> BoxOptions
activateBoxSpacing spacing boxOptions = boxOptions
{ boxSpacing = spacing
, boxCollapse = AvoidBoxCollapse
}