File: Font.hs

package info (click to toggle)
haskell-hgl 3.1-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 432 kB
  • ctags: 12
  • sloc: haskell: 2,585; makefile: 60; sh: 22
file content (174 lines) | stat: -rw-r--r-- 5,235 bytes parent folder | download | duplicates (7)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.HGL.Draw.Font
-- Copyright   :  (c) Alastair Reid, 1999-2003
-- License     :  BSD-style (see the file libraries/base/LICENSE)
-- 
-- Maintainer  :  libraries@haskell.org
-- Stability   :  provisional
-- Portability :  non-portable (requires concurrency)
--
-- Text fonts.
--
-- Portability notes:
--
-- * X11 does not directly support font rotation so 'createFont' and
--   'mkFont' always ignore the rotation angle argument in the X11
--   implementation of this library.
--
-- * Many of the font families typically available on Win32 are not
--   available on X11 (and /vice-versa/).  In our experience, the font
--   families /courier/, /helvetica/ and /times/ are somewhat portable.
--
-----------------------------------------------------------------------------

#include "HsHGLConfig.h"

module Graphics.HGL.Draw.Font
	( Font
	, createFont
	, deleteFont
	, selectFont		-- :: Font -> Draw Font
	, mkFont
	) where

#if !X_DISPLAY_MISSING
import qualified Graphics.HGL.Internals.Utilities as Utils
import Graphics.HGL.X11.Types (Font(Font), DC(..), DC_Bits(..))
import Graphics.HGL.X11.Display (getDisplay)
import qualified Graphics.X11.Xlib as X
import Control.Concurrent.MVar (takeMVar, putMVar)
#else
import Graphics.HGL.Win32.Types
import qualified Graphics.Win32 as Win32
#endif

import Graphics.HGL.Units (Size, Angle)
import Graphics.HGL.Draw.Monad (Draw, bracket, ioToDraw)
import Graphics.HGL.Internals.Draw (mkDraw)

----------------------------------------------------------------
-- Interface
----------------------------------------------------------------

#if X_DISPLAY_MISSING
newtype Font = MkFont Win32.HFONT
#endif

-- | Create a font.
-- The rotation angle is ignored if the font is not a \"TrueType\" font
-- (e.g., a @System@ font on Win32).
createFont
	:: Size		-- ^ size of character glyphs in pixels
	-> Angle	-- ^ rotation angle
	-> Bool		-- ^ bold font?
	-> Bool		-- ^ italic font?
	-> String	-- ^ font family
	-> IO Font

-- | Delete a font created with 'createFont'.
deleteFont :: Font -> IO ()

-- | Set the font for subsequent text, and return the previous font.
selectFont :: Font -> Draw Font  

-- | Generate a font for use in a drawing, and delete it afterwards.
-- The rotation angle is ignored if the font is not a \"TrueType\" font
-- (e.g., a @System@ font on Win32).
mkFont	:: Size		-- ^ size of character glyphs in pixels
	-> Angle	-- ^ rotation angle
	-> Bool		-- ^ bold font?
	-> Bool		-- ^ italic font?
	-> String	-- ^ font family
	-> (Font  -> Draw a)
	-> Draw a

----------------------------------------------------------------
-- Implementation
----------------------------------------------------------------

mkFont size angle bold italic family =
  bracket (ioToDraw $ createFont size angle bold italic family)
          (ioToDraw . deleteFont)

#if !X_DISPLAY_MISSING

createFont (width, height) escapement bold italic family = do
  display <- getDisplay
--  print fontName
  r <- Utils.safeTry (X.loadQueryFont display fontName)
  case r of
    Left e  -> ioError (userError $ "Unable to load font " ++ fontName)
    Right f -> return (Font f)
 where
  fontName = concatMap ('-':) fontParts
  fontParts = [ foundry
              , family
              , weight
              , slant
              , sWdth
              , adstyl
              , pxlsz
              , ptSz
              , resx
              , resy
              , spc
              , avgWidth
              , registry
              , encoding
              ]
  foundry  = "*" -- eg "adobe"
  -- family   = "*" -- eg "courier"
  weight   = if bold then "bold" else "medium"
  slant    = if italic then "i" else "r"
  sWdth    = "normal"
  adstyl   = "*"
  pxlsz    = show height
  ptSz     = "*"
  resx     = "75"
  resy     = "75"
  spc      = "*"
  avgWidth = show (width*10) -- not sure what unit they use
  registry = "*"
  encoding = "*"

deleteFont (Font f) = do
  display <- getDisplay
  X.freeFont display f

selectFont f@(Font x) = mkDraw $ \ dc -> do
  bs <- takeMVar (ref_bits dc)
  putMVar (ref_bits dc) bs{font=f}
  X.setFont (disp dc) (textGC dc) (X.fontFromFontStruct x)
  return (font bs)

#else /* X_DISPLAY_MISSING */

createFont (width, height) escapement bold italic family = 
 Win32.createFont (fromDimension height) (fromDimension width)
                  (round (escapement * 1800/pi))
                  0                     -- orientation
                  weight
                  italic False False    -- italic, underline, strikeout
                  Win32.aNSI_CHARSET
                  Win32.oUT_DEFAULT_PRECIS
                  Win32.cLIP_DEFAULT_PRECIS
                  Win32.dEFAULT_QUALITY
                  Win32.dEFAULT_PITCH
                  family
  >>= return . MkFont
 where
  weight | bold      = Win32.fW_BOLD
         | otherwise = Win32.fW_NORMAL

deleteFont (MkFont f) = Win32.deleteFont f

selectFont (MkFont f) = mkDraw (\hdc -> do
  f' <- Win32.selectFont hdc f
  return (MkFont f'))

#endif /* X_DISPLAY_MISSING */

----------------------------------------------------------------
-- End
----------------------------------------------------------------