github.com/kintar/etxt@v0.0.9/eglyr/glyph_renderer.go (about)

     1  // The eglyr subpackage defines a [Renderer] struct that behaves like the main
     2  // [etxt.Renderer], but overriding a few methods to operate with glyph indices
     3  // instead of strings.
     4  //
     5  // This subpackage is only relevant if you are doing [text shaping] on your own.
     6  //
     7  // This subpackage also demonstrates how to use type embedding and the original
     8  // etxt renderer methods in order to create a more specialized renderer (in this
     9  // case, one that improves support for working with glyph indices).
    10  //
    11  // [text shaping]: https://github.com/kintar/etxt/blob/main/docs/shaping.md
    12  package eglyr
    13  
    14  import "github.com/kintar/etxt"
    15  import "github.com/kintar/etxt/emask"
    16  import "golang.org/x/image/math/fixed"
    17  
    18  // A type alias to prevent exposing the internal etxt.Renderer embedded
    19  // in the new glyph-specialized renderer.
    20  type internalRenderer = etxt.Renderer
    21  
    22  // A renderer just like [etxt.Renderer], but with a few methods overridden
    23  // and adapted to operate with [GlyphIndex] slices instead of strings.
    24  //
    25  // Despite the documentation missing the inherited methods, notice that all
    26  // the property setters and getters available for [etxt.Renderer] are also
    27  // available for this renderer.
    28  type Renderer struct{ internalRenderer }
    29  
    30  // Creates a new glyph-specialized [Renderer] with the default vector
    31  // rasterizer.
    32  //
    33  // This method is the eglyr equivalent to [etxt.NewStdRenderer]().
    34  func NewStdRenderer() *Renderer {
    35  	return NewRenderer(&emask.DefaultRasterizer{})
    36  }
    37  
    38  // Creates a new [Renderer] with the given glyph mask rasterizer.
    39  // For the default rasterizer, see [NewStdRenderer]() instead.
    40  //
    41  // This method is the eglyr equivalent to [etxt.NewRenderer]().
    42  func NewRenderer(rasterizer emask.Rasterizer) *Renderer {
    43  	return &Renderer{*etxt.NewRenderer(rasterizer)}
    44  }
    45  
    46  // An alias for [etxt.Renderer.SelectionRectGlyphs]().
    47  func (self *Renderer) SelectionRect(glyphIndices []GlyphIndex) etxt.RectSize {
    48  	return self.internalRenderer.SelectionRectGlyphs(glyphIndices)
    49  }
    50  
    51  // Draws the given glyphs with the current configuration. Glyph indices
    52  // outside the [0, font.NumGlyphs()) range will cause the renderer to panic.
    53  //
    54  // This method is the eglyr equivalent to [etxt.Renderer.Draw]().
    55  func (self *Renderer) Draw(glyphIndices []GlyphIndex, x, y int) fixed.Point26_6 {
    56  	fx, fy := fixed.Int26_6(x<<6), fixed.Int26_6(y<<6)
    57  	return self.DrawFract(glyphIndices, fx, fy)
    58  }
    59  
    60  // Same as [Renderer.Draw](), but accepting [fractional pixel] coordinates.
    61  //
    62  // This method is the eglyr equivalent to [etxt.Renderer.DrawFract]().
    63  //
    64  // [fractional pixel]: https://github.com/kintar/etxt/blob/main/docs/fixed-26-6.md
    65  func (self *Renderer) DrawFract(glyphIndices []GlyphIndex, x, y fixed.Int26_6) fixed.Point26_6 {
    66  	if len(glyphIndices) == 0 {
    67  		return fixed.Point26_6{X: x, Y: y}
    68  	}
    69  
    70  	// traverse glyphs and draw them
    71  	return self.TraverseGlyphs(glyphIndices, fixed.Point26_6{X: x, Y: y},
    72  		func(currentDot fixed.Point26_6, glyphIndex GlyphIndex) {
    73  			mask := self.LoadGlyphMask(glyphIndex, currentDot)
    74  			self.DefaultDrawFunc(currentDot, mask, glyphIndex)
    75  		})
    76  }