{-# LANGUAGE OverloadedStrings #-} module Language.LaTeX.Builder.Color ( -- * The type of colors Color -- * Coloring commands ,pagecolor ,color ,textcolor ,colorbox ,fcolorbox ,preamblecolor ,normalcolor -- * Making colors ,named, rgb, cmyk, gray, html, rgb256 -- * Predefined colors ,red, green, blue, black, white, cyan, magenta, yellow, orange -- * Package name ,pkg) where import Data.String import Data.Word import Language.LaTeX.Types import qualified Language.LaTeX.Builder.Internal as BI import Control.Monad.Error (throwError) -- Some HTML docs at http://en.wikibooks.org/wiki/LaTeX/Colors data Color = BaseColor String | NamedColor String | RGB Rational Rational Rational | RGB256 Word8 Word8 Word8 | HTML String | CMYK Rational Rational Rational Rational | Gray Rational colorArgs :: Color -> [Arg AnyItem] colorArgs = (BI.packageDependency pkg:) . f where f (BaseColor n) = [man n] f (NamedColor n) = [opt "named", man n] f (RGB r g b) = model "rgb" (checkRatios [r,g,b]) f (RGB256 r g b) = model "RGB" [r,g,b] f (CMYK c m y k) = model "cmyk" (checkRatios [c,m,y,k]) f (Gray g) = model "gray" (checkRatios [g]) f (HTML s) = [opt "HTML", man . checkHTML $ s] opt = BI.optionalLatexItem . fromString man = BI.mandatoryLatexItem . fromString model name cs = [opt name, BI.mandatoryList . map BI.num $ cs] check msg p x | p x = x | otherwise = error msg checkHTML = check "Not a HTML color (6 hex digits)" (\s -> length s == 6 && all (`elem` (['0'..'9']++['a'..'F']++['A'..'F'])) s) checkRatios = check "Not a rational number between 0 and 1" (all checkRatio) checkRatio x = x >= 0 && x <= 1 red, green, blue, black, white, cyan, magenta, yellow :: Color [red, green, blue, black, white, cyan, magenta, yellow] = map BaseColor ["red", "green", "blue", "black", "white", "cyan", "magenta", "yellow"] orange :: Color orange = rgb 1 0.5 0 pkg :: PackageName pkg = BI.pkgName "color" named :: String -> Color named = NamedColor rgb :: Rational -> Rational -> Rational -> Color rgb = RGB cmyk :: Rational -> Rational -> Rational -> Rational -> Color cmyk = CMYK gray :: Rational -> Color gray = Gray rgb256 :: Word8 -> Word8 -> Word8 -> Color rgb256 = RGB256 html :: String -> Color html = HTML -- | 'pagecolor' sets the background colour for the current and following pages pagecolor :: Color -> ParItem pagecolor = BI.parCmdArgs "pagecolor" . colorArgs -- | 'color' is a declaration to switch to setting text in the given colour color :: Color -> TexDecl color = BI.texDecl' "color" . colorArgs -- | 'textcolor' sets the text of its argument in the given colour textcolor :: Color -> LatexItem -> LatexItem textcolor c x = BI.latexCmdAnyArgs "textcolor" (colorArgs c ++ [BI.mandatoryLatexItem x]) -- | 'colorbox' sets its argument in a box with the given colour as background colorbox :: Color -> LatexItem -> LatexItem colorbox c x = BI.latexCmdAnyArgs "colorbox" (colorArgs c ++ [BI.mandatoryLatexItem x]) -- | @fcolorbox c1 c2 text@ is like 'colorbox', with a frame of @c1@ around a box -- of background colour @c2@. -- For example, @fcolorbox red green "Text"@ sets `Text' in the current text colour -- on a green background with a red frame. -- -- The two specifications must either both be defined ones, or both use the same -- model, which is given only once, this limitation only make sense in LaTeX -- parlance but is helpful here to understand why this function can fail. fcolorbox :: Color -> Color -> LatexItem -> LatexItem fcolorbox c1 c2 x = let args = case (colorArgs c1, colorArgs c2) of ([p, m1, a1], [_, m2, a2]) | m1 == m2 -> [p, m1, a1, a2] ([p, a1], [_, a2]) -> [p, a1, a2] _ -> [BI.mandatory (AnyItem $ throwError "fcolorbox: arguments must be either of the same model,\ \ or be defined colors.")] in BI.latexCmdAnyArgs "fcolorbox" (args ++ [BI.mandatoryLatexItem x]) -- | Like 'color' but usable in the preamble. preamblecolor :: Color -> PreambleItem preamblecolor = BI.preambleCmdArgs "color" . colorArgs -- | 'normalcolor' switches to the colour that was active at the end of the preamble. -- Thus placing a 'color' declaration in the preamble can change the standard colour -- for the whole document. This is the equivalent to 'normalfont' for font selection. normalcolor :: TexDecl normalcolor = BI.texDecl' "normalcolor" [BI.packageDependency pkg]