~jaro/balkon

03d36342529a318aa40fa9da94e8555e2f2017d5 — Jaro 11 months ago 3bea858
Implement Rich pagination.
M src/Data/Text/ParagraphLayout/Internal/Paginable.hs => src/Data/Text/ParagraphLayout/Internal/Paginable.hs +9 -0
@@ 12,6 12,8 @@ import Data.Text.ParagraphLayout.Internal.LinePagination
import Data.Text.ParagraphLayout.Internal.ParagraphLine
import qualified Data.Text.ParagraphLayout.Internal.Plain.ParagraphLayout
    as Plain
import qualified Data.Text.ParagraphLayout.Internal.Rich.ParagraphLayout
    as Rich

-- | Defines options for breaking a layout into pages.
data PageOptions = PageOptions


@@ 81,6 83,13 @@ instance Paginable (Plain.ParagraphLayout d) where
        (c, p, Nothing) -> (c, mergeLines p, Nothing)
        (c, p, Just rest) -> (c, mergeLines p, Just (mergeLines rest))

-- | Implementation of paginating a rich text paragraph layout.
-- Breaks the layout on page boundaries and automatically adjusts coordinates.
instance Paginable (Rich.ParagraphLayout d) where
    paginate opts pl = case paginate opts (cutLines pl) of
        (c, p, Nothing) -> (c, mergeLines p, Nothing)
        (c, p, Just rest) -> (c, mergeLines p, Just (mergeLines rest))

-- | Perform page breaking on the entire input, returning a list of pages.
paginateAll :: Paginable a => PageOptions -> a -> [(PageContinuity, a)]
paginateAll opts pl = case paginate opts pl of

M src/Data/Text/ParagraphLayout/Internal/ParagraphLine.hs => src/Data/Text/ParagraphLayout/Internal/ParagraphLine.hs +10 -0
@@ 10,6 10,7 @@ import qualified Data.List.NonEmpty as NonEmpty

import Data.Text.ParagraphLayout.Internal.Fragment
import qualified Data.Text.ParagraphLayout.Internal.Plain.ParagraphLayout as P
import qualified Data.Text.ParagraphLayout.Internal.Rich.ParagraphLayout as R
import Data.Text.ParagraphLayout.Internal.Rect

class GenericLayout pl where


@@ 45,6 46,15 @@ instance GenericLayout (P.ParagraphLayout d) where
    shiftFragments dy = P.mapFragments (shiftFragment dy)
    appendFragments = P.appendFragments

instance GenericLayout (R.ParagraphLayout d) where
    empty = R.emptyParagraphLayout
    rect = R.paragraphRect
    topDistance pl = topFragmentOrigin $ R.paragraphFragments pl
    lineNumbers pl = uniqueFragmentLines $ R.paragraphFragments pl
    limitFragments n = R.filterFragments (fragmentIsOnLine n)
    shiftFragments dy = R.mapFragments (shiftFragment dy)
    appendFragments = R.appendFragments

-- | Split the given `ParagraphLayout` into single-line layouts.
cutLines :: GenericLayout pl => pl -> [pl]
cutLines pl = map (\ n -> cutLine n pl) (lineNumbers pl)

M src/Data/Text/ParagraphLayout/Internal/Rich/ParagraphLayout.hs => src/Data/Text/ParagraphLayout/Internal/Rich/ParagraphLayout.hs +4 -0
@@ 14,6 14,7 @@ where
import Data.Int (Int32)

import Data.Text.ParagraphLayout.Internal.Fragment
import Data.Text.ParagraphLayout.Internal.LinePagination
import Data.Text.ParagraphLayout.Internal.ParagraphExtents
import Data.Text.ParagraphLayout.Internal.Rect



@@ 28,6 29,9 @@ data ParagraphLayout d = ParagraphLayout
    }
    deriving (Eq, Read, Show)

instance Line (ParagraphLayout d) where
    lineHeight pl = height $ paragraphRect pl

-- | Wrap the given `Fragment`s and compute their containing rectangle.
paragraphLayout :: [Fragment d] -> ParagraphLayout d
paragraphLayout frags = ParagraphLayout pRect frags