text/emoji/bitmap.go

Functions Structs

Functions

func BestStrikeForPPEM

BestStrikeForPPEM returns the strike index best matching the requested ppem.

func (p *SBIXParser) BestStrikeForPPEM(ppem uint16) int {
	if len(p.strikes) == 0 {
		return -1
	}

	bestIdx := 0
	bestDiff := absDiff(p.strikes[0].ppem, ppem)

	for i := 1; i < len(p.strikes); i++ {
		diff := absDiff(p.strikes[i].ppem, ppem)
		// Prefer larger or equal size
		if diff < bestDiff || (diff == bestDiff && p.strikes[i].ppem > p.strikes[bestIdx].ppem) {
			bestIdx = i
			bestDiff = diff
		}
	}

	return bestIdx
}

func Decode

Decode decodes the bitmap data to an image.Image.

Currently only supports PNG format.

Returns nil if the format is not supported or data is invalid.

func (b *BitmapGlyph) Decode() (image.Image, error) {
	switch b.Format {
	case FormatPNG:
		return png.Decode(bytes.NewReader(b.Data))
	case FormatJPEG:
		// JPEG support would require image/jpeg import
		// For now, return an error indicating it's not yet implemented
		return nil, errors.New("emoji: JPEG bitmap decoding not yet implemented")
	default:
		return nil, ErrUnsupportedBitmapFormat
	}
}

func GetGlyph

GetGlyph extracts bitmap data for a glyph at the given strike.

func (p *SBIXParser) GetGlyph(glyphID, strikeIndex int) (*BitmapGlyph, error) {
	if strikeIndex < 0 || strikeIndex >= len(p.strikes) {
		return nil, ErrGlyphNotInBitmap
	}
	if glyphID < 0 || glyphID >= int(p.numGlyphs) {
		return nil, ErrGlyphNotInBitmap
	}

	strike := &p.strikes[strikeIndex]
	glyphStart := strike.glyphData[glyphID]
	glyphEnd := strike.glyphData[glyphID+1]

	if glyphEnd <= glyphStart {
		return nil, ErrGlyphNotInBitmap
	}

	// Glyph data format:
	// originOffsetX: int16
	// originOffsetY: int16
	// graphicType: 4 bytes (tag)
	// data: remaining bytes

	dataOffset := strike.offset + glyphStart
	if int(dataOffset)+8 > len(p.data) {
		return nil, ErrInvalidSBIXData
	}

	// #nosec G115 -- uint16 to int16 reinterpretation is intentional for font data
	originX := int16(binary.BigEndian.Uint16(p.data[dataOffset : dataOffset+2]))
	// #nosec G115 -- uint16 to int16 reinterpretation is intentional for font data
	originY := int16(binary.BigEndian.Uint16(p.data[dataOffset+2 : dataOffset+4]))
	graphicType := string(p.data[dataOffset+4 : dataOffset+8])

	// Determine format from graphic type tag
	format, err := parseGraphicType(graphicType)
	if err != nil {
		return nil, err
	}

	// Extract image data
	imageDataOffset := dataOffset + 8
	imageDataEnd := strike.offset + glyphEnd
	if int(imageDataEnd) > len(p.data) {
		return nil, ErrInvalidSBIXData
	}

	imageData := p.data[imageDataOffset:imageDataEnd]

	bitmap := &BitmapGlyph{
		GlyphID:	uint16(glyphID),	//#nosec G115 -- bounds checked above
		Data:		imageData,
		Format:		format,
		OriginX:	float32(originX),
		OriginY:	float32(originY),
		PPEM:		strike.ppem,
	}

	// Try to decode PNG to get dimensions
	if format == FormatPNG && len(imageData) > 0 {
		if img, decodeErr := png.Decode(bytes.NewReader(imageData)); decodeErr == nil {
			bounds := img.Bounds()
			bitmap.Width = bounds.Dx()
			bitmap.Height = bounds.Dy()
		}
	}

	return bitmap, nil
}

func HasGlyph

HasGlyph returns true if the glyph has bitmap data at the given strike.

func (p *SBIXParser) HasGlyph(glyphID, strikeIndex int) bool {
	if strikeIndex < 0 || strikeIndex >= len(p.strikes) {
		return false
	}
	if glyphID < 0 || glyphID >= int(p.numGlyphs) {
		return false
	}

	strike := &p.strikes[strikeIndex]
	glyphStart := strike.glyphData[glyphID]
	glyphEnd := strike.glyphData[glyphID+1]

	return glyphEnd > glyphStart
}

func HasTable

HasTable returns true if CBDT/CBLC tables are present.

func (p *CBDTParser) HasTable() bool {
	return len(p.cbdtData) > 0 && len(p.cblcData) > 0
}

func NewCBDTParser

NewCBDTParser creates a new CBDT parser.

func NewCBDTParser(cbdtData, cblcData []byte) (*CBDTParser, error) {
	if len(cbdtData) == 0 {
		return nil, ErrNoCBDTTable
	}
	if len(cblcData) == 0 {
		return nil, errors.New("emoji: font has no CBLC table")
	}

	return &CBDTParser{
		cbdtData:	cbdtData,
		cblcData:	cblcData,
	}, nil
}

func NewSBIXParser

NewSBIXParser creates a new sbix parser.

numGlyphs should be from the maxp table.

func NewSBIXParser(data []byte, numGlyphs uint16) (*SBIXParser, error) {
	if len(data) == 0 {
		return nil, ErrNoSBIXTable
	}
	if len(data) < 8 {
		return nil, ErrInvalidSBIXData
	}

	p := &SBIXParser{
		data:		data,
		numGlyphs:	numGlyphs,
	}

	if err := p.parse(); err != nil {
		return nil, err
	}

	return p, nil
}

func NumStrikes

NumStrikes returns the number of bitmap strikes (sizes).

func (p *SBIXParser) NumStrikes() int {
	return len(p.strikes)
}

func StrikePPEM

StrikePPEM returns the ppem for a strike index.

func (p *SBIXParser) StrikePPEM(strikeIndex int) uint16 {
	if strikeIndex < 0 || strikeIndex >= len(p.strikes) {
		return 0
	}
	return p.strikes[strikeIndex].ppem
}

func String

String returns the string name of the bitmap format.

func (f BitmapFormat) String() string {
	if int(f) < len(bitmapFormatNames) {
		return bitmapFormatNames[f]
	}
	return unknownStr
}

Structs

type BitmapGlyph struct

BitmapGlyph represents a bitmap emoji from sbix/CBDT tables.

type BitmapGlyph struct {
	// GlyphID is the glyph ID this bitmap represents.
	GlyphID	uint16

	// Data contains the raw bitmap data (PNG, JPEG, etc.).
	Data	[]byte

	// Format indicates how Data is encoded.
	Format	BitmapFormat

	// Width is the bitmap width in pixels.
	Width	int

	// Height is the bitmap height in pixels.
	Height	int

	// OriginX is the horizontal offset from glyph origin.
	OriginX	float32

	// OriginY is the vertical offset from glyph origin.
	OriginY	float32

	// PPEM is the pixels-per-em for this bitmap size.
	PPEM	uint16
}

type SBIXParser struct

SBIXParser parses the sbix (Standard Bitmap Graphics) table.

sbix is Apple's format for embedded bitmap graphics (emoji).

type SBIXParser struct {
	data		[]byte
	numGlyphs	uint16

	// Parsed strike information
	strikes	[]sbixStrike
}

type CBDTParser struct

CBDTParser parses the CBDT (Color Bitmap Data) table.

CBDT is Google's format for embedded bitmap graphics (emoji).

It works together with CBLC (Color Bitmap Location) table.

type CBDTParser struct {
	cbdtData	[]byte
	cblcData	[]byte
}