# Plane

A plane is a filled rectangle [gr/rect] . It extends the rectangle and adds a
color buffer to it, one color per pixel. The size of the buffer depends on its
color encoding [gr/color] .

The buffer is a sequence of horizontal lines with each line being "pitch" bytes
in size, beginning with the top line. Each line is a sequence of pixels, with
the size in bytes of each pixel depending on the color encoding, beginning with
the leftmost pixel.

Drawing on a plane is stateful. You set "tx" and "ty" (your target point), set
the active color with the "color" field and then call the appropriate drawing
method.

## API

Fields:

encoding  A color encoding ID from gr/color
pitch     Size in bytes of each line
tx        Target point X
ty        Target point Y
color     Color that is currently drawn
buffer    Pointer to the pixel buffer

Methods:

xyoff ( x y plane -- n )
  Returns the offset, relative to "buffer", corresponding to position "x,y" and
  do all preparation necessary (for example bank switching) to make that offset
  readily accessible.

blt ( srcaddr dstaddr bytewidth height srcpitch dstpitch plane -- )
  Copy a rectangle of pixels from "srcaddr" to "dstaddr". That rectangle is
  "height" lines high and each line has a pitch of "srcpitch" and "dstpitch".
  For each line, copy "bytewidth" bytes from source to dest.

bltfill ( width height addr color pitch plane -- width height )
  Fill rectangle at "addr" or dimensions "width" and "height" with "color".

bltpixel ( color addr plane -- )
  Set pixel at "addr" to "color".

Words:

newplane ( width height encoding -- plane )
  Create a new plane and calculate pitch from color encoding. Does not allocate
  a buffer and initializes it to 0.

allotbuf ( plane -- )
  Allocate a new buffer of the proper size (considering height and pitch) and
  set "buffer" to it.

pixel! ( plane -- )
  Set a pixel at tx,ty to the value of field "color".

pos! ( x y plane -- )
  Set current target position.

tx+ ( n plane -- )
  Increase tx by n, wrapping around if necessary.

ty+ ( n plane -- )
  Increase ty by n, wrapping around if necessary.

fillplane ( width height plane -- )
  Fill the area in the rect tx,ty,width,height with field "color".

copy< ( rect src plane -- )
  Copy the contents of "rect" from plane "src" into plane at target position
  tx,ty. Color encodings must be the same but pitch doesn't have to.

copy> ( rect dst plane -- )
  Copy the contents with the size of "rect" from "plane" into plane "dst"'s. The
  position of the rectangle at source is plane.tx,plane.ty and the origin of the
  rectangle at dst is rect.x,rect,y.

  Confused? yeah, it is a little bit. Here's the idea: :copy< and :copy> allows
  a plane to copy contents in and out of another plane without changing that
  other plane's tx/ty fields. In both copy directions, it is "plane" fields that
  change.

     plane           src/dst
  +-----------+   +-----------+
  |  ty       |   |  rectxy   |
  |tx+--+     |   |  +--+     |
  |  |  |-------copy>|  |     |
  |  |  |     |   |  |  |     |
  |  |  |copy<-------|  |     |
  |  +--+     |   |  +--+     |
  |    rectwh |   |    rectwh |
  +-----------+   +-----------+

  "src", "dst" and "plane" can be the same plane. In that case, copying will
  take place in the same buffer. When doing this, one must be careful in cases
  of overlap. Copying occurs from top to bottom, left to right. Therefore,
  copying with overlap can only work if the destination rectangle is "higher"
  (lower Y value) than the source rect.
