faiface / pixel

A hand-crafted 2D game library in Go
MIT License
4.45k stars 245 forks source link

Text is not well positioned with some fonts #255

Open roipoussiere opened 4 years ago

roipoussiere commented 4 years ago

I use Material icons as font for a project.

In the example below, the letters and icons are both drawn from the same origin, but the icons start with an unexpected offset:

image

Where:

See the source code for more details:

source code (click to expand)
package main

import (
    "fmt"
    "github.com/faiface/pixel"
    "github.com/faiface/pixel/imdraw"
    "github.com/faiface/pixel/pixelgl"
    "github.com/faiface/pixel/text"
    "github.com/golang/freetype/truetype"
    "golang.org/x/image/colornames"
    "golang.org/x/image/font/gofont/goregular"
    "image/color"
    "io/ioutil"
    "os"
    "path"
)

const fontSize float64 = 64
const distance float64 = 100

var offset pixel.Vec = pixel.V(25, 25)

func main() {
    pixelgl.Run(run)
}

func run() {
    cfg := pixelgl.WindowConfig{
        Title:  "Pixel Rocks!",
        Bounds: pixel.R(0, 0, 300, 300),
    }

    win, err := pixelgl.NewWindow(cfg)
    if err != nil {
        panic(err)
    }

    win.Clear(colornames.Lightgray)

    textFont, err := truetype.Parse(goregular.TTF)
    if err != nil {
        panic(err)
    }
    textFace := truetype.NewFace(textFont, &truetype.Options{Size: fontSize, GlyphCacheEntries: 1})
    textAtlas := text.NewAtlas(textFace, text.ASCII)

    iconFont, err := getTTF("MaterialIcons-Regular.ttf")
    if err != nil {
        panic(err)
    }
    iconFace := truetype.NewFace(iconFont, &truetype.Options{Size: fontSize, GlyphCacheEntries: 1})
    iconAtlas := text.NewAtlas(iconFace, []rune{'\ue313', '\ue314', '\ue315', '\ue316'})

    north := pixel.V(1, 2).Scaled(distance).Add(offset)
    drawTxt(win, north, textAtlas, "n", colornames.Red, colornames.Pink)
    drawTxt(win, north, iconAtlas, string('\ue316'), colornames.Green, colornames.Lightgreen)
    drawDot(win, north, colornames.Blue)

    east := pixel.V(2, 1).Scaled(distance).Add(offset)
    drawTxt(win, east, textAtlas, "e", colornames.Red, colornames.Pink)
    drawTxt(win, east, iconAtlas, string('\ue315'), colornames.Green, colornames.Lightgreen)
    drawDot(win, east, colornames.Blue)

    south := pixel.V(1, 0).Scaled(distance).Add(offset)
    drawTxt(win, south, textAtlas, "s", colornames.Red, colornames.Pink)
    drawTxt(win, south, iconAtlas, string('\ue313'), colornames.Green, colornames.Lightgreen)
    drawDot(win, south, colornames.Blue)

    west := pixel.V(0, 1).Scaled(distance).Add(offset)
    drawTxt(win, west, textAtlas, "w", colornames.Red, colornames.Pink)
    drawTxt(win, west, iconAtlas, string('\ue314'), colornames.Green, colornames.Lightgreen)
    drawDot(win, west, colornames.Blue)

    for !win.Closed() {
        win.Update()
    }
}

func getTTF(fontName string) (*truetype.Font, error) {
    file, err := os.Open(path.Join("assets", fontName))
    if err != nil {
        return nil, err
    }
    defer file.Close()

    bytes, err := ioutil.ReadAll(file)
    if err != nil {
        return nil, err
    }

    ttf, err := truetype.Parse(bytes)
    if err != nil {
        return nil, err
    }

    return ttf, nil
}

func drawTxt(win *pixelgl.Window, pos pixel.Vec, atlas *text.Atlas, txtContent string, color, bgColor color.Color) {
    txt := text.New(pos, atlas)
    txt.Color = color
    fmt.Fprint(txt, txtContent)
    drawDot(win, txt.Dot, color)
    drawRect(win, txt.Bounds(), bgColor)
    txt.Draw(win, pixel.IM)
}

func drawDot(win *pixelgl.Window, pos pixel.Vec, color color.Color) {
    drawRect(win, pixel.R(pos.X-3, pos.Y-3, pos.X+3, pos.Y+3), color)
}

func drawRect(win *pixelgl.Window, rect pixel.Rect, color color.Color) {
    imd := imdraw.New(nil)
    imd.Color = color
    imd.Push(rect.Min, rect.Max)
    imd.Rectangle(0)
    imd.Draw(win)
}
Asday commented 4 years ago

I'd imagine this is because the baseline of those characters is different.

Could you put them in a line in a word processor or browser and see if they still exhibit the same positioning?

roipoussiere commented 4 years ago

Could you put them in a line in a word processor or browser and see if they still exhibit the same positioning?

image

Here, I selected the two first icons.

source code:

<!DOCTYPE html>
<html>
    <head>
        <style>
            @font-face { font-family: "iconsFont"; src: url("assets/MaterialIcons-Regular.ttf"); }
            .icon { font-family: "iconsFont"; font-size: large }
        </style>
    </head>
    <body>
        <p>Some icons: <span class="icon">&#xe313;&#xe314;&#xe315;&#xe316;</span></p>
    </body>
</html>