Exemple #1
0
func NewSDFFont3(fontPath string, size float64, dpi int, readonly bool, firstRune, lastRune rune, sdfSize float64, scanRange int) (*Font, error) {
	fontBytes, err := ioutil.ReadFile(fontPath)
	if err != nil {
		return nil, err
	}
	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		return nil, err
	}

	fontBytes = nil

	c := freetype.NewContext()
	c.SetDPI(dpi)
	c.SetFont(font)
	c.SetFontSize(sdfSize)
	c.SetSrc(image.White)

	ratio := sdfSize / size

	text := ""
	for i := firstRune; i < lastRune+1; i++ {
		text += string(i)
	}

	rects := make([]image.Rectangle, 0)
	LetterArray := make(map[rune]*LetterInfo)

	for _, r := range text {
		index := font.Index(r)
		mask, offset, err := c.Glyph(index, freetype.Pt(0, 0))
		if err != nil {
			fmt.Println("Rune generation error:", err)
			continue
		}
		bd := mask.Bounds()

		AdvanceWidth := c.FUnitToFix32(int(font.HMetric(index).AdvanceWidth)).Float()
		LeftSideBearing := c.FUnitToFix32(int(font.HMetric(index).LeftSideBearing)).Float()
		AdvanceWidth = AdvanceWidth / float32(sdfSize)
		LeftSideBearing = LeftSideBearing / float32(sdfSize)
		YOffset := (float32(-offset.Y) - float32(mask.Bounds().Max.Y)) / float32(sdfSize)
		relativeWidth := float32(bd.Dx()) / float32(sdfSize)
		relativeHeight := float32(bd.Dy()) / float32(sdfSize)

		sdfBounds := mask.Bounds()
		sdfBounds.Max.X = int(float64(sdfBounds.Max.X)/ratio) + 2
		sdfBounds.Max.Y = int(float64(sdfBounds.Max.Y)/ratio) + 2

		rects = append(rects, sdfBounds)

		LetterArray[r] = &LetterInfo{sdfBounds, YOffset, LeftSideBearing, AdvanceWidth, relativeWidth, relativeHeight}
	}

	ay, ax, e := FindOptimalSize(10, rects...)
	if e != nil {
		return nil, e
	}

	dst := image.NewRGBA(image.Rect(0, 0, int(ax), int(ay)))
	node := NewBin(int(ax), int(ay), Padding)

	rects, e = node.InsertArray(rects)
	if e != nil {
		return nil, e
	}

	rectIndex := 0
	for _, r := range text {
		index := font.Index(r)
		mask, _, err := c.Glyph(index, freetype.Pt(0, 0))
		if err != nil {
			fmt.Println("Rune generation error:", err)
			continue
		}

		rect := rects[rectIndex]
		newMask := image.NewAlpha(rect)

		//Note: this is slow we need to find better algorithm
		for xx := 0; xx < newMask.Bounds().Dx(); xx++ {
			for yy := 0; yy < newMask.Bounds().Dy(); yy++ {
				alpha := FindSDFAlpha(mask, int(float64(xx)*ratio), int(float64(yy)*ratio), scanRange)
				newMask.SetAlpha(xx, yy, color.Alpha{uint8(alpha)})
			}
		}

		draw.Draw(dst, rect, newMask, image.ZP, draw.Src)
		LetterArray[r].Rect = rect
		rectIndex++
	}

	texture, err := NewTexture(dst, dst.Pix)
	if err != nil {
		return nil, err
	}

	if readonly {
		texture.SetReadOnly()
	}

	texture.SetFiltering(Linear, Linear)

	return &Font{texture, LetterArray, size, dpi, true}, nil
}
Exemple #2
0
func NewFont2(fontPath string, size float64, dpi int, readonly bool, firstRune, lastRune rune) (*Font, error) {
	fontBytes, err := ioutil.ReadFile(fontPath)
	if err != nil {
		return nil, err
	}
	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		return nil, err
	}

	fontBytes = nil

	c := freetype.NewContext()
	c.SetDPI(dpi)
	c.SetFont(font)
	c.SetFontSize(size)
	c.SetSrc(image.White)

	text := ""
	for i := firstRune; i < lastRune+1; i++ {
		text += string(i)
	}

	rects := make([]image.Rectangle, 0)
	LetterArray := make(map[rune]*LetterInfo)

	for _, r := range text {
		index := font.Index(r)
		mask, offset, err := c.Glyph(index, freetype.Pt(0, 0))
		if err != nil {
			fmt.Println("Rune generation error:", err)
			continue
		}
		bd := mask.Bounds()

		AdvanceWidth := c.FUnitToFix32(int(font.HMetric(index).AdvanceWidth)).Float()
		LeftSideBearing := c.FUnitToFix32(int(font.HMetric(index).LeftSideBearing)).Float()
		AdvanceWidth = AdvanceWidth / float32(size)
		LeftSideBearing = LeftSideBearing / float32(size)
		YOffset := (float32(-offset.Y) - float32(mask.Bounds().Max.Y)) / float32(size)
		relativeWidth := float32(bd.Dx()) / float32(size)
		relativeHeight := float32(bd.Dy()) / float32(size)

		rects = append(rects, mask.Bounds())

		LetterArray[r] = &LetterInfo{bd, YOffset, LeftSideBearing, AdvanceWidth, relativeWidth, relativeHeight}
	}

	ay, ax, e := FindOptimalSize(10, rects...)
	if e != nil {
		return nil, e
	}

	dst := image.NewRGBA(image.Rect(0, 0, int(ax), int(ay)))
	node := NewBin(int(ax), int(ay), Padding)
	rects, e = node.InsertArray(rects)
	if e != nil {
		return nil, e
	}

	rectIndex := 0
	for _, r := range text {
		index := font.Index(r)
		mask, _, err := c.Glyph(index, freetype.Pt(0, 0))
		if err != nil {
			fmt.Println("Rune generation error:", err)
			continue
		}

		rect := rects[rectIndex]

		draw.Draw(dst, rect, mask, image.ZP, draw.Src)
		LetterArray[r].Rect = rect
		rectIndex++
	}

	texture, err := NewTexture(dst, dst.Pix)
	if err != nil {
		return nil, err
	}

	if readonly {
		texture.SetReadOnly()
	}

	texture.SetFiltering(Linear, Linear)

	return &Font{texture, LetterArray, size, dpi, false}, nil

}