~jaro/balkon

024cddaac622db5ccd0d57c48ba1b06a1eaf82a8 — Jaro 1 year, 1 month ago 3c9b4c5
Decompose text slicing.
M src/Data/Text/ParagraphLayout/Internal/Paragraph.hs => src/Data/Text/ParagraphLayout/Internal/Paragraph.hs +21 -0
@@ 2,6 2,8 @@ module Data.Text.ParagraphLayout.Internal.Paragraph
    ( Paragraph (..)
    , ParagraphOptions (..)
    , paragraphSpanBounds
    , paragraphSpanTexts
    , paragraphText
    )
where



@@ 10,6 12,7 @@ import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
import Data.Text.Array (Array)
import Data.Text.Glyphize (Font)
import Data.Text.Internal (Text (Text))

import Data.Text.ParagraphLayout.Internal.LineHeight
import Data.Text.ParagraphLayout.Internal.Span


@@ 79,4 82,22 @@ data ParagraphOptions = ParagraphOptions
-- will be one larger than the list of input spans.
paragraphSpanBounds :: Paragraph -> NonEmpty Int
paragraphSpanBounds (Paragraph _ initialOffset spans _) =
    -- TODO: Consider adding checks for array bounds.
    NonEmpty.scanl (+) initialOffset (map spanLength spans)

-- | Turn each span of the input `Paragraph` into a `Text`.
paragraphSpanTexts :: Paragraph -> [Text]
paragraphSpanTexts p@(Paragraph arr _ _ _) = zipWith toText sStarts sEnds
    where
        toText start end = Text arr start (end - start)
        sStarts = NonEmpty.init sBounds
        sEnds = NonEmpty.tail sBounds
        sBounds = paragraphSpanBounds p

-- | Turn all spans of the input `Paragraph` into one combined `Text`.
paragraphText :: Paragraph -> Text
paragraphText p@(Paragraph arr _ _ _) = Text arr start (end - start)
    where
        start = NonEmpty.head sBounds
        end = NonEmpty.last sBounds
        sBounds = paragraphSpanBounds p

M src/Data/Text/ParagraphLayout/Internal/Plain.hs => src/Data/Text/ParagraphLayout/Internal/Plain.hs +12 -16
@@ 8,6 8,7 @@ import Data.List (mapAccumL)
import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty, (<|))
import qualified Data.List.NonEmpty as NonEmpty
import Data.Maybe (catMaybes)
import Data.Text (Text)
import Data.Text.Foreign (lengthWord8)
import Data.Text.Glyphize
    ( Buffer (..)


@@ 21,7 22,6 @@ import Data.Text.Glyphize
    )
import Data.Text.ICU (Breaker, LocaleName, breakCharacter, breakLine)
import qualified Data.Text.ICU as BreakStatus (Line (Hard))
import Data.Text.Internal (Text (Text))
import qualified Data.Text.Lazy as Lazy

import Data.Text.ParagraphLayout.Internal.BiDiReorder


@@ 259,25 259,24 @@ shapeRun (WithSpan rs run) = shape font buffer features
        features = []

resolveSpans :: Paragraph -> [RS.ResolvedSpan]
resolveSpans p@(Paragraph arr pStart spans pOpts) = do
resolveSpans p@(Paragraph _ pStart spans pOpts) = do
    let sBounds = paragraphSpanBounds p
    let pEnd = NonEmpty.last sBounds
    let sTexts = paragraphSpanTexts p
    let pText = paragraphText p
    let sStarts = NonEmpty.init sBounds
    let sLengths = map spanLength spans

    (i, s, sStart, sLen) <- getZipList $ (,,,)
    (i, s, sStart, sText) <- getZipList $ (,,,)
        <$> ZipList [0 ..]
        <*> ZipList spans
        <*> ZipList sStarts
        <*> ZipList sLengths
        <*> ZipList sTexts
    let lang = spanLanguage $ spanOptions s
    let lBreaks = paragraphBreaks breakLine p pEnd lang
    let cBreaks = paragraphBreaks breakCharacter p pEnd lang
    let lBreaks = paragraphBreaks breakLine pText lang
    let cBreaks = paragraphBreaks breakCharacter pText lang
    return RS.ResolvedSpan
        { RS.spanIndex = i
        , RS.spanOffsetInParagraph = sStart - pStart
        -- TODO: Consider adding checks for array bounds.
        , RS.spanText = Text arr sStart sLen
        , RS.spanText = sText
        , RS.spanFont = paragraphFont pOpts
        , RS.spanLineHeight = paragraphLineHeight pOpts
        , RS.spanLanguage = lang


@@ 285,12 284,9 @@ resolveSpans p@(Paragraph arr pStart spans pOpts) = do
        , RS.spanCharacterBreaks = subOffsetsDesc (sStart - pStart) cBreaks
        }

paragraphBreaks :: (LocaleName -> Breaker a) -> Paragraph -> Int -> String ->
    [(Int, a)]
paragraphBreaks breakFunc (Paragraph arr off _ _) end lang =
    breaksDesc (breakFunc (locale lang LBAuto)) paragraphText
    where
        paragraphText = Text arr off (end - off)
paragraphBreaks :: (LocaleName -> Breaker a) -> Text -> String -> [(Int, a)]
paragraphBreaks breakFunc txt lang =
    breaksDesc (breakFunc (locale lang LBAuto)) txt

runLineBreaks :: WithSpan Run -> [(Int, BreakStatus.Line)]
runLineBreaks (WithSpan rs run) =