-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhbox.hs
75 lines (58 loc) · 2.43 KB
/
hbox.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{-# LANGUAGE FlexibleContexts #-}
import Diagrams.Backend.PGF.CmdLine
import Diagrams.Prelude
import Diagrams.TwoD.Vector (perp)
import Diagrams.Size
type D2 = Diagram PGF
-- The simplest way to construct a hbox with an envelope is to use
--
-- envelopedText = surfHbox mysurf "text" :: Diagram PGF V2 Double
--
-- which can be used just like any other diagram. However, each box like this
-- makes a call to TeX, so for multiple boxes this can become slow.
--
-- This examples shows how to use the OnlineTeX monad to construct a diagram
-- with multiple hboxs with a single call to TeX.
main = main1
-- The simplest option. The command line gives the option to use the default
-- latex, context or plain tex surface (latex is the default).
main1 = onlineMain example
-- Similar to 'onlineMain' but uses the specified surface.
main2 = onlineMainWithSurf (with & command .~ "lualatex") example
-- Alternatively, 'renderOnlinePDF' can be used to directly generate a pdf.
main3 = renderOnlinePGF "hbox.pdf" absolute example
-- "renderOnlinePDF'" allows choosing rendering options
main4 = renderOnlinePGF' "hbox.tex"
(with & sizeSpec .~ mkWidth 300 & standalone .~ True)
example
example :: OnlineTex D2
example = frame 5 . scale 10 <$> hboxLines "\\TeX"
-- Use the envelope from the hbox to label the width, height and depth.
hboxLines :: String -> OnlineTex D2
hboxLines str = do
txt <- hboxOnline str
let h = envelopeV unitY txt
d = envelopeV unit_Y txt
w = envelopeV unitX txt
hArrow <- labeledArrow False "height" h
dArrow <- labeledArrow True "depth" d
wArrow <- labeledArrow False "width" w
return $ (txt <> boundingRect txt <> fromOffsets [w])
||| strutX 1 ||| (hArrow === dArrow)
=== strutY 1
=== wArrow
--
-- Draw an arrow with a horizontal label above or below.
labeledArrow :: Bool -> String -> V2 Double -> OnlineTex D2
labeledArrow above label r = diaArrow <$> hboxOnline label
where
diaArrow txt = atDirection ((direction . rev . perp) r)
(arr # translate (negated $ r^/2))
(txt # centerXY # scale 0.1 # frame 0.3)
# translate (r^/2)
where
rev = if above then id else negated
arr = arrowV' ops r
ops = with & arrowHead .~ spike
& arrowTail .~ spike'
& lengths .~ normalized 0.015