Permalink
Browse files

big improvements to cairo documentation

  • Loading branch information...
1 parent eda6f32 commit b7203e915804c9cc78939d770bf79e9e6a50c914 Brent Yorgey committed Jan 5, 2013
@@ -10,9 +10,21 @@
-- A full-featured rendering backend for diagrams using the
-- cairo rendering engine.
--
--- To invoke the cairo backend, use methods from the
--- 'Diagrams.Core.Types.Backend' instance for @Cairo@. In particular,
--- 'Diagrams.Core.Types.renderDia' has the generic type
+-- To invoke the cairo backend, you have three options.
+--
+-- * You can use the "Diagrams.Backend.Cairo.CmdLine" module to create
+-- standalone executables which output images when invoked.
+--
+-- * You can use the 'renderCairo' function provided by this module,
+-- which gives you more flexible programmatic control over when and
+-- how images are output (making it easy to, for example, write a
+-- single program that outputs multiple images, or one that outputs
+-- images dynamically based on user input, and so on).
+--
+-- * Finally, for the most flexibility, you can directly
+-- use methods from the
+-- 'Diagrams.Core.Types.Backend' instance for @Cairo@. In particular,
+-- 'Diagrams.Core.Types.renderDia' has the generic type
--
-- > renderDia :: b -> Options b v -> QDiagram b v m -> Result b v
--
@@ -31,10 +43,6 @@
-- > }
--
-- @
--- data family Render Cairo R2 = C ('RenderM' ())
--- @
---
--- @
-- type family Result Cairo R2 = (IO (), 'Graphics.Rendering.Cairo.Render' ())
-- @
--
@@ -44,11 +52,18 @@
-- renderDia :: Cairo -> Options Cairo R2 -> QDiagram Cairo R2 m -> (IO (), 'Graphics.Rendering.Cairo.Render' ())
-- @
--
--- which you could call like @renderDia Cairo (CairoOptions "foo.png"
--- (Width 250) PNG False) myDiagram@. This would return a pair; the
--- first element is an @IO ()@ action which will write out @foo.png@
--- to disk, and the second is a cairo rendering action which can be
--- used, for example, to directly draw to a Gtk window.
+-- which you could call like so:
+--
+-- @
+-- renderDia Cairo (CairoOptions \"foo.png\" (Width 250) PNG False) (myDiagram :: Diagram Cairo R2)
+-- @
+--
+-- This would return a pair; the first element is an @IO ()@ action
+-- which will write out @foo.png@ to disk, and the second is a cairo
+-- rendering action which can be used, for example, to directly draw
+-- to a Gtk window. Note the type annotation on @myDiagram@ which may
+-- be necessary to fix the type variable @m@; this example uses the
+-- type synonym @Diagram b v = QDiagram b v Any@ to fix @m = Any@.
--
-----------------------------------------------------------------------------
module Diagrams.Backend.Cairo
@@ -96,10 +111,8 @@ import Diagrams.Prelude
-- > , cairoOutputType :: OutputType -- ^ the output format and associated options
-- > }
--
--- So, for example, you could call the 'renderDia' function (from
--- "Graphics.Rendering.Diagrams.Core") like this:
---
--- > renderDia Cairo (CairoOptions "foo.png" (Width 250) PNG) myDiagram
+-- See the documentation at the top of "Diagrams.Backend.Cairo" for
+-- information on how to make use of this.
--
-- /Important note/: a bug in GHC 7.0.x and 7.4.1 prevents
-- re-exporting this data family. (Strangely, this bug seems to be
@@ -26,8 +26,12 @@
-- 'defaultMain' (or 'multiMain', or 'animMain') in a call to
-- 'System.Environment.withArgs'.
--
--- * A more flexible approach is to directly call 'renderDia'; see
--- "Diagrams.Backend.Cairo" for more information.
+-- * A more flexible approach is to use the 'renderCairo' function
+-- provided in the "Diagrams.Backend.Cairo" module.
+--
+-- * For the most flexibility, you can call the generic 'renderDia'
+-- function directly; see "Diagrams.Backend.Cairo" for more
+-- information.
--
-----------------------------------------------------------------------------
@@ -29,6 +29,10 @@
-- sometimes to work around an apparent bug in certain versions of
-- GHC, which results in a \"not in scope\" error for 'CairoOptions'.
--
+-- The types of all the @fromX@ functions look funny in the Haddock
+-- output, which displays them like @Type -> Type@. In fact they are
+-- all of the form @Type -> Graphics.Rendering.Cairo.Type@, /i.e./
+-- they convert from a diagrams type to a cairo type of the same name.
-----------------------------------------------------------------------------
module Diagrams.Backend.Cairo.Internal where
@@ -56,23 +60,24 @@ import Data.Typeable
-- | This data declaration is simply used as a token to distinguish
-- the cairo backend: (1) when calling functions where the type
--- inference engine would otherwise have know way to know which
+-- inference engine would otherwise have no way to know which
-- backend you wanted to use, and (2) as an argument to the
-- 'Backend' and 'Renderable' type classes.
data Cairo = Cairo
deriving (Eq,Ord,Read,Show,Typeable)
-- | Output types supported by cairo, including four different file
-- types (PNG, PS, PDF, SVG). If you want to output directly to GTK
--- windows, see the diagrams-gtk package.
+-- windows, see the @diagrams-gtk@ package.
data OutputType =
- PNG -- ^ Portable Network Graphics output.
- | PS -- ^ PostScript output
- | PDF -- ^ Portable Document Format output.
- | SVG -- ^ Scalable Vector Graphics output.
+ PNG -- ^ Portable Network Graphics output.
+ | PS -- ^ PostScript output
+ | PDF -- ^ Portable Document Format output.
+ | SVG -- ^ Scalable Vector Graphics output.
| RenderOnly -- ^ Don't output any file; the returned @IO ()@
- -- action will do nothing, but the @Render ()@ action
- -- can be used (e.g. to draw to a Gtk window)
+ -- action will do nothing, but the @Render ()@
+ -- action can be used (/e.g./ to draw to a Gtk
+ -- window; see the @diagrams-gtk@ package).
instance Monoid (Render Cairo R2) where
mempty = C $ return ()
@@ -152,6 +157,7 @@ instance Backend Cairo R2 where
c opts (d # reflectY)
where setCairoSizeSpec sz o = o { cairoSizeSpec = sz }
+-- | Render an object that the cairo backend knows how to render.
renderC :: (Renderable a Cairo, V a ~ R2) => a -> RenderM ()
renderC a = case (render Cairo a) of C r -> r
@@ -209,6 +215,7 @@ cairoStrokeStyle s =
lDashing (getDashing -> Dashing ds offs) =
C.setDash ds offs
+-- | Set the source color.
setSource :: Color c => c -> Style v -> C.Render ()
setSource c s = C.setSourceRGBA r g b a'
where (r,g,b,a) = colorToSRGBA c
@@ -26,15 +26,16 @@ module Diagrams.Backend.Cairo.Text
(
-- * Primitives
- -- | These create diagrams instantiated with extents-based envelopes
+ -- | These create diagrams instantiated with extent-based envelopes.
textLineBoundedIO, textVisualBoundedIO
-- ** Unsafe
-- | These are convenient unsafe variants of the above operations
- -- postfixed with \"IO\". They should be pretty well-behaved as the
- -- results just depend on the parameters and the font information
- -- (which ought to stay the same during a given execution).
+ -- using 'unsafePerformIO'. In practice, they should be fairly
+ -- safe as the results depend only on the parameters and the
+ -- font information (which ought to stay the same during a given
+ -- execution).
, kerningCorrection, textLineBounded, textVisualBounded
@@ -66,13 +67,13 @@ import qualified Graphics.Rendering.Cairo as C
queryCairo :: C.Render a -> IO a
queryCairo c = C.withImageSurface C.FormatA1 0 0 (`C.renderWith` c)
--- | Unsafely invokes @queryCairo@.
+-- | Unsafely invokes 'queryCairo' using 'unsafePerformIO'.
unsafeCairo :: C.Render a -> a
unsafeCairo = unsafePerformIO . queryCairo
--- | Executes the given cairo action, with styling applied.
--- This does not do all styling - just attributes that are processed by
--- \"cairoMiscStyle\", which does clip, fill color, fill rule, and,
+-- | Executes the given cairo action, with styling applied. This does
+-- not do all styling, only attributes that are processed by
+-- 'cairoMiscStyle', which does clip, fill color, fill rule, and,
-- importantly for this module, font face, style, and weight.
cairoWithStyle :: C.Render a -> Style R2 -> C.Render a
cairoWithStyle f style = do
@@ -110,9 +111,9 @@ getFontExtents :: Style R2 -> C.Render FontExtents
getFontExtents style
= cairoWithStyle (processFontExtents <$> C.fontExtents) style
--- | Gets both the "FontExtents" and "TextExtents" of the string with the a
+-- | Gets both the 'FontExtents' and 'TextExtents' of the string with the a
-- particular style applied. This is more efficient than calling both
--- @getFontExtents@ and @getTextExtents@.
+-- 'getFontExtents' and 'getTextExtents'.
getExtents :: Style R2 -> String -> C.Render (FontExtents, TextExtents)
getExtents style str = cairoWithStyle (do
fe <- processFontExtents <$> C.fontExtents
@@ -121,8 +122,8 @@ getExtents style str = cairoWithStyle (do
) style
-- | Queries the amount of horizontal offset that needs to be applied in order to
--- position the second character properly, in the event that it is @hcat@-ed
--- @baselineText@.
+-- position the second character properly, in the event that it is 'hcat'-ed
+-- 'baselineText'.
kerningCorrectionIO :: Style R2 -> Char -> Char -> IO Double
kerningCorrectionIO style a b = do
let ax t = fst . unr2 . advance <$> queryCairo (getTextExtents style t)
@@ -132,7 +133,7 @@ kerningCorrectionIO style a b = do
return $ l - la - lb
-- | Creates text diagrams with their envelopes set such that using
--- @vcat . map (textLineBounded style)@ stacks them in the way that
+-- @'vcat' . map ('textLineBounded' style)@ stacks them in the way that
-- the font designer intended.
textLineBoundedIO :: Style R2 -> String -> IO (Diagram Cairo R2)
textLineBoundedIO style str = do
@@ -150,9 +151,25 @@ textVisualBoundedIO style str = do
((origin .+^ bearing te) .+^ textSize te)
return . setEnvelope (getEnvelope box) . applyStyle style $ baselineText str
+-- | Queries the amount of horizontal offset that needs to be applied
+-- in order to position the second character properly, in the event
+-- that it is 'hcat'-ed 'baselineText'. See 'kerningCorrectionIO';
+-- this variant uses 'unsafePerformIO' but should be fairly safe in
+-- practice.
kerningCorrection :: Style R2 -> Char -> Char -> Double
kerningCorrection style a = unsafePerformIO . kerningCorrectionIO style a
-textLineBounded, textVisualBounded :: Style R2 -> String -> Diagram Cairo R2
+-- | Creates text diagrams with their envelopes set such that using
+-- @'vcat' . map ('textLineBounded' style)@ stacks them in the way
+-- that the font designer intended. See 'textLineBoundedIO'; this
+-- variant uses 'unsafePerformIO' but should be fairly safe in
+-- practice.
+textLineBounded :: Style R2 -> String -> Diagram Cairo R2
textLineBounded style = unsafePerformIO . textLineBoundedIO style
+
+-- | Creates a text diagram with its envelope set to enclose the
+-- glyphs of the text, including leading (though not trailing)
+-- whitespace. See 'textVisualBoundedIO'; this variant uses
+-- 'unsafePerformIO' but should be fairly safe in practice.
+textVisualBounded :: Style R2 -> String -> Diagram Cairo R2
textVisualBounded style = unsafePerformIO . textVisualBoundedIO style

0 comments on commit b7203e9

Please sign in to comment.