cursor

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2026 License: MIT Imports: 10 Imported by: 0

README

go-cursor

Go Reference

Go library for parsing and decoding Windows static (.cur) and animated (.ani) cursor files.

Features

  • Windows static cursors (.cur ICONDIR resource type 2)
  • Windows animated cursors (.ani RIFF ACON containers with anih, LIST/fram, rate, and seq chunks)
  • Image decoding for 32-bit DIB, 24-bit DIB with 1-bpp AND mask transparency, and PNG-compressed cursors
  • Pixel hotspot coordinates and normalized fractional coordinates with crop bounds (HotspotFraction)
  • Frame delays converted from Windows jiffies (1/60s) into time.Duration and millisecond delays
  • Bounds checks against malformed files and memory bombs
  • Standard library only, no CGO or external image libraries

Installation

go get github.com/fumbledlol/go-cursor

Quick start

Decoding a cursor
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/fumbledlol/go-cursor"
)

func main() {
	file, err := os.Open("custom.ani")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	cur, err := cursor.Decode(file)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Dimensions: %dx%d\n", cur.Width, cur.Height)
	fmt.Printf("Hotspot: (%d, %d)\n", cur.HotspotX, cur.HotspotY)
	fmt.Printf("Animated: %v (Frames: %d)\n", cur.Animated, len(cur.Frames))

	for i, delay := range cur.Delays {
		fmt.Printf("  Frame %d: delay %v\n", i, delay)
	}

	// Normalized fractional hotspot survives image resizing:
	hx, hy := cur.HotspotFraction(0, 0, 0, 0)
	fmt.Printf("Normalized hotspot: (%.2f, %.2f)\n", hx, hy)
}
Checking file format
data, _ := os.ReadFile("unknown.dat")

if cursor.IsCursor(data) {
	if cursor.IsANI(data) {
		fmt.Println("Windows animated cursor (.ani)")
	} else if cursor.IsCUR(data) {
		fmt.Println("Windows static cursor (.cur)")
	}
}

Benchmarks

BenchmarkDecodeCUR-12    85923    16738 ns/op

License

MIT

Documentation

Overview

Package cursor provides a pure Go parser and decoder for Windows static (.cur) and animated (.ani) cursor files, extracting animation frames, per-frame durations, and pixel-precise cursor hotspots.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnsupportedFormat indicates the input data is neither a valid .cur nor .ani file.
	ErrUnsupportedFormat = errors.New("unsupported cursor format: only .cur and .ani files are supported")
	// ErrTruncatedData indicates the input stream terminated prematurely.
	ErrTruncatedData = errors.New("truncated cursor data")
	// ErrInvalidHeader indicates malformed header metadata.
	ErrInvalidHeader = errors.New("invalid cursor header")
	// ErrNoFrames indicates the cursor file contains no decodable image frames.
	ErrNoFrames = errors.New("cursor file contains no frames")
	// ErrFrameLimitExceeded indicates an animation exceeded the maximum allowed frames.
	ErrFrameLimitExceeded = errors.New("animation frame limit exceeded")
)

Functions

func IsANI

func IsANI(data []byte) bool

IsANI reports whether the given data begins with the RIFF ACON container header.

func IsCUR

func IsCUR(data []byte) bool

IsCUR reports whether the given data begins with an ICONDIR header configured for Windows cursor resources (resource type 2).

func IsCursor

func IsCursor(data []byte) bool

IsCursor reports whether the given data starts with a valid .cur or .ani header.

Types

type Cursor

type Cursor struct {
	// Frames contains each decoded image frame (NRGBA or RGBA).
	Frames []image.Image
	// Delays contains the display duration for each frame.
	Delays []time.Duration
	// DelayMs contains the display duration in integer milliseconds for each frame.
	DelayMs []int
	// HotspotX is the raw pixel X coordinate of the cursor active point.
	HotspotX int
	// HotspotY is the raw pixel Y coordinate of the cursor active point.
	HotspotY int
	// Width is the nominal width of the cursor in pixels.
	Width int
	// Height is the nominal height of the cursor in pixels.
	Height int
	// Animated reports whether this cursor contains multiple animation frames (.ani).
	Animated bool
}

Cursor represents a decoded Windows static or animated cursor.

func Decode

func Decode(r io.Reader) (*Cursor, error)

Decode reads cursor data from an io.Reader and returns the decoded Cursor.

func DecodeBytes

func DecodeBytes(data []byte) (*Cursor, error)

DecodeBytes parses cursor data from a byte slice and returns the decoded Cursor.

func (*Cursor) HotspotFraction

func (c *Cursor) HotspotFraction(cropX, cropY, cropW, cropH int) (float64, float64)

HotspotFraction converts the raw pixel hotspot into normalized [0.0, 1.0] fractions relative to a given crop rectangle. If crop dimensions are not positive, fractions are computed relative to the cursor nominal source dimensions. Normalized fractions survive scaling and resizing operations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL