File: GraphicsPicture.hs

package info (click to toggle)
hugs 1.4.199801-1
  • links: PTS
  • area: non-free
  • in suites: slink
  • size: 7,220 kB
  • ctags: 5,609
  • sloc: ansic: 32,083; haskell: 12,143; yacc: 949; perl: 823; sh: 602; makefile: 236
file content (166 lines) | stat: -rw-r--r-- 5,147 bytes parent folder | download
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
module GraphicsPicture
	( module GraphicsTypes
	, module GraphicsText
	, module GraphicsRegion
	, module GraphicsFont
	, module GraphicsBrush
	, module GraphicsPen
	, module GraphicsBitmap
	, empty, over, overMany
	, ellipse, shearEllipse, line
	, polyline, polygon, polyBezier
	, withRGB
	, DrawFun, drawPicture, drawBufferedPicture, drawBufferedPictureBC
	, drawBufferedPicture', applyDefaults
	, savePicture
	) where

import GraphicsTypes
import GraphicsText
import GraphicsRegion
import GraphicsFont
import GraphicsBrush
import GraphicsPen
import GraphicsBitmap
import qualified Win32

import GraphicsUtilities( bracket, bracket_ )

----------------------------------------------------------------

empty        :: Picture
over         :: Picture -> Picture -> Picture
overMany     :: [Picture] -> Picture

ellipse      :: Point -> Point          -> Picture
shearEllipse :: Point -> Point -> Point -> Picture
line         :: Point -> Point          -> Picture

polyline     :: [Point] -> Picture
polygon      :: [Point] -> Picture
polyBezier   :: [Point] -> Picture

-- select a color for printing text, drawing lines, and filling areas
withRGB      :: RGB -> Picture -> Picture

----------------------------------------------------------------

empty      = \ hdc -> return ()
p `over` q = \ hdc -> q hdc >> p hdc
overMany   = foldr over empty

ellipse p0 p1  = \ hdc -> Win32.ellipse hdc x0 y0 x1 y1
 where 
  (x0,y0) = fromPoint p0
  (x1,y1) = fromPoint p1

shearEllipse p0 p1 p2 = \ hdc -> 
  Win32.transformedEllipse hdc (fromPoint p0) (fromPoint p1) (fromPoint p2)

line p0 p1 = \ hdc -> Win32.moveToEx hdc x0 y0 >> Win32.lineTo   hdc x1 y1
 where 
  (x0,y0) = fromPoint p0
  (x1,y1) = fromPoint p1

polyline pts   = \ hdc -> Win32.polyline   hdc (map fromPoint pts)
polygon pts    = \ hdc -> Win32.polygon    hdc (map fromPoint pts)
polyBezier pts = \ hdc -> Win32.polyBezier hdc (map fromPoint pts)

withRGB c p = 
  mkBrush c       $ \ brush ->
  withBrush brush $
  mkPen Solid 2 c $ \ pen ->
  withPen pen     $
  withTextColor c $
  p

----------------------------------------------------------------

-- These don't really seem to belong here

type DrawFun = Win32.HWND -> Win32.HDC -> IO ()

drawPicture         :: Picture -> DrawFun
drawBufferedPicture :: Picture -> DrawFun
drawBufferedPictureBC :: Win32.RasterOp3 -> RGB -> Picture -> DrawFun
savePicture         :: String -> Point -> Picture -> IO ()

drawBufferedPicture' :: Picture -> Win32.HWND -> IO ()

----------------------------------------------------------------

backgroundColor = Win32.bLACKNESS
--backgroundColor = Win32.wHITENESS

defaultColor = RGB 255 255 255

applyDefaults :: Picture -> Picture
applyDefaults p = 
   withRGB    defaultColor $
   withBkMode Transparent       $
   p

drawPicture p = \ hwnd hdc -> do
  (w,h) <- windowSize hwnd
  Win32.bitBlt hdc 0 0 w h hdc 0 0 backgroundColor
  applyDefaults p hdc

-- Note that we create a bitmap which is compatible with the hdc
-- onto which we are going to zap the picture.  It might seem that
-- it would be enough for it to be compatible with the buffer -
-- but, sadly, this isn't the case.  The problem is that the buffer
-- is initially 0 pixels wide, 0 pixels high and 1 bit deep
-- (ie it looks monochrome); it only becomes n-bits deep when you
-- select in a bitmap which is n-bits deep.
--
-- If it wasn't for that, we'd have swapped these two lines:
--
--   withCompatibleBitmap w h   $ \ bitmap ->
--   withCompatibleDC           $ \ hdc    ->
--
drawBufferedPicture = drawBufferedPictureBC backgroundColor defaultColor

drawBufferedPictureBC bgColor dColor p = \ hwnd hdc -> do
  (w,h) <- windowSize hwnd
  withDC (Just hwnd)           $
    withCompatibleBitmap w h   $ \ bitmap ->
    withCompatibleDC           $ \ _      ->
    withBitmap bitmap          $ \ buffer -> do
      Win32.bitBlt buffer 0 0 w h buffer 0 0 bgColor
      applyDefaults (withRGB dColor p) buffer
      Win32.bitBlt hdc 0 0 w h buffer 0 0 Win32.sRCCOPY

drawBufferedPicture' p = \ hwnd -> do
  (w,h) <- windowSize hwnd
  withDC (Just hwnd)           $ \ hdc    -> (
    withCompatibleBitmap w h   $ \ bitmap ->
    withCompatibleDC           $ \ _      ->
    withBitmap bitmap          $ \ buffer -> do
      Win32.bitBlt buffer 0 0 w h buffer 0 0 backgroundColor
      applyDefaults p buffer
      Win32.bitBlt hdc 0 0 w h buffer 0 0 Win32.sRCCOPY
      ) hdc

savePicture fileName size p =
    let (w,h) = fromPoint size in
    withDC Nothing             $
    withCompatibleBitmap w h   $ \ bitmap ->
    withCompatibleDC           $ \ _      ->
    withBitmap bitmap          $ \ buffer -> do
      Win32.bitBlt buffer 0 0 w h buffer 0 0 backgroundColor
      p buffer
      createBitmapFile fileName bitmap buffer
 where
  backgroundColor = Win32.bLACKNESS


withDC :: Maybe Win32.HWND -> (Win32.HDC -> IO ()) -> IO ()
withDC mhwnd = 
  bracket (Win32.getDC mhwnd) (Win32.releaseDC mhwnd)

-- Get the width and height of a window's client area, in pixels.
windowSize :: Win32.HWND -> IO (Win32.LONG,Win32.LONG)
windowSize hwnd =
 Win32.getClientRect hwnd >>= \ (l',t',r',b') ->
 return (r' - l', b' - t')