Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions editor/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type editorConfig struct {
IgnoreSaveConfirmationWithCloseButton bool
UseWSL bool
ShowDiffDialogOnDrop bool
ProportionalFontAlignGutter bool
}

type cursorConfig struct {
Expand Down
35 changes: 28 additions & 7 deletions editor/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ func (c *Cursor) paintEvent(event *gui.QPaintEvent) {
c.devicePixelRatio = float64(p.PaintEngine().PaintDevice().DevicePixelRatio())
}

if c.sourcetext == "" || c.devicePixelRatio == 0 || c.width < int(font.cellwidth/2.0) {
// Fixed font aren't draw if cursor isn't wide enough.
// But for proportional, it would ends not drawing "i","t","!"...
if c.sourcetext == "" || c.devicePixelRatio == 0 || (c.width < int(font.cellwidth/2.0) && !c.font.proportional) {
p.DestroyQPainter()
return
}
Expand Down Expand Up @@ -372,7 +374,7 @@ func (c *Cursor) updateFont(targetWin *Window, font *Font, fallbackfonts []*Font
}
}

func (c *Cursor) updateCursorShape() {
func (c *Cursor) updateCursorShape(win *Window) {
if !c.ws.cursorStyleEnabled {
return
}
Expand Down Expand Up @@ -461,8 +463,16 @@ func (c *Cursor) updateCursorShape() {
var cellwidth float64
var height, lineSpace int


if c.font != nil {
cellwidth = c.font.cellwidth
if !c.font.proportional {
cellwidth = c.font.cellwidth
} else {
fm := c.font.fontMetrics
char := win.content[c.row][c.col].char
cellwidth = fm.HorizontalAdvance(char, -1)
}

height = c.font.height
lineSpace = c.font.lineSpace
if lineSpace < 0 {
Expand All @@ -478,7 +488,7 @@ func (c *Cursor) updateCursorShape() {
}
}
width := int(math.Trunc(cellwidth))
if !c.normalWidth {
if !c.normalWidth && (c.font == nil || !c.font.proportional) {
width = width * 2
}

Expand All @@ -495,8 +505,13 @@ func (c *Cursor) updateCursorShape() {
}
case "vertical":
c.isTextDraw = true
width = int(math.Ceil(float64(width) * p))
c.horizontalShift = 0
font := win.font
if font == nil || !font.proportional {
width = int(math.Ceil(float64(width) * p))
} else {
width = int(font.cellwidth) / 10
}
default:
c.isTextDraw = true
c.horizontalShift = 0
Expand Down Expand Up @@ -567,7 +582,13 @@ func (c *Cursor) updateCursorPos(row, col int, win *Window) {
horScrollPixels += win.scrollPixels[0]
}

x := float64(winx + int(float64(col)*font.cellwidth) + horScrollPixels)
var x float64 = float64(winx + horScrollPixels)
if !c.font.proportional {
x += float64(col)*font.cellwidth
} else {
x += win.getSinglePixelX(c.row, c.col)
}

y := float64(winy + int(float64(row*font.lineHeight)+float64(verScrollPixels)))
if font.lineSpace > 0 {
y += float64(font.lineSpace) / 2.0
Expand Down Expand Up @@ -660,7 +681,7 @@ func (c *Cursor) update() {
c.updateCursorText(row, col, win)

// update cursor shape
c.updateCursorShape()
c.updateCursorShape(win)

// if ext_cmdline is true
if c.ws.cmdline != nil {
Expand Down
42 changes: 40 additions & 2 deletions editor/font.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type Font struct {
lineSpace int
letterSpace int
shift int

// Variant font metrics (only set for Proportional Fonts)
proportional bool
italicFontMetrics *gui.QFontMetricsF
boldFontMetrics *gui.QFontMetricsF
italicBoldFontMetrics *gui.QFontMetricsF
}

func fontSizeNew(font *gui.QFont) (float64, int, float64, float64) {
Expand Down Expand Up @@ -60,11 +66,18 @@ func initFontNew(family string, size float64, weight gui.QFont__Weight, stretch,
font.SetWeight(int(weight))
font.SetStretch(stretch)

font.SetFixedPitch(true)
proportional := !gui.NewQFontInfo(font).FixedPitch()
font.SetFixedPitch(proportional)
font.SetKerning(false)

width, height, ascent, italicWidth := fontSizeNew(font)

// Proportional Fonts
var italicFM, boldFM, italicBoldFM *gui.QFontMetricsF
if proportional {
italicFM, boldFM, italicBoldFM = getFontMetricsVariants(font)
}

return &Font{
family: family,
size: size,
Expand All @@ -81,6 +94,12 @@ func initFontNew(family string, size float64, weight gui.QFont__Weight, stretch,
shift: int(float64(lineSpace)/2 + ascent),
ascent: ascent,
italicWidth: italicWidth,

// Proportional fonts
proportional: proportional,
italicFontMetrics: italicFM,
boldFontMetrics: boldFM,
italicBoldFontMetrics: italicBoldFM,
}
}

Expand All @@ -101,7 +120,8 @@ func (f *Font) change(family string, size float64, weight gui.QFont__Weight, str
f.qfont.SetWeight(int(weight))
f.qfont.SetStretch(stretch)

f.qfont.SetFixedPitch(true)
f.proportional = !gui.NewQFontInfo(f.qfont).FixedPitch()
f.qfont.SetFixedPitch(f.proportional)
f.qfont.SetKerning(false)

width, height, ascent, italicWidth := fontSizeNew(f.qfont)
Expand All @@ -115,6 +135,11 @@ func (f *Font) change(family string, size float64, weight gui.QFont__Weight, str
f.shift = int(float64(f.lineSpace)/2 + ascent)
f.italicWidth = italicWidth

// Font Metrics variants for proportional fonts
if f.proportional {
f.italicFontMetrics, f.boldFontMetrics, f.italicBoldFontMetrics = getFontMetricsVariants(f.qfont)
}

f.family = family
f.size = size
f.weight = weight
Expand All @@ -123,6 +148,18 @@ func (f *Font) change(family string, size float64, weight gui.QFont__Weight, str
// f.putDebugLog()
}

// Get Font Metrics variants (italic, bold, bold+italic)
func getFontMetricsVariants(font *gui.QFont) (italicFM, boldFM, italicBoldFM *gui.QFontMetricsF) {
font.SetStyle(gui.QFont__StyleItalic)
italicFM = gui.NewQFontMetricsF(font)
font.SetBold(true)
italicBoldFM = gui.NewQFontMetricsF(font)
font.SetStyle(gui.QFont__StyleNormal)
boldFM = gui.NewQFontMetricsF(font)
font.SetBold(false)
return italicFM, boldFM, italicBoldFM
}

// func (f *Font) hasGlyph(s string) bool {
// rawfont := gui.NewQRawFont()
// rawfont = rawfont.FromFont(f.qfont, gui.QFontDatabase__Any)
Expand Down Expand Up @@ -165,6 +202,7 @@ func (f *Font) putDebugLog() {
fi.PointSizeF(),
fi.StyleName(),
fmt.Sprintf("%v", fi.PointSizeF()),
fmt.Sprintf("(fixed pitch: %v) ", fi.FixedPitch()),
)
}

Expand Down
1 change: 1 addition & 0 deletions editor/nvim.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ func setupGoneovimCommands(neovim *nvim.Nvim) {
}
gonvimCommands = gonvimCommands + `
command! -nargs=1 GonvimGridFont call rpcnotify(g:goneovim_channel_id, "Gui", "gonvim_grid_font", <args>)
command! -nargs=1 GonvimGridFontAutomaticHeight call rpcnotify(g:goneovim_channel_id, "Gui", "gonvim_grid_font_automatic_height", <args>)
command! -nargs=1 GonvimLetterSpacing call rpcnotify(g:goneovim_channel_id, "Gui", "gonvim_letter_spacing", <args>)
command! -nargs=1 GuiMacmeta call rpcnotify(g:goneovim_channel_id, "Gui", "gonvim_macmeta", <args>)
command! -nargs=? GonvimMaximize call rpcnotify(g:goneovim_channel_id, "Gui", "gonvim_maximize", <args>)
Expand Down
108 changes: 108 additions & 0 deletions editor/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,114 @@ func (s *Screen) gridFont(update interface{}) {
}
}

/* Based on `gridFont`, this function compute the height of the selected
* font to keep the same number of row in the window. Thus, it avoids issues
* while resizing (especially with status line).
*
* NOTE: Vertical splitting after using this function will leads to very
* weird behaviour, and should be avoided.
*/
func (s *Screen) gridFontAutomaticHeight(update interface{}) {

// Get current window
grid := s.ws.cursor.gridid
if !editor.config.Editor.ExtCmdline {
grid = s.ws.cursor.bufferGridid
}

// Workaround for autocmds triggered with BufEnter/BufWinEnter/...
// When a file is opened directly e.g. with `goneovim plainfile.txt`
// would end with applying the new font to the status line.
if grid == 1 {
grid = 2
}

win, ok := s.getWindow(grid)
if !ok {
return
}

// The function parameter is the font family
fontFamily, ok := update.(string)
if !ok {
return
}
if fontFamily == "" {
return
}

font := win.getFont()
oldCellWidth := font.cellwidth

// The font height we'll try to approximate with the new font
oldFontHeight := font.fontMetrics.Height()

// Create the font
f := gui.NewQFont()
f.SetFamily(fontFamily)
f.SetFixedPitch(false)
f.SetKerning(false)

// The values we'll Iteratively modify
var newFontHeight float64
var newFontSize float64

// Create the font metrics and initialize a font size
newFontSize = font.size
f.SetPointSizeF(newFontSize)
fm := gui.NewQFontMetricsF(f)
newFontHeight = fm.Height()

// Function to update the font size
updateFont := func (u float64) {
newFontSize += u
f.SetPointSizeF(newFontSize)
fm := gui.NewQFontMetricsF(f)
newFontHeight = fm.Height()
}

// Iteratively change the font size until the right height is reached
for newFontHeight < oldFontHeight {
updateFont(1)
}
for newFontHeight > oldFontHeight {
updateFont(-1)
}

// Refresh the screen while the font.cellwidth hasn't change.
// It avoids old text to stay forever, between windows.
// (Especially between window and statusbar.)
s.refresh()

// Build the new font
win.font = initFontNew(fontFamily, newFontSize, font.weight, font.stretch, font.lineSpace, font.letterSpace)
if win.font == nil {
return
}
s.ws.cursor.font = win.font
win.fallbackfonts = nil
s.ws.cursor.fallbackfonts = win.fallbackfonts

// Keep the old cellwidth matters. Changing it would impact e.g.
// Window.paint(). Plus, proportional font doesn't have something
// such as a `cellwidth`.
win.font.cellwidth = oldCellWidth

// TODO: Resize Grid if enough space to add a row

// Cache
cache := win.cache
if cache == (Cache{}) {
cache := newCache()
win.cache = cache
} else {
win.paintMutex.Lock()
win.cache.purge()
win.paintMutex.Unlock()
}

}

func (s *Screen) purgeTextCacheForWins() {
if !editor.config.Editor.CachedDrawing {
return
Expand Down
Loading
Loading