From e109466dc37ab61a41256b463de591e95ab8e1bb Mon Sep 17 00:00:00 2001 From: Jaro Date: Sat, 11 Mar 2023 00:40:49 +0100 Subject: [PATCH] Use a single list of line breaking alternatives. --- .../Text/ParagraphLayout/Internal/Plain.hs | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/Data/Text/ParagraphLayout/Internal/Plain.hs b/src/Data/Text/ParagraphLayout/Internal/Plain.hs index f1a1dff..53ce413 100644 --- a/src/Data/Text/ParagraphLayout/Internal/Plain.hs +++ b/src/Data/Text/ParagraphLayout/Internal/Plain.hs @@ -12,7 +12,6 @@ import Data.Int (Int32) import Data.List (mapAccumL) import Data.List.NonEmpty (NonEmpty((:|))) import qualified Data.List.NonEmpty as NonEmpty -import Data.Maybe (catMaybes, fromMaybe, listToMaybe) import Data.Text.Foreign (lengthWord8) import Data.Text.Glyphize (Buffer(..) @@ -154,23 +153,29 @@ positionFragmentH originY originX (WithSpan rs pf) = (nextX, WithSpan rs frag) -- and return the remaining runs to be placed on other lines. layoutAndWrapRunsH :: Int32 -> [WithSpan Run] -> ([WithSpan PF.ProtoFragment], [WithSpan Run]) -layoutAndWrapRunsH maxWidth runs = - fromMaybe lastResortSplit $ listToMaybe validSplits +layoutAndWrapRunsH maxWidth runs = NonEmpty.head $ validLayouts where - lastResortSplit = do - let (runs1, runs2) = splitTextsAt8 1 runs - let pfs = layoutRunsH runs1 - (pfs, runs2) - applySplit (runs1, runs2) = do - let pfs = layoutRunsH $ trimTextsEnd isEndSpace runs1 - if totalAdvances pfs <= maxWidth - then Just (pfs, runs2) - else Nothing - validSplits = catMaybes $ map applySplit splits - splits = noSplit : (filter hasContent $ breakSplits [] (reverse runs)) + validLayouts = dropWhile1 tooLong layouts + tooLong (pfs, _) = totalAdvances pfs > maxWidth + layouts = NonEmpty.map layoutFst splits + layoutFst (runs1, runs2) = (layout runs1, runs2) + layout runs1 = layoutRunsH $ trimTextsEnd isEndSpace runs1 + splits = noSplit :| (wordSplits ++ [lastResortSplit]) noSplit = (runs, []) + wordSplits = (filter hasContent $ breakSplits [] (reverse runs)) + lastResortSplit = splitTextsAt8 1 runs hasContent = not . null . fst +-- | The suffix remaining after removing the longest prefix of the list for +-- which the predicate holds, except always including at least the last element +-- of the original list. +dropWhile1 :: (a -> Bool) -> NonEmpty a -> NonEmpty a +dropWhile1 p list = case NonEmpty.uncons list of + (_, Nothing) -> list + (x, Just xs) -> if p x + then dropWhile1 p xs + else list + -- | Calculate layout for multiple horizontal runs on the same line, without -- any breaking. layoutRunsH :: [WithSpan Run] -> [WithSpan PF.ProtoFragment] -- 2.30.2