module Graphics.Aosd.Pango(
TextRenderer(..),Width(..),textRenderer,
PangoText,pText,pRaw,pEmpty,pTag,
pSpan,pBold,pBig,pItalic,pStrikethrough,pSmall,pSub,pSup,pUnderline,pMono,
pSized,
pIntercalate,pUnlines,pUnwords,pShow,
SpanAttribute(..),
LayoutAlignment(..),
LayoutWrapMode(..),
TabPosition,
Size(..),
sRGB,
module Graphics.Aosd,
module Data.Monoid,
module Data.Colour.Names
) where
import Control.Monad.IO.Class
import Foreign.C
import Graphics.Aosd
import Graphics.Aosd.Util
import Graphics.Rendering.Pango.Cairo
import Graphics.Rendering.Pango.Enums
import Graphics.Rendering.Pango.Layout
import Control.Monad(void)
import Graphics.Rendering.Pango.Markup
import Data.Monoid
import Data.String
import Data.List(intersperse)
import Data.Colour
import Data.Colour.SRGB
import Data.Colour.Names
data TextRenderer = TextRenderer {
colour :: Colour Double,
opacity :: Double,
width :: Maybe Width,
wrapMode :: Maybe LayoutWrapMode,
justify :: Maybe Bool,
alignment :: Maybe LayoutAlignment,
lineSpacing :: Maybe Double,
tabs :: Maybe [TabPosition],
singleParagraphMode :: Maybe Bool,
tcText :: PangoText
}
data Width = Unlimited
| Width Double
deriving(Show,Eq)
unsup :: String -> t
unsup s = error (s ++ " unsupported for Graphics.Aosd.Pango.Width")
instance Num Width where
fromInteger = Width . fromIntegral
(+) = unsup "(+)"
(*) = unsup "(*)"
abs = unsup "abs"
signum = unsup "signum"
() = unsup "(-)"
negate = unsup "negate"
instance Fractional Width where
fromRational = Width . fromRational
(/) = unsup "/"
recip = unsup "recip"
textRenderer :: PangoText -> TextRenderer
textRenderer t = TextRenderer {
colour = green,
opacity = 1,
width = Nothing,
wrapMode = Nothing,
justify = Nothing,
alignment = Nothing,
lineSpacing = Nothing,
tabs = Nothing,
singleParagraphMode = Nothing,
tcText = t
}
data PangoText = PlainText ShowS
| PangoMarkup ShowS
| Empty
toMarkup :: PangoText -> ShowS
toMarkup (PlainText s) = showString (escapeMarkup (s ""))
toMarkup (PangoMarkup s) = s
toMarkup Empty = mempty
instance IsString PangoText where
fromString = pText
instance Monoid PangoText where
mempty = Empty
mappend Empty x2 = x2
mappend x1 Empty = x1
mappend (PlainText s1) (PlainText s2) = PlainText (s1 . s2)
mappend x1 x2 = PangoMarkup (toMarkup x1 . toMarkup x2)
instance Show PangoText where
showsPrec _ Empty = showString "pEmpty"
showsPrec prec (PlainText s) = showParen (prec >= 11) (showString "pText " . shows (s ""))
showsPrec prec (PangoMarkup s) = showParen (prec >= 11) (showString "pRaw " . shows (s ""))
pEmpty :: PangoText
pEmpty = Empty
pRaw :: String -> PangoText
pRaw = PangoMarkup . showString
pText :: String -> PangoText
pText = PlainText . showString
pSpan :: [SpanAttribute] -> PangoText -> PangoText
pSpan (attrs :: [SpanAttribute]) inner = PangoMarkup it
where
it =
showString "<span" .
foldr (.) (showChar '>') (map shows attrs) .
toMarkup inner .
showString "</span>"
pIntercalate :: PangoText -> [PangoText] -> PangoText
pIntercalate x = mconcat . intersperse x
pUnlines :: [PangoText] -> PangoText
pUnlines = pIntercalate (pText "\n")
pUnwords :: [PangoText] -> PangoText
pUnwords = pIntercalate (pText " ")
pShow :: Show a => a -> PangoText
pShow = pText . show
pSized :: Double -> PangoText -> PangoText
pSized pt = pSpan [FontSize (SizePoint pt)]
pTag :: String
-> PangoText -> PangoText
pTag tagName inner = PangoMarkup $
showChar '<' . showString tagName . showChar '>' .
toMarkup inner .
showString "</" . showString tagName . showChar '>'
pBold :: PangoText -> PangoText
pBold = pTag "b"
pBig :: PangoText -> PangoText
pBig = pTag "big"
pItalic :: PangoText -> PangoText
pItalic = pTag "i"
pStrikethrough :: PangoText -> PangoText
pStrikethrough = pTag "s"
pSub :: PangoText -> PangoText
pSub = pTag "sub"
pSup :: PangoText -> PangoText
pSup = pTag "sup"
pSmall :: PangoText -> PangoText
pSmall = pTag "small"
pMono :: PangoText -> PangoText
pMono = pTag "tt"
pUnderline :: PangoText -> PangoText
pUnderline = pTag "u"
layoutSetWidth' :: PangoLayout -> Width -> IO ()
layoutSetWidth' layout w = layoutSetWidth layout (case w of
Unlimited -> Nothing
Width x -> Just x)
instance AosdRenderer TextRenderer where
toGeneralRenderer TextRenderer{..} = do
fm <- cairoFontMapGetDefault
cxt <- cairoCreateContext (Just fm)
layout <- layoutEmpty cxt
case tcText of
Empty -> return ()
PlainText s -> layoutSetText layout (s "")
PangoMarkup s -> void (layoutSetMarkup layout (s ""))
let go :: (PangoLayout -> a -> IO ()) -> Maybe a -> IO ()
go f = maybeDo (f layout)
go layoutSetWidth' width
go layoutSetWrap wrapMode
go layoutSetJustify justify
go layoutSetAlignment alignment
go layoutSetSpacing lineSpacing
go layoutSetTabs tabs
go layoutSetSingleParagraphMode singleParagraphMode
(grInkExtent,grPositioningExtent) <- layoutGetPixelExtents layout
let render = do
setSourceColour colour opacity
showLayout layout
return GeneralRenderer { grInkExtent, grPositioningExtent, grRender = render }