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

     1  // #include <u.h>
     2  // #include <libc.h>
     3  // #include <draw.h>
     4  // #include <memdraw.h>
     5  
     6  package memdraw
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"9fans.net/go/draw"
    12  )
    13  
    14  // Compressed image file parameters.
    15  const (
    16  	_NMATCH  = 3              /* shortest match possible */
    17  	_NRUN    = (_NMATCH + 31) /* longest match possible */
    18  	_NMEM    = 1024           /* window size */
    19  	_NDUMP   = 128            /* maximum length of dump */
    20  	_NCBLOCK = 6000           /* size of compressed blocks */
    21  )
    22  
    23  func cloadmemimage(i *Image, r draw.Rectangle, data []uint8) (int, error) {
    24  	if !draw.RectInRect(r, i.R) {
    25  		return 0, fmt.Errorf("invalid rectangle")
    26  	}
    27  	bpl := draw.BytesPerLine(r, i.Depth)
    28  	u := data
    29  	var mem [_NMEM]byte
    30  	memp := mem[:]
    31  	y := r.Min.Y
    32  	linep := byteaddr(i, draw.Pt(r.Min.X, y))
    33  	linep = linep[:bpl]
    34  	for {
    35  		if len(linep) == 0 {
    36  			y++
    37  			if y == r.Max.Y {
    38  				break
    39  			}
    40  			linep = byteaddr(i, draw.Pt(r.Min.X, y))
    41  			linep = linep[:bpl]
    42  		}
    43  		if len(u) == 0 { /* buffer too small */
    44  			return len(data) - len(u), fmt.Errorf("buffer too small")
    45  		}
    46  		c := u[0]
    47  		u = u[1:]
    48  		if c >= 128 {
    49  			for cnt := c - 128 + 1; cnt != 0; cnt-- {
    50  				if len(u) == 0 { /* buffer too small */
    51  					return len(data) - len(u), fmt.Errorf("buffer too small")
    52  				}
    53  				if len(linep) == 0 { /* phase error */
    54  					return len(data) - len(u), fmt.Errorf("phase error")
    55  				}
    56  				linep[0] = u[0]
    57  				linep = linep[1:]
    58  				memp[0] = u[0]
    59  				memp = memp[1:]
    60  				u = u[1:]
    61  				if len(memp) == 0 {
    62  					memp = mem[:]
    63  				}
    64  			}
    65  		} else {
    66  			if len(u) == 0 { /* short buffer */
    67  				return len(data) - len(u), fmt.Errorf("buffer too small")
    68  			}
    69  			offs := int(u[0]) + (int(c&3) << 8) + 1
    70  			u = u[1:]
    71  			var omemp []byte
    72  			if δ := len(mem) - len(memp); δ < offs {
    73  				omemp = mem[δ+(_NMEM-offs):]
    74  			} else {
    75  				omemp = mem[δ-offs:]
    76  			}
    77  			for cnt := (c >> 2) + _NMATCH; cnt != 0; cnt-- {
    78  				if len(linep) == 0 { /* phase error */
    79  					return len(data) - len(u), fmt.Errorf("phase error")
    80  				}
    81  				linep[0] = omemp[0]
    82  				linep = linep[1:]
    83  				memp[0] = omemp[0]
    84  				memp = memp[1:]
    85  				omemp = omemp[1:]
    86  				if len(omemp) == 0 {
    87  					omemp = mem[:]
    88  				}
    89  				if len(memp) == 0 {
    90  					memp = mem[:]
    91  				}
    92  			}
    93  		}
    94  	}
    95  	return len(data) - len(u), nil
    96  }