9fans.net/go@v0.0.5/draw/draw.go (about)

     1  package draw // import "9fans.net/go/draw"
     2  
     3  // An Op represents a Porter-Duff compositing operator.
     4  //
     5  // See T. Porter, T. Duff. “Compositing Digital Images”,
     6  // Computer Graphics (Proc. SIGGRAPH), 18:3, pp. 253-259, 1984.
     7  type Op int
     8  
     9  const (
    10  	Clear Op = 0
    11  
    12  	SinD  Op = 8
    13  	DinS  Op = 4
    14  	SoutD Op = 2
    15  	DoutS Op = 1
    16  
    17  	S      = SinD | SoutD
    18  	SoverD = SinD | SoutD | DoutS
    19  	SatopD = SinD | DoutS
    20  	SxorD  = SoutD | DoutS
    21  
    22  	D      = DinS | DoutS
    23  	DoverS = DinS | DoutS | SoutD
    24  	DatopS = DinS | SoutD
    25  	DxorS  = DoutS | SoutD // == SxorD
    26  
    27  	Ncomp = 12
    28  )
    29  
    30  func setdrawop(d *Display, op Op) {
    31  	if op != SoverD {
    32  		a := d.bufimage(2)
    33  		a[0] = 'O'
    34  		a[1] = byte(op)
    35  	}
    36  }
    37  
    38  func draw(dst *Image, r Rectangle, src *Image, p0 Point, mask *Image, p1 Point, op Op) {
    39  	setdrawop(dst.Display, op)
    40  
    41  	a := dst.Display.bufimage(1 + 4 + 4 + 4 + 4*4 + 2*4 + 2*4)
    42  	if src == nil {
    43  		src = dst.Display.Black
    44  	}
    45  	if mask == nil {
    46  		mask = dst.Display.Opaque
    47  	}
    48  	a[0] = 'd'
    49  	bplong(a[1:], dst.id)
    50  	bplong(a[5:], src.id)
    51  	bplong(a[9:], mask.id)
    52  	bplong(a[13:], uint32(r.Min.X))
    53  	bplong(a[17:], uint32(r.Min.Y))
    54  	bplong(a[21:], uint32(r.Max.X))
    55  	bplong(a[25:], uint32(r.Max.Y))
    56  	bplong(a[29:], uint32(p0.X))
    57  	bplong(a[33:], uint32(p0.Y))
    58  	bplong(a[37:], uint32(p1.X))
    59  	bplong(a[41:], uint32(p1.Y))
    60  }
    61  
    62  func (dst *Image) draw(r Rectangle, src, mask *Image, p1 Point) {
    63  	draw(dst, r, src, p1, mask, p1, SoverD)
    64  }
    65  
    66  // Draw is the standard drawing function. Only those pixels within the
    67  // intersection of dst.R and dst.Clipr will be affected; draw ignores
    68  // dst.Repl. The operation proceeds as follows (this is a description of
    69  // the behavior, not the implementation):
    70  //
    71  // 1. If Repl is set in src or mask, replicate their contents to fill
    72  // their clip rectangles.
    73  //
    74  // 2. Translate src and mask so p is aligned with r.Min.
    75  //
    76  // 3. Set r to the intersection of r and dst.R.
    77  //
    78  // 4. Intersect r with src.Clipr. If src.Repl is false, also intersect r
    79  // with src.R.
    80  //
    81  // 5. Intersect r with mask.Clipr. If mask.Repl is false, also intersect
    82  // r with mask.R
    83  //
    84  // 6. For each location in r, combine the dst pixel with the src pixel
    85  // using the alpha value corresponding to the mask pixel. If the mask has
    86  // an explicit alpha channel, the alpha value corresponding to the mask
    87  // pixel is simply that pixel's alpha chan- nel. Otherwise, the alpha
    88  // value is the NTSC greyscale equivalent of the color value, with white
    89  // meaning opaque and black transparent. In terms of the Porter-Duff
    90  // compositing algebra, draw replaces the dst pixels with (src in mask)
    91  // over dst. (In the extended form provided by DrawOp, “over” is replaced
    92  // by op).
    93  //
    94  // The various pixel channel formats involved need not be identical.
    95  // If the channels involved are smaller than 8-bits, they will be
    96  // promoted before the calculation by replicating the extant bits; after
    97  // the calculation, they will be truncated to their proper sizes.
    98  //
    99  // Mask may be nil, in which case a fully opaque mask is assumed.
   100  func (dst *Image) Draw(r Rectangle, src, mask *Image, p Point) {
   101  	dst.Display.mu.Lock()
   102  	defer dst.Display.mu.Unlock()
   103  	draw(dst, r, src, p, mask, p, SoverD)
   104  }
   105  
   106  // DrawOp is like Draw but specifies a Porter-Duff operator op to use in place of “S over D”.
   107  // That is, dst.Draw(r, src, mask, p) is the same as dst.DrawOp(r, src, mask, p, SoverD).
   108  func (dst *Image) DrawOp(r Rectangle, src, mask *Image, p Point, op Op) {
   109  	dst.Display.mu.Lock()
   110  	defer dst.Display.mu.Unlock()
   111  	draw(dst, r, src, p, mask, p, op)
   112  }
   113  
   114  // GenDraw is like Draw except that it aligns the source and mask differently:
   115  // src is aligned so p0 corresponds to r.Min, while mask is aligned so p1 corresponds to r.Min.
   116  // GenDraw differs from Draw only when both of src or mask are non-trivial.
   117  // For most purposes, Draw is sufficient.
   118  func (dst *Image) GenDraw(r Rectangle, src *Image, p0 Point, mask *Image, p1 Point) {
   119  	dst.Display.mu.Lock()
   120  	defer dst.Display.mu.Unlock()
   121  	draw(dst, r, src, p0, mask, p1, SoverD)
   122  }
   123  
   124  // GenDrawOp is like GenDraw but specifies a Porter-Duff operator op to use in place of “S over D”.
   125  func GenDrawOp(dst *Image, r Rectangle, src *Image, p0 Point, mask *Image, p1 Point, op Op) {
   126  	dst.Display.mu.Lock()
   127  	defer dst.Display.mu.Unlock()
   128  	draw(dst, r, src, p0, mask, p1, op)
   129  }