ggfnt

package module
v0.0.0-...-6ad6dc7 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2024 License: MIT Imports: 13 Imported by: 28

README

ggfnt

Go Reference

A bitmap font format that no one asked for:

This is an opinionated format with many hard limits, a specific memory layout for the data and a fair amount of unconventional choices (when compared to more standard font formats). Compatibility with existing formats is a non-goal. Being "generally better" than existing formats is a non-goal. I do have some knowledge about text rendering and font formats, but I don't claim to be an authority nor having done extensive research. I simply built what I wanted to build based on my experience with etxt and game development with Ebitengine.

Status

The basics are functional, but many advanced features and checks and tests and everything are missing. Very WIP.

Examples

You can see some fonts in action through tinne26.github.io/ptxt-examples.

Specification

See the specification document.

Summary of features and technical properties:

  • Single file spec under 400 lines (not simple, but accessible).
  • Many hard limits to make life safer.
  • Support for vertical text.
  • Support for colored glyphs with up to 255 colors.
  • Support for variables and conditional character mapping.
  • Support for kerning and kerning classes during edition.
  • Font data layout is directly usable once ungzipped (not many additional structures required).

In my opinion, though, the most important property is that ggfnt has been designed alongside the ptxt renderer, while also having experience from developing etxt. This results in a font format design that understands indie game usage needs and renderer implementation details. This leads to fairly good harmony between the format design and the tools that need to use it. At the same time, ggfnt doesn't shy away from adding more advanced features that might seem strange at first sight, like conditional character mapping and variables to control it. These add a non trivial amount of complexity to the format, but they also give a lot of power in the relevant context of game development (these features would be much more complex to shoehorn into the rendering tools separately).

Other points not directly related to spec features but worth mentioning:

  • The fonts can be easily edited to add custom icons for your games, adding variables or adjusting mapping for custom effects and so on. This tends to be less relevant in other contexts, but in game development it's great to have the door open to hack your own things. And editing bitmaps (unlike vectorial fonts) is easy. You can even add custom glyphs at runtime.
  • While the font format is not Golang-specific, all the related code is written in Golang, Golang-aware and Golang-friendly.
  • The font object can be operated at a low-level for some advanced features without feeling like a hacker. For example, querying named font variables and playing with their values at runtime can be perfectly reasonable and should be accessible.
  • I always put a lot of effort on documentation. The current state is still WIP and very spammy and possibly unclear in some cases, but I will get there.
  • ttf and otf: can't be compared at all as these are vectorial font formats. But they are very inaccessible monsters in comparison.
  • bmfont: ggfnt is fairly more complex, but at the same time the binary format has explicit safety limits and tends to use smaller data types. With the extra complexity, ggfnt gains more detailed metrics, support for vertical text, optional names and labels for some glyphs and other elements of the font, conditional character mapping, variables, etc. During edition, ggfnt also supports kerning classes and category names. On the negative side, ggfnt doesn't care about compatibility or convertibility with other formats at all, and as already said, it's more complex.
  • PCF: maybe the most similar format to ggfnt. Almost all the features of PCF are also provided by ggfnt, but ggfnt allows quite a few more things. PCF is a bit quirky with compression, ggfnt is quirky with data layout and binary-searchability. If you wanted to create a bitmap rendering library for an already existing format, then PCF and bmfont would probably be your main contenders.
  • BDF: this thing includes the following quote on its spec: "The Adobe Systems glyph bitmaps are typically distributed on magnetic tape". Not to be ageist, the format is actually ok, but it's very limited and verbose... and practices, style and expectations have changed a lot since 1987.

Transparency

While I'm pretty happy with ggfnt's features and general direction, I feel like it would be dishonest if I didn't also talk about the less shiny parts. In particular, the current implementation is rather hacky and far less modular and clean than it could be... but the spec is also quite quirky and could define the different sections in much more consistent and homogeneous ways, making implementation easier at the same time. The safety of the format is also quite hand-wavy, with me saying "yeah well we have size limits" as if that would hold as a formal proof of anything. And then we also have some features like rewrite rules that turned out to be way harder to implement in practice than I ever intended. At the end of the day, this is a rather rogue attempt at creating a font format, and it's quite unprofessional, quirky, overly exploratory and hacky in many ways.

In other words, while I really enjoy ggfnt's vision, a top-tier execution would require way more time, effort and discussion with knowledgeable individuals in order to reach consensus, polish the rough edges and iron out the quirky bits. It's not like I tried to make ggfnt anything beyond a font format that could be used for indie game development with Ebitengine, but yeah... let's remind everyone that that's all it is —if it ever looked any prettier—.

Documentation

Index

Constants

View Source
const FormatVersion = internal.FormatVersion
View Source
const MaxFontDataSize = internal.MaxFontDataSize // check both total file size and after uncompressing without signature
View Source
const MaxGlyphs = internal.MaxGlyphs

Variables

This section is empty.

Functions

func GetPredefinedWord

func GetPredefinedWord(i uint8) string

Types

type AnimationFlags

type AnimationFlags uint8
const (
	AnimFlagLoopable   AnimationFlags = 0b0000_0001 // can wrap back to start after reaching the end
	AnimFlagSequential AnimationFlags = 0b0000_0010 // should play from start to finish in order, or the reverse
	AnimFlagTerminal   AnimationFlags = 0b0000_0100 // animation shouldn't be rewinded/replayed automatically
	AnimFlagSplit      AnimationFlags = 0b0000_1000 // frames are independent and we can stop/rest at any of them
	AnimFlagsGroupMask AnimationFlags = 0b1111_0000 // usage still undefined. maybe better leave as custom use flags?
)

type Date

type Date struct {
	Year  uint16
	Month uint8
	Day   uint8
}

func CurrentDate

func CurrentDate() Date

func (*Date) HasDay

func (self *Date) HasDay() bool

func (*Date) HasMonth

func (self *Date) HasMonth() bool

func (*Date) HasYear

func (self *Date) HasYear() bool

func (*Date) IsComplete

func (self *Date) IsComplete() bool

Returns true only when neither year, month nor day are missing.

func (*Date) IsValid

func (self *Date) IsValid() bool

Doesn't check if the date is in the future, only if it's logically valid.

func (*Date) MonthName

func (self *Date) MonthName() string

func (*Date) String

func (self *Date) String() string

Returns the date in "DAY MonthName YEAR" format (e.g. "1 January 1999"). If day and/or month are missing, they are not added. If the whole date is undefined, "(Unknown Date)" is returned. Invalid dates will be converted to string too.

type DyeKey

type DyeKey uint8

Dyes are part of the font coloring. See FontColor for more details.

Dye keys go from 0 to FontColor.NumDyes() - 1, so they can be used directly for slice indexing if necessary.

type FmtValidation

type FmtValidation bool

TODO: don't worry about this until actually implementing validation, I'll

see there how easy it is to make, and what might or might not be reasonable
const (
	FmtDefault FmtValidation = false // basic and inexpensive checks only
	FmtStrict  FmtValidation = true  // check everything that can be checked
)

type Font

type Font internal.Font

A Font is a read-only object that contains all the data required to use a font. To create a Font, we use the Parse() method.

Fonts contain multiple sections or tables, which are exposed through gateway methods and differentiated types:

func Parse

func Parse(reader io.Reader) (*Font, error)

func ParseFromFS

func ParseFromFS(filesys fs.FS, filename string) (*Font, error)

Utility method for parsing from a fs.FS, like when using embed.

func ParseFromPath

func ParseFromPath(path string) (*Font, error)

Utility method for parsing a local font file directly from its path.

func (*Font) Color

func (self *Font) Color() *FontColor

func (*Font) Export

func (self *Font) Export(writer io.Writer) error

func (*Font) Glyphs

func (self *Font) Glyphs() *FontGlyphs

func (*Font) Header

func (self *Font) Header() *FontHeader

func (*Font) Kerning

func (self *Font) Kerning() *FontKerning

func (*Font) Mapping

func (self *Font) Mapping() *FontMapping

func (*Font) Metrics

func (self *Font) Metrics() *FontMetrics

func (*Font) RawSize

func (self *Font) RawSize() int

func (*Font) Rewrites

func (self *Font) Rewrites() *FontRewrites

func (*Font) Settings

func (self *Font) Settings() *FontSettings

func (*Font) Validate

func (self *Font) Validate(mode FmtValidation) error

type FontColor

type FontColor Font

func (*FontColor) Count

func (self *FontColor) Count() uint8

func (*FontColor) EachDye

func (self *FontColor) EachDye(fn func(DyeKey, string))

Notice: the string is an unsafe.String, so don't store it indefinitely.

func (*FontColor) EachDyeAlpha

func (self *FontColor) EachDyeAlpha(key DyeKey, fn func(uint8))

func (*FontColor) EachPalette

func (self *FontColor) EachPalette(fn func(PaletteKey, string))

func (*FontColor) EachPaletteColor

func (self *FontColor) EachPaletteColor(key PaletteKey, fn func(color.RGBA))

func (*FontColor) GoColorPalette

func (self *FontColor) GoColorPalette() color.Palette

func (*FontColor) NumDyeAlphas

func (self *FontColor) NumDyeAlphas(key DyeKey) uint8

func (*FontColor) NumDyeIndices

func (self *FontColor) NumDyeIndices() uint8

This is not FontColor.NumDyes(), but the total number of alpha values for each dye, the total number of font color indices taken by the dyes.

func (*FontColor) NumDyes

func (self *FontColor) NumDyes() uint8

func (*FontColor) NumPaletteColors

func (self *FontColor) NumPaletteColors(key PaletteKey) uint8

func (*FontColor) NumPaletteIndices

func (self *FontColor) NumPaletteIndices() uint8

This is not FontColor.NumPalettes(), but the total number of color values for each palette, the total number of font color indices taken by the palettes.

func (*FontColor) NumPalettes

func (self *FontColor) NumPalettes() uint8

func (*FontColor) Validate

func (self *FontColor) Validate(mode FmtValidation) error

type FontGlyphs

type FontGlyphs Font

func (*FontGlyphs) Advance

func (self *FontGlyphs) Advance(glyphIndex GlyphIndex) uint8

func (*FontGlyphs) Count

func (self *FontGlyphs) Count() uint16

Same as FontMetrics.NumGlyphs() (it actually refers to the data in the font metrics section).

func (*FontGlyphs) FindIndexByName

func (self *FontGlyphs) FindIndexByName(name string) GlyphIndex

If not found, the return value will be GlyphMissing.

func (*FontGlyphs) NamedCount

func (self *FontGlyphs) NamedCount() uint16

func (*FontGlyphs) Placement

func (self *FontGlyphs) Placement(glyphIndex GlyphIndex) GlyphPlacement

func (*FontGlyphs) RasterizeMask

func (self *FontGlyphs) RasterizeMask(glyphIndex GlyphIndex) *image.Alpha

func (*FontGlyphs) Validate

func (self *FontGlyphs) Validate(mode FmtValidation) error

type FontHeader

type FontHeader Font

func (*FontHeader) About

func (self *FontHeader) About() string

func (*FontHeader) Author

func (self *FontHeader) Author() string

func (*FontHeader) Family

func (self *FontHeader) Family() string

func (*FontHeader) FirstVersionDate

func (self *FontHeader) FirstVersionDate() Date

func (*FontHeader) FormatVersion

func (self *FontHeader) FormatVersion() uint32

func (*FontHeader) ID

func (self *FontHeader) ID() uint64

func (*FontHeader) MajorVersionDate

func (self *FontHeader) MajorVersionDate() Date

func (*FontHeader) MinorVersionDate

func (self *FontHeader) MinorVersionDate() Date

func (*FontHeader) Name

func (self *FontHeader) Name() string

func (*FontHeader) Validate

func (self *FontHeader) Validate(mode FmtValidation) error

func (*FontHeader) VersionMajor

func (self *FontHeader) VersionMajor() uint16

func (*FontHeader) VersionMinor

func (self *FontHeader) VersionMinor() uint16

type FontKerning

type FontKerning Font

func (*FontKerning) EachPair

func (self *FontKerning) EachPair(func(prev, curr GlyphIndex, kern int8))

func (*FontKerning) EachVertPair

func (self *FontKerning) EachVertPair(func(prev, curr GlyphIndex, kern int8))

func (*FontKerning) Get

func (self *FontKerning) Get(prev, curr GlyphIndex) int8

func (*FontKerning) GetVert

func (self *FontKerning) GetVert(prev, curr GlyphIndex) int8

func (*FontKerning) NumPairs

func (self *FontKerning) NumPairs() uint32

func (*FontKerning) NumVertPairs

func (self *FontKerning) NumVertPairs() uint32

func (*FontKerning) Validate

func (self *FontKerning) Validate(mode FmtValidation) error

type FontMapping

type FontMapping Font

func (*FontMapping) Ascii

func (self *FontMapping) Ascii(codePoint byte, settings []uint8) (GlyphMappingGroup, bool)

func (*FontMapping) EvaluateSwitch

func (self *FontMapping) EvaluateSwitch(switchKey uint8, settings []uint8) uint8

func (*FontMapping) NumEntries

func (self *FontMapping) NumEntries() uint16

func (*FontMapping) NumSwitchTypes

func (self *FontMapping) NumSwitchTypes() uint8

More than this might be needed for more complex switch caches, but it might not even be relevant, maybe the default cache is ok, without any interface at all.

func (*FontMapping) Utf8

func (self *FontMapping) Utf8(codePoint rune, settings []uint8) (GlyphMappingGroup, bool)

Notice: line breaks and other control codes shouldn't be requested here, but manually taken into account by the caller instead.

func (*FontMapping) Utf8WithCache

func (self *FontMapping) Utf8WithCache(codePoint rune, settingsCache *SettingsCache) (GlyphMappingGroup, bool)

func (*FontMapping) Validate

func (self *FontMapping) Validate(mode FmtValidation) error

type FontMetrics

type FontMetrics Font

func (*FontMetrics) Ascent

func (self *FontMetrics) Ascent() uint8

func (*FontMetrics) Descent

func (self *FontMetrics) Descent() uint8

func (*FontMetrics) ExtraAscent

func (self *FontMetrics) ExtraAscent() uint8

func (*FontMetrics) ExtraDescent

func (self *FontMetrics) ExtraDescent() uint8

func (*FontMetrics) HasVertLayout

func (self *FontMetrics) HasVertLayout() bool

func (*FontMetrics) HorzInterspacing

func (self *FontMetrics) HorzInterspacing() uint8

func (*FontMetrics) LineGap

func (self *FontMetrics) LineGap() uint8

func (*FontMetrics) LineHeight

func (self *FontMetrics) LineHeight() int

Utility method returning the ascent + descent + line gap.

func (*FontMetrics) MidlineAscent

func (self *FontMetrics) MidlineAscent() uint8

func (*FontMetrics) MonoWidth

func (self *FontMetrics) MonoWidth() uint8

func (*FontMetrics) Monospaced

func (self *FontMetrics) Monospaced() bool

func (*FontMetrics) NumGlyphs

func (self *FontMetrics) NumGlyphs() uint16

func (*FontMetrics) UppercaseAscent

func (self *FontMetrics) UppercaseAscent() uint8

func (*FontMetrics) Validate

func (self *FontMetrics) Validate(mode FmtValidation) error

func (*FontMetrics) VertInterspacing

func (self *FontMetrics) VertInterspacing() uint8

func (*FontMetrics) VertLineFullWidth

func (self *FontMetrics) VertLineFullWidth() int

func (*FontMetrics) VertLineGap

func (self *FontMetrics) VertLineGap() uint8

func (*FontMetrics) VertLineWidth

func (self *FontMetrics) VertLineWidth() uint8

Notice: doesn't include FontMetrics.VertLineGap(). See FontMetrics.VertLineFullWidth().

type FontRewrites

type FontRewrites Font

func (*FontRewrites) EvaluateCondition

func (self *FontRewrites) EvaluateCondition(conditionKey uint8, settings []uint8) bool

func (*FontRewrites) GetGlyphRule

func (self *FontRewrites) GetGlyphRule(index uint16) GlyphRewriteRule

func (*FontRewrites) GetGlyphSet

func (self *FontRewrites) GetGlyphSet(set uint8) GlyphRewriteSet

func (*FontRewrites) GetUtf8Rule

func (self *FontRewrites) GetUtf8Rule(index uint16) Utf8RewriteRule

func (*FontRewrites) GetUtf8Set

func (self *FontRewrites) GetUtf8Set(set uint8) Utf8RewriteSet

func (*FontRewrites) NumConditions

func (self *FontRewrites) NumConditions() uint8

func (*FontRewrites) NumGlyphRules

func (self *FontRewrites) NumGlyphRules() uint16

func (*FontRewrites) NumGlyphSets

func (self *FontRewrites) NumGlyphSets() uint8

func (*FontRewrites) NumUTF8Rules

func (self *FontRewrites) NumUTF8Rules() uint16

func (*FontRewrites) NumUTF8Sets

func (self *FontRewrites) NumUTF8Sets() uint8

func (*FontRewrites) Validate

func (self *FontRewrites) Validate(mode FmtValidation) error

type FontSettings

type FontSettings Font

Obtained through Font.Settings().

Settings can't be modified on the *Font object itself, that kind of state must be managed by a renderer or similar.

func (*FontSettings) Count

func (self *FontSettings) Count() uint8

func (*FontSettings) Each

func (self *FontSettings) Each(fn func(key SettingKey, name string))

func (*FontSettings) EachOption

func (self *FontSettings) EachOption(key SettingKey, each func(optionIndex uint8, optionName string))

func (*FontSettings) GetNumOptions

func (self *FontSettings) GetNumOptions(key SettingKey) uint8

func (self *FontSettings) FindKeyByName(name string) SettingKey { panic("unimplemented") } func (self *FontSettings) GetInitValue(key SettingKey) uint8 { panic("unimplemented") }

func (*FontSettings) GetOptionName

func (self *FontSettings) GetOptionName(key SettingKey, option uint8) string

func (*FontSettings) GetWord

func (self *FontSettings) GetWord(index uint8) string

func (*FontSettings) NumWords

func (self *FontSettings) NumWords() uint8

func (*FontSettings) Validate

func (self *FontSettings) Validate(mode FmtValidation) error

type GlyphIndex

type GlyphIndex uint16
const (
	GlyphMissing GlyphIndex = 56789
	GlyphZilch   GlyphIndex = 56790
	GlyphNewLine GlyphIndex = 56791

	GlyphCustomMin GlyphIndex = 60000
	GlyphCustomMax GlyphIndex = 62000
)

type GlyphMappingGroup

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

Returned from FontMapping.Utf8().

func (*GlyphMappingGroup) AnimationFlags

func (self *GlyphMappingGroup) AnimationFlags() AnimationFlags

func (*GlyphMappingGroup) CaseBranch

func (self *GlyphMappingGroup) CaseBranch() uint8

func (*GlyphMappingGroup) Select

func (self *GlyphMappingGroup) Select(choice uint8) GlyphIndex

Precondition: choice must be between 0 and GlyphMappingGroup.Size() - 1

func (*GlyphMappingGroup) Size

func (self *GlyphMappingGroup) Size() uint8

type GlyphPlacement

type GlyphPlacement struct {
	Advance uint8

	// vertical bounds fields: these will be zero
	// unless the font includes vertical layout data
	TopAdvance, BottomAdvance uint8
	HorzCenter                uint8 // offset to the glyph's center pixel, from the origin
}

type GlyphRange

type GlyphRange struct {
	First GlyphIndex // included
	Last  GlyphIndex // included
}

func NewRange

func NewRange(first, last GlyphIndex) GlyphRange

func (*GlyphRange) Contains

func (self *GlyphRange) Contains(index GlyphIndex) bool

func (*GlyphRange) Validate

func (self *GlyphRange) Validate(maxGlyphs uint16) error

type GlyphRewriteRule

type GlyphRewriteRule internal.RawBlock

func (*GlyphRewriteRule) BodyLen

func (self *GlyphRewriteRule) BodyLen() uint8

func (*GlyphRewriteRule) Condition

func (self *GlyphRewriteRule) Condition() uint8

TODO: a validation method would be nice

func (*GlyphRewriteRule) EachOut

func (self *GlyphRewriteRule) EachOut(each func(GlyphIndex))

func (*GlyphRewriteRule) Equals

func (self *GlyphRewriteRule) Equals(other GlyphRewriteRule) bool

func (*GlyphRewriteRule) HeadLen

func (self *GlyphRewriteRule) HeadLen() uint8

func (*GlyphRewriteRule) InLen

func (self *GlyphRewriteRule) InLen() uint8

func (*GlyphRewriteRule) OutLen

func (self *GlyphRewriteRule) OutLen() uint8

func (*GlyphRewriteRule) TailLen

func (self *GlyphRewriteRule) TailLen() uint8

type GlyphRewriteSet

type GlyphRewriteSet internal.RawBlock

func (*GlyphRewriteSet) EachListGlyph

func (self *GlyphRewriteSet) EachListGlyph(each func(GlyphIndex) error) error

func (*GlyphRewriteSet) EachRange

func (self *GlyphRewriteSet) EachRange(each func(GlyphRange) error) error

type MappingCache

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

Glyph mapping cache. These are recommended to be used at small sizes, like 192. In general, a glyph mapping cache is not even critical for operation unless the font has multiple settings affecting mapping, animations and so on. In those cases, the mapping can get more expensive, and using a mapping cache can be beneficial.

func NewMappingCache

func NewMappingCache(font *Font, size int) *MappingCache

The size is statically allocated.

func (*MappingCache) Drop

func (self *MappingCache) Drop()

Drops must be manually requested due to variable changes.

func (*MappingCache) Get

func (self *MappingCache) Get(codePoint rune, settings *SettingsCache) (GlyphMappingGroup, bool)

Returned bool will be false if not found.

func (*MappingCache) Reset

func (self *MappingCache) Reset(font *Font)

Resets the mapping cache completely, with only the size being preserved.

type PaletteKey

type PaletteKey uint8

Palettes are part of the font coloring. See FontColor for more details.

Palette keys go from 0 to FontColor.NumPalettes() - 1, so they can be used directly for slice indexing if necessary.

type SettingKey

type SettingKey uint8

Index to a font setting. See FontSettings.

type SettingsCache

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

func NewSettingsCache

func NewSettingsCache(font *Font) *SettingsCache

func (*SettingsCache) CacheMappingCase

func (self *SettingsCache) CacheMappingCase(switchTypeIndex uint8, result uint8)

func (*SettingsCache) CacheRewriteCondition

func (self *SettingsCache) CacheRewriteCondition(conditionIndex uint8, satisfied bool)

func (*SettingsCache) Get

func (self *SettingsCache) Get(key SettingKey) uint8

func (*SettingsCache) GetMappingCase

func (self *SettingsCache) GetMappingCase(switchTypeIndex uint8) (uint8, bool)

First uint8 is the case value, second bool is case being cached or not. If not cached, the first result must be ignored.

func (*SettingsCache) GetRewriteCondition

func (self *SettingsCache) GetRewriteCondition(conditionIndex uint8) (bool, bool)

First bool is the condition being satisfied or not. Second bool is condition being cached or not. If not cached, the first result must be ignored.

func (*SettingsCache) Set

func (self *SettingsCache) Set(key SettingKey, option uint8) (mappingsAffected, rewriteConditionsAffected bool)

Returns two bools for mappings and rewrite conditions affected.

func (*SettingsCache) UnsafeSlice

func (self *SettingsCache) UnsafeSlice() []uint8

TODO: read only, might remove later.

type Utf8RewriteRule

type Utf8RewriteRule internal.RawBlock

func (*Utf8RewriteRule) BodyLen

func (self *Utf8RewriteRule) BodyLen() uint8

func (*Utf8RewriteRule) Condition

func (self *Utf8RewriteRule) Condition() uint8

func (*Utf8RewriteRule) EachOut

func (self *Utf8RewriteRule) EachOut(each func(rune))

func (*Utf8RewriteRule) Equals

func (self *Utf8RewriteRule) Equals(other Utf8RewriteRule) bool

func (*Utf8RewriteRule) HeadLen

func (self *Utf8RewriteRule) HeadLen() uint8

func (*Utf8RewriteRule) InLen

func (self *Utf8RewriteRule) InLen() uint8

func (*Utf8RewriteRule) OutLen

func (self *Utf8RewriteRule) OutLen() uint8

func (*Utf8RewriteRule) String

func (self *Utf8RewriteRule) String() string

func (*Utf8RewriteRule) TailLen

func (self *Utf8RewriteRule) TailLen() uint8

type Utf8RewriteSet

type Utf8RewriteSet internal.RawBlock

func (*Utf8RewriteSet) EachListRune

func (self *Utf8RewriteSet) EachListRune(each func(rune) error) error

func (*Utf8RewriteSet) EachRange

func (self *Utf8RewriteSet) EachRange(each func(start, end rune) error) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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