File: bitmap.sml

package info (click to toggle)
smlnj 110.79-8
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid
  • size: 82,564 kB
  • sloc: ansic: 32,532; asm: 6,314; sh: 2,296; makefile: 1,821; perl: 1,170; pascal: 295; yacc: 190; cs: 78; python: 77; lisp: 19
file content (129 lines) | stat: -rw-r--r-- 3,502 bytes parent folder | download | duplicates (5)
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
(* bitmap.sml
 *
 * COPYRIGHT (c) 1996 AT&T Research.
 *)

signature BITMAP =
  sig
    structure W : WIDGET
    structure CML : CONCUR_ML

    exception BadParam

    type bitmap

    val mkBitmap : W.root -> {
      backgrnd : W.EXB.color option,
      foregrnd : W.EXB.color option,
      horzCells : int,
      vertCells : int
    } -> bitmap

    val widgetOf : bitmap -> W.widget
    val setPixel : bitmap -> (bool * W.G.point) -> unit
    val imageOf : bitmap -> W.EXB.image

  end

structure Bitmap : BITMAP =
  struct
    structure W = Widget
    structure CML = CML
    structure EXB = EXeneBase

    open CML Geometry EXeneBase EXeneWin Interact Drawing Widget

    exception BadParam

    type pixchange = bool * point

    datatype rqst = 
      DoRealize of {
        env : in_env,
        win : window,
        sz : size
      }
    | Set of pixchange
    | ImageOf of image chan

    datatype bitmap = BM of {widget : widget, setChan : rqst chan}

    fun setColor scr (SOME c, _) = c
      | setColor scr (NONE, dflt) = dflt

    fun mkBitmap root {horzCells, vertCells, foregrnd, backgrnd} = let
      val scr = screenOf root
      val setChan = channel ()
      val psize = SIZE{wid=horzCells,ht=vertCells}
      val pixMap = createPixmap scr (psize,1)
      val pm = drawableOfPM pixMap
      val prect = mkRect(originPt,psize)
      val _ = clearDrawable pm
      val size = fixBounds (horzCells, vertCells)
      val maxX = horzCells-1
      val maxY = vertCells-1
      val forec = setColor scr (foregrnd, blackOfScr scr)
      val backc = setColor scr (backgrnd, whiteOfScr scr)

      val onPen = newPen [PV_Foreground color1]
      val offPen = newPen [PV_Foreground color0]
      val copyPen = newPen [PV_Foreground forec, PV_Background backc]

      fun set (true, pt) = drawPt pm onPen pt
        | set (false, pt) = drawPt pm offPen pt

      fun blt dw r = bitBlt dw copyPen {src=PMSRC pixMap, src_rect=r, dst_pos=originOfRect r}
   
      fun redraw(dw,rlist) = app (blt dw) rlist

      fun sendImage rchan = send(rchan, createImageFromPixmap pixMap)

      fun realize {env, win, sz} = let
        val InEnv{ci,...} = ignoreInput env
        val mChan = channel ()
        val dw = drawableOfWin win
  
        fun handleCI (CI_Resize (RECT{x,y,wid,ht})) = ()
          | handleCI (CI_Redraw rlist) = (redraw (dw,rlist); ())
          | handleCI CI_OwnDeath = ()
          | handleCI _ = ()
  
        fun handleSet (DoRealize _) = ()
          | handleSet (ImageOf arg) = (sendImage arg; ())
          | handleSet (Set arg) = (set arg; redraw(dw,[prect]); ())

        fun loop () =
          loop(select [
            wrap (ci, fn evt => (handleCI (msgBodyOf evt))),
            wrap (receive setChan, fn evt => (handleSet evt))
          ])
      in
        loop ()
      end

      fun initLoop () =
        case (accept setChan) of
          DoRealize arg => realize arg
        | Set arg => (set arg; initLoop ())
        | ImageOf arg => (sendImage arg; initLoop ())
    in
      spawn initLoop;
      BM {
        widget = mkWidget{
          root=root, 
          boundsOf = fn () => size, 
          realize= fn arg => send(setChan, DoRealize arg)
        },
        setChan = setChan
      }
    end

    fun widgetOf (BM{widget,...}) = widget
    fun setPixel (BM{setChan,...}) arg = send(setChan,Set arg)
    fun imageOf (BM{setChan,...}) = let
      val retChan = channel ()
    in
      send(setChan,ImageOf retChan);
      accept retChan
    end
  end