{-# LANGUAGE CApiFFI, OverloadedStrings #-}
-- | A set of fonts to query, or resulting from a query.
module Graphics.Text.Font.Choose.FontSet(
        FontSet, validFontSet, fontSetList, fontSetMatch, fontSetSort, FontFaceParser(..), emptyParser
    ) where

import Graphics.Text.Font.Choose.Pattern hiding (map)
import Graphics.Text.Font.Choose.Config
import Graphics.Text.Font.Choose.ObjectSet
import Graphics.Text.Font.Choose.CharSet as CS hiding (map)
import Graphics.Text.Font.Choose.Internal.FFI

import Foreign.C.String (CString)
import Foreign.Ptr (Ptr)
import Data.MessagePack (MessagePack)

import Stylist (StyleSheet(..))
import Stylist.Parse (parseProperties)
import Data.CSS.Syntax.Tokens (Token(..), serialize)
import Data.Text (Text, unpack)
import qualified Data.Text as Txt
import qualified Data.Map as M
import Data.List (intercalate)

import Graphics.Text.Font.Choose.Range (iRange)
import Graphics.Text.Font.Choose.Value (ToValue(..), Value)

-- | holds a list of patterns; these are used to return the results of listing available fonts.
type FontSet = [Pattern]

-- | Can the FontSet be processed by FontConfig?
validFontSet :: FontSet -> Bool
validFontSet :: FontSet -> Bool
validFontSet = (Pattern -> Bool) -> FontSet -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Pattern -> Bool
validPattern

-- | holds a list of patterns; these are used to return the results of listing available fonts.
-- If the fontset is invalid, 
fontSetList :: Config -> [FontSet] -> Pattern -> ObjectSet -> FontSet
fontSetList :: Config -> [FontSet] -> Pattern -> ObjectSet -> FontSet
fontSetList Config
a [FontSet]
b Pattern
c ObjectSet
d | (FontSet -> Bool) -> [FontSet] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all FontSet -> Bool
validFontSet [FontSet]
b =
    (Ptr Int -> CString) -> FontSet
forall a. MessagePack a => (Ptr Int -> CString) -> a
fromMessage0 ((Ptr Int -> CString) -> FontSet)
-> (Ptr Int -> CString) -> FontSet
forall a b. (a -> b) -> a -> b
$ ObjectSet
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg ObjectSet
d ((CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString)
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. (a -> b) -> a -> b
$ Pattern
-> (CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg Pattern
c ((CString -> Int -> CString -> Int -> Ptr Int -> CString)
 -> CString -> Int -> Ptr Int -> CString)
-> (CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. (a -> b) -> a -> b
$ [FontSet]
-> (CString
    -> Int -> CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> CString
-> Int
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg [FontSet]
b ((CString
  -> Int -> CString -> Int -> CString -> Int -> Ptr Int -> CString)
 -> CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> (CString
    -> Int -> CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> CString
-> Int
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. (a -> b) -> a -> b
$ (Ptr Config'
 -> CString
 -> Int
 -> CString
 -> Int
 -> CString
 -> Int
 -> Ptr Int
 -> CString)
-> Config
-> CString
-> Int
-> CString
-> Int
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. (Ptr a -> b) -> ForeignPtr a -> b
withForeignPtr' Ptr Config'
-> CString
-> Int
-> CString
-> Int
-> CString
-> Int
-> Ptr Int
-> CString
fcFontSetList Config
a
  | Bool
otherwise = []

foreign import capi "fontconfig-wrap.h" fcFontSetList ::
        Ptr Config' -> CString -> Int -> CString -> Int -> CString -> Int ->
        Ptr Int -> CString

-- | Finds the font in sets most closely matching pattern and returns the result
-- of `fontRenderPrepare` for that font and the provided pattern.
fontSetMatch :: Config -> [FontSet] -> Pattern -> Maybe FontSet
fontSetMatch :: Config -> [FontSet] -> Pattern -> Maybe FontSet
fontSetMatch Config
a [FontSet]
b Pattern
c | (FontSet -> Bool) -> [FontSet] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all FontSet -> Bool
validFontSet [FontSet]
b Bool -> Bool -> Bool
&& Pattern -> Bool
validPattern Pattern
c =
        (Ptr Int -> CString) -> Maybe FontSet
forall a. MessagePack a => (Ptr Int -> CString) -> Maybe a
fromMessage ((Ptr Int -> CString) -> Maybe FontSet)
-> (Ptr Int -> CString) -> Maybe FontSet
forall a b. (a -> b) -> a -> b
$ Pattern
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg Pattern
c ((CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString)
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. (a -> b) -> a -> b
$ [FontSet]
-> (CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg [FontSet]
b ((CString -> Int -> CString -> Int -> Ptr Int -> CString)
 -> CString -> Int -> Ptr Int -> CString)
-> (CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> CString
-> Int
-> Ptr Int
-> CString
forall a b. (a -> b) -> a -> b
$ (Ptr Config'
 -> CString -> Int -> CString -> Int -> Ptr Int -> CString)
-> Config -> CString -> Int -> CString -> Int -> Ptr Int -> CString
forall a b. (Ptr a -> b) -> ForeignPtr a -> b
withForeignPtr' Ptr Config'
-> CString -> Int -> CString -> Int -> Ptr Int -> CString
fcFontSetMatch Config
a
    | Bool
otherwise = Maybe FontSet
forall a. Maybe a
Nothing

foreign import capi "fontconfig-wrap.h" fcFontSetMatch ::
        Ptr Config' -> CString -> Int -> CString -> Int -> Ptr Int -> CString

-- | Returns the list of fonts from sets sorted by closeness to pattern.
-- If True is passed, elements in the list which don't include Unicode coverage
-- not provided by earlier elements in the list are elided.
-- The union of Unicode coverage of all of the fonts is returned alongside the fontset.

-- Returns an empty CharSet & Nothing upon error, or invalid inputs.
fontSetSort :: Config -> [FontSet] -> Pattern -> Bool -> (Maybe FontSet, CharSet')
fontSetSort :: Config -> [FontSet] -> Pattern -> Bool -> (Maybe FontSet, CharSet')
fontSetSort Config
a [FontSet]
b Pattern
c Bool
d | (FontSet -> Bool) -> [FontSet] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all FontSet -> Bool
validFontSet [FontSet]
b Bool -> Bool -> Bool
&& Pattern -> Bool
validPattern Pattern
c =
        (Ptr Int -> CString) -> (Maybe FontSet, CharSet')
forall a. MessagePack a => (Ptr Int -> CString) -> a
fromMessage0 ((Ptr Int -> CString) -> (Maybe FontSet, CharSet'))
-> (Ptr Int -> CString) -> (Maybe FontSet, CharSet')
forall a b. (a -> b) -> a -> b
$ ((Ptr Config' -> Ptr Int -> CString)
 -> Config -> Ptr Int -> CString)
-> Config
-> (Ptr Config' -> Ptr Int -> CString)
-> Ptr Int
-> CString
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Ptr Config' -> Ptr Int -> CString) -> Config -> Ptr Int -> CString
forall a b. (Ptr a -> b) -> ForeignPtr a -> b
withForeignPtr' Config
a ((Ptr Config' -> Ptr Int -> CString) -> Ptr Int -> CString)
-> (Ptr Config' -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. (a -> b) -> a -> b
$ \Ptr Config'
a' ->
            [FontSet]
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg [FontSet]
b ((CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString)
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. (a -> b) -> a -> b
$ \CString
b' Int
x -> Pattern
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg Pattern
c ((CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString)
-> (CString -> Int -> Ptr Int -> CString) -> Ptr Int -> CString
forall a b. (a -> b) -> a -> b
$ \CString
c' Int
y -> Ptr Config'
-> CString -> Int -> CString -> Int -> Bool -> Ptr Int -> CString
fcFontSetSort Ptr Config'
a' CString
b' Int
x CString
c' Int
y Bool
d
    | Bool
otherwise = (Maybe FontSet
forall a. Maybe a
Nothing, CharSet -> CharSet'
CharSet' CharSet
CS.empty)

foreign import capi "fontconfig-wrap.h" fcFontSetSort ::
        Ptr Config' -> CString -> Int -> CString -> Int -> Bool -> Ptr Int -> CString

------
--- Utilities
------
-- | Variation of `withMessage` that's proving to be more concise.
arg :: MessagePack a => a -> (CString -> Int -> b) -> b
arg :: forall a b. MessagePack a => a -> (CString -> Int -> b) -> b
arg = ((CString -> Int -> b) -> a -> b)
-> a -> (CString -> Int -> b) -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip (CString -> Int -> b) -> a -> b
forall a b. MessagePack a => (CString -> Int -> b) -> a -> b
withMessage

------
--- CSS Bindings
------

-- | `StyleSheet` wrapper to parse @font-face rules.
data FontFaceParser a = FontFaceParser { forall a. FontFaceParser a -> FontSet
cssFonts :: FontSet, forall a. FontFaceParser a -> a
cssInner :: a}

emptyParser :: a -> FontFaceParser a
emptyParser :: forall a. a -> FontFaceParser a
emptyParser = FontSet -> a -> FontFaceParser a
forall a. FontSet -> a -> FontFaceParser a
FontFaceParser []

parseFontFaceSrc :: [Token] -> [String]
parseFontFaceSrc :: [Token] -> ObjectSet
parseFontFaceSrc (Function Text
"local":Ident Text
name:Token
RightParen:Token
Comma:[Token]
rest) =
    ([Char]
"local:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
unpack Text
name)[Char] -> ObjectSet -> ObjectSet
forall a. a -> [a] -> [a]
:[Token] -> ObjectSet
parseFontFaceSrc [Token]
rest
parseFontFaceSrc (Function Text
"local":String Text
name:Token
RightParen:Token
Comma:[Token]
rest) =
    ([Char]
"local:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
unpack Text
name)[Char] -> ObjectSet -> ObjectSet
forall a. a -> [a] -> [a]
:[Token] -> ObjectSet
parseFontFaceSrc [Token]
rest
parseFontFaceSrc (Function Text
"local":Ident Text
name:Token
RightParen:[]) = [[Char]
"local:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
unpack Text
name]
parseFontFaceSrc (Function Text
"local":String Text
name:Token
RightParen:[]) = [[Char]
"local:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
unpack Text
name]

parseFontFaceSrc (Function Text
"url":String Text
link:Token
RightParen:[Token]
toks) =
    [Token] -> ObjectSet
parseFontFaceSrc (Text -> Token
Url Text
linkToken -> [Token] -> [Token]
forall a. a -> [a] -> [a]
:[Token]
toks) -- TODO: Why's this needed?

parseFontFaceSrc (Url Text
link:[Token]
toks)
    | Token
Comma:[Token]
rest <- [Token] -> [Token]
skipMeta [Token]
toks = Text -> [Char]
unpack Text
link[Char] -> ObjectSet -> ObjectSet
forall a. a -> [a] -> [a]
:[Token] -> ObjectSet
parseFontFaceSrc [Token]
rest
    | [] <- [Token] -> [Token]
skipMeta [Token]
toks = [Text -> [Char]
unpack Text
link]
    | Bool
otherwise = [[Char]
""] -- Error indicator!
  where
    skipMeta :: [Token] -> [Token]
skipMeta (Function Text
"format":Ident Text
_:Token
RightParen:[Token]
rest) = [Token] -> [Token]
skipMeta [Token]
rest
    skipMeta (Function Text
"format":String Text
_:Token
RightParen:[Token]
rest) = [Token] -> [Token]
skipMeta [Token]
rest
    skipMeta (Function Text
"tech":Ident Text
_:Token
RightParen:[Token]
rest) = [Token] -> [Token]
skipMeta [Token]
rest
    skipMeta (Function Text
"tech":String Text
_:Token
RightParen:[Token]
rest) = [Token] -> [Token]
skipMeta [Token]
rest
    skipMeta [Token]
toks' = [Token]
toks'

parseFontFaceSrc [Token]
_ = [[Char]
""]

v :: ToValue x => x -> Value
v :: forall x. ToValue x => x -> Value
v = x -> Value
forall x. ToValue x => x -> Value
toValue

properties2font :: [(Text, [Token])] -> Pattern
properties2font :: [(Text, [Token])] -> Pattern
properties2font ((Text
"font-family", [String Text
font]):[(Text, [Token])]
props) =
    Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"family" [(Binding
Strong, [Char] -> Value
forall x. ToValue x => x -> Value
v ([Char] -> Value) -> [Char] -> Value
forall a b. (a -> b) -> a -> b
$ Text -> [Char]
unpack Text
font)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props
properties2font ((Text
"font-family", [Ident Text
font]):[(Text, [Token])]
props) =
    Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"family" [(Binding
Strong, [Char] -> Value
forall x. ToValue x => x -> Value
v ([Char] -> Value) -> [Char] -> Value
forall a b. (a -> b) -> a -> b
$ Text -> [Char]
unpack Text
font)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

properties2font ((Text
"font-stretch", [Token
tok]):[(Text, [Token])]
props) | Just Int
x <- Token -> Maybe Int
parseFontStretch Token
tok =
    Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"width" [(Binding
Strong, Int -> Value
forall x. ToValue x => x -> Value
v Int
x)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props
properties2font ((Text
"font-stretch", [Token
start, Token
end]):[(Text, [Token])]
props)
    | Just Int
x <- Token -> Maybe Int
parseFontStretch Token
start, Just Int
y <- Token -> Maybe Int
parseFontStretch Token
end =
        Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"width" [(Binding
Strong, Range -> Value
forall x. ToValue x => x -> Value
v (Range -> Value) -> Range -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Range
iRange Int
x Int
y)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

properties2font ((Text
"font-weight", [Token
tok]):[(Text, [Token])]
props) | Just Int
x <- Token -> Maybe Int
parseFontWeight Token
tok =
    Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"weight" [(Binding
Strong, Int -> Value
forall x. ToValue x => x -> Value
v Int
x)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props
properties2font ((Text
"font-weight", [Token
start, Token
end]):[(Text, [Token])]
props)
    | Just Int
x <- Token -> Maybe Int
parseFontStretch Token
start, Just Int
y <- Token -> Maybe Int
parseFontStretch Token
end =
        Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"weight" [(Binding
Strong, Range -> Value
forall x. ToValue x => x -> Value
v (Range -> Value) -> Range -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Range
iRange Int
x Int
y)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

properties2font ((Text
"font-feature-settings", [Token]
toks):[(Text, [Token])]
props)
    | ([([Char], Int)]
features, Bool
True, []) <- [Token] -> ([([Char], Int)], Bool, [Token])
parseFontFeatures [Token]
toks =
        Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"fontfeatures" [(Binding
Strong, [Char] -> Value
forall x. ToValue x => x -> Value
v ([Char] -> Value) -> [Char] -> Value
forall a b. (a -> b) -> a -> b
$ [Char] -> ObjectSet -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"," (ObjectSet -> [Char]) -> ObjectSet -> [Char]
forall a b. (a -> b) -> a -> b
$ (([Char], Int) -> [Char]) -> [([Char], Int)] -> ObjectSet
forall a b. (a -> b) -> [a] -> [b]
map ([Char], Int) -> [Char]
forall a b. (a, b) -> a
fst [([Char], Int)]
features)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$
            [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

properties2font ((Text
"font-variation-settings", [Token]
toks):[(Text, [Token])]
props)
    | ([([Char], Double)]
_, Bool
True, []) <- [Token] -> ([([Char], Double)], Bool, [Token])
parseFontVars [Token]
toks =
        Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"variable" [(Binding
Strong, Bool -> Value
forall x. ToValue x => x -> Value
v (Bool -> Value) -> Bool -> Value
forall a b. (a -> b) -> a -> b
$ Bool
True)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

properties2font ((Text
"unicode-range", [Token]
toks):[(Text, [Token])]
props)
    | Just CharSet
chars <- [Char] -> Maybe CharSet
parseCharSet ([Char] -> Maybe CharSet) -> [Char] -> Maybe CharSet
forall a b. (a -> b) -> a -> b
$ Text -> [Char]
unpack (Text -> [Char]) -> Text -> [Char]
forall a b. (a -> b) -> a -> b
$ HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
Txt.replace Text
"/**/" Text
"" (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ [Token] -> Text
serialize [Token]
toks =
        Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"charset" [(Binding
Strong, CharSet' -> Value
forall x. ToValue x => x -> Value
v (CharSet' -> Value) -> CharSet' -> Value
forall a b. (a -> b) -> a -> b
$ CharSet -> CharSet'
CharSet' CharSet
chars)] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

-- Ignoring metadata & trusting in FreeType's broad support for fonts.
properties2font ((Text
"src", [Token]
toks):[(Text, [Token])]
props)
    | fonts :: ObjectSet
fonts@([Char]
_:ObjectSet
_) <- [Token] -> ObjectSet
parseFontFaceSrc [Token]
toks, [Char]
"" [Char] -> ObjectSet -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` ObjectSet
fonts =
        Text -> [(Binding, Value)] -> Pattern -> Pattern
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
"web-src" [(Binding
Strong, [Char] -> Value
forall x. ToValue x => x -> Value
v [Char]
f) | [Char]
f <- ObjectSet
fonts] (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
$ [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props

properties2font ((Text, [Token])
_:[(Text, [Token])]
props) = [(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
props
properties2font [] = Pattern
forall k a. Map k a
M.empty

instance StyleSheet a => StyleSheet (FontFaceParser a) where
    setPriorities :: [Int] -> FontFaceParser a -> FontFaceParser a
setPriorities [Int]
prio (FontFaceParser FontSet
x a
self) = FontSet -> a -> FontFaceParser a
forall a. FontSet -> a -> FontFaceParser a
FontFaceParser FontSet
x (a -> FontFaceParser a) -> a -> FontFaceParser a
forall a b. (a -> b) -> a -> b
$ [Int] -> a -> a
forall s. StyleSheet s => [Int] -> s -> s
setPriorities [Int]
prio a
self
    addRule :: FontFaceParser a -> StyleRule -> FontFaceParser a
addRule (FontFaceParser FontSet
x a
self) StyleRule
rule = FontSet -> a -> FontFaceParser a
forall a. FontSet -> a -> FontFaceParser a
FontFaceParser FontSet
x (a -> FontFaceParser a) -> a -> FontFaceParser a
forall a b. (a -> b) -> a -> b
$ a -> StyleRule -> a
forall s. StyleSheet s => s -> StyleRule -> s
addRule a
self StyleRule
rule

    addAtRule :: FontFaceParser a -> Text -> [Token] -> (FontFaceParser a, [Token])
addAtRule (FontFaceParser FontSet
fonts a
self) Text
"font-face" [Token]
toks =
        let (([(Text, [Token])]
props, Text
_), [Token]
toks') = Parser ([(Text, [Token])], Text)
parseProperties [Token]
toks
        in (FontSet -> a -> FontFaceParser a
forall a. FontSet -> a -> FontFaceParser a
FontFaceParser ([(Text, [Token])] -> Pattern
properties2font [(Text, [Token])]
propsPattern -> FontSet -> FontSet
forall a. a -> [a] -> [a]
:FontSet
fonts) a
self, [Token]
toks')
    addAtRule (FontFaceParser FontSet
x a
self) Text
key [Token]
toks =
        let (a
a, [Token]
b) = a -> Text -> [Token] -> (a, [Token])
forall s. StyleSheet s => s -> Text -> [Token] -> (s, [Token])
addAtRule a
self Text
key [Token]
toks in (FontSet -> a -> FontFaceParser a
forall a. FontSet -> a -> FontFaceParser a
FontFaceParser FontSet
x a
a, [Token]
b)