{-# LANGUAGE CApiFFI #-}
-- | Languages supported by different fonts.
module Graphics.Text.Font.Choose.LangSet(
LangSet, LangSet'(..), module S, LangComparison(..), validLangSet, validLangSet',
cmp, has, defaultLangs, langs, normalize, langCharSet) where
import Data.Set (Set)
import qualified Data.Set as S
import Data.MessagePack (MessagePack(..))
import Test.QuickCheck (Arbitrary(..), elements, listOf)
import Graphics.Text.Font.Choose.StrSet (StrSet(..))
import Graphics.Text.Font.Choose.CharSet as CS (CharSet'(..), empty)
import Foreign.C.String (CString)
import Foreign.Ptr (Ptr)
import Graphics.Text.Font.Choose.Internal.FFI (withMessage, fromMessage0, withCString', peekCString')
import Graphics.Text.Font.Choose.Result
import Control.Exception (throw)
type LangSet = Set String
newtype LangSet' = LangSet' { unLangSet :: LangSet } deriving (Eq, Show, Read)
validLangSet :: LangSet -> Bool
validLangSet x = all validLang x && not (null x)
validLangSet' :: LangSet' -> Bool
validLangSet' = validLangSet . unLangSet
validLang :: String -> Bool
validLang = (`elem` unStrSet langs)
instance MessagePack LangSet' where
toObject = toObject . S.toList . unLangSet
fromObject msg = LangSet' <$> S.fromList <$> fromObject msg
instance Arbitrary LangSet' where
arbitrary = LangSet' <$> S.fromList <$> listOf (elements $ S.toList $ unStrSet langs)
data LangComparison = SameLang | SameTerritory | DifferentLang
i2cmp :: Int -> LangComparison
i2cmp 0 = DifferentLang
i2cmp 1 = SameLang
i2cmp 2 = SameTerritory
i2cmp _ = throw ErrOOM
cmp :: LangSet' -> LangSet' -> LangComparison
cmp a b | valid a && valid b = i2cmp $ withMessage fcLangSetCompare [a, b]
| otherwise = DifferentLang
where valid = validLangSet'
foreign import capi "fontconfig-wrap.h" fcLangSetCompare :: CString -> Int -> Int
has :: LangSet' -> String -> LangComparison
has a b | validLangSet' a && validLang b =
i2cmp $ flip withCString' b $ withMessage fcLangSetHasLang a
| otherwise = DifferentLang
foreign import capi "fontconfig-wrap.h" fcLangSetHasLang :: CString -> Int -> CString -> Int
defaultLangs :: StrSet
defaultLangs = fromMessage0 fcGetDefaultLangs
foreign import capi "fontconfig-wrap.h" fcGetDefaultLangs :: Ptr Int -> CString
langs :: StrSet
langs = fromMessage0 fcGetLangs
foreign import capi "fontconfig-wrap.h" fcGetLangs :: Ptr Int -> CString
normalize :: String -> String
normalize = peekCString' . withCString' fcLangNormalize
foreign import capi "fontconfig-wrap.h" fcLangNormalize :: CString -> CString
langCharSet :: String -> CharSet'
langCharSet a | validLang a = fromMessage0 $ withCString' fcLangGetCharSet a
| otherwise = CharSet' CS.empty
foreign import capi "fontconfig-wrap.h" fcLangGetCharSet :: CString -> Ptr Int -> CString