{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TemplateHaskell #-} ------------------------------------------------------------------------------- -- | -- Module : Diagrams.Backend.Rasterific.Text -- Copyright : (c) 2015 diagrams-rasterific team (see LICENSE) -- License : BSD-style (see LICENSE) -- Maintainer : diagrams-discuss@googlegroups.com -- -- Experimental module to create text with an envelope and trace. The -- texterifc functions build diagrams with text size of @'local' 1@ and -- a s specified slant and weight. The size should be changed only with -- the scale functions and changing the slant and/or weight after the -- text has benn created can result in an slightly incorrect envelope. ------------------------------------------------------------------------------- module Diagrams.Backend.Rasterific.Text ( texterific' , texterific , fromFontStyle , textBoundingBox ) where import Graphics.Text.TrueType hiding (BoundingBox) import Diagrams.Prelude import Diagrams.TwoD.Text hiding (Font) import Data.FileEmbed (embedDir) import Data.ByteString (ByteString) import Data.ByteString.Lazy (fromStrict) -- | Get the 'BoundingBox' for some font with the origin at the start of -- the baseline. textBoundingBox :: RealFloat n => Font -> PointSize -> String -> BoundingBox V2 n textBoundingBox f p s = fromCorners (mkP2 (2*r2f _xMin bb) (r2f _yMin bb)) (mkP2 (r2f _xMax bb + r2f _xMin bb) (r2f _yMax bb)) where r2f = fmap realToFrac bb = stringBoundingBox f 96 p s -- | Create a primitive text diagram from the given 'FontSlant', -- 'FontWeight', and string, with baseline alignment, envelope and trace -- based on the 'BoundingBox' of the text. texterific' :: (TypeableFloat n, Renderable (Text n) b) => FontSlant -> FontWeight -> String -> QDiagram b V2 n Any texterific' fs fw s = recommendFillColor black . fontSizeL 1 . fontSlant fs . fontWeight fw $ mkQD (Prim $ Text mempty BaselineText s) (getEnvelope bb) (getTrace bb) mempty (getQuery bb) where bb = textBoundingBox fnt (PointSize 1) s fnt = fromFontStyle fs fw -- | Create a primitive text diagram from the given string, with -- baseline alignment, envelope and trace based on the 'BoundingBox' -- of the text. Designed to be a replacement for the function 'text' -- in Diagrams.TwoD.Text. texterific :: (TypeableFloat n, Renderable (Text n) b) => String -> QDiagram b V2 n Any texterific s = texterific' FontSlantNormal FontWeightNormal s -- | Get an OpenSans font with the given 'FontSlant' and 'FontWeight'. fromFontStyle :: FontSlant -> FontWeight -> Font fromFontStyle FontSlantItalic FontWeightBold = openSansBoldItalic fromFontStyle FontSlantOblique FontWeightBold = openSansBoldItalic fromFontStyle FontSlantNormal FontWeightBold = openSansBold fromFontStyle FontSlantItalic FontWeightNormal = openSansItalic fromFontStyle FontSlantOblique FontWeightNormal = openSansItalic fromFontStyle _ _ = openSansRegular fonts :: [(FilePath,ByteString)] fonts = $(embedDir "fonts") -- Read a static font file which is included with the package. staticFont :: String -> Font staticFont nm = case lookup nm fonts of Nothing -> error ("Font not found: " ++ nm) Just f -> case decodeFont (fromStrict f) of Right r -> r Left e -> error e openSansRegular :: Font openSansRegular = staticFont "OpenSans-Regular.ttf" openSansBold :: Font openSansBold = staticFont "OpenSans-Bold.ttf" openSansItalic :: Font openSansItalic = staticFont "OpenSans-Italic.ttf" openSansBoldItalic :: Font openSansBoldItalic = staticFont "OpenSans-BoldItalic.ttf"