162 lines
4.9 KiB
Go
162 lines
4.9 KiB
Go
package generator
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPackAlphaBlock(t *testing.T) {
|
|
var dst [4]byte
|
|
packAlphaBlock(dst[:], [3]uint32{64, 512, 940})
|
|
|
|
word := binary.LittleEndian.Uint32(dst[:])
|
|
|
|
if got := word & 0x3ff; got != 64 {
|
|
t.Errorf("sample 0 = %d, want 64", got)
|
|
}
|
|
if got := (word >> 10) & 0x3ff; got != 512 {
|
|
t.Errorf("sample 1 = %d, want 512", got)
|
|
}
|
|
if got := (word >> 20) & 0x3ff; got != 940 {
|
|
t.Errorf("sample 2 = %d, want 940", got)
|
|
}
|
|
if got := word >> 30; got != 0 {
|
|
t.Errorf("unused bits = %d, want 0", got)
|
|
}
|
|
}
|
|
|
|
func TestPackAlphaBlockMasksSamples(t *testing.T) {
|
|
var dst [4]byte
|
|
packAlphaBlock(dst[:], [3]uint32{0x401, 0x802, 0xc03})
|
|
|
|
word := binary.LittleEndian.Uint32(dst[:])
|
|
|
|
if got := word & 0x3ff; got != 1 {
|
|
t.Errorf("sample 0 = %d, want 1", got)
|
|
}
|
|
if got := (word >> 10) & 0x3ff; got != 2 {
|
|
t.Errorf("sample 1 = %d, want 2", got)
|
|
}
|
|
if got := (word >> 20) & 0x3ff; got != 3 {
|
|
t.Errorf("sample 2 = %d, want 3", got)
|
|
}
|
|
}
|
|
|
|
func TestFillAlphaPlaneCompleteBlocks(t *testing.T) {
|
|
const width, height = 6, 2
|
|
dst := make([]byte, AlphaFrameSize(width, height))
|
|
if err := fillAlphaPlane(dst, width, height, alphaOpaque); err != nil {
|
|
t.Fatalf("fillAlphaPlane: %v", err)
|
|
}
|
|
|
|
for y := 0; y < height; y++ {
|
|
for x := 0; x < width; x++ {
|
|
if got := sampleAlpha(dst, width, x, y); got != alphaOpaque {
|
|
t.Errorf("sample (%d,%d) = %d, want %d", x, y, got, alphaOpaque)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFillAlphaPlaneZerosPartialBlockPadding(t *testing.T) {
|
|
const width, height = 4, 2
|
|
dst := make([]byte, AlphaFrameSize(width, height))
|
|
if err := fillAlphaPlane(dst, width, height, alphaTransparent); err != nil {
|
|
t.Fatalf("fillAlphaPlane: %v", err)
|
|
}
|
|
|
|
stride := AlphaLineSize(width)
|
|
for y := 0; y < height; y++ {
|
|
for x := 0; x < width; x++ {
|
|
if got := sampleAlpha(dst, width, x, y); got != alphaTransparent {
|
|
t.Errorf("sample (%d,%d) = %d, want %d", x, y, got, alphaTransparent)
|
|
}
|
|
}
|
|
lastWord := binary.LittleEndian.Uint32(dst[y*stride+4:])
|
|
if got := (lastWord >> 10) & 0x3ff; got != 0 {
|
|
t.Errorf("row %d padding sample 1 = %d, want 0", y, got)
|
|
}
|
|
if got := (lastWord >> 20) & 0x3ff; got != 0 {
|
|
t.Errorf("row %d padding sample 2 = %d, want 0", y, got)
|
|
}
|
|
if got := lastWord >> 30; got != 0 {
|
|
t.Errorf("row %d unused bits = %d, want 0", y, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFillAlphaPlaneRejectsSmallDestination(t *testing.T) {
|
|
const width, height = 6, 2
|
|
dst := make([]byte, AlphaFrameSize(width, height)-1)
|
|
err := fillAlphaPlane(dst, width, height, alphaOpaque)
|
|
if err == nil || !strings.Contains(err.Error(), "destination is too small") {
|
|
t.Fatalf("error = %v, want destination size error", err)
|
|
}
|
|
}
|
|
|
|
func TestPatchAlphaMovingSquare(t *testing.T) {
|
|
const width, height = 304, 200
|
|
dst := make([]byte, AlphaFrameSize(width, height))
|
|
if err := fillAlphaPlane(dst, width, height, alphaOpaque); err != nil {
|
|
t.Fatalf("fillAlphaPlane: %v", err)
|
|
}
|
|
if err := patchAlphaMovingSquare(dst, width, height, 0); err != nil {
|
|
t.Fatalf("patchAlphaMovingSquare: %v", err)
|
|
}
|
|
|
|
if got := sampleAlpha(dst, width, width/2, height/2); got != alphaTransparent {
|
|
t.Errorf("square center = %d, want transparent %d", got, alphaTransparent)
|
|
}
|
|
if got := sampleAlpha(dst, width, 10, height/2); got != alphaOpaque {
|
|
t.Errorf("outside square = %d, want opaque %d", got, alphaOpaque)
|
|
}
|
|
|
|
// At frame zero the square begins at x=77. Its first three-sample word
|
|
// therefore contains two opaque samples followed by one transparent sample.
|
|
for x, want := range []uint32{alphaOpaque, alphaOpaque, alphaTransparent} {
|
|
if got := sampleAlpha(dst, width, 75+x, height/2); got != want {
|
|
t.Errorf("boundary sample x=%d = %d, want %d", 75+x, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPatchAlphaMovingSquarePreservesPartialBlockPadding(t *testing.T) {
|
|
const width, height = 100, 200
|
|
dst := make([]byte, AlphaFrameSize(width, height))
|
|
if err := fillAlphaPlane(dst, width, height, alphaOpaque); err != nil {
|
|
t.Fatalf("fillAlphaPlane: %v", err)
|
|
}
|
|
if err := patchAlphaMovingSquare(dst, width, height, 0); err != nil {
|
|
t.Fatalf("patchAlphaMovingSquare: %v", err)
|
|
}
|
|
|
|
lastWordOffset := height/2*AlphaLineSize(width) + (width/3)*4
|
|
lastWord := binary.LittleEndian.Uint32(dst[lastWordOffset:])
|
|
if got := lastWord & 0x3ff; got != alphaTransparent {
|
|
t.Errorf("last visible sample = %d, want %d", got, alphaTransparent)
|
|
}
|
|
if got := lastWord >> 10; got != 0 {
|
|
t.Errorf("partial-block padding bits = %#x, want 0", got)
|
|
}
|
|
}
|
|
|
|
func TestPatchAlphaMovingSquareRejectsSmallDestination(t *testing.T) {
|
|
const width, height = 100, 200
|
|
err := patchAlphaMovingSquare(
|
|
make([]byte, AlphaFrameSize(width, height)-1),
|
|
width,
|
|
height,
|
|
0,
|
|
)
|
|
if err == nil || !strings.Contains(err.Error(), "destination is too small") {
|
|
t.Fatalf("error = %v, want destination size error", err)
|
|
}
|
|
}
|
|
|
|
func sampleAlpha(buf []byte, width, x, y int) uint32 {
|
|
offset := y*AlphaLineSize(width) + x/3*4
|
|
word := binary.LittleEndian.Uint32(buf[offset:])
|
|
return (word >> uint(x%3*10)) & 0x3ff
|
|
}
|