buffer

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 8, 2026 License: MIT Imports: 0 Imported by: 0

Documentation

Overview

Package buffer implements HarfBuzz-compatible text buffer for shaping.

This is a pure Go implementation designed for maximum compatibility with HarfBuzz's buffer behavior.

Index

Constants

This section is empty.

Variables

View Source
var (
	ScriptInvalid = Script(0)
	ScriptCommon  = MakeScript('Z', 'y', 'y', 'y')
	ScriptLatin   = MakeScript('L', 'a', 't', 'n')
	ScriptArabic  = MakeScript('A', 'r', 'a', 'b')
	ScriptHebrew  = MakeScript('H', 'e', 'b', 'r')
	ScriptGreek   = MakeScript('G', 'r', 'e', 'k')
	ScriptHan     = MakeScript('H', 'a', 'n', 'i')
)

Common script values.

Functions

func ClusterGroupFunc

func ClusterGroupFunc(a, b *GlyphInfo) bool

ClusterGroupFunc returns true if two glyphs are in the same cluster.

Types

type Buffer

type Buffer struct {
	// Public properties
	Props        SegmentProperties
	Flags        Flags
	ClusterLevel ClusterLevel

	// Replacement codepoint for invalid characters (default: U+FFFD)
	Replacement Codepoint

	// Glyph to use for invisible characters (0 = hide)
	Invisible Codepoint

	// Glyph to use when cmap lookup fails (0 = .notdef)
	NotFound Codepoint

	// Glyph for variation selector lookup failure
	NotFoundVariationSelector Codepoint
	// contains filtered or unexported fields
}

Buffer holds input text and output glyphs for shaping.

The buffer uses a two-buffer system internally to handle GSUB substitutions that change the number of glyphs. During GSUB processing, glyphs are read from the input buffer (info) and written to the output buffer (outInfo). After processing, the buffers are swapped via Sync().

For GPOS processing, modifications happen in-place since glyph count doesn't change.

func New

func New() *Buffer

New creates a new empty buffer with default settings.

func (*Buffer) Add

func (b *Buffer) Add(codepoint Codepoint, cluster uint32)

Add adds a single codepoint with the given cluster value.

func (*Buffer) AddMasks

func (b *Buffer) AddMasks(mask Mask)

AddMasks ORs the given mask into all glyph masks.

func (*Buffer) AddRunes

func (b *Buffer) AddRunes(runes []rune)

AddRunes adds Unicode codepoints from a rune slice. Each rune gets its index as cluster value.

func (*Buffer) AddString

func (b *Buffer) AddString(s string)

AddString adds Unicode codepoints from a string. Cluster values are byte offsets into the original string.

func (*Buffer) AddUTF8

func (b *Buffer) AddUTF8(text []byte)

AddUTF8 adds text from a UTF-8 byte slice. Cluster values are byte offsets.

func (*Buffer) BacktrackLen

func (b *Buffer) BacktrackLen() int

BacktrackLen returns the number of glyphs available for backtracking.

func (*Buffer) Clear

func (b *Buffer) Clear()

Clear clears the buffer contents and resets segment properties.

func (*Buffer) ClearOutput

func (b *Buffer) ClearOutput()

ClearOutput initializes the output buffer for GSUB processing. After calling this, use NextGlyph, ReplaceGlyph, OutputGlyph to process.

func (*Buffer) ClearPositions

func (b *Buffer) ClearPositions()

ClearPositions initializes position data for GPOS processing.

func (*Buffer) ContentType

func (b *Buffer) ContentType() ContentType

ContentType returns the current content type.

func (*Buffer) CopyGlyph

func (b *Buffer) CopyGlyph() bool

CopyGlyph copies the current glyph to output without advancing.

func (*Buffer) Cur

func (b *Buffer) Cur(offset int) *GlyphInfo

Cur returns a pointer to the current input glyph.

func (*Buffer) CurPos

func (b *Buffer) CurPos(offset int) *GlyphPosition

CurPos returns a pointer to the current input glyph position.

func (*Buffer) DeleteGlyph

func (b *Buffer) DeleteGlyph()

DeleteGlyph merges clusters and skips the current glyph. Used for removing glyphs during shaping.

func (*Buffer) Digest

func (b *Buffer) Digest() SetDigest

Digest returns the current digest.

func (*Buffer) Enter

func (b *Buffer) Enter()

Enter prepares the buffer for shaping.

func (*Buffer) GroupEnd

func (b *Buffer) GroupEnd(start int, sameGroup func(a, b *GlyphInfo) bool) int

GroupEnd returns the end of the group starting at start, where consecutive glyphs satisfy the sameGroup predicate.

func (*Buffer) GuessSegmentProperties

func (b *Buffer) GuessSegmentProperties()

GuessSegmentProperties guesses script and direction if not set.

func (*Buffer) HavePositions

func (b *Buffer) HavePositions() bool

HavePositions returns true if position data is available.

func (*Buffer) Idx

func (b *Buffer) Idx() int

Idx returns the current input position.

func (*Buffer) InError

func (b *Buffer) InError() bool

InError returns true if an allocation or operation error occurred.

func (*Buffer) Info

func (b *Buffer) Info() []GlyphInfo

Info returns the glyph info slice.

func (*Buffer) Leave

func (b *Buffer) Leave()

Leave cleans up after shaping.

func (*Buffer) Len

func (b *Buffer) Len() int

Len returns the number of glyphs in the buffer.

func (*Buffer) LookaheadLen

func (b *Buffer) LookaheadLen() int

LookaheadLen returns the number of glyphs available for lookahead.

func (*Buffer) MergeClusters

func (b *Buffer) MergeClusters(start, end int)

MergeClusters merges clusters in the given range to the minimum cluster value.

func (*Buffer) MoveTo

func (b *Buffer) MoveTo(i int) bool

MoveTo moves the output cursor to position i. Used for rewinding during contextual lookups.

func (*Buffer) NextGlyph

func (b *Buffer) NextGlyph() bool

NextGlyph copies the current glyph to output and advances. If there's no output buffer, just advances idx.

func (*Buffer) NextGlyphs

func (b *Buffer) NextGlyphs(n int) bool

NextGlyphs copies n glyphs to output and advances.

func (*Buffer) NextSerial

func (b *Buffer) NextSerial() uint8

NextSerial returns the next serial number for lookup tracking.

func (*Buffer) OutLen

func (b *Buffer) OutLen() int

OutLen returns the current output length.

func (*Buffer) OutputGlyph

func (b *Buffer) OutputGlyph(glyphID Codepoint) bool

OutputGlyph outputs a glyph without consuming input. Used for 1→N substitutions.

func (*Buffer) OutputInfo

func (b *Buffer) OutputInfo(info GlyphInfo) bool

OutputInfo outputs a complete GlyphInfo to the output buffer.

func (*Buffer) Pos

func (b *Buffer) Pos() []GlyphPosition

Pos returns the glyph position slice. Only valid after shaping (when HavePositions is true).

func (*Buffer) Prev

func (b *Buffer) Prev() *GlyphInfo

Prev returns a pointer to the previous output glyph.

func (*Buffer) ReplaceGlyph

func (b *Buffer) ReplaceGlyph(glyphID Codepoint) bool

ReplaceGlyph replaces the current input glyph with a new glyph ID. Equivalent to ReplaceGlyphs(1, 1, ...)

func (*Buffer) ReplaceGlyphs

func (b *Buffer) ReplaceGlyphs(numIn int, glyphData []Codepoint) bool

ReplaceGlyphs replaces numIn input glyphs with the given output glyphs. Handles cluster merging for the replaced glyphs.

func (*Buffer) Reset

func (b *Buffer) Reset()

Reset clears the buffer and resets all settings to defaults.

func (*Buffer) ResetMasks

func (b *Buffer) ResetMasks(mask Mask)

ResetMasks sets all glyph masks to the given value.

func (*Buffer) Reverse

func (b *Buffer) Reverse()

Reverse reverses the buffer contents.

func (*Buffer) ReverseClusters

func (b *Buffer) ReverseClusters()

ReverseClusters reverses cluster groups while keeping glyphs within clusters in their original order.

func (*Buffer) ReverseRange

func (b *Buffer) ReverseRange(start, end int)

ReverseRange reverses a range of the buffer.

func (*Buffer) SetContentType

func (b *Buffer) SetContentType(ct ContentType)

SetContentType sets the content type.

func (*Buffer) SetMasks

func (b *Buffer) SetMasks(value, mask Mask, clusterStart, clusterEnd uint32)

SetMasks sets mask bits for glyphs in a cluster range.

func (*Buffer) SkipGlyph

func (b *Buffer) SkipGlyph()

SkipGlyph advances the input cursor without copying to output.

func (*Buffer) Sort

func (b *Buffer) Sort(start, end int, less func(a, b *GlyphInfo) bool)

Sort sorts glyphs in the given range using the provided comparison function.

func (*Buffer) Sync

func (b *Buffer) Sync() bool

Sync transfers output buffer to input buffer after GSUB processing. Returns true if successful.

func (*Buffer) UpdateDigest

func (b *Buffer) UpdateDigest()

UpdateDigest updates the Bloom filter digest with current glyphs.

type ClusterLevel

type ClusterLevel uint8

ClusterLevel controls how clusters are handled during shaping.

const (
	// ClusterLevelMonotoneGraphemes groups clusters by graphemes in monotone order.
	// This is the default and maintains backward compatibility.
	ClusterLevelMonotoneGraphemes ClusterLevel = iota

	// ClusterLevelMonotoneCharacters assigns separate cluster values to
	// non-base characters but maintains monotone order.
	ClusterLevelMonotoneCharacters

	// ClusterLevelCharacters assigns separate cluster values without
	// enforcing monotone order. Most granular level.
	ClusterLevelCharacters

	// ClusterLevelGraphemes groups by graphemes without enforcing monotone order.
	ClusterLevelGraphemes

	// ClusterLevelDefault is the default cluster level.
	ClusterLevelDefault = ClusterLevelMonotoneGraphemes
)

func (ClusterLevel) IsGraphemes

func (c ClusterLevel) IsGraphemes() bool

IsGraphemes returns true if the cluster level groups by graphemes.

func (ClusterLevel) IsMonotone

func (c ClusterLevel) IsMonotone() bool

IsMonotone returns true if the cluster level enforces monotone order.

type Codepoint

type Codepoint = uint32

Codepoint represents either a Unicode codepoint or a glyph ID.

const CodepointInvalid Codepoint = 0xFFFFFFFF

CodepointInvalid represents an invalid codepoint value.

const ReplacementCodepoint Codepoint = 0xFFFD

ReplacementCodepoint is the default replacement for invalid characters (U+FFFD).

type ContentType

type ContentType uint8

ContentType indicates whether buffer contains characters or glyphs.

const (
	ContentTypeInvalid ContentType = iota
	ContentTypeUnicode             // Buffer contains Unicode codepoints (before shaping)
	ContentTypeGlyphs              // Buffer contains glyph IDs (after shaping)
)

type Direction

type Direction uint8

Direction represents text direction.

const (
	DirectionInvalid Direction = iota
	DirectionLTR               // Left-to-right
	DirectionRTL               // Right-to-left
	DirectionTTB               // Top-to-bottom
	DirectionBTT               // Bottom-to-top
)

func (Direction) IsBackward

func (d Direction) IsBackward() bool

IsBackward returns true if direction is backward (RTL or BTT).

func (Direction) IsForward

func (d Direction) IsForward() bool

IsForward returns true if direction is forward (LTR or TTB).

func (Direction) IsHorizontal

func (d Direction) IsHorizontal() bool

IsHorizontal returns true if direction is horizontal (LTR or RTL).

func (Direction) IsValid

func (d Direction) IsValid() bool

IsValid returns true if direction is valid (not Invalid).

func (Direction) IsVertical

func (d Direction) IsVertical() bool

IsVertical returns true if direction is vertical (TTB or BTT).

func (Direction) Reverse

func (d Direction) Reverse() Direction

Reverse returns the reverse direction.

type Flags

type Flags uint32

Flags controls buffer behavior during shaping.

const (
	FlagDefault Flags = 0

	// FlagBOT indicates beginning of text (enables special handling).
	FlagBOT Flags = 1 << iota

	// FlagEOT indicates end of text (enables special handling).
	FlagEOT

	// FlagPreserveDefaultIgnorables keeps default ignorable characters
	// visible instead of hiding them.
	FlagPreserveDefaultIgnorables

	// FlagRemoveDefaultIgnorables removes default ignorable characters
	// from the output instead of hiding them.
	FlagRemoveDefaultIgnorables

	// FlagDoNotInsertDottedCircle prevents insertion of dotted circle
	// for incorrect character sequences.
	FlagDoNotInsertDottedCircle

	// FlagVerify enables verification of shaping results.
	FlagVerify

	// FlagProduceUnsafeToConcat enables generation of the
	// GlyphFlagUnsafeToConcat flag during shaping.
	FlagProduceUnsafeToConcat

	// FlagProduceSafeToInsertTatweel enables generation of the
	// GlyphFlagSafeToInsertTatweel flag during shaping.
	FlagProduceSafeToInsertTatweel
)

type GlyphFlags

type GlyphFlags uint32

GlyphFlags are per-glyph flags set during shaping.

const (
	// GlyphFlagUnsafeToBreak indicates that breaking at this cluster
	// boundary requires reshaping both sides.
	GlyphFlagUnsafeToBreak GlyphFlags = 1 << iota

	// GlyphFlagUnsafeToConcat indicates that changing text on either
	// side of this cluster may change shaping results.
	GlyphFlagUnsafeToConcat

	// GlyphFlagSafeToInsertTatweel indicates it's safe to insert
	// a tatweel (U+0640) before this cluster for elongation.
	GlyphFlagSafeToInsertTatweel

	// GlyphFlagDefined is a mask of all defined glyph flags.
	GlyphFlagDefined = GlyphFlagUnsafeToBreak | GlyphFlagUnsafeToConcat | GlyphFlagSafeToInsertTatweel
)

type GlyphInfo

type GlyphInfo struct {
	// Codepoint is either a Unicode codepoint (before shaping)
	// or a glyph ID (after shaping).
	Codepoint Codepoint

	// Mask contains feature flags during shaping.
	// After shaping, the lower bits contain GlyphFlags.
	Mask Mask

	// Cluster is the index of the character in the original text
	// that corresponds to this glyph. Multiple glyphs can share
	// the same cluster value.
	Cluster uint32
	// contains filtered or unexported fields
}

GlyphInfo holds information about a single glyph.

Before shaping, Codepoint contains a Unicode codepoint. After shaping, Codepoint contains a glyph ID.

The Mask field contains feature flags during shaping and glyph flags (GlyphFlagUnsafeToBreak, etc.) after shaping.

The internal fields (glyphProps, unicodeProps, etc.) are used during shaping and should not be accessed directly.

func (*GlyphInfo) GlyphFlags

func (g *GlyphInfo) GlyphFlags() GlyphFlags

GlyphFlags returns the glyph flags from the mask.

func (*GlyphInfo) IsBase

func (g *GlyphInfo) IsBase() bool

IsBase returns true if this is a base glyph.

func (*GlyphInfo) IsComponent

func (g *GlyphInfo) IsComponent() bool

IsComponent returns true if this is a component of a ligature.

func (*GlyphInfo) IsLigated

func (g *GlyphInfo) IsLigated() bool

IsLigated returns true if this glyph was ligated.

func (*GlyphInfo) IsLigature

func (g *GlyphInfo) IsLigature() bool

IsLigature returns true if this glyph is the result of a ligature substitution.

func (*GlyphInfo) IsMark

func (g *GlyphInfo) IsMark() bool

IsMark returns true if this is a mark (combining) glyph.

func (*GlyphInfo) IsMultiplied

func (g *GlyphInfo) IsMultiplied() bool

IsMultiplied returns true if this glyph was multiplied (expanded from one to many).

func (*GlyphInfo) IsSubstituted

func (g *GlyphInfo) IsSubstituted() bool

IsSubstituted returns true if this glyph was substituted by GSUB.

type GlyphPosition

type GlyphPosition struct {
	// XAdvance is how much the line advances horizontally after this glyph.
	XAdvance Position

	// YAdvance is how much the line advances vertically after this glyph.
	YAdvance Position

	// XOffset is the horizontal offset from the current position.
	XOffset Position

	// YOffset is the vertical offset from the current position.
	YOffset Position
	// contains filtered or unexported fields
}

GlyphPosition holds positioning information for a glyph.

type Language

type Language string

Language represents a BCP 47 language tag. Stored as a pointer for efficient comparison (interned strings).

const LanguageInvalid Language = ""

type Mask

type Mask = uint32

Mask is a bitmask used for feature application.

type Position

type Position = int32

Position is a font unit value (typically 1/64th of a pixel at 72dpi).

type ScratchFlags

type ScratchFlags uint32

ScratchFlags are internal flags used during shaping.

const (
	ScratchFlagDefault ScratchFlags = 0

	ScratchFlagHasFractionSlash             ScratchFlags = 1 << 0
	ScratchFlagHasDefaultIgnorables         ScratchFlags = 1 << 1
	ScratchFlagHasSpaceFallback             ScratchFlags = 1 << 2
	ScratchFlagHasGPOSAttachment            ScratchFlags = 1 << 3
	ScratchFlagHasCGJ                       ScratchFlags = 1 << 4
	ScratchFlagHasBrokenSyllable            ScratchFlags = 1 << 5
	ScratchFlagHasVariationSelectorFallback ScratchFlags = 1 << 6
	ScratchFlagHasContinuations             ScratchFlags = 1 << 7

	// Reserved for shapers
	ScratchFlagShaper0 ScratchFlags = 1 << 24
	ScratchFlagShaper1 ScratchFlags = 1 << 25
	ScratchFlagShaper2 ScratchFlags = 1 << 26
	ScratchFlagShaper3 ScratchFlags = 1 << 27
)

type Script

type Script uint32

Script represents a Unicode script. Values correspond to ISO 15924 script codes.

func MakeScript

func MakeScript(a, b, c, d byte) Script

MakeScript creates a Script from a 4-character tag.

type SegmentProperties

type SegmentProperties struct {
	Direction Direction
	Script    Script
	Language  Language
}

SegmentProperties holds the properties of a text segment.

func (SegmentProperties) Equal

func (p SegmentProperties) Equal(other SegmentProperties) bool

Equal returns true if both segment properties are equal.

func (SegmentProperties) Hash

func (p SegmentProperties) Hash() uint32

Hash returns a hash value for the segment properties.

type SetDigest

type SetDigest struct {
	// contains filtered or unexported fields
}

SetDigest is a Bloom filter for fast glyph existence checks.

During shaping, lookups use the digest to quickly skip glyphs that can't possibly match. This avoids expensive lookup processing for most glyphs.

The digest is not perfectly accurate (false positives possible), but false negatives never occur: if MayHave returns false, the glyph is definitely not in the set.

func (*SetDigest) Add

func (d *SetDigest) Add(g Codepoint)

Add adds a glyph ID to the digest.

func (*SetDigest) AddArray

func (d *SetDigest) AddArray(glyphs []Codepoint)

AddArray adds multiple glyph IDs to the digest.

func (*SetDigest) AddRange

func (d *SetDigest) AddRange(first, last Codepoint)

AddRange adds all glyph IDs in the range [first, last] to the digest.

func (*SetDigest) Clear

func (d *SetDigest) Clear()

Clear resets the digest to empty.

func (*SetDigest) IsEmpty

func (d *SetDigest) IsEmpty() bool

IsEmpty returns true if the digest is empty.

func (*SetDigest) IsFull

func (d *SetDigest) IsFull() bool

IsFull returns true if the digest covers all possible values.

func (*SetDigest) MayHave

func (d *SetDigest) MayHave(g Codepoint) bool

MayHave returns true if the glyph might be in the set. Returns false only if the glyph is definitely not in the set.

func (*SetDigest) MayIntersect

func (d *SetDigest) MayIntersect(other SetDigest) bool

MayIntersect returns true if the two digests might have common elements.

func (*SetDigest) Union

func (d *SetDigest) Union(other SetDigest)

Union combines this digest with another.

Jump to

Keyboard shortcuts

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