From 93c6516bd685ea45627cd62abfd2241d91711553 Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Sun, 9 Apr 2023 14:33:37 +1200 Subject: [PATCH] Commence reference documentation! --- Graphics/Layout/CSS/Font.hs | 19 +++++++++++++++++++ Graphics/Layout/CSS/Length.hs | 26 ++++++++++++++++++++++++++ Graphics/Layout/Inline.hs | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/Graphics/Layout/CSS/Font.hs b/Graphics/Layout/CSS/Font.hs index b9ab1a3..c2de2c3 100644 --- a/Graphics/Layout/CSS/Font.hs +++ b/Graphics/Layout/CSS/Font.hs @@ -18,11 +18,15 @@ import Graphics.Text.Font.Choose (Pattern(..), Value(..), normalizePattern, import qualified Data.ByteString as B import System.IO.Unsafe (unsafePerformIO) +-- | zero'd `Font'` to serve as the root's parent in a font heirarchy. placeholderFont = Font' undefined [] (const 0) (const 0) 0 0 0 0 0 0 0 0 1 +-- | Scale-factor for text-shaping APIs. hbScale :: Font' -> Double hbScale f = fontSize f*hbUnit +-- | Magic number informing the value of `hbScale`. hbUnit = 64 :: Double +-- | Convert from FontConfig query result to a Harfbuzz font. pattern2hbfont :: Pattern -> Int -> [Variation] -> Font pattern2hbfont pat scale variations = createFontWithOptions options face where @@ -37,6 +41,8 @@ pattern2hbfont pat scale variations = createFontWithOptions options face value2opt opts ("fontvariations", _:_) = opts {optionVariations = variations} value2opt opts _ = opts +-- | Convert Parsed CSS to a `Font'`. +-- Includes sizing parameters derived from a root & parent `Font'`. pattern2font :: Pattern -> CSSFont -> Font' -> Font' -> Font' pattern2font pat styles@CSSFont { cssFontSize = (x,"initial") } parent root = pattern2font pat styles { cssFontSize = (x*fontSize root," ") } parent root @@ -73,20 +79,32 @@ pattern2font pat styles parent root = Font' { font' = pattern2hbfont font (round scale') $ variations' fontSize' styles scale' = fontSize'*hbUnit +-- | Parsed CSS font properties, excluding the FontConfig query. data CSSFont = CSSFont { + -- | Parsed CSS font-size. cssFontSize :: Unitted, + -- | Parsed CSS line-height. cssLineheight :: Unitted, + -- | Parsed CSS font-variation-settings. variations :: [Variation], + -- | Parsed CSS font-weight. weightVariation :: Variation, + -- | Parsed CSS font-stretch. widthVariation :: Variation, + -- | Parsed CSS font-style. slantVariation :: Variation, + -- | Parsed CSS font-optical-sizing. opticalSize :: Bool } +-- | All font-variations from the parsed CSS properties. +-- | Requires the resolved font-size in case font-optical-sizing is set. variations' :: Double -> CSSFont -> [Variation] variations' fontsize self = (if opticalSize self then (Variation opsz (realToFrac fontsize):) else id) (slantVariation self:widthVariation self:weightVariation self:variations self) +-- | Represents a multiple of the initial font-size. +-- Resolved by `pattern2font`. fracDefault :: CSSFont -> Double -> Maybe CSSFont fracDefault self frac = Just self { cssFontSize = (frac,"initial") @@ -194,6 +212,7 @@ instance PropertyParser CSSFont where longhand _ _ _ _ = Nothing +-- | Utility for parsing multiple font variations (via Harfbuzz). parseVariations (x@(String _):y@(Number _ _):Comma:toks) | Just var <- parseVariation $ Txt.unpack $ serialize [x, y], Just vars <- parseVariations toks = Just $ var:vars diff --git a/Graphics/Layout/CSS/Length.hs b/Graphics/Layout/CSS/Length.hs index bdc971c..2fa0e40 100644 --- a/Graphics/Layout/CSS/Length.hs +++ b/Graphics/Layout/CSS/Length.hs @@ -11,10 +11,15 @@ import Graphics.Text.Font.Choose (Pattern(..)) import Graphics.Layout.Box +-- | A number+unit, prior to resolving side units. +-- The unit may alternately represent a keyword, in which case the number is +-- ignored & typically set to 0. type Unitted = (Double, Txt.Text) +-- | The CSS `auto` keyword. auto :: Unitted auto = (0,"auto") +-- | Parse a pre-tokenized CSS length value. parseLength :: [Token] -> Maybe Unitted parseLength [Percentage _ x] = Just (n2f x,"%") parseLength [Dimension _ x unit] @@ -23,15 +28,20 @@ parseLength [Dimension _ x unit] parseLength [Ident "auto"] = Just (0,"auto") parseLength [Ident "initial"] = Just (0,"auto") parseLength _ = Nothing +-- | Variant of `parseLength` which supports min-content & max-content keywords. parseLength' [Ident "min-content"] = Just (0,"min-content") parseLength' [Ident "max-content"] = Just (0,"max-content") parseLength' toks = parseLength toks +-- | Supported length units. units = Txt.words "cap ch em ex ic lh rem rlh vh vw vmax vmin px cm mm Q in pc pt %" +-- | Convert a lexed number to a Double. +n2f :: (Fractional x, RealFloat x) => NumericValue -> x n2f (NVInteger x) = realToFrac x n2f (NVNumber x) = toRealFloat x +-- | Resolve a parsed length according to the sizing parameters in a given `Font'`. finalizeLength :: Unitted -> Font' -> Length finalizeLength (x,"cap") f = Pixels $ x*fontHeight f 'A' finalizeLength (x,"ch") f = Pixels $ x*fontAdvance f '0' @@ -59,20 +69,36 @@ finalizeLength (_,"min-content") _ = Min finalizeLength (_,"max-content") _ = Preferred finalizeLength (x, " ") _ = Pixels x -- Internal constant value... finalizeLength (_,unit) _ = trace ("Invalid unit " ++ Txt.unpack unit) $ Pixels 0 +-- | Convert from a computed length to the "pt" unit. px2pt f x = x / scale f / 96 * 72 +-- | A Harfbuzz font with sizing parameters. data Font' = Font' { + -- | The Harfbuzz font used to shape text & query character-size information. hbFont :: Font, + -- | The FontConfig query result. Useful to incorporate into output rendering. pattern :: Pattern, + -- | Query the height of a character. + -- Used for cap, ex, or ic units. fontHeight :: Char -> Double, + -- | Query the width of a character, used for ch unit. fontAdvance :: Char -> Double, + -- | The desired font-size, used for em unit. fontSize :: Double, + -- | The root font's size, used for rem unit. rootEm :: Double, + -- | The desired line-height, used for lh unit. lineheight :: Double, + -- | The root font's line-height, used for rlh unit. rlh :: Double, + -- | Scale-factor for vh unit. vh :: Double, + -- | Scale-factor for vw unit. vw :: Double, + -- | Scale-factor for vmax unit. vmax :: Double, + -- | Scale-factor for vmin unit. vmin :: Double, + -- | How many device pixels in a CSS px? scale :: Double } diff --git a/Graphics/Layout/Inline.hs b/Graphics/Layout/Inline.hs index 6828d55..8c83421 100644 --- a/Graphics/Layout/Inline.hs +++ b/Graphics/Layout/Inline.hs @@ -22,7 +22,7 @@ inlineMinWidth :: Font' -> Paragraph -> Double inlineMinWidth font self = hbScale' font $ width $ layoutPlain' self 0 inlineMin :: (CastDouble x, CastDouble y) => Font' -> Paragraph -> Size x y inlineMin font self = Size (c font $ width rect) (c font $ height rect) - where rect = layoutPlain' self 0 + where rect = layoutPlain' self 0 inlineNatWidth :: Font' -> Paragraph -> Double inlineNatWidth font self = hbScale' font $ width $ layoutPlain' self maxBound inlineHeight :: Font' -> Double -> Paragraph -> Double -- 2.30.2