{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.Backend.PGF -- Copyright : (c) 2014 Christopher Chalmers -- License : BSD-style (see LICENSE) -- Maintainer : diagrams-discuss@googlegroups.com -- -- A hbox a primitive Tex box, typically used for holding text and -- formulas but can hold anything. This module provides functions for -- retrieving the dimensions of these boxes to give diagrams the correct -- envelopes. ----------------------------------------------------------------------------- module Diagrams.Backend.PGF.Hbox ( Hbox (..) -- * Enveloped diagrams -- | The dimensions of a hbox can be recovered by calling Tex. The -- resulting envelope has its origin at the baseline of the text. -- -- <> , hboxOnline -- ** Non-Online version -- | These versions bypass 'OnlineTex' by just running a whole tex -- program just to get the size of a single hbox. This is not -- recommended but because it is slow, but can be convientient if -- you only need one or two hbox sizes. , hboxSurf , hboxSurfIO -- * Point envelope diagrams , hboxPoint ) where import Data.ByteString.Char8 (pack) import Data.Monoid import Data.Typeable import System.IO.Unsafe import System.Texrunner.Online hiding (hbox) import qualified System.Texrunner.Online as Online import System.Texrunner.Parse import Diagrams.Core.Envelope (pointEnvelope) import Diagrams.Prelude hiding (Box, (<>)) import Diagrams.Backend.PGF.Surface -- | Primitive for placing raw Tex commands in a hbox. data Hbox n = Hbox (Transformation V2 n) String deriving Typeable type instance V (Hbox n) = V2 type instance N (Hbox n) = n instance Fractional n => Transformable (Hbox n) where transform t (Hbox tt str) = Hbox (t <> tt) str instance Fractional n => Renderable (Hbox n) NullBackend where render _ _ = mempty -- | Raw Tex commands in a hbox with no envelope. Transformations are -- applied normally. This primitive ignores -- 'Diagrams.TwoD.Text.FontSize'. hboxPoint :: (OrderedField n, Typeable n, Renderable (Hbox n) b) => String -> QDiagram b V2 n Any hboxPoint raw = mkQD (Prim (Hbox mempty raw)) (pointEnvelope origin) mempty mempty mempty -- | Hbox with bounding box envelope. Note that each box requires a call to -- Tex. For multiple boxes consider using 'onlineHbox' to get multiple boxes -- from a single call. (uses unsafePerformIO) hboxSurf :: (TypeableFloat n, Renderable (Hbox n) b) => Surface -> String -> QDiagram b V2 n Any hboxSurf surf txt = unsafePerformIO (hboxSurfIO surf txt) {-# NOINLINE hboxSurf #-} -- | Hbox with bounding box envelope. Note that each box requires a call to -- Tex. For multiple boxes consider using 'onlineHbox' to get multiple boxes -- from a single call. hboxSurfIO :: (TypeableFloat n, Renderable (Hbox n) b) => Surface -> String -> IO (QDiagram b V2 n Any) hboxSurfIO surf txt = surfOnlineTexIO surf (hboxOnline txt) -- | Hbox with bounding box envelope. hboxOnline :: (TypeableFloat n, Renderable (Hbox n) b) => String -> OnlineTex (QDiagram b V2 n Any) hboxOnline txt = do Box h d w <- Online.hbox (pack txt) let bb = fromCorners (P $ V2 0 (-d)) (P $ V2 w h) return $ mkQD (Prim (Hbox mempty txt)) (getEnvelope bb) (getTrace bb) mempty (boundingBoxQuery bb)