~jaro/balkon

d5807a8ebe4763c4fbdf157357e16eae70ff0f00 — Jaro 11 months ago 882dd63
Add tests for mixed text direction.
A .golden/richParagraphLayout/mixedDirectionComplexLTR.golden => .golden/richParagraphLayout/mixedDirectionComplexLTR.golden +137 -0
@@ 0,0 1,137 @@
ParagraphLayout
    { paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 20949, y_size = -1500}
    , paragraphFragments =
        [ Fragment
            { fragmentUserData = "text1"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 5748, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 90, cluster = 7, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 8, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 9, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 10, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 11, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 6, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 580, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 16, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 17, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 6, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 580, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 19, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 20, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 21, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 22, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 23, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 24, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                [ AncestorBox {boxUserData = "box1", boxLeftEdge = SpacedEdge 0, boxRightEdge = NoEdge, boxStartEdge = SpacedEdge 0, boxEndEdge = NoEdge}
                ]
            , fragmentRect = Rect {x_origin = 5748, y_origin = 0, x_size = 1252, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 3, cluster = 25, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 26, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 27, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 28, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 29, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                [ AncestorBox {boxUserData = "box1", boxLeftEdge = NoEdge, boxRightEdge = NoEdge, boxStartEdge = NoEdge, boxEndEdge = NoEdge}
                ]
            , fragmentRect = Rect {x_origin = 7000, y_origin = 0, x_size = 4090, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 3, cluster = 47, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 46, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 45, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 44, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 43, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 293, cluster = 41, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 270, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 389, cluster = 39, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 38, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 37, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 36, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 35, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 34, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 512, cluster = 32, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 839, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 286, cluster = 30, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 224, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                [ AncestorBox {boxUserData = "box1", boxLeftEdge = NoEdge, boxRightEdge = SpacedEdge 0, boxStartEdge = NoEdge, boxEndEdge = SpacedEdge 0}
                ]
            , fragmentRect = Rect {x_origin = 11090, y_origin = 0, x_size = 4342, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 26, cluster = 48, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 351, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 27, cluster = 49, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 50, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 51, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 52, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 53, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 54, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 27, cluster = 55, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 26, cluster = 56, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 351, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 57, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 58, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 59, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 60, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 61, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text3"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 15432, y_origin = 0, x_size = 1252, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 3, cluster = 62, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 63, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 64, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 65, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 66, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text3"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 16684, y_origin = 0, x_size = 4265, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 90, cluster = 83, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 82, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 81, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 80, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 517, cluster = 78, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 839, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 955, cluster = 76, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 455, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 75, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 74, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 73, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 72, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 71, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 971, cluster = 69, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 450, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 394, cluster = 67, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        ]
    }

A .golden/richParagraphLayout/mixedDirectionComplexRTL.golden => .golden/richParagraphLayout/mixedDirectionComplexRTL.golden +137 -0
@@ 0,0 1,137 @@
ParagraphLayout
    { paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 20949, y_size = -1500}
    , paragraphFragments =
        [ Fragment
            { fragmentUserData = "text3"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 4265, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 90, cluster = 83, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 82, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 81, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 80, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 517, cluster = 78, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 839, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 955, cluster = 76, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 455, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 75, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 74, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 73, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 72, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 71, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 971, cluster = 69, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 450, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 394, cluster = 67, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                [ AncestorBox {boxUserData = "box1", boxLeftEdge = SpacedEdge 0, boxRightEdge = NoEdge, boxStartEdge = NoEdge, boxEndEdge = SpacedEdge 0}
                ]
            , fragmentRect = Rect {x_origin = 4265, y_origin = 0, x_size = 4342, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 26, cluster = 48, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 351, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 27, cluster = 49, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 50, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 51, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 52, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 53, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 54, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 27, cluster = 55, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 26, cluster = 56, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 351, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 57, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 58, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 59, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 60, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 61, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text3"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 8607, y_origin = 0, x_size = 1252, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 3, cluster = 62, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 63, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 64, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 65, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 66, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                [ AncestorBox {boxUserData = "box1", boxLeftEdge = NoEdge, boxRightEdge = NoEdge, boxStartEdge = NoEdge, boxEndEdge = NoEdge}
                ]
            , fragmentRect = Rect {x_origin = 9859, y_origin = 0, x_size = 4090, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 3, cluster = 47, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 46, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 45, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 44, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 43, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 293, cluster = 41, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 270, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 389, cluster = 39, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 38, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 37, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 36, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 35, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 34, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 512, cluster = 32, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 839, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 286, cluster = 30, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 224, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text1"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 13949, y_origin = 0, x_size = 5748, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 90, cluster = 7, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 8, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 9, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 10, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 11, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 6, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 580, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 16, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 17, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 6, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 580, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 19, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 20, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 21, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 22, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 23, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 24, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text2"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                [ AncestorBox {boxUserData = "box1", boxLeftEdge = NoEdge, boxRightEdge = SpacedEdge 0, boxStartEdge = SpacedEdge 0, boxEndEdge = NoEdge}
                ]
            , fragmentRect = Rect {x_origin = 19697, y_origin = 0, x_size = 1252, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 3, cluster = 25, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 26, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 27, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 90, cluster = 28, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 272, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 3, cluster = 29, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 236, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        ]
    }

A .golden/richParagraphLayout/mixedDirectionSimpleLTR.golden => .golden/richParagraphLayout/mixedDirectionSimpleLTR.golden +50 -0
@@ 0,0 1,50 @@
ParagraphLayout
    { paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 7954, y_size = -1500}
    , paragraphFragments =
        [ Fragment
            { fragmentUserData = "text"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 3397, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 6, cluster = 0, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 580, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 1, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 14, cluster = 2, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 24, cluster = 3, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 363, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 4, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 15, cluster = 5, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 250, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 20, cluster = 6, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 3397, y_origin = 0, x_size = 1578, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 1143, cluster = 9, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 1095, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 920, cluster = 7, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 483, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 4975, y_origin = 0, x_size = 2979, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 17, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 517, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 27, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 29, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 759, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 16, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 15, cluster = 17, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 250, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 26, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 351, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        ]
    }

A .golden/richParagraphLayout/mixedDirectionSimpleRTL.golden => .golden/richParagraphLayout/mixedDirectionSimpleRTL.golden +50 -0
@@ 0,0 1,50 @@
ParagraphLayout
    { paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 7954, y_size = -1500}
    , paragraphFragments =
        [ Fragment
            { fragmentUserData = "text"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 2979, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 17, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 517, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 27, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 29, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 759, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 16, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 15, cluster = 17, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 250, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 26, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 351, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 2979, y_origin = 0, x_size = 1578, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 1143, cluster = 9, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 1095, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 920, cluster = 7, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 483, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        , Fragment
            { fragmentUserData = "text"
            , fragmentLine = 1
            , fragmentAncestorBoxes =
                []
            , fragmentRect = Rect {x_origin = 4557, y_origin = 0, x_size = 3397, y_size = -1500}
            , fragmentPen = (0, -1085)
            , fragmentGlyphs =
                [ (GlyphInfo {codepoint = 6, cluster = 0, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 580, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 1, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 14, cluster = 2, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 24, cluster = 3, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 363, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 4, cluster = 4, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 534, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 15, cluster = 5, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 250, y_advance = 0, x_offset = 0, y_offset = 0})
                , (GlyphInfo {codepoint = 20, cluster = 6, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False}, GlyphPos {x_advance = 568, y_advance = 0, x_offset = 0, y_offset = 0})
                ]
            }
        ]
    }

M test/Data/Text/ParagraphLayout/Internal/BiDiLevelsSpec.hs => test/Data/Text/ParagraphLayout/Internal/BiDiLevelsSpec.hs +6 -0
@@ 65,6 65,12 @@ spec = do
        describe "on Serbian mixed script" $
            serbianMixedScript `shouldHaveLevels` [0]

        describe "on mixed direction with base LTR" $
            mixedDirectionSimple DirLTR `shouldHaveLevels` [0, 1, 0]

        describe "on mixed direction with base RTL" $
            mixedDirectionSimple DirRTL `shouldHaveLevels` [2, 1, 2]

        describe "on Arabic around English" $
            arabicAroundEnglish `shouldHaveLevels` [1, 2, 1, 2, 1]


M test/Data/Text/ParagraphLayout/Internal/RunSpec.hs => test/Data/Text/ParagraphLayout/Internal/RunSpec.hs +54 -0
@@ 94,6 94,60 @@ spec = do
                    , runScript = Just "Cyrl"
                    }
                ]
        it "handles mixed direction with base LTR" $ do
            let levels = levelsRLE [(7, 0), (3, 1), (6, 0)]
            let inputSpan = sampleSpan (mixedDirectionSimple DirLTR) levels
            let runs = spanToRuns inputSpan
            runs `shouldBe`
                [ Run
                    { runOffsetInSpan = 0
                    , runText = pack "bahrain"
                    , runLevel = 0
                    , runDirection = Just DirLTR
                    , runScript = Just "Latn"
                    }
                , Run
                    { runOffsetInSpan = 7
                    , runText = pack "مصر"
                    , runLevel = 1
                    , runDirection = Just DirRTL
                    , runScript = Just "Arab"
                    }
                , Run
                    { runOffsetInSpan = 13
                    , runText = pack "kuwait"
                    , runLevel = 0
                    , runDirection = Just DirLTR
                    , runScript = Just "Latn"
                    }
                ]
        it "handles mixed direction with base RTL" $ do
            let levels = levelsRLE [(7, 2), (3, 1), (6, 2)]
            let inputSpan = sampleSpan (mixedDirectionSimple DirRTL) levels
            let runs = spanToRuns inputSpan
            runs `shouldBe`
                [ Run
                    { runOffsetInSpan = 0
                    , runText = pack "bahrain"
                    , runLevel = 2
                    , runDirection = Just DirLTR
                    , runScript = Just "Latn"
                    }
                , Run
                    { runOffsetInSpan = 7
                    , runText = pack "مصر"
                    , runLevel = 1
                    , runDirection = Just DirRTL
                    , runScript = Just "Arab"
                    }
                , Run
                    { runOffsetInSpan = 13
                    , runText = pack "kuwait"
                    , runLevel = 2
                    , runDirection = Just DirLTR
                    , runScript = Just "Latn"
                    }
                ]
        it "handles Arabic text with English inside" $ do
            let levels = levelsRLE [(3, 1), (9, 2), (36, 1), (3, 2), (1, 1)]
            let inputSpan = sampleSpan arabicAroundEnglish levels

M test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs => test/Data/Text/ParagraphLayout/Rich/ParagraphData.hs +45 -1
@@ 2,6 2,8 @@ module Data.Text.ParagraphLayout.Rich.ParagraphData
    ( hardBoxBreakLTRParagraph
    , hardBoxBreakRTLParagraph
    , loremIpsumParagraph
    , mixedDirectionComplexParagraph
    , mixedDirectionSimpleParagraph
    , mixedScriptParagraph
    , mixedSizesParagraph
    , nestedBoxesParagraph


@@ 10,7 12,7 @@ module Data.Text.ParagraphLayout.Rich.ParagraphData
where

import Data.Int (Int32)
import Data.Text (Text, pack)
import Data.Text (Text, empty, pack)
import Data.Text.Glyphize (Direction (DirLTR, DirRTL), Font)

import Data.Text.ParagraphLayout.Internal.BoxOptions


@@ 18,6 20,7 @@ import Data.Text.ParagraphLayout.Internal.ParagraphOptions
import Data.Text.ParagraphLayout.Internal.Rich.Paragraph
import Data.Text.ParagraphLayout.Internal.TextOptions
import Data.Text.ParagraphLayout.Internal.Tree
import Data.Text.ParagraphLayout.TextData

tLTR :: TextOptions
tLTR = defaultTextOptions DirLTR


@@ 88,6 91,47 @@ loremIpsumParagraph font = constructParagraph
    where
        t = tLTR { textFont = font, textLanguage = "zxx" }

-- | Edge case:
-- Directionally neutral characters between box boundary and direction boundary.
--
-- In the case of a LTR paragraph, neutral characters should only be considered
-- RTL when surrounded by RTL characters on both sides, otherwise they should
-- be LTR.
--
-- In the case of a RTL paragraph, neutral characters should only be considered
-- LTR when surrounded by LTR characters on both sides, otherwise they should
-- be RTL.
--
-- Box boundaries should not, by default, affect the direction of neutral
-- characters.
mixedDirectionComplexParagraph :: Direction -> Font -> ParagraphOptions ->
    Paragraph String
mixedDirectionComplexParagraph dir font = constructParagraph
    (pack "prefix")
    (rootBox t
        [ text "text1" " . . ab . . ba . . "
        , box "box1" b_ t
            [ text "text2" " . . اب . . با . . tu . . ut . . "
            ]
        , text "text3" " . . تو . . وت . . "
        ]
    )
    (pack "suffix")
    where
        t = (defaultTextOptions dir) { textFont = font, textLanguage = "zxx" }

-- | A paragraph that contains only strongly directional letters of mixed
-- directions, no spaces or other neutral characters, for basic BiDi tests.
mixedDirectionSimpleParagraph :: Direction -> Font -> ParagraphOptions ->
    Paragraph String
mixedDirectionSimpleParagraph dir font = constructParagraph
    empty
    (rootBox t [TextSequence "text" textContents])
    empty
    where
        t = (defaultTextOptions dir) { textFont = font, textLanguage = lang }
        (_, lang, textContents, _) = mixedDirectionSimple dir

mixedScriptParagraph :: Font -> ParagraphOptions -> Paragraph String
mixedScriptParagraph font = constructParagraph
    (pack "prefix")

M test/Data/Text/ParagraphLayout/RichSpec.hs => test/Data/Text/ParagraphLayout/RichSpec.hs +25 -0
@@ 1,6 1,7 @@
module Data.Text.ParagraphLayout.RichSpec (spec) where

import Data.Int (Int32)
import Data.Text.Glyphize (Direction (DirLTR, DirRTL))

import Test.Hspec
import System.FilePath ((</>))


@@ 120,6 121,30 @@ spec = do
                let result = layoutRich input
                result `shouldBeGolden` "hardBoxBreakRTL"

            it "handles simple mixed direction in RTL paragraph" $ do
                let opts = defaultParagraphOptions
                let input = mixedDirectionSimpleParagraph DirRTL font opts
                let result = layoutRich input
                result `shouldBeGolden` "mixedDirectionSimpleRTL"

            it "handles simple mixed direction in LTR paragraph" $ do
                let opts = defaultParagraphOptions
                let input = mixedDirectionSimpleParagraph DirLTR font opts
                let result = layoutRich input
                result `shouldBeGolden` "mixedDirectionSimpleLTR"

            it "handles complex mixed direction in RTL paragraph" $ do
                let opts = defaultParagraphOptions
                let input = mixedDirectionComplexParagraph DirRTL font opts
                let result = layoutRich input
                result `shouldBeGolden` "mixedDirectionComplexRTL"

            it "handles complex mixed direction in LTR paragraph" $ do
                let opts = defaultParagraphOptions
                let input = mixedDirectionComplexParagraph DirLTR font opts
                let result = layoutRich input
                result `shouldBeGolden` "mixedDirectionComplexLTR"

    describe "paginate" $ do
        let
            goldenDir = ".golden" </> "paginatedRichParagraphLayout"

M test/Data/Text/ParagraphLayout/TextData.hs => test/Data/Text/ParagraphLayout/TextData.hs +13 -0
@@ 5,6 5,7 @@ module Data.Text.ParagraphLayout.TextData
    , arabicHello
    , czechHello
    , serbianMixedScript
    , mixedDirectionSimple
    , arabicAroundEnglish
    , englishAroundArabic
    )


@@ 67,6 68,18 @@ serbianMixedScript =

-- | Source:
-- <https://www.w3.org/International/articles/inline-bidi-markup/uba-basics>
--
-- Used to test the effect of base direction.
mixedDirectionSimple :: Direction -> Sample
mixedDirectionSimple dir =
    ( dir
    , "ar"
    , pack "bahrainمصرkuwait"
    , [7, 3, 6]
    )

-- | Source:
-- <https://www.w3.org/International/articles/inline-bidi-markup/uba-basics>
arabicAroundEnglish :: Sample
arabicAroundEnglish =
    ( DirRTL