func NewFont(path string, runes string, OgScale fixed.Int26_6) *Font {
	// Inittialize a new Font struct
	f := new(Font)
	f.OgScale = OgScale
	f.GlyphMap = make(map[rune]*Shape)
	// Read and parse the file provided
	fontFile, err := ioutil.ReadFile(path)
	orDie(err)
	ttFont, err := sfnt.Parse(fontFile)
	orDie(err)
	f.TtfFont = ttFont
	// If Default scale is 0, set it to a default value
	if f.OgScale == 0 {
		f.OgScale = fixed.I(64)
	}
	boundR, err := ttFont.Bounds(nil, f.OgScale, font.HintingNone)
	orDie(err)
	bound := boundR.Max.Sub(boundR.Min)
	maxX, maxY := bound.X.Round(), bound.Y.Round()

	// Get the glyphs from rune 0 to 512 and create shapes out of them
	// and store them in the Font struct
	for _, i := range runes {
		// Initialize a new glyph for rune i, with the provided scale and no hinting
		glyph := &sfnt.Buffer{}
		I, err := ttFont.GlyphIndex(glyph, rune(i))
		orDie(err)
		segs, err := ttFont.LoadGlyph(glyph, I, f.OgScale, nil)
		// Add the glyph to Font if needed elesewhere
		f.GlyphMap[rune(i)] = NewShape(mgl32.Ident4(), program)
		// If the given rune has no shape in it, then give it a line
		// This happens in case of space, escape codes and invalid characters
		if len(segs) == 0 {
			f.GlyphMap[rune(i)].Pts = make([]*Point, 2)
			f.GlyphMap[rune(i)].Pts[0] = P(-1, -1, 1)
			f.GlyphMap[rune(i)].Pts[1] = P(1, -1, 1)
		} else {
			// Get the bounds of the glyph
			// Make a point to store the coords of SegmentOpMoveTo
			prevP := P(0, 0, 0)
			for _, val := range segs {
				// Scale its coords to -1 to 1
				x0, y0 := -float32(val.Args[0].X.Round())/float32(maxX), -float32(val.Args[0].Y.Round())/float32(maxY)
				x1, y1 := -float32(val.Args[1].X.Round())/float32(maxX), -float32(val.Args[1].Y.Round())/float32(maxY)
				x2, y2 := -float32(val.Args[2].X.Round())/float32(maxX), -float32(val.Args[2].Y.Round())/float32(maxY)
				//fmt.Println(x1, y1)
				switch val.Op {

				case sfnt.SegmentOpMoveTo:
					prevP = P(x0, y0, 1)
				case sfnt.SegmentOpLineTo:
					f.GlyphMap[rune(i)].Pts = append(f.GlyphMap[rune(i)].Pts,
						P(prevP.X(), prevP.Y(), 1),
						P(x0, y0, 1))
					prevP = P(x0, y0, 1)
				case sfnt.SegmentOpQuadTo:
					f.GlyphMap[rune(i)].Pts = append(f.GlyphMap[rune(i)].Pts,
						LineStripToSeg(BezCurve(8/float32(f.OgScale),
							P(prevP.X(), prevP.Y(), 1),
							P(x0, y0, 1),
							P(x1, y1, 1))...)...)

					prevP = P(x1, y1, 1)

				case sfnt.SegmentOpCubeTo:
					f.GlyphMap[rune(i)].Pts = append(f.GlyphMap[rune(i)].Pts,
						LineStripToSeg(CubicBezCurve(8/float32(f.OgScale),
							P(prevP.X(), prevP.Y(), 1),
							P(x0, y0, 1),
							P(x1, y1, 1),
							P(x2, y2, 1))...)...)

					prevP = P(x2, y2, 1)
				}
			}
		}

		f.GlyphMap[rune(i)].SetTypes(gl.LINES)
		//	f.GlyphMap[rune(i)].GenVao()
		orDie(err)
	}
	return f
}
// This function creates a new Font to be used by TextToShape function
// Supply the characters to load in runes
// NOTE: This function is not very memory efficient, donot call this in loop
This function creates a new Font to be used by TextToShape function
Supply the characters to load in runes
NOTE: This function is not very memory efficient, donot call this in loop
// This function creates a new Font to be used by TextToShape function // Supply the characters to load in runes // NOTE : This function is not very memory efficient donot call this in loop
func NewFont(path string, runes string, OgScale fixed.Int26_6) *Font {
	f := new(Font)
	f.OgScale = OgScale
	f.GlyphMap = make(map[rune]*Shape)
	fontFile, err := ioutil.ReadFile(path)
	orDie(err)
	ttFont, err := sfnt.Parse(fontFile)
	orDie(err)
	f.TtfFont = ttFont
	if f.OgScale == 0 {
		f.OgScale = fixed.I(64)
	}
	boundR, err := ttFont.Bounds(nil, f.OgScale, font.HintingNone)
	orDie(err)
	bound := boundR.Max.Sub(boundR.Min)
	maxX, maxY := bound.X.Round(), bound.Y.Round()
	for _, i := range runes {
		glyph := &sfnt.Buffer{}
		I, err := ttFont.GlyphIndex(glyph, rune(i))
		orDie(err)
		segs, err := ttFont.LoadGlyph(glyph, I, f.OgScale, nil)
		f.GlyphMap[rune(i)] = NewShape(mgl32.Ident4(), program)
		if len(segs) == 0 {
			f.GlyphMap[rune(i)].Pts = make([]*Point, 2)
			f.GlyphMap[rune(i)].Pts[0] = P(-1, -1, 1)
			f.GlyphMap[rune(i)].Pts[1] = P(1, -1, 1)
		} else {
			prevP := P(0, 0, 0)
			for _, val := range segs {
				x0, y0 := -float32(val.Args[0].X.Round())/float32(maxX), -float32(val.Args[0].Y.Round())/float32(maxY)
				x1, y1 := -float32(val.Args[1].X.Round())/float32(maxX), -float32(val.Args[1].Y.Round())/float32(maxY)
				x2, y2 := -float32(val.Args[2].X.Round())/float32(maxX), -float32(val.Args[2].Y.Round())/float32(maxY)
				switch val.Op {
				case sfnt.SegmentOpMoveTo:
					prevP = P(x0, y0, 1)
				case sfnt.SegmentOpLineTo:
					f.GlyphMap[rune(i)].Pts = append(f.GlyphMap[rune(i)].Pts,
						P(prevP.X(), prevP.Y(), 1),
						P(x0, y0, 1))
					prevP = P(x0, y0, 1)
				case sfnt.SegmentOpQuadTo:
					f.GlyphMap[rune(i)].Pts = append(f.GlyphMap[rune(i)].Pts,
						LineStripToSeg(BezCurve(8/float32(f.OgScale),
							P(prevP.X(), prevP.Y(), 1),
							P(x0, y0, 1),
							P(x1, y1, 1))...)...)
					prevP = P(x1, y1, 1)
				case sfnt.SegmentOpCubeTo:
					f.GlyphMap[rune(i)].Pts = append(f.GlyphMap[rune(i)].Pts,
						LineStripToSeg(CubicBezCurve(8/float32(f.OgScale),
							P(prevP.X(), prevP.Y(), 1),
							P(x0, y0, 1),
							P(x1, y1, 1),
							P(x2, y2, 1))...)...)
					prevP = P(x2, y2, 1)
				}
			}
		}
		f.GlyphMap[rune(i)].SetTypes(gl.LINES)
		orDie(err)
	}
	return f
}
func NewFont ( path string , runes string , OgScale fixed . Int26_6 ) * Font { f := new ( Font ) f . OgScale = OgScale f . GlyphMap = make ( map [ rune ] * Shape ) fontFile , err := ioutil . ReadFile ( path ) orDie ( err ) ttFont , err := sfnt . Parse ( fontFile ) orDie ( err ) f . TtfFont = ttFont if f . OgScale == 0 { f . OgScale = fixed . I ( 64 ) } boundR , err := ttFont . Bounds ( nil , f . OgScale , font . HintingNone ) orDie ( err ) bound := boundR . Max . Sub ( boundR . Min ) maxX , maxY := bound . X . Round ( ) , bound . Y . Round ( ) for _ , i := range runes { glyph := & sfnt . Buffer { } I , err := ttFont . GlyphIndex ( glyph , rune ( i ) ) orDie ( err ) segs , err := ttFont . LoadGlyph ( glyph , I , f . OgScale , nil ) f . GlyphMap [ rune ( i ) ] = NewShape ( mgl32 . Ident4 ( ) , program ) if len ( segs ) == 0 { f . GlyphMap [ rune ( i ) ] . Pts = make ( [ ] * Point , 2 ) f . GlyphMap [ rune ( i ) ] . Pts [ 0 ] = P ( - 1 , - 1 , 1 ) f . GlyphMap [ rune ( i ) ] . Pts [ 1 ] = P ( 1 , - 1 , 1 ) } else { prevP := P ( 0 , 0 , 0 ) for _ , val := range segs { x0 , y0 := - float32 ( val . Args [ 0 ] . X . Round ( ) ) / float32 ( maxX ) , - float32 ( val . Args [ 0 ] . Y . Round ( ) ) / float32 ( maxY ) x1 , y1 := - float32 ( val . Args [ 1 ] . X . Round ( ) ) / float32 ( maxX ) , - float32 ( val . Args [ 1 ] . Y . Round ( ) ) / float32 ( maxY ) x2 , y2 := - float32 ( val . Args [ 2 ] . X . Round ( ) ) / float32 ( maxX ) , - float32 ( val . Args [ 2 ] . Y . Round ( ) ) / float32 ( maxY ) switch val . Op { case sfnt . SegmentOpMoveTo : prevP = P ( x0 , y0 , 1 ) case sfnt . SegmentOpLineTo : f . GlyphMap [ rune ( i ) ] . Pts = append ( f . GlyphMap [ rune ( i ) ] . Pts , P ( prevP . X ( ) , prevP . Y ( ) , 1 ) , P ( x0 , y0 , 1 ) ) prevP = P ( x0 , y0 , 1 ) case sfnt . SegmentOpQuadTo : f . GlyphMap [ rune ( i ) ] . Pts = append ( f . GlyphMap [ rune ( i ) ] . Pts , LineStripToSeg ( BezCurve ( 8 / float32 ( f . OgScale ) , P ( prevP . X ( ) , prevP . Y ( ) , 1 ) , P ( x0 , y0 , 1 ) , P ( x1 , y1 , 1 ) ) ... ) ... ) prevP = P ( x1 , y1 , 1 ) case sfnt . SegmentOpCubeTo : f . GlyphMap [ rune ( i ) ] . Pts = append ( f . GlyphMap [ rune ( i ) ] . Pts , LineStripToSeg ( CubicBezCurve ( 8 / float32 ( f . OgScale ) , P ( prevP . X ( ) , prevP . Y ( ) , 1 ) , P ( x0 , y0 , 1 ) , P ( x1 , y1 , 1 ) , P ( x2 , y2 , 1 ) ) ... ) ... ) prevP = P ( x2 , y2 , 1 ) } } } f . GlyphMap [ rune ( i ) ] . SetTypes ( gl . LINES ) orDie ( err ) } return f }
This function creates a new Font to be used by TextToShape function
Supply the characters to load in runes
NOTE: This function is not very memory efficient, donot call this in loop
This function creates a new Font to be used by TextToShape function Supply the characters to load in runes NOTE : This function is not very memory efficient donot call this in loop
// Inittialize a new Font struct // Read and parse the file provided // If Default scale is 0, set it to a default value // Get the glyphs from rune 0 to 512 and create shapes out of them // and store them in the Font struct // Initialize a new glyph for rune i, with the provided scale and no hinting // Add the glyph to Font if needed elesewhere // If the given rune has no shape in it, then give it a line // This happens in case of space, escape codes and invalid characters // Get the bounds of the glyph // Make a point to store the coords of SegmentOpMoveTo // Scale its coords to -1 to 1 //fmt.Println(x1, y1) //	f.GlyphMap[rune(i)].GenVao()