Skip to content

Commit

Permalink
Fix #280, blur font on darwin (#298)
Browse files Browse the repository at this point in the history
* fix #280
Font's on retina will be blur cause Rentina have 2x DPI
Now we times the DPI by 2 when on darwin, and scale the Label panel by 0.5 to keep the original size
Since we scaled the panel size back, so it should not affect much on non-Rentina darwin
However, if you are using non-darwin with rentina monitor, issue #280 will still happen, need a way to detect the monitor

* remove a debug log

* we should devide on int but not floor, or the text will be out of shape

* Revert "we should devide on int but not floor, or the text will be out of shape"
I was completely wrong, we should divide on the floor or the text won't keep it's original size

This reverts commit 73f1b6a.

* use `window.Get().GetScale()` instead of hardcoded size and os

* use explicit rune casting to pass `go test`

* fix format for font.go

* fix for Edit
  • Loading branch information
zyxkad authored Dec 10, 2023
1 parent 26e011b commit 4e30d5c
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 29 deletions.
2 changes: 1 addition & 1 deletion gui/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ func AttribCheckIcons(b *Builder, am map[string]interface{}, fname string) error
if err != nil {
return b.err(am, fname, fmt.Sprintf("Invalid icon codepoint value/name:%v", parts[i]))
}
text += string(val)
text += string(rune(val))
}
am[fname] = text
return nil
Expand Down
10 changes: 6 additions & 4 deletions gui/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ func (ed *Edit) CursorInput(s string) {

// Checks if new text exceeds edit width
width, _ := ed.Label.font.MeasureText(newText)
if float32(width)+editMarginX+float32(1) >= ed.Label.ContentWidth() {
if float32(width) / float32(ed.Label.font.ScaleX()) + editMarginX + float32(1) >= ed.Label.ContentWidth() {
return
}

Expand All @@ -412,7 +412,8 @@ func (ed *Edit) CursorInput(s string) {
func (ed *Edit) redraw(caret bool) {

line := 0
ed.Label.setTextCaret(ed.text, editMarginX, ed.width, caret, line, ed.col, ed.selStart, ed.selEnd)
scaleX, _ := window.Get().GetScale()
ed.Label.setTextCaret(ed.text, editMarginX, int(float64(ed.width) * scaleX), caret, line, ed.col, ed.selStart, ed.selEnd)
}

// onKey receives subscribed key events
Expand Down Expand Up @@ -499,7 +500,7 @@ func (ed *Edit) handleMouse(mouseX float32, dragged bool) {
for nchars = 1; nchars <= text.StrCount(ed.text); nchars++ {
width, _ := ed.Label.font.MeasureText(text.StrPrefix(ed.text, nchars))
posx := mouseX - ed.pospix.X
if posx < editMarginX+float32(width) {
if posx < editMarginX + float32(float64(width) / ed.Label.font.ScaleX()) {
break
}
}
Expand Down Expand Up @@ -597,8 +598,9 @@ func (ed *Edit) applyStyle(s *EditStyle) {
//ed.Label.SetBgAlpha(s.BgAlpha)

if !ed.focus && len(ed.text) == 0 && len(ed.placeHolder) > 0 {
scaleX, _ := window.Get().GetScale()
ed.Label.SetColor4(&s.HolderColor)
ed.Label.setTextCaret(ed.placeHolder, editMarginX, ed.width, false, -1, ed.col, ed.selStart, ed.selEnd)
ed.Label.setTextCaret(ed.placeHolder, editMarginX, int(float64(ed.width) * scaleX), false, -1, ed.col, ed.selStart, ed.selEnd)
} else {
ed.Label.SetColor4(&s.FgColor)
ed.redraw(ed.focus)
Expand Down
14 changes: 12 additions & 2 deletions gui/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/g3n/engine/math32"
"github.com/g3n/engine/text"
"github.com/g3n/engine/texture"
"github.com/g3n/engine/window"
)

// Label is a panel which contains a texture with text.
Expand Down Expand Up @@ -83,6 +84,9 @@ func (l *Label) SetText(text string) {
l.font.SetAttributes(&l.style.FontAttributes)
l.font.SetColor(&l.style.FgColor)

scaleX, scaleY := window.Get().GetScale()
l.font.SetScaleXY(scaleX, scaleY)

// Create an image with the text
textImage := l.font.DrawText(text)

Expand All @@ -98,7 +102,10 @@ func (l *Label) SetText(text string) {
}

// Update label panel dimensions
l.Panel.SetContentSize(float32(textImage.Rect.Dx()), float32(textImage.Rect.Dy()))
width, height := float32(textImage.Rect.Dx()), float32(textImage.Rect.Dy())
// since we enlarged the font texture for higher quality, we have to scale it back to it's original point size
width, height = width / float32(scaleX), height / float32(scaleY)
l.Panel.SetContentSize(width, height)
}

// Text returns the label text.
Expand Down Expand Up @@ -219,6 +226,9 @@ func (l *Label) setTextCaret(msg string, mx, width int, drawCaret bool, line, co
l.font.SetAttributes(&l.style.FontAttributes)
l.font.SetColor(&l.style.FgColor)

scaleX, scaleY := window.Get().GetScale()
l.font.SetScaleXY(scaleX, scaleY)

// Create canvas and draw text
_, height := l.font.MeasureText(msg)
canvas := text.NewCanvas(width, height, &l.style.BgColor)
Expand All @@ -237,6 +247,6 @@ func (l *Label) setTextCaret(msg string, mx, width int, drawCaret bool, line, co
l.tex.SetMinFilter(gls.NEAREST)

// Updates label panel dimensions
l.Panel.SetContentSize(float32(width), float32(height))
l.Panel.SetContentSize(float32(width) / float32(scaleX), float32(height) / float32(scaleY))
l.text = msg
}
76 changes: 54 additions & 22 deletions text/font.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"image/color"
"image/draw"
"io/ioutil"
"math"
"strings"

"github.com/g3n/engine/math32"
Expand All @@ -20,12 +21,13 @@ import (
// Font represents a TrueType font face.
// Attributes must be set prior to drawing.
type Font struct {
ttf *truetype.Font // The TrueType font
face font.Face // The font face
attrib FontAttributes // Internal attribute cache
fg *image.Uniform // Text color cache
bg *image.Uniform // Background color cache
changed bool // Whether attributes have changed and the font face needs to be recreated
ttf *truetype.Font // The TrueType font
face font.Face // The font face
attrib FontAttributes // Internal attribute cache
fg *image.Uniform // Text color cache
bg *image.Uniform // Background color cache
scaleX, scaleY float64 // Scales of actual pixel/GL point, used for fix Retina Monitor
changed bool // Whether attributes have changed and the font face needs to be recreated
}

// FontAttributes contains tunable attributes of a font.
Expand All @@ -36,6 +38,18 @@ type FontAttributes struct {
Hinting font.Hinting // Font hinting
}

func (a *FontAttributes) newTTOptions(scaleX, scaleY float64) *truetype.Options {
dpi := a.DPI
if scaleX != 0 && scaleY != 0 {
dpi *= math.Sqrt(scaleX * scaleY)
}
return &truetype.Options{
Size: a.PointSize,
DPI: dpi,
Hinting: a.Hinting,
}
}

// Font Hinting types.
const (
HintingNone = font.HintingNone
Expand Down Expand Up @@ -75,11 +89,7 @@ func NewFontFromData(fontData []byte) (*Font, error) {
f.SetColor(&math32.Color4{0, 0, 0, 1})

// Create font face
f.face = truetype.NewFace(f.ttf, &truetype.Options{
Size: f.attrib.PointSize,
DPI: f.attrib.DPI,
Hinting: f.attrib.Hinting,
})
f.face = truetype.NewFace(f.ttf, f.attrib.newTTOptions(f.scaleX, f.scaleY))

return f, nil
}
Expand Down Expand Up @@ -124,6 +134,29 @@ func (f *Font) SetHinting(hinting font.Hinting) {
f.changed = true
}

func (f *Font) ScaleXY() (x, y float64) {
return f.scaleX, f.scaleY
}

func (f *Font) ScaleX() float64 {
return f.scaleX
}

func (f *Font) ScaleY() float64 {
return f.scaleY
}

// SetScale sets the ratio of actual pixel/GL point.
func (f *Font) SetScaleXY(x, y float64) {

if x == f.scaleX && y == f.scaleY {
return
}
f.scaleX = x
f.scaleY = y
f.changed = true
}

// SetFgColor sets the text color.
func (f *Font) SetFgColor(color *math32.Color4) {

Expand Down Expand Up @@ -158,11 +191,7 @@ func (f *Font) SetAttributes(fa *FontAttributes) {
func (f *Font) updateFace() {

if f.changed {
f.face = truetype.NewFace(f.ttf, &truetype.Options{
Size: f.attrib.PointSize,
DPI: f.attrib.DPI,
Hinting: f.attrib.Hinting,
})
f.face = truetype.NewFace(f.ttf, f.attrib.newTTOptions(f.scaleX, f.scaleY))
f.changed = false
}
}
Expand Down Expand Up @@ -277,6 +306,7 @@ func (c Canvas) DrawTextCaret(x, y int, text string, f *Font, drawCaret bool, li
d := &font.Drawer{Dst: c.RGBA, Src: f.fg, Face: f.face}

// Draw text
actualPointSize := int(f.attrib.PointSize * f.scaleY)
metrics := f.face.Metrics()
py := y + metrics.Ascent.Round()
lineHeight := (metrics.Ascent + metrics.Descent).Ceil()
Expand All @@ -291,8 +321,8 @@ func (c Canvas) DrawTextCaret(x, y int, text string, f *Font, drawCaret bool, li
// TODO This will not work when the selection spans multiple lines
// Currently there is no multiline edit text
// Once there is, this needs to change
caretH := int(f.attrib.PointSize) + 2
caretY := int(d.Dot.Y>>6) - int(f.attrib.PointSize) + 2
caretH := actualPointSize + 2
caretY := int(d.Dot.Y>>6) - actualPointSize + 2
color := Color4RGBA(&math32.Color4{0, 0, 1, 0.5}) // Hardcoded to blue, alpha 50%
for w := width; w < widthEnd; w++ {
for j := caretY; j < caretY+caretH; j++ {
Expand All @@ -305,11 +335,13 @@ func (c Canvas) DrawTextCaret(x, y int, text string, f *Font, drawCaret bool, li
if drawCaret && l == line && col <= StrCount(s) {
width, _ := f.MeasureText(StrPrefix(s, col))
// Draw caret vertical line
caretH := int(f.attrib.PointSize) + 2
caretY := int(d.Dot.Y>>6) - int(f.attrib.PointSize) + 2
caretH := actualPointSize + 2
caretY := int(d.Dot.Y>>6) - actualPointSize + 2
color := Color4RGBA(&math32.Color4{0, 0, 0, 1}) // Hardcoded to black
for j := caretY; j < caretY+caretH; j++ {
c.RGBA.Set(x+width, j, color)
for i := 0; i < int(f.scaleX); i++ {
for j := caretY; j < caretY+caretH; j++ {
c.RGBA.Set(x+width+i, j, color)
}
}
}
py += lineHeight
Expand Down

0 comments on commit 4e30d5c

Please sign in to comment.