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

     1  package etxt
     2  
     3  import "golang.org/x/image/math/fixed"
     4  
     5  // Only private methods related to alignment operations.
     6  
     7  // precondition: non-empty text
     8  func (self *Renderer) alignTextDotY(text string, y fixed.Int26_6) fixed.Int26_6 {
     9  	if self.vertAlignRequiresHeight() { // compute height if needed
    10  		return self.alignDotY(self.textHeight(text), y)
    11  	}
    12  	return self.alignDotY(0, y) // height not needed
    13  }
    14  
    15  // precondition: non-empty glyphIndices
    16  func (self *Renderer) alignGlyphsDotY(y fixed.Int26_6) fixed.Int26_6 {
    17  	if self.vertAlignRequiresHeight() { // compute height if needed
    18  		if self.metrics == nil {
    19  			self.updateMetrics()
    20  		}
    21  		return self.alignDotY(self.metrics.Height, y)
    22  	}
    23  	return self.alignDotY(0, y) // height not needed
    24  }
    25  
    26  // Given a reference y coordinate, it aligns it to the baseline drawing
    27  // point based on the current vertical align and the height of the
    28  // content to draw.
    29  func (self *Renderer) alignDotY(height, y fixed.Int26_6) fixed.Int26_6 {
    30  	// return early on simple Baseline case
    31  	if self.vertAlign == Baseline {
    32  		return y
    33  	}
    34  
    35  	// align y coordinate
    36  	if self.metrics == nil {
    37  		self.updateMetrics()
    38  	}
    39  	switch self.vertAlign {
    40  	case YCenter:
    41  		y += self.metrics.Ascent
    42  		if self.lineSpacing < 0 { // evil edge case
    43  			y -= height - self.metrics.Height
    44  		}
    45  		y -= (height >> 1)
    46  	case Top:
    47  		y += self.metrics.Ascent
    48  		if self.lineSpacing < 0 { // evil edge case
    49  			y -= height - self.metrics.Height
    50  		}
    51  	case Bottom:
    52  		y -= self.metrics.Descent
    53  		if self.lineSpacing >= 0 {
    54  			y -= height - self.metrics.Height
    55  		} else { // evil edge case
    56  			y += height - self.metrics.Height
    57  		}
    58  	}
    59  
    60  	return y
    61  }
    62  
    63  func (self *Renderer) vertAlignRequiresHeight() bool {
    64  	switch self.vertAlign {
    65  	case YCenter:
    66  		return true
    67  	case Bottom:
    68  		return true
    69  	case Top:
    70  		return (self.lineSpacing < 0)
    71  	case Baseline:
    72  		return false
    73  	default:
    74  		panic("unhandled switch case")
    75  	}
    76  }