home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / gprocs / bitplane.icn < prev    next >
Text File  |  2001-05-02  |  11KB  |  342 lines

  1. ############################################################################
  2. #
  3. #    File:     bitplane.icn
  4. #
  5. #    Subject:  Procedures for bitplane manipulation
  6. #
  7. #    Author:   Gregg M. Townsend
  8. #
  9. #    Date:     May 2, 2001
  10. #
  11. ############################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #
  17. #    These procedures allow a window to be treated as a series of
  18. #    overlapping, independent layers, subject to some fairly severe
  19. #    restrictions.
  20. #
  21. #    AlcPlane(W n)        allocates planes.
  22. #
  23. #    FrontPlane(W bp, color)    moves a layer to the front.
  24. #
  25. #    BackPlane(W bp, color)    moves a layer to the back.
  26. #
  27. #    PlaneOp(W bp, op)    initializes layer operations.
  28. #
  29. #    Deplane(W color)    restores a window to normal.
  30. #
  31. ############################################################################
  32. #
  33. #     These procedures allow drawing and erasing in individual bitplanes of
  34. #  a window.  One way to use bitplanes is to think of them as transparent
  35. #  panes in front of a solid background.  Each pane can be drawn with a
  36. #  single color, obscuring the panes beyond (and the background).  A pane
  37. #  can also be erased, wholly or selectively, exposing what is beyond; and
  38. #  a pane need not be visible to be drawn or erased.  Panes can be restacked
  39. #  in a different order, and the color of a pane (or the background) can be
  40. #  changed.
  41. #
  42. #     For example, the pane in back could be drawn with a city map.  The
  43. #  pane in front of that could be used to lay out bus routes, and the paths
  44. #  could be erased and rerouted without having to redraw the map.  Using a
  45. #  third plane in front of those, buses could be moved along the routes
  46. #  without having to redraw either the routes or the map behind them.
  47. #
  48. #     Bitplanes that are allocated together and interact with each other
  49. #  form a bitplane group.  A bitplane group need not fill the window;
  50. #  indeed, it can be used in discontiguous portions of a window or even
  51. #  in multiple windows on the same display.  On the other hand, multiple
  52. #  bitplane groups can be used different parts of the same window.
  53. #
  54. #     Bitplanes are implemented using Icon's mutable colors, and they
  55. #  are gluttonous of color map entries.  A set of n bitplanes requires
  56. #  at least 2^n color map entries, so the practical limit of n is 5 or 6.
  57. #  On the other hand, sets of 2 or 3 bitplanes are relatively cheap and
  58. #  using several of them is not unreasonable.
  59. #
  60. #     Each bitplane group is identified by a base index b, which is the
  61. #  index of the mutable color representing the background.  The individual
  62. #  bitplanes are referenced as b+1, b+2, b+4 etc. using powers of two.
  63. #  Other indices between b and b+2^n (exclusive) control the colors used
  64. #  used when multiple bitplanes are drawn.  The FrontPlane and BackPlane
  65. #  procedures provides simple control of these, and more sophisticated
  66. #  effects (such as making a bitplane partially transparent) are possible
  67. #  by setting them individually.
  68. #
  69. #
  70. #
  71. #  AlcPlane([win,] n) -- alc colors for n bitplanes
  72. #
  73. #     AlcPlane allocates a set of 2^n mutable colors chosen to be suitable
  74. #  for the bitplane manipulations described below.  The colors are
  75. #  consecutively indexed, and the base value b (the most negative index
  76. #  value) is returned.  The base color is initialized to the current
  77. #  background color, and the others are initialized to the foreground color.
  78. #
  79. #     A sequence of AlcPlane calls with different values of n is more
  80. #  likely to succeed if the larger sets are allocated first.
  81. #
  82. #
  83. #
  84. #  FrontPlane([win,] bp, color) -- move indexed plane to "front"
  85. #
  86. #     FrontPlane sets the pixels in a bitplane to the given color and
  87. #  moves the bitplane in front of the others in the set.  The color is
  88. #  optional.
  89. #
  90. #     bp is the index (base+1, base+2, base+4, or whatever) denoting a
  91. #  particular bitplane.  The move-to-the-front effect is accomplished by
  92. #  calling Color() for all colors in the bitplane group whose index
  93. #  after subtracting the base includes the particular bit.
  94. #
  95. #
  96. #
  97. #  BackPlane([win,] bp, color) -- move indexed plane to "back"
  98. #
  99. #     BackPlane sets the pixels in a bitplane to the given color and
  100. #  moves the bitplane in back of the others in the set.  The color is
  101. #  optional.
  102. #
  103. #     bp is the index (base+1, base+2, base+4, or whatever) denoting a
  104. #  particular bitplane.  The move-to-the-back effect is accomplished by
  105. #  calling Color() for all colors in the bitplane group whose index
  106. #  after subtracting the base includes the particular bit.
  107. #
  108. #     A plane can be effectively rendered invisible by calling
  109. #  BackPlane(win, bp, base);  this moves it to the back and sets
  110. #  its color to the color of the background plane.
  111. #
  112. #
  113. #
  114. #  PlaneOp([win,] bp, op) -- set graphics context for plane operation
  115. #
  116. #     PlaneOp initializes the graphics context for drawing or erasing in
  117. #  a particular bitplane.  bp is a bitplane index, as for FrontPlane;
  118. #  multiple bits can be set to draw or erase several bitplanes
  119. #  simultaneously.  op is usually one of two strings:
  120. #
  121. #    "set"    to draw the bits in a bitplane
  122. #    "clear"    to erase the bits in a bitplane
  123. #
  124. #  Subsequent drawing operations will affect only the bits in the selected
  125. #  bitplane.  Foreground operations are used for both drawing and erasure:
  126. #  use FillRectangle, not EraseArea.
  127. #
  128. #     After calling PlaneOp with "set" or "clear", be SURE to draw only
  129. #  in portions of the screen previously initialized with pixel values
  130. #  from the same bitplane group.  Drawing anywhere else is liable to
  131. #  produce strange, unwanted results.  Deplane (below) resets the window
  132. #  for normal operation.
  133. #
  134. #     The op parameter can also be "copy", in which case the previous
  135. #  contents of the window are immaterial and the drawn pixels are
  136. #  initialized with the bitplanes specified.
  137. #
  138. #
  139. #  Deplane([win,] color) -- restore normal drawop and set foreground
  140. #
  141. #     Deplane is called to restore normal drawing operations after setting
  142. #  or clearing bits in a particular bitplane.  The foreground color can be
  143. #  changed optionally.
  144. #
  145. #
  146. #
  147. #  Example:
  148. #
  149. #    b := AlcPlane(win, 3)            # get 3 planes
  150. #    Color(win, b, "white")            # background will be white
  151. #    FrontPlane(win, 1, "gray")        # city map will be gray
  152. #    FrontPlane(win, 2, "navy")        # routes will be dark blue
  153. #    FrontPlane(win, 4, "red")        # buses will be red
  154. #    Fg(win, b)
  155. #    DrawRectangle(win, x, y, w, h)        # initialize background
  156. #    PlaneOp(win, b+1, "set")
  157. #    drawmap()                # draw map
  158. #    repeat {
  159. #       PlaneOp(win, b+2, "clear")
  160. #       DrawRectangle(x, y, w, h)        # clear old routes
  161. #       PlaneOp(win, b+2, "set")
  162. #       drawroutes()                # draw new routes
  163. #       while routes_ok() do
  164. #          runbuses()            # run buses using plane b+4
  165. #       }
  166. #
  167. #
  168. #
  169. #  Caveats
  170. #
  171. #     AlcPlane must repeatedly ask for new mutable colors until it gets a
  172. #  set that is suitable.  Unwanted colors cannot be returned or freed, so
  173. #  some color table entries are usually wasted.
  174. #
  175. #     No more than 7 bitplanes can be requested, and even that is chancy.
  176. #
  177. #     These routines will be confused by multiple displays.  Multiple
  178. #  windows on a single display, or multiple bitplane sets in a window,
  179. #  are no problem.
  180. #
  181. #     These routines depend on the internals of Icon, specifically the
  182. #  mapping of window-system pixel values to mutable color indices.
  183. #
  184. #     The use of unusual "and" and "or" drawops makes the code hard to
  185. #  understand.
  186. #
  187. ############################################################################
  188. #
  189. #  Requires:  Version 9 graphics
  190. #
  191. ############################################################################
  192.  
  193.  
  194. global Plane_Mask
  195.  
  196.  
  197. #  AlcPlane(win, n) -- allocate 2^n colors for bitplanes and return base b
  198.  
  199. procedure AlcPlane(win, n)        #: allocate colors for bitplane
  200.    local ncolors, mask, b, seqlen, prev, fg, clist
  201.  
  202.    if type(win) ~== "window" then {
  203.       n := win
  204.       win := &window
  205.       }
  206.  
  207.    if n < 1 | n > 7 then
  208.       runerr(205, n)
  209.    fg := Fg(win)
  210.  
  211.    ncolors := 2 ^ n
  212.    mask := ncolors - 1
  213.  
  214.    # need to get ncolors colors in sequence, with the last one having the
  215.    # low order n bits (of the actual pixel value) set
  216.  
  217.    # alternatives on Color are in case current fg/bg would cause failure
  218.  
  219.    b := NewColor(win, fg | "black") | fail
  220.    clist := [b]
  221.    seqlen := 1
  222.    while seqlen < ncolors | iand(-1 - b, mask) ~= mask do {
  223.       prev := b
  224.       b := NewColor(win, fg | "black") | fail
  225.       push(clist, b)
  226.       if prev - b ~= 1 then
  227.          seqlen := 1
  228.       else
  229.          seqlen +:= 1
  230.       }
  231.  
  232.    # discard unwanted colors
  233.    every 1 to ncolors do
  234.       pop(clist)
  235.    if *clist > 0 then {
  236.       push(clist, win)
  237.       FreeColor ! clist
  238.       }
  239.  
  240.    # set base color to background and return result
  241.    Color(win, b, Bg(win) | "white")
  242.    /Plane_Mask := table()
  243.    every Plane_Mask [b to b + mask] := mask
  244.    return b
  245. end
  246.  
  247.  
  248.  
  249. #  FrontPlane(win, bp, color) -- move indexed plane to "front", set color
  250.  
  251. procedure FrontPlane(win, bp, color)    #: move bitplane to front
  252.    local mask, base, bits, i
  253.  
  254.    if type(win) ~== "window" then {
  255.       win :=: bp :=: color
  256.       win := &window
  257.       }
  258.  
  259.    mask := \Plane_Mask[bp] | runerr(205, bp)
  260.    base := iand(icom(mask), bp)
  261.    bits := bp - base
  262.    /color := bp
  263.    every i := base to base + mask do
  264.       if iand(i, bits) = bits then
  265.          Color(win, i, color)
  266.    return win
  267. end
  268.  
  269.  
  270.  
  271. #  BackPlane(win, bp, color) -- move indexed plane to "back", set color
  272.  
  273. procedure BackPlane(win, bp, color)    #: move bitplane to back
  274.    local mask, base, bits, i
  275.  
  276.    if type(win) ~== "window" then {
  277.       win :=: bp :=: color
  278.       win := &window
  279.       }
  280.  
  281.    mask := \Plane_Mask[bp] | runerr(205, bp)
  282.    base := iand(icom(mask), bp)
  283.    bits := bp - base
  284.    Color(win, bp, \color)            # set color if specified
  285.    every i := base to base + mask do
  286.       if iand(i, bits) = bits & i ~= bp then
  287.          Color(win, i, ixor(i, bits))        # set color as if plane unset
  288.    return win
  289. end
  290.  
  291.  
  292.  
  293. #  PlaneOp(win, bp, op) -- set graphics context for plane operation
  294.  
  295. procedure PlaneOp(win, bp, op)        #: set context for bitplane operation
  296.    local mask, base, bits, i
  297.  
  298.    if type(win) ~== "window" then {
  299.       win :=: bp :=: op
  300.       win := &window
  301.       }
  302.  
  303.    mask := \Plane_Mask[bp] | runerr(205, bp)
  304.    base := iand(icom(mask), bp)
  305.    bits := bp - base
  306.  
  307.    case op of {
  308.       "copy": {
  309.          WAttrib(win, "drawop=copy")
  310.          Fg(win, bp)
  311.          }
  312.       "set": {
  313.          i := base + bits
  314.          WAttrib(win, "drawop=and")
  315.          Fg(win, i)
  316.          }
  317.       "clear": {
  318.          i := base + (mask - bits)
  319.          WAttrib(win, "drawop=or")
  320.          Fg(win, i)
  321.          }
  322.       default:
  323.          runerr(205, op)
  324.       }
  325.    return win
  326. end
  327.  
  328.  
  329.  
  330. #  Deplane(win, color) -- restore normal drawop and set fg to color
  331.  
  332. procedure Deplane(win, color)
  333.  
  334.    if type(win) ~== "window" then {
  335.       color := win
  336.       win := &window
  337.       }
  338.    WAttrib(win, "drawop=copy")
  339.    Fg(win, \color)
  340.    return win
  341. end
  342.