Contents

Class BitBlt


Inheritance:

Object  »
  BitBlt

BitBlt represents a block transfer (BLT) of pixels into a rectangle (destX, destY, width, height) of the destinationForm. The source of pixels may be a similar rectangle (at sourceX, sourceY) in the sourceForm, or a constant color, currently called halftoneForm. If both are specified, their pixel values are combined with a logical AND function prior to transfer. In any case, the pixels from the source are combined with those of the destination as specified by the combinationRule.

Hint: BitBlt works slightly different for monochrome display media. For a monochrome destination form, the fill color is translated into a halftone form, a form with black and white pixels in a regular sequence. Such forms were used in Smalltalk-80 to create the impression of various gray levels. (See examples below)

Instance Variables:

Class methods:

Ensure that you always provide a Rectangle as the actual value following the name clipRect:. The virtual machine may crash immediately when the value provided is not a rectangle.
When you want to use the entire display area of your display device, you can use Display boundingBox to obtain a suitable clipping rectangle.

BitBlt is the most basic interface to display operations. BitBlt operations are heavily used, but explicit use of BitBlt is infrequently needed. Most of the following examples look quite artificial.

Examples of Use:

Filling a rectangular area of the screen:

  | bitBlt |
bitBlt := BitBlt destForm: Display
                 sourceForm: nil
                 fillColor: Color red
                 combinationRule: Form over
                 destOrigin: 0 @ 0 
                 sourceOrigin: 0 @ 0
                 extent: 200@200
                 clipRect: Display fullBoundingBox.
 bitBlt copyBits.

The instance creation method that is used here answers a fully initialized instance of BitBlt. It is therefore possible to immediately send it the message copyBits which performs the bitBlt operation on all bits in the rectangle 0 @ 0 extent: 200 @ 200.

When you change the combination rule, the background is not erased and the colored region looks as if a colored transparent sheet was placed in front of the display screen:

  | bitBlt |
bitBlt := BitBlt destForm: Display
                 sourceForm: nil
                 fillColor: Color red
                 combinationRule: Form and
                 destOrigin: 0 @ 0 
                 sourceOrigin: 0 @ 0
                 extent: 200@200
                 clipRect: Display fullBoundingBox.
 bitBlt copyBits.

Try also the combination rule Form under:

  | bitBlt |
bitBlt := BitBlt destForm: Display
                 sourceForm: nil
                 fillColor: Color red
                 combinationRule: Form under
                 destOrigin: 0 @ 0 
                 sourceOrigin: 0 @ 0
                 extent: 200@200
                 clipRect: Display fullBoundingBox.
 bitBlt copyBits.

The combination rule Form reverse has a special property: It is an operation that can be fully reversed by repetition. To demonstrate this, the bitBlt copyBity is performed twice in the following example.

  | bitBlt |
bitBlt := BitBlt destForm: Display
                 sourceForm: nil
                 fillColor: Color red
                 combinationRule: Form reverse
                 destOrigin: 0 @ 0 
                 sourceOrigin: 0 @ 0
                 extent: 200@200
                 clipRect: Display fullBoundingBox.
 bitBlt copyBits.
(Delay forMilliseconds: 500) wait.
 bitBlt copyBits.

To get a better impression from the power of BitBlt, you should try all the preceding examples with different fill colors.

The following example is a nice demo without practical value. It copies the right half of the display screen into the left half:

  | bitBlt |
bitBlt := BitBlt
             destForm: Display
             sourceForm: Display
             fillColor: nil
             combinationRule: Form over
             destOrigin: 0 @ 0 
             sourceOrigin: Display fullBoundingBox width // 2 @ 0
             extent: Display fullBoundingBox width // 2 
                      @ Display fullBoundingBox height
             clipRect: Display fullBoundingBox.
bitBlt copyBits.

Just for fun, you should also try this example:

  | bitBlt |

bitBlt := BitBlt destForm: Display sourceForm: Display fillColor: Color red combinationRule: Form and destOrigin: 0 @ 0 sourceOrigin: Display fullBoundingBox width // 2 @ 0 extent: Display fullBoundingBox width // 2 @ Display fullBoundingBox height clipRect: Display fullBoundingBox. bitBlt copyBits.

Examples with a monochrom destination form:

For a monochrome destination form, the fill color is converted into a halftone form:

  | bitBlt form |

form := Form extent: 100 @ 100 depth: 1.
bitBlt := BitBlt destForm: form
                 sourceForm: nil
                 fillColor: Color lightGray
                 combinationRule: Form over
                 destOrigin: 0 @ 0 
                 sourceOrigin: 0 @ 0
                 extent: 100 @ 100
                 clipRect: form boundingBox.
 bitBlt copyBits.
 form displayAt: 10 @ 10

Here, we provide a halftone form:

  | bitBlt form halftone |

form := Form extent: 100 @ 100 depth: 1.
halftone := Bitmap withAll:
        #( 286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224
           286331153 572662306 1145324612 2290649224).
bitBlt := BitBlt destForm: form
                 sourceForm: nil
                 fillColor: halftone
                 combinationRule: Form over
                 destOrigin: 0 @ 0 
                 sourceOrigin: 0 @ 0
                 extent: 100 @ 100
                 clipRect: form boundingBox.
 bitBlt copyBits.
 form displayAt: 10 @ 10

Here is a more practical example. It draws a grid. Drawing a grid with BitBlt operations is very fast and this piece of code can be used in diagram painting software.

  | painter mf |
mf := 10.
Display fill: (0 @ 0 extent: 110 @ 110)
        fillColor: Color white.
painter := BitBlt destForm: Display
                  sourceForm: nil
                  halftoneForm: Color black
                  combinationRule: Form over
                  destOrigin: 5 @ 5
                  sourceOrigin: 0 @ 0
                  extent: 1 @ 101
                  clipRect: Display fullBoundingBox.

  "  now, draw the vertical lines.
     In fact, we fill rectangles of width 1 and height 101 "
  
0 to: 10 do:
   [:idx |
      painter destOrigin: idx * mf @ 0 + 4;
              copyBits.
   ].

  " draw the horizontal lines. "
  " first, change the settings in painter to
    fill rectangles of width 101 and height 1: "
painter width: 101;
        height: 1.
  " now draw the 11 grid lines: "
0 to: 10 do:
   [:idx |
      painter destOrigin: 0 @ (idx * mf) + 4;
              copyBits.
   ].

The combination rule whose value is 0 through 15 programs the transfer to produce 1 or 0 according to its 4-bit representation as follows:

At each pixel the corresponding bits of the source and destination pixel values determine one of these conditions; if the combination rule has a 1 in the corresponding bit position, then the new destination value will be 1, otherwise it will be zero. Forms may be of different depths, see the comment in class Form.

In addition to the original 16 combination rules, this BitBlt supports

The color specified by halftoneForm may be either a Color or a Pattern. A Color is converted to a pixelValue for the depth of the destinationForm. If a Pattern, BitBlt will simply interpret its bitmap as an array of Color pixelValues. BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. Within each scan line the 32-bit value is repeated from left to right across the form. If the value repeats on pixels boundaries, the effect will be a constant color; if not, it will produce a halftone that repeats on 32-bit boundaries.

Any transfer specified is further clipped by the specified rectangle (clipX, clipY, clipWidth, clipHeight), and also by the bounds of the source and destination forms. To make a small Form repeat and fill a big form, use an InfiniteForm as the source. To write on a form and leave with both transparent and opaque areas, use a MaskedForm as the source.

Pixels from a source to a destination whose pixels have a different depth are converted based on the optional colorMap. If colorMap is nil, then conversion to more bits is done by filling the new high-order bits with zero, and conversion to fewer bits is done by truncating the lost high-order bits.

The colorMap, if specified, must be a either word array (ie Bitmap) with 2^n elements, where n is the pixel depth of the source, or a fully specified ColorMap which may contain a lookup table (ie Bitmap) and/or four separate masks and shifts which are applied to the pixels. For every source pixel, BitBlt will first perform masking and shifting and then index the lookup table, and select the corresponding pixelValue and mask it to the destination pixel size before storing.

When blitting from a 32 or 16 bit deep Form to one 8 bits or less, the default is truncation. This will produce very strange colors, since truncation of the high bits does not produce the nearest encoded color. Supply a 512 long colorMap, and red, green, and blue will be shifted down to 3 bits each, and mapped. The message copybits...stdColors will use the best map to the standard colors for destinations of depths 8, 4, 2 and 1. Two other sized of colorMaps are allowed, 4096 (4 bits per color) and 32786 (five bits per color).

Normal blits between 16 and 32 bit forms truncates or pads the colors automatically to provide the best preservation of colors.

Colors can be remapped at the same depth. Sometimes a Form is in terms of colors that are not the standard colors for this depth, for example in a GIF file. Convert the Form to a MaskedForm and send colorMap: the list of colors that the picture is in terms of. MaskedForm will use the colorMap when copying to the display or another Form. (Note also that a Form can be copied to itself, and transformed in the process, if a non-nil colorMap is supplied.)


Contents