module Data.Text.ParagraphLayout.Internal.BoxOptions ( BoxCollapse (..) , BoxOptions (..) , BoxSpacing (..) , VerticalAlignment (..) , 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. -- -- In order to get CSS defaults, use: -- -- > defaultBoxOptions { boxVerticalAlignment = AlignBaseline 0 } 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. , boxVerticalAlignment :: VerticalAlignment -- ^ Determines how fragments are aligned vertically within a line. } 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) -- | Determines how the contents of a line should be aligned vertically, -- that is, how fragments should fill (and possibly extend) the vertical space -- inside a line. -- -- Vertical alignment takes place after line breaking. data VerticalAlignment = AlignLineTop -- ^ Align the top of this box with the top of the line. -- -- The /top of this box/ is the topmost coordinate of any fragment -- descended from this box, except for fragments that are descended from -- another box with `AlignLineTop` or `AlignLineBottom` closer to them. -- -- t`Data.Text.ParagraphLayout.Rich.LineHeight` is included -- when considering the /top/ coordinates of descended fragments, -- and thus, leading is included. -- -- This behaviour is equivalent to @vertical-align: top@ in CSS. | AlignLineBottom -- ^ Align the bottom of this box with the bottom of the line. -- -- The /bottom of this box/ is the bottommost coordinate of any fragment -- descended from this box, except for fragments that are descended from -- another box with `AlignLineTop` or `AlignLineBottom` closer to them. -- -- t`Data.Text.ParagraphLayout.Rich.LineHeight` is included -- when considering the /bottom/ coordinates of descended fragments, -- and thus, leading is included. -- -- This behaviour is equivalent to @vertical-align: bottom@ in CSS. | AlignBaseline Int32 -- ^ Align the baseline of this box with the baseline of its parent box, -- optionally shifting it by a specified amount upwards. -- -- @`AlignBaseline` 0@ is equivalent to @vertical-align: baseline@ in CSS. -- -- @`AlignBaseline` x@ is equivalent to @vertical-align: \@ in CSS, -- after an appropriate unit conversion. deriving (Eq, Read, Show) -- | `BoxOptions` with backwards-compatible values. -- -- Note that this sets `boxVerticalAlignment` to `AlignLineTop`, -- whereas the CSS default should be `AlignBaseline 0`. defaultBoxOptions :: BoxOptions defaultBoxOptions = BoxOptions { boxSpacing = BoxSpacingLeftRight 0 0 , boxCollapse = AllowBoxCollapse , boxVerticalAlignment = AlignLineTop } -- | 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 }