M lib/Data/Text/ParagraphLayout/Rich.hs => lib/Data/Text/ParagraphLayout/Rich.hs +7 -1
@@ 5,7 5,13 @@ module Data.Text.ParagraphLayout.Rich
-- * Input paragraph
( Paragraph (Paragraph)
, constructParagraph
- , ParagraphAlignment (AlignLeft, AlignRight, AlignCentreH)
+ , ParagraphAlignment
+ ( AlignStart
+ , AlignEnd
+ , AlignLeft
+ , AlignRight
+ , AlignCentreH
+ )
, BoxSpacing (BoxSpacingLeftRight)
, LineHeight (Absolute, Normal)
, ParagraphOptions
M src/Data/Text/ParagraphLayout/Internal/Layout.hs => src/Data/Text/ParagraphLayout/Internal/Layout.hs +25 -5
@@ 121,7 121,7 @@ positionLineH dir align maxWidth originY (num, pl) = (nextY, frags)
wpfs = PL.applyBoxes pl
originX = paragraphOriginX + if lineWidth > maxWidth
then overflowingLineOffset dir (lineWidth - maxWidth)
- else fittingLineOffset align (maxWidth - lineWidth)
+ else fittingLineOffset align dir (maxWidth - lineWidth)
lineWidth = PL.width pl
-- | Inline offset of the first fragment on a line that overflows.
@@ 133,10 133,30 @@ overflowingLineOffset DirRTL excess = -excess
overflowingLineOffset DirBTT excess = -excess
-- | Inline offset of the first fragment on a line with extra blank space.
-fittingLineOffset :: ParagraphAlignment -> Int32 -> Int32
-fittingLineOffset AlignLeft _ = 0
-fittingLineOffset AlignRight slack = slack
-fittingLineOffset AlignCentreH slack = slack `div` 2
+fittingLineOffset :: ParagraphAlignment -> Direction -> Int32 -> Int32
+fittingLineOffset AlignLeft _ = leftAlignOffset
+fittingLineOffset AlignRight _ = rightAlignOffset
+fittingLineOffset AlignCentreH _ = centreAlignOffset
+fittingLineOffset AlignStart DirLTR = leftAlignOffset
+fittingLineOffset AlignEnd DirLTR = rightAlignOffset
+fittingLineOffset AlignStart DirRTL = rightAlignOffset
+fittingLineOffset AlignEnd DirRTL = leftAlignOffset
+-- For completeness, treat vertical directions as horizontal directions
+-- rotated 90° clockwise, thus left becomes top and right becomes bottom.
+-- TODO: Verify this when vertical text is implemented.
+fittingLineOffset AlignStart DirTTB = leftAlignOffset
+fittingLineOffset AlignEnd DirTTB = rightAlignOffset
+fittingLineOffset AlignStart DirBTT = rightAlignOffset
+fittingLineOffset AlignEnd DirBTT = leftAlignOffset
+
+leftAlignOffset :: Int32 -> Int32
+leftAlignOffset _ = 0
+
+rightAlignOffset :: Int32 -> Int32
+rightAlignOffset slack = slack
+
+centreAlignOffset :: Int32 -> Int32
+centreAlignOffset slack = slack `div` 2
-- | Position the given horizontal fragment on a line,
-- using @originY@ as its top edge and @originX@ as its left edge,
M src/Data/Text/ParagraphLayout/Internal/ParagraphAlignment.hs => src/Data/Text/ParagraphLayout/Internal/ParagraphAlignment.hs +9 -1
@@ 10,7 10,15 @@ where
-- This has no effect on lines with overflowing content.
data ParagraphAlignment
- = AlignLeft
+ = AlignStart
+ -- ^ Behave like `AlignLeft` when the base direction of the paragraph
+ -- is LTR, and like `AlignRight` when the base direction is RTL.
+
+ | AlignEnd
+ -- ^ Behave like `AlignLeft` when the base direction of the paragraph
+ -- is RTL, and like `AlignRight` when the base direction is LTR.
+
+ | AlignLeft
-- ^ Stack fragments to the left edge of each line,
-- leaving free space on the right side.
--
M src/Data/Text/ParagraphLayout/Internal/ParagraphOptions.hs => src/Data/Text/ParagraphLayout/Internal/ParagraphOptions.hs +8 -1
@@ 15,6 15,10 @@ import Data.Text.ParagraphLayout.Internal.ParagraphAlignment
-- This record type is likely to be extended in the future.
-- Use `defaultParagraphOptions` and update it with specific record selectors
-- instead of constructing `ParagraphOptions` directly.
+--
+-- In order to get CSS defaults, use:
+--
+-- > defaultParagraphOptions { paragraphAlignment = AlignStart }
data ParagraphOptions = ParagraphOptions
{ paragraphFont :: Font
@@ 38,7 42,10 @@ data ParagraphOptions = ParagraphOptions
}
deriving (Eq)
--- | `ParagraphOptions` with default values.
+-- | `ParagraphOptions` with backwards-compatible values.
+--
+-- Note that this sets `paragraphAlignment` to `AlignLeft`,
+-- whereas the CSS default should be `AlignStart`.
defaultParagraphOptions :: ParagraphOptions
defaultParagraphOptions = ParagraphOptions
{ paragraphFont = emptyFont
M src/Data/Text/ParagraphLayout/Internal/Rich.hs => src/Data/Text/ParagraphLayout/Internal/Rich.hs +4 -0
@@ 33,6 33,10 @@ layoutRich p = paragraphLayout $ map unwrap frags
Just xs -> layoutAndAlignLines dir align maxWidth xs
Nothing -> []
wrappedRuns = spansToRunsWrapped spans
+ -- TODO: To support @unicode-bidi: plaintext@ as in CSS, allow ignoring
+ -- the text direction of the root box, and instead use the BiDi
+ -- rules P2 and P3 to determine the base directionality, which
+ -- may differ between lines.
dir = textDirection rootTextOpts
align = paragraphAlignment opts
maxWidth = paragraphMaxWidth opts