github.com/Kintar/etxt@v0.0.0-20221224033739-2fc69f000137/renderer_draw.go (about)

     1  package etxt
     2  
     3  import "strconv"
     4  
     5  import "golang.org/x/image/math/fixed"
     6  
     7  import "github.com/Kintar/etxt/emask"
     8  
     9  // Drawing functions for the Renderer type.
    10  
    11  // Draws the given text with the current configuration (font, size, color,
    12  // target, etc). The position at which the text will be drawn depends on
    13  // the given pixel coordinates and the renderer's align (see
    14  // [Renderer.SetAlign]() rules).
    15  //
    16  // The returned value should be ignored except on advanced use-cases
    17  // (refer to [Renderer.Traverse]() documentation).
    18  //
    19  // Missing glyphs in the current font will cause the renderer to panic.
    20  // See [GetMissingRunes]() if you need to make your system more robust.
    21  //
    22  // Line breaks encoded as \n will be handled automatically.
    23  func (self *Renderer) Draw(text string, x, y int) fixed.Point26_6 {
    24  	fx, fy := fixed.Int26_6(x<<6), fixed.Int26_6(y<<6)
    25  	return self.DrawFract(text, fx, fy)
    26  }
    27  
    28  // Exactly the same as [Renderer.Draw](), but accepting [fractional pixel] coordinates.
    29  //
    30  // Notice that passing a fractional coordinate won't make the draw operation
    31  // be fractionally aligned by itself, that still depends on the renderer's
    32  // [QuantizationMode].
    33  //
    34  // [fractional pixel]: https://github.com/Kintar/etxt/blob/main/docs/fixed-26-6.md
    35  func (self *Renderer) DrawFract(text string, x, y fixed.Int26_6) fixed.Point26_6 {
    36  	// safety checks
    37  	if self.target == nil {
    38  		panic("draw called while target == nil (tip: renderer.SetTarget())")
    39  	}
    40  	if self.font == nil {
    41  		panic("draw called while font == nil (tip: renderer.SetFont())")
    42  	}
    43  	if text == "" {
    44  		return fixed.Point26_6{X: x, Y: y}
    45  	}
    46  
    47  	// traverse text and draw each glyph
    48  	return self.Traverse(text, fixed.Point26_6{X: x, Y: y},
    49  		func(currentDot fixed.Point26_6, codePoint rune, glyphIndex GlyphIndex) {
    50  			if codePoint == '\n' {
    51  				return
    52  			}
    53  			mask := self.LoadGlyphMask(glyphIndex, currentDot)
    54  			self.DefaultDrawFunc(currentDot, mask, glyphIndex)
    55  		})
    56  }
    57  
    58  // Low-level function typically used with [Renderer.Traverse]*() functions when
    59  // drawing glyph masks manually.
    60  //
    61  // LoadGlyphMask loads the mask for the given glyph at the given fractional
    62  // pixel position. The renderer's cache handler, font, size, rasterizer and
    63  // mask format are all taken into account.
    64  func (self *Renderer) LoadGlyphMask(index GlyphIndex, dot fixed.Point26_6) GlyphMask {
    65  	// if the mask is available in the cache, that's all
    66  	if self.cacheHandler != nil {
    67  		glyphMask, found := self.cacheHandler.GetMask(index)
    68  		if found {
    69  			return glyphMask
    70  		}
    71  	}
    72  
    73  	// glyph mask not cached, let's rasterize on our own
    74  	segments, err := self.font.LoadGlyph(&self.buffer, index, self.sizePx, nil)
    75  	if err != nil {
    76  		// if you need to deal with missing glyphs, you should do so before
    77  		// reaching this point with functions like GetMissingRunes() and
    78  		// replacing the relevant runes or glyphs
    79  		panic("font.LoadGlyph(index = " + strconv.Itoa(int(index)) + ") error: " + err.Error())
    80  	}
    81  
    82  	// rasterize the glyph mask
    83  	alphaMask, err := emask.Rasterize(segments, self.rasterizer, dot)
    84  	if err != nil {
    85  		panic("RasterizeGlyphMask failed: " + err.Error())
    86  	}
    87  
    88  	// pass to cache and return
    89  	glyphMask := convertAlphaImageToGlyphMask(alphaMask)
    90  	if self.cacheHandler != nil {
    91  		self.cacheHandler.PassMask(index, glyphMask)
    92  	}
    93  	return glyphMask
    94  }