From 204b64a75e39324d850ca014f3f33eb6333924f3 Mon Sep 17 00:00:00 2001 From: donmor Date: Fri, 17 Jun 2022 21:58:24 +0800 Subject: [PATCH 01/12] Added integer scaling --- menu/scene_settings.go | 6 ++++++ settings/settings.go | 1 + video/video.go | 42 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/menu/scene_settings.go b/menu/scene_settings.go index c5e93bf1..203b355c 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -168,6 +168,12 @@ var incrCallbacks = map[string]callbackIncrement{ menu.ContextReset() settings.Save() }, + "VideoIntScaling": func(f *structs.Field, direction int) { + v := f.Value().(bool) + v = !v + f.Set(v) + settings.Save() + }, "VideoMonitorIndex": func(f *structs.Field, direction int) { v := f.Value().(int) v += direction diff --git a/settings/settings.go b/settings/settings.go index b3d6fb87..98911390 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -23,6 +23,7 @@ import ( // Widget sets the graphical representation of the value. type Settings struct { VideoFullscreen bool `hide:"ludos" toml:"video_fullscreen" label:"Video Fullscreen" fmt:"%t" widget:"switch"` + VideoIntScaling bool `toml:"video_int_scaling" label:"Video Integer Scaling" fmt:"%t" widget:"switch"` VideoMonitorIndex int `toml:"video_monitor_index" label:"Video Monitor Index" fmt:"%d"` VideoFilter string `toml:"video_filter" label:"Video Filter" fmt:"<%s>"` VideoDarkMode bool `toml:"video_dark_mode" label:"Video Dark Mode" fmt:"%t" widget:"switch"` diff --git a/video/video.go b/video/video.go index 03d2dc71..38029969 100644 --- a/video/video.go +++ b/video/video.go @@ -309,12 +309,41 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo aspectRatio = float32(video.Geom.BaseWidth) / float32(video.Geom.BaseHeight) } - h = fbh - w = fbh * aspectRatio - if w > fbw { - h = fbw / aspectRatio - w = fbw + // (C) donmor 2022 patch-1 BEGIN + if settings.Current.VideoIntScaling { + gh := video.Geom.BaseHeight + if gh == 0 { + gh = fbHeight + } + scale := fbHeight / gh + h = float32(gh * scale) + if scale == 0 { + h = fbh + } + w = h * aspectRatio + if w > fbw { + gw := video.Geom.BaseWidth + if gw == 0 { + gw = fbWidth + } + scale = fbWidth / int(float32(gh)*aspectRatio) + h = float32(gh * scale) + if scale == 0 { + h = fbw / aspectRatio + w = fbw + } else { + w = h * aspectRatio + } + } + } else { + h = fbh + w = fbh * aspectRatio + if w > fbw { + h = fbw / aspectRatio + w = fbw + } } + // (C) donmor 2022 patch-1 END // Place the content in the middle of the window. x = (fbw - w) / 2 @@ -350,7 +379,10 @@ func (video *Video) Render() { return } + // (C) donmor 2022 patch-1 BEGIN + // fbw, fbh := video.Window.GetFramebufferSize() fbw, fbh := video.Window.GetFramebufferSize() + // (C) donmor 2022 patch-1 END _, _, w, h := video.coreRatioViewport(fbw, fbh) gl.UseProgram(video.program) From f99649f362b17ce9f4b5b57a44a33e7d354e743d Mon Sep 17 00:00:00 2001 From: donmor Date: Fri, 17 Jun 2022 22:46:02 +0800 Subject: [PATCH 02/12] Minor: Remove unused definitions --- video/video.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/video/video.go b/video/video.go index 38029969..45154b9f 100644 --- a/video/video.go +++ b/video/video.go @@ -322,10 +322,6 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo } w = h * aspectRatio if w > fbw { - gw := video.Geom.BaseWidth - if gw == 0 { - gw = fbWidth - } scale = fbWidth / int(float32(gh)*aspectRatio) h = float32(gh * scale) if scale == 0 { From b29bdd6c3c7ef08590443511c71487b3490ff099 Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 18 Jun 2022 01:03:29 +0800 Subject: [PATCH 03/12] Added super resolution --- menu/scene_settings.go | 6 ++++++ settings/settings.go | 1 + video/video.go | 16 ++++++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/menu/scene_settings.go b/menu/scene_settings.go index 203b355c..932b80cf 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -174,6 +174,12 @@ var incrCallbacks = map[string]callbackIncrement{ f.Set(v) settings.Save() }, + "VideoSuperRes": func(f *structs.Field, direction int) { + v := f.Value().(bool) + v = !v + f.Set(v) + settings.Save() + }, "VideoMonitorIndex": func(f *structs.Field, direction int) { v := f.Value().(int) v += direction diff --git a/settings/settings.go b/settings/settings.go index 98911390..2a8e2f17 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -24,6 +24,7 @@ import ( type Settings struct { VideoFullscreen bool `hide:"ludos" toml:"video_fullscreen" label:"Video Fullscreen" fmt:"%t" widget:"switch"` VideoIntScaling bool `toml:"video_int_scaling" label:"Video Integer Scaling" fmt:"%t" widget:"switch"` + VideoSuperRes bool `toml:"video_super_res" label:"Video Super Resolution" fmt:"%t" widget:"switch"` VideoMonitorIndex int `toml:"video_monitor_index" label:"Video Monitor Index" fmt:"%d"` VideoFilter string `toml:"video_filter" label:"Video Filter" fmt:"<%s>"` VideoDarkMode bool `toml:"video_dark_mode" label:"Video Dark Mode" fmt:"%t" widget:"switch"` diff --git a/video/video.go b/video/video.go index 45154b9f..98587b5e 100644 --- a/video/video.go +++ b/video/video.go @@ -320,7 +320,15 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo if scale == 0 { h = fbh } - w = h * aspectRatio + if settings.Current.VideoSuperRes && scale > 0 { + srScale := fbWidth / (int(float32(gh)*aspectRatio) * scale) + if srScale == 0 { + srScale = 1 + } + w = h * aspectRatio * float32(srScale) + } else { + w = h * aspectRatio + } if w > fbw { scale = fbWidth / int(float32(gh)*aspectRatio) h = float32(gh * scale) @@ -333,7 +341,11 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo } } else { h = fbh - w = fbh * aspectRatio + if settings.Current.VideoSuperRes { + w = fbw + } else { + w = fbh * aspectRatio + } if w > fbw { h = fbw / aspectRatio w = fbw From 545bf2ac68ccf6d0cae5484b7322492ef1691a66 Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 18 Jun 2022 01:34:28 +0800 Subject: [PATCH 04/12] Minor: added default values --- settings/defaults.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings/defaults.go b/settings/defaults.go index 072615ec..93a858ee 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -9,6 +9,8 @@ import ( func defaultSettings() Settings { return Settings{ VideoFullscreen: false, + VideoIntScaling: false, + VideoSuperRes: false, VideoMonitorIndex: 0, VideoFilter: "Pixel Perfect", MapAxisToDPad: false, From 05b1a5203d60489bae9edd9931228bfecb9723a3 Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 18 Jun 2022 13:48:32 +0800 Subject: [PATCH 05/12] Minor: Let Printf work properly under super-res --- menu/hints.go | 4 ++-- menu/menu.go | 13 +++++++++++- menu/notifications.go | 8 +++---- menu/scene.go | 28 ++++++++++++------------- menu/scene_core_disk_control.go | 2 +- menu/scene_core_options.go | 2 +- menu/scene_dialog.go | 26 +++++++++++------------ menu/scene_history.go | 37 +++++++++++++++++---------------- menu/scene_keyboard.go | 4 ++-- menu/scene_playlist.go | 31 ++++++++++++++------------- menu/scene_savestates.go | 18 ++++++++-------- menu/scene_settings.go | 13 ++++++------ menu/scene_tabs.go | 14 ++++++------- menu/scene_wifi.go | 2 +- video/font.go | 13 +++++++++--- video/video.go | 3 --- 16 files changed, 118 insertions(+), 100 deletions(-) diff --git a/menu/hints.go b/menu/hints.go index ace0d6cc..023bef8c 100644 --- a/menu/hints.go +++ b/menu/hints.go @@ -8,9 +8,9 @@ import ( func stackHint(stack *float32, icon uint32, label string, h int) { menu.Font.SetColor(darkGrey) *stack += 30 * menu.ratio - menu.DrawImage(icon, *stack, float32(h)-70*menu.ratio, 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey) + menu.DrawImage(icon, *stack, float32(h)-70*menu.ratio2, 70*menu.ratio, 70*menu.ratio2, 1.0, darkGrey) *stack += 70 * menu.ratio - menu.Font.Printf(*stack, float32(h)-23*menu.ratio, 0.4*menu.ratio, label) + menu.Font.Printf(*stack, float32(h)-23*menu.ratio2, 0.4*menu.ratio2, label) *stack += menu.Font.Width(0.4*menu.ratio, label) } diff --git a/menu/menu.go b/menu/menu.go index 192b5f6c..4a5ffc92 100644 --- a/menu/menu.go +++ b/menu/menu.go @@ -21,6 +21,7 @@ type Menu struct { tweens Tweens scroll float32 ratio float32 + ratio2 float32 t float64 *video.Video // we embbed video here to have direct access to drawing functions @@ -30,13 +31,18 @@ type Menu struct { // If a game is already running, it will warp the user to the quick menu. // If not, it will display the menu tabs. func Init(v *video.Video) *Menu { - w, _ := v.GetFramebufferSize() + w, h := v.GetFramebufferSize() menu = &Menu{} menu.Video = v menu.stack = []Scene{} menu.tweens = make(Tweens) menu.ratio = float32(w) / 1920 + if settings.Current.VideoSuperRes { + menu.ratio2 = float32(h) / 1080 + } else { + menu.ratio2 = menu.ratio + } menu.icons = map[string]uint32{} menu.Push(buildTabs()) @@ -63,6 +69,11 @@ func (m *Menu) Render(dt float32) { m.t += float64(dt * 8) w, h := m.GetFramebufferSize() m.ratio = float32(w) / 1920 + if settings.Current.VideoSuperRes { + menu.ratio2 = float32(h) / 1080 + } else { + menu.ratio2 = menu.ratio + } if state.CoreRunning { m.DrawRect(0, 0, float32(w), float32(h), 0, bgColor.Alpha(0.85)) diff --git a/menu/notifications.go b/menu/notifications.go index b71945c7..4a432c21 100644 --- a/menu/notifications.go +++ b/menu/notifications.go @@ -36,8 +36,8 @@ func (m *Menu) RenderNotifications() { bg := severityBgColor[n.Severity] m.DrawRect( 25*m.ratio, - (stack+offset-46)*m.ratio, - lw+40*m.ratio, + (stack+offset-46)*m.ratio2, + lw+40*m.ratio2, 70*m.ratio, 0.25, bg.Alpha(fading), @@ -45,8 +45,8 @@ func (m *Menu) RenderNotifications() { m.Font.SetColor(fg.Alpha(fading)) m.Font.Printf( 45*m.ratio, - (stack+offset)*m.ratio, - 0.5*m.ratio, + (stack+offset)*m.ratio2, + 0.5*m.ratio2, n.Message, ) stack += h + offset diff --git a/menu/scene.go b/menu/scene.go index f3020a6b..1654dfb2 100644 --- a/menu/scene.go +++ b/menu/scene.go @@ -152,11 +152,11 @@ func genericSegueNext(list *entry) { func genericDrawCursor(list *entry) { w, h := menu.GetFramebufferSize() menu.DrawImage(menu.icons["arrow"], - 530*menu.ratio, float32(h)*list.cursor.yp-35*menu.ratio, - 70*menu.ratio, 70*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha)) + 530*menu.ratio, float32(h)*list.cursor.yp-35*menu.ratio2, + 70*menu.ratio, 70*menu.ratio2, 1, cursorBg.Alpha(list.cursor.alpha)) menu.DrawRect( - 550*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio, - float32(w)-630*menu.ratio, 100*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha)) + 550*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio2, + float32(w)-630*menu.ratio, 100*menu.ratio2, 1, cursorBg.Alpha(list.cursor.alpha)) } // thumbnailDrawCursor draws the blinking rectangular background of the active @@ -164,11 +164,11 @@ func genericDrawCursor(list *entry) { func thumbnailDrawCursor(list *entry) { w, h := menu.GetFramebufferSize() menu.DrawImage(menu.icons["arrow"], - 500*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio, - 100*menu.ratio, 100*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha)) + 500*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio2, + 100*menu.ratio, 100*menu.ratio2, 1, cursorBg.Alpha(list.cursor.alpha)) menu.DrawRect( - 530*menu.ratio, float32(h)*list.cursor.yp-120*menu.ratio, - float32(w)-630*menu.ratio, 240*menu.ratio, 0.2, cursorBg.Alpha(list.cursor.alpha)) + 530*menu.ratio, float32(h)*list.cursor.yp-120*menu.ratio2, + float32(w)-630*menu.ratio, 240*menu.ratio2, 0.2, cursorBg.Alpha(list.cursor.alpha)) } // genericRender renders a vertical list of menu entries @@ -185,12 +185,12 @@ func genericRender(list *entry) { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 menu.DrawImage(menu.icons[e.icon], 610*menu.ratio-64*0.5*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*0.5*menu.ratio+fontOffset, - 128*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*0.5*menu.ratio2+fontOffset, + 128*menu.ratio, 128*menu.ratio2, 0.5, textColor.Alpha(e.iconAlpha)) if e.labelAlpha > 0 { @@ -198,7 +198,7 @@ func genericRender(list *entry) { menu.Font.Printf( 670*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) if e.widget != nil { e.widget(&e) @@ -207,7 +207,7 @@ func genericRender(list *entry) { menu.Font.Printf( float32(w)-lw-128*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.stringValue()) + 0.5*menu.ratio2, e.stringValue()) } } } @@ -264,7 +264,7 @@ func askDeleteSavestateConfirmation(cb func()) { func genericDrawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_core_disk_control.go b/menu/scene_core_disk_control.go index ef3dfd13..dd7483c5 100644 --- a/menu/scene_core_disk_control.go +++ b/menu/scene_core_disk_control.go @@ -77,7 +77,7 @@ func (s *sceneCoreDiskControl) render() { func (s *sceneCoreDiskControl) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, leftRight, _, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_core_options.go b/menu/scene_core_options.go index e347d7dd..8e0b8efe 100644 --- a/menu/scene_core_options.go +++ b/menu/scene_core_options.go @@ -81,7 +81,7 @@ func (s *sceneCoreOptions) render() { func (s *sceneCoreOptions) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, leftRight, _, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_dialog.go b/menu/scene_dialog.go index 7da8c35e..0b227253 100644 --- a/menu/scene_dialog.go +++ b/menu/scene_dialog.go @@ -63,21 +63,21 @@ func (s *sceneDialog) render() { menu.DrawRect( fw/2-width/2*menu.ratio, - fh/2-height/2*menu.ratio, + fh/2-height/2*menu.ratio2, width*menu.ratio, - height*menu.ratio, + height*menu.ratio2, 0.05, white, ) menu.Font.SetColor(orange) lw1 := menu.Font.Width(0.7*menu.ratio, s.title) - menu.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio+20*menu.ratio, 0.7*menu.ratio, s.title) + menu.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio2+20*menu.ratio2, 0.7*menu.ratio2, s.title) menu.Font.SetColor(black) lw2 := menu.Font.Width(0.5*menu.ratio, s.line1) - menu.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, s.line1) + menu.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio2+20*menu.ratio2, 0.5*menu.ratio2, s.line1) lw3 := menu.Font.Width(0.5*menu.ratio, s.line2) - menu.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, s.line2) + menu.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio2+20*menu.ratio2, 0.5*menu.ratio2, s.line2) menu.Font.SetColor(darkGrey) @@ -88,23 +88,23 @@ func (s *sceneDialog) render() { menu.DrawImage( b, fw/2-width/2*menu.ratio+margin*menu.ratio, - fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio, - 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey) + fh/2+height/2*menu.ratio2-70*menu.ratio2-margin*menu.ratio2, + 70*menu.ratio, 70*menu.ratio2, 1.0, darkGrey) menu.Font.Printf( fw/2-width/2*menu.ratio+margin*menu.ratio+70*menu.ratio, - fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio, - 0.4*menu.ratio, + fh/2+height/2*menu.ratio2-23*menu.ratio2-margin*menu.ratio2, + 0.4*menu.ratio2, "NO") menu.DrawImage( a, fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio, - fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio, - 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey) + fh/2+height/2*menu.ratio2-70*menu.ratio2-margin*menu.ratio2, + 70*menu.ratio, 70*menu.ratio2, 1.0, darkGrey) menu.Font.Printf( fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio+70*menu.ratio, - fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio, - 0.4*menu.ratio, + fh/2+height/2*menu.ratio2-23*menu.ratio2-margin*menu.ratio2, + 0.4*menu.ratio2, "YES") } diff --git a/menu/scene_history.go b/menu/scene_history.go index c52b4ccd..e221e748 100644 --- a/menu/scene_history.go +++ b/menu/scene_history.go @@ -1,6 +1,7 @@ package menu import ( + "math" "os" "path/filepath" @@ -163,39 +164,39 @@ func (s *sceneHistory) render() { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 if e.labelAlpha > 0 { drawThumbnail( list, i, e.system, e.gameName, 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio, 128*menu.ratio2, e.scale, white.Alpha(e.iconAlpha), ) menu.DrawBorder( 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if e.path == state.GamePath && e.path != "" { menu.DrawCircle( 680*menu.ratio, - float32(h)*e.yp-14*menu.ratio+fontOffset, - 90*menu.ratio*e.scale, + float32(h)*e.yp-14*menu.ratio2+fontOffset, + 90*float32(math.Sqrt(float64(menu.ratio*menu.ratio2)))*e.scale, black.Alpha(e.iconAlpha)) menu.DrawImage(menu.icons["resume"], 680*menu.ratio-25*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset, - 50*menu.ratio, 50*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-25*e.scale*menu.ratio2+fontOffset, + 50*menu.ratio, 50*menu.ratio2, e.scale, white.Alpha(e.iconAlpha)) } // Offset on Y to vertically center label + sublabel if there is a sublabel slOffset := float32(0) if e.subLabel != "" { - slOffset = 30 * menu.ratio * e.subLabelAlpha + slOffset = 30 * menu.ratio2 * e.subLabelAlpha } menu.Font.SetColor(textColor.Alpha(e.labelAlpha)) @@ -203,7 +204,7 @@ func (s *sceneHistory) render() { menu.Font.Printf( 840*menu.ratio, float32(h)*e.yp+fontOffset-slOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) stack += float32(int(menu.Font.Width(0.5*menu.ratio, e.label))) stack += 10 @@ -212,10 +213,10 @@ func (s *sceneHistory) render() { stack += 20 menu.DrawImage( menu.icons[tag], - stack, float32(h)*e.yp-22*menu.ratio-slOffset, - 60*menu.ratio, 44*menu.ratio, 1.0, white.Alpha(e.tagAlpha)) - menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio-slOffset, - 60*menu.ratio, 44*menu.ratio, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) + stack, float32(h)*e.yp-22*menu.ratio2-slOffset, + 60*menu.ratio, 44*menu.ratio2, 1.0, white.Alpha(e.tagAlpha)) + menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio2-slOffset, + 60*menu.ratio, 44*menu.ratio2, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) stack += 60 * menu.ratio } } @@ -223,8 +224,8 @@ func (s *sceneHistory) render() { menu.Font.SetColor(mediumGrey.Alpha(e.subLabelAlpha)) menu.Font.Printf( 840*menu.ratio, - float32(h)*e.yp+fontOffset+60*menu.ratio-slOffset, - 0.5*menu.ratio, e.subLabel) + float32(h)*e.yp+fontOffset+60*menu.ratio2-slOffset, + 0.5*menu.ratio2, e.subLabel) } } @@ -233,7 +234,7 @@ func (s *sceneHistory) render() { func (s *sceneHistory) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, x, _, _, _, guide := hintIcons() diff --git a/menu/scene_keyboard.go b/menu/scene_keyboard.go index 96765b23..507ab582 100644 --- a/menu/scene_keyboard.go +++ b/menu/scene_keyboard.go @@ -152,7 +152,7 @@ func (s *sceneKeyboard) render() { w, h := menu.GetFramebufferSize() lines := float32(4) kbh := float32(h) * 0.6 - ksp := (kbh - (50 * menu.ratio)) / (lines + 1) + ksp := (kbh - (50 * menu.ratio2)) / (lines + 1) ksz := ksp * 0.9 ttw := 10 * ksp @@ -205,7 +205,7 @@ func (s *sceneKeyboard) render() { func (s *sceneKeyboard) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) arrows, _, _, a, b, x, y, start, _, _ := hintIcons() diff --git a/menu/scene_playlist.go b/menu/scene_playlist.go index 705cf18a..25d2bbe4 100644 --- a/menu/scene_playlist.go +++ b/menu/scene_playlist.go @@ -1,6 +1,7 @@ package menu import ( + "math" "os" "path/filepath" "regexp" @@ -203,32 +204,32 @@ func (s *scenePlaylist) render() { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 if e.labelAlpha > 0 { drawThumbnail( list, i, list.label, e.gameName, 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio, 128*menu.ratio2, e.scale, white.Alpha(e.iconAlpha), ) menu.DrawBorder( 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if e.path == state.GamePath && e.path != "" { menu.DrawCircle( 680*menu.ratio, - float32(h)*e.yp-14*menu.ratio+fontOffset, - 90*menu.ratio*e.scale, + float32(h)*e.yp-14*menu.ratio2+fontOffset, + 90*float32(math.Sqrt(float64(menu.ratio*menu.ratio2)))*e.scale, black.Alpha(e.iconAlpha)) menu.DrawImage(menu.icons["resume"], 680*menu.ratio-25*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset, - 50*menu.ratio, 50*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-25*e.scale*menu.ratio2+fontOffset, + 50*menu.ratio, 50*menu.ratio2, e.scale, white.Alpha(e.iconAlpha)) } @@ -237,7 +238,7 @@ func (s *scenePlaylist) render() { menu.Font.Printf( 840*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) stack += float32(int(menu.Font.Width(0.5*menu.ratio, e.label))) stack += 10 @@ -246,10 +247,10 @@ func (s *scenePlaylist) render() { stack += 20 menu.DrawImage( menu.icons[tag], - stack, float32(h)*e.yp-22*menu.ratio, - 60*menu.ratio, 44*menu.ratio, 1.0, white.Alpha(e.tagAlpha)) - menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio, - 60*menu.ratio, 44*menu.ratio, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) + stack, float32(h)*e.yp-22*menu.ratio2, + 60*menu.ratio, 44*menu.ratio2, 1.0, white.Alpha(e.tagAlpha)) + menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio2, + 60*menu.ratio, 44*menu.ratio2, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) stack += 60 * menu.ratio } } @@ -261,7 +262,7 @@ func (s *scenePlaylist) render() { func (s *scenePlaylist) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, x, _, _, _, guide := hintIcons() diff --git a/menu/scene_savestates.go b/menu/scene_savestates.go index 7eb5d7ef..3ad14205 100644 --- a/menu/scene_savestates.go +++ b/menu/scene_savestates.go @@ -127,27 +127,27 @@ func (s *sceneSavestates) render() { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 if e.labelAlpha > 0 { drawSavestateThumbnail( list, i, filepath.Join(settings.Current.ScreenshotsDirectory, utils.FileName(e.path)+".png"), 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio, 128*menu.ratio2, e.scale, textColor.Alpha(e.iconAlpha), ) menu.DrawBorder( 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if i == 0 { menu.DrawImage(menu.icons["savestate"], 680*menu.ratio-25*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset, - 50*menu.ratio, 50*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-25*e.scale*menu.ratio2+fontOffset, + 50*menu.ratio, 50*menu.ratio2, e.scale, textColor.Alpha(e.iconAlpha)) } @@ -155,14 +155,14 @@ func (s *sceneSavestates) render() { menu.Font.Printf( 840*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) } } } func (s *sceneSavestates) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) ptr := menu.stack[len(menu.stack)-1].Entry().ptr diff --git a/menu/scene_settings.go b/menu/scene_settings.go index 932b80cf..66478256 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -2,6 +2,7 @@ package menu import ( "fmt" + "math" "os" "path/filepath" @@ -137,8 +138,8 @@ var widgets = map[string]func(*entry){ w, h := menu.GetFramebufferSize() menu.DrawImage(menu.icons[icon], float32(w)-128*menu.ratio-128*menu.ratio, - float32(h)*e.yp-64*1.25*menu.ratio, - 128*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-64*1.25*menu.ratio2, + 128*menu.ratio, 128*menu.ratio2, 1.25, textColor.Alpha(e.iconAlpha)) }, @@ -146,13 +147,13 @@ var widgets = map[string]func(*entry){ "range": func(e *entry) { fbw, fbh := menu.GetFramebufferSize() x := float32(fbw) - 128*menu.ratio - 175*menu.ratio - y := float32(fbh)*e.yp - 4*menu.ratio + y := float32(fbh)*e.yp - 4*menu.ratio2 w := 175 * menu.ratio - h := 8 * menu.ratio + h := 8 * menu.ratio2 menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha/4)) w = 175 * menu.ratio * e.value().(float32) menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha)) - menu.DrawCircle(x+w, y+4*menu.ratio, 38*menu.ratio, textColor.Alpha(e.iconAlpha)) + menu.DrawCircle(x+w, y+4*menu.ratio2, 38*float32(math.Sqrt(float64(menu.ratio*menu.ratio2))), textColor.Alpha(e.iconAlpha)) }, } @@ -286,7 +287,7 @@ func (s *sceneSettings) render() { func (s *sceneSettings) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, leftRight, a, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_tabs.go b/menu/scene_tabs.go index 630d4a1a..9af7f3d9 100644 --- a/menu/scene_tabs.go +++ b/menu/scene_tabs.go @@ -295,24 +295,24 @@ func (tabs sceneTabs) render() { if e.labelAlpha > 0 { menu.Font.SetColor(c.Alpha(e.labelAlpha)) lw := menu.Font.Width(0.5*menu.ratio, e.label) - menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio)), 0.5*menu.ratio, e.label) + menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio2)), 0.5*menu.ratio2, e.label) lw = menu.Font.Width(0.4*menu.ratio, e.subLabel) - menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio)), 0.4*menu.ratio, e.subLabel) + menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio2)), 0.4*menu.ratio2, e.subLabel) } menu.DrawImage(menu.icons["hexagon"], - x-220*e.scale*menu.ratio, float32(h)/2-220*e.scale*menu.ratio, - 440*menu.ratio, 440*menu.ratio, e.scale, c) + x-220*e.scale*menu.ratio, float32(h)/2-220*e.scale*menu.ratio2, + 440*menu.ratio, 440*menu.ratio2, e.scale, c) menu.DrawImage(menu.icons[e.icon], - x-128*e.scale*menu.ratio, float32(h)/2-128*e.scale*menu.ratio, - 256*menu.ratio, 256*menu.ratio, e.scale, white.Alpha(e.iconAlpha)) + x-128*e.scale*menu.ratio, float32(h)/2-128*e.scale*menu.ratio2, + 256*menu.ratio, 256*menu.ratio2, e.scale, white.Alpha(e.iconAlpha)) } } func (tabs sceneTabs) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, _, leftRight, a, _, x, _, _, _, guide := hintIcons() diff --git a/menu/scene_wifi.go b/menu/scene_wifi.go index 0af9d257..ce5c01f8 100644 --- a/menu/scene_wifi.go +++ b/menu/scene_wifi.go @@ -86,7 +86,7 @@ func (s *sceneWiFi) render() { func (s *sceneWiFi) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, _, _, _, _, _ := hintIcons() diff --git a/video/font.go b/video/font.go index 2a139782..0f48762c 100644 --- a/video/font.go +++ b/video/font.go @@ -11,6 +11,7 @@ import ( "github.com/go-gl/gl/v2.1/gl" "github.com/golang/freetype" "github.com/golang/freetype/truetype" + "github.com/libretro/ludo/settings" "golang.org/x/image/font" "golang.org/x/image/math/fixed" ) @@ -44,6 +45,7 @@ type Font struct { color Color atlasWidth float32 atlasHeight float32 + xScale float32 } type point [4]float32 @@ -241,6 +243,11 @@ func (f *Font) UpdateResolution(windowWidth int, windowHeight int) { resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00")) gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) gl.UseProgram(0) + f.xScale = float32(1) + if settings.Current.VideoSuperRes { + bw, bh := float32(windowWidth), float32(windowHeight) + f.xScale = (bw / bh) / (16.0 / 9.0) + } } // Printf draws a string to the screen, takes a list of arguments like printf @@ -280,9 +287,9 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ } // Calculate position and size for current rune - xpos := x - 1 + float32(ch.bearingH)*scale + xpos := x - 1 + float32(ch.bearingH)*scale*f.xScale ypos := y - 2 - float32(ch.height-ch.bearingV)*scale - w := float32(ch.width+2) * scale + w := float32(ch.width+2) * scale * f.xScale h := float32(ch.height+2) * scale // Set quad positions @@ -299,7 +306,7 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ coords = append(coords, point{x2, y2, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) - x += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + x += float32((ch.advance >> 6)) * scale * f.xScale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) } bindVertexArray(f.vao) diff --git a/video/video.go b/video/video.go index 98587b5e..8735bbf1 100644 --- a/video/video.go +++ b/video/video.go @@ -387,10 +387,7 @@ func (video *Video) Render() { return } - // (C) donmor 2022 patch-1 BEGIN - // fbw, fbh := video.Window.GetFramebufferSize() fbw, fbh := video.Window.GetFramebufferSize() - // (C) donmor 2022 patch-1 END _, _, w, h := video.coreRatioViewport(fbw, fbh) gl.UseProgram(video.program) From 3e26ef3ee6b885145735554a700205675c41ca9b Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 18 Jun 2022 22:29:08 +0800 Subject: [PATCH 06/12] Added unicode font support --- menu/scene_settings.go | 8 ++ settings/defaults.go | 1 + settings/settings.go | 1 + video/font.go | 196 +++++++++++++++++++++++++++++++++++++---- video/video.go | 3 + 5 files changed, 194 insertions(+), 15 deletions(-) diff --git a/menu/scene_settings.go b/menu/scene_settings.go index 66478256..70c18333 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -216,6 +216,14 @@ var incrCallbacks = map[string]callbackIncrement{ f.Set(v) settings.Save() }, + "VideoUniFont": func(f *structs.Field, direction int) { + v := f.Value().(bool) + v = !v + f.Set(v) + menu.Reconfigure(settings.Current.VideoFullscreen) + menu.ContextReset() + settings.Save() + }, "MapAxisToDPad": func(f *structs.Field, direction int) { v := f.Value().(bool) v = !v diff --git a/settings/defaults.go b/settings/defaults.go index 93a858ee..dfbf39eb 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -13,6 +13,7 @@ func defaultSettings() Settings { VideoSuperRes: false, VideoMonitorIndex: 0, VideoFilter: "Pixel Perfect", + VideoUniFont: false, MapAxisToDPad: false, AudioVolume: 0.5, MenuAudioVolume: 0.25, diff --git a/settings/settings.go b/settings/settings.go index 2a8e2f17..466ead89 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -28,6 +28,7 @@ type Settings struct { VideoMonitorIndex int `toml:"video_monitor_index" label:"Video Monitor Index" fmt:"%d"` VideoFilter string `toml:"video_filter" label:"Video Filter" fmt:"<%s>"` VideoDarkMode bool `toml:"video_dark_mode" label:"Video Dark Mode" fmt:"%t" widget:"switch"` + VideoUniFont bool `toml:"video_uni_font" label:"Video Enable Unicode Font" fmt:"%t" widget:"switch"` AudioVolume float32 `toml:"audio_volume" label:"Audio Volume" fmt:"%.1f" widget:"range"` diff --git a/video/font.go b/video/font.go index 0f48762c..33897b36 100644 --- a/video/font.go +++ b/video/font.go @@ -4,14 +4,17 @@ import ( "fmt" "image" "image/draw" + "image/png" "io" "io/ioutil" + "math" "os" "github.com/go-gl/gl/v2.1/gl" "github.com/golang/freetype" "github.com/golang/freetype/truetype" "github.com/libretro/ludo/settings" + "github.com/nfnt/resize" "golang.org/x/image/font" "golang.org/x/image/math/fixed" ) @@ -208,6 +211,107 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale int32, low, high rune, return f, nil } +// LoadUniFont builds a set of textures based on a ttf files gylphs +func LoadUniFont(program uint32, r io.Reader, scale int32) (*Font, error) { + var bMap image.Image + var err error + bMap, err = png.Decode(r) + if err != nil { + return nil, err + } + + low, high := 1, 65536 // 131072 if with plane 1 in the future + + // Make Font stuct type + f := new(Font) + f.fontChar = make([]*character, 0, high-low+1) + f.program = program // Set shader program + f.SetColor(Color{R: 1, G: 1, B: 1, A: 1}) // Set default white + + hOffset, vOffset := 32, 64 // Blanking in unifont glyphs + iScale := int(scale) + lineHeight := 16 * iScale + f.atlasWidth = float32(16 * 256 * iScale) + f.atlasHeight = float32(16 * 256 * iScale) + rect := image.Rect(0, 0, 16*256, int(16*256)) + rgba := image.NewRGBA(rect) + draw.Draw(rgba, rgba.Bounds(), bMap, image.Pt(hOffset, vOffset), draw.Over) + rgba = resize.Resize(uint(16*256*iScale), uint(16*256*iScale), rgba, resize.NearestNeighbor).(*image.RGBA) + x := 0 + y := 0 + + // Make each gylph + for ch := low; ch <= high; ch++ { + char := new(character) + char.x = x + char.y = y + char.width = 8 * iScale + char.height = 16 * iScale + char.advance = char.width << 6 + char.bearingV = char.height + char.bearingH = char.width + + // Check if is full-widthed + sRune := image.NewRGBA(image.Rect(0, 0, 16*iScale, 16*iScale)) + draw.Draw(sRune, sRune.Bounds(), rgba, image.Pt(x, y), draw.Over) + isFW := false + for i := 0; i < 8*iScale; i++ { + for j := 0; j < 16*iScale; j++ { + r, g, b, _ := sRune.At(8*iScale+i, j).RGBA() + isFW = r != 0 || g != 0 || b != 0 + if isFW { + char.width *= 2 + char.advance = char.width << 6 + char.bearingV = char.height + char.bearingH = char.width + break + } + } + if isFW { + break + } + } + + x += 16 * iScale + if x+16*iScale > int(f.atlasWidth) { + x = 0 + y += lineHeight + } + f.fontChar = append(f.fontChar, char) + } + + // Generate texture + gl.GenTextures(1, &f.textureID) + gl.BindTexture(gl.TEXTURE_2D, f.textureID) + gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) + + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) + + gl.GenerateMipmap(gl.TEXTURE_2D) + gl.BindTexture(gl.TEXTURE_2D, 0) + + // Configure VAO/VBO for texture quads + genVertexArrays(1, &f.vao) + gl.GenBuffers(1, &f.vbo) + bindVertexArray(f.vao) + gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo) + + vertAttrib := uint32(gl.GetAttribLocation(f.program, gl.Str("vert\x00"))) + gl.EnableVertexAttribArray(vertAttrib) + gl.VertexAttribPointerWithOffset(vertAttrib, 2, gl.FLOAT, false, 4*4, 0) + + texCoordAttrib := uint32(gl.GetAttribLocation(f.program, gl.Str("vertTexCoord\x00"))) + gl.EnableVertexAttribArray(texCoordAttrib) + gl.VertexAttribPointerWithOffset(texCoordAttrib, 2, gl.FLOAT, false, 4*4, 2*4) + + gl.BindBuffer(gl.ARRAY_BUFFER, 0) + bindVertexArray(0) + + return f, nil +} + // LoadFont loads the specified font at the given scale. func LoadFont(file string, scale int32, windowWidth int, windowHeight int) (*Font, error) { fd, err := os.Open(file) @@ -229,7 +333,11 @@ func LoadFont(file string, scale int32, windowWidth int, windowHeight int) (*Fon resUniform := gl.GetUniformLocation(program, gl.Str("resolution\x00")) gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) - return LoadTrueTypeFont(program, fd, scale, 32, 256, LeftToRight) + if settings.Current.VideoUniFont { + return LoadUniFont(program, fd, 1) // 16x16, for performance + } else { + return LoadTrueTypeFont(program, fd, scale, 32, 256, LeftToRight) + } } // SetColor allows you to set the text color to be used when you draw the text @@ -253,12 +361,16 @@ func (f *Font) UpdateResolution(windowWidth int, windowHeight int) { // Printf draws a string to the screen, takes a list of arguments like printf func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{}) error { indices := []rune(fmt.Sprintf(fs, argv...)) + unifont := settings.Current.VideoUniFont if len(indices) == 0 { return nil } - lowChar := rune(32) + lowChar := rune(0) + if !unifont { + lowChar = rune(32) + } // Setup blending mode gl.Enable(gl.BLEND) @@ -271,6 +383,18 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ var coords []point + uniScale := int(scale*5 + 0.01) + uniXScale := int(f.xScale + 0.75) + if f.xScale < 0.8 { + uniScale -= int(1 / f.xScale) + } + if uniScale <= 0 { + uniScale = 1 + } + if uniXScale <= 0 { + uniXScale = 1 + } + // Iterate through all characters in string for i := range indices { // Get rune @@ -287,26 +411,48 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ } // Calculate position and size for current rune - xpos := x - 1 + float32(ch.bearingH)*scale*f.xScale - ypos := y - 2 - float32(ch.height-ch.bearingV)*scale - w := float32(ch.width+2) * scale * f.xScale - h := float32(ch.height+2) * scale + var xpos float32 + var ypos float32 + if unifont { + xpos = x + ypos = y - float32(ch.height*uniScale) + } else { + xpos = x - 1 + float32(ch.bearingH)*scale*f.xScale + ypos = y - 2 - float32(ch.height-ch.bearingV)*scale + } + var w float32 + var h float32 + if unifont { + w = float32(ch.width * uniScale * uniXScale) + h = float32(ch.height * uniScale) + } else { + w = float32(ch.width+2) * scale * f.xScale + h = float32(ch.height+2) * scale + } // Set quad positions var x1 = xpos var x2 = xpos + w var y1 = ypos var y2 = ypos + h + padding := 0 + if !unifont { + padding = 1 + } - coords = append(coords, point{x1, y1, float32(ch.x-1) / f.atlasWidth, float32(ch.y-1) / f.atlasHeight}) - coords = append(coords, point{x2, y1, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y-1) / f.atlasHeight}) - coords = append(coords, point{x1, y2, float32(ch.x-1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) - coords = append(coords, point{x2, y1, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y-1) / f.atlasHeight}) - coords = append(coords, point{x1, y2, float32(ch.x-1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) - coords = append(coords, point{x2, y2, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) + coords = append(coords, point{x1, y1, float32(ch.x-padding) / f.atlasWidth, float32(ch.y-padding) / f.atlasHeight}) + coords = append(coords, point{x2, y1, float32(ch.x+ch.width+padding) / f.atlasWidth, float32(ch.y-padding) / f.atlasHeight}) + coords = append(coords, point{x1, y2, float32(ch.x-padding) / f.atlasWidth, float32(ch.y+ch.height+padding) / f.atlasHeight}) + coords = append(coords, point{x2, y1, float32(ch.x+ch.width+padding) / f.atlasWidth, float32(ch.y-padding) / f.atlasHeight}) + coords = append(coords, point{x1, y2, float32(ch.x-padding) / f.atlasWidth, float32(ch.y+ch.height+padding) / f.atlasHeight}) + coords = append(coords, point{x2, y2, float32(ch.x+ch.width+padding) / f.atlasWidth, float32(ch.y+ch.height+padding) / f.atlasHeight}) // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) - x += float32((ch.advance >> 6)) * scale * f.xScale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + if unifont { + x += float32(ch.width * uniScale * uniXScale) + } else { + x += float32((ch.advance >> 6)) * scale * f.xScale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + } } bindVertexArray(f.vao) @@ -328,12 +474,28 @@ func (f *Font) Width(scale float32, fs string, argv ...interface{}) float32 { var width float32 indices := []rune(fmt.Sprintf(fs, argv...)) + unifont := settings.Current.VideoUniFont if len(indices) == 0 { return 0 } - lowChar := rune(32) + lowChar := rune(0) + if !unifont { + lowChar = rune(32) + } + + uniScale := int(scale*5 + 0.01) + uniXScale := int(math.Sqrt(float64(f.xScale + 0.75))) + if f.xScale < 0.8 { + uniScale -= int(1 / f.xScale) + } + if uniScale <= 0 { + uniScale = 1 + } + if uniXScale <= 0 { + uniXScale = 1 + } // Iterate through all characters in string for i := range indices { @@ -351,7 +513,11 @@ func (f *Font) Width(scale float32, fs string, argv ...interface{}) float32 { ch := f.fontChar[runeIndex-lowChar] // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) - width += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + if unifont { + width += float32(ch.width * uniScale * uniXScale) + } else { + width += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + } } diff --git a/video/video.go b/video/video.go index 8735bbf1..17ba0088 100644 --- a/video/video.go +++ b/video/video.go @@ -119,6 +119,9 @@ func (video *Video) Configure(fullscreen bool) { // LoadFont (fontfile, font scale, window width, window height) fontPath := filepath.Join(settings.Current.AssetsDirectory, "font.ttf") + if settings.Current.VideoUniFont { + fontPath = filepath.Join(settings.Current.AssetsDirectory, "unifont.png") + } video.Font, err = LoadFont(fontPath, int32(36*2), fbw, fbh) if err != nil { panic(err) From bf31bee7a4845813adc3eb8b73f8e03393488223 Mon Sep 17 00:00:00 2001 From: donmor Date: Sun, 19 Jun 2022 02:03:22 +0800 Subject: [PATCH 07/12] Refactorred Super Resolution to Aspect Correction --- menu/menu.go | 8 ++++++-- menu/scene_settings.go | 14 +++++++++++--- settings/defaults.go | 2 +- settings/settings.go | 2 +- video/font.go | 5 ++++- video/video.go | 42 +++++++++++++++++++++++++++--------------- 6 files changed, 50 insertions(+), 23 deletions(-) diff --git a/menu/menu.go b/menu/menu.go index 4a5ffc92..47631f17 100644 --- a/menu/menu.go +++ b/menu/menu.go @@ -38,8 +38,10 @@ func Init(v *video.Video) *Menu { menu.stack = []Scene{} menu.tweens = make(Tweens) menu.ratio = float32(w) / 1920 - if settings.Current.VideoSuperRes { + if settings.Current.VideoSuperRes == "16:9" { menu.ratio2 = float32(h) / 1080 + } else if settings.Current.VideoSuperRes == "4:3" { + menu.ratio2 = float32(h) / 1440 } else { menu.ratio2 = menu.ratio } @@ -69,8 +71,10 @@ func (m *Menu) Render(dt float32) { m.t += float64(dt * 8) w, h := m.GetFramebufferSize() m.ratio = float32(w) / 1920 - if settings.Current.VideoSuperRes { + if settings.Current.VideoSuperRes == "16:9" { menu.ratio2 = float32(h) / 1080 + } else if settings.Current.VideoSuperRes == "4:3" { + menu.ratio2 = float32(h) / 1440 } else { menu.ratio2 = menu.ratio } diff --git a/menu/scene_settings.go b/menu/scene_settings.go index 70c18333..ef1d8829 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -176,9 +176,17 @@ var incrCallbacks = map[string]callbackIncrement{ settings.Save() }, "VideoSuperRes": func(f *structs.Field, direction int) { - v := f.Value().(bool) - v = !v - f.Set(v) + filters := []string{"Disabled", "4:3", "16:9"} + v := f.Value().(string) + i := utils.IndexOfString(v, filters) + i += direction + if i < 0 { + i = len(filters) - 1 + } + if i > len(filters)-1 { + i = 0 + } + f.Set(filters[i]) settings.Save() }, "VideoMonitorIndex": func(f *structs.Field, direction int) { diff --git a/settings/defaults.go b/settings/defaults.go index dfbf39eb..4b86d36d 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -10,7 +10,7 @@ func defaultSettings() Settings { return Settings{ VideoFullscreen: false, VideoIntScaling: false, - VideoSuperRes: false, + VideoSuperRes: "Disabled", VideoMonitorIndex: 0, VideoFilter: "Pixel Perfect", VideoUniFont: false, diff --git a/settings/settings.go b/settings/settings.go index 466ead89..1135ac3a 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -24,7 +24,7 @@ import ( type Settings struct { VideoFullscreen bool `hide:"ludos" toml:"video_fullscreen" label:"Video Fullscreen" fmt:"%t" widget:"switch"` VideoIntScaling bool `toml:"video_int_scaling" label:"Video Integer Scaling" fmt:"%t" widget:"switch"` - VideoSuperRes bool `toml:"video_super_res" label:"Video Super Resolution" fmt:"%t" widget:"switch"` + VideoSuperRes string `toml:"video_super_res" label:"Video Aspect Correction" fmt:"<%s>"` VideoMonitorIndex int `toml:"video_monitor_index" label:"Video Monitor Index" fmt:"%d"` VideoFilter string `toml:"video_filter" label:"Video Filter" fmt:"<%s>"` VideoDarkMode bool `toml:"video_dark_mode" label:"Video Dark Mode" fmt:"%t" widget:"switch"` diff --git a/video/font.go b/video/font.go index 33897b36..3a7b2622 100644 --- a/video/font.go +++ b/video/font.go @@ -352,9 +352,12 @@ func (f *Font) UpdateResolution(windowWidth int, windowHeight int) { gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) gl.UseProgram(0) f.xScale = float32(1) - if settings.Current.VideoSuperRes { + if settings.Current.VideoSuperRes == "16:9" { bw, bh := float32(windowWidth), float32(windowHeight) f.xScale = (bw / bh) / (16.0 / 9.0) + } else if settings.Current.VideoSuperRes == "4:3" { + bw, bh := float32(windowWidth), float32(windowHeight) + f.xScale = (bw / bh) / (4.0 / 3.0) } } diff --git a/video/video.go b/video/video.go index 17ba0088..261086fe 100644 --- a/video/video.go +++ b/video/video.go @@ -314,6 +314,7 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo // (C) donmor 2022 patch-1 BEGIN if settings.Current.VideoIntScaling { + gw := video.Geom.BaseWidth gh := video.Geom.BaseHeight if gh == 0 { gh = fbHeight @@ -323,35 +324,46 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo if scale == 0 { h = fbh } - if settings.Current.VideoSuperRes && scale > 0 { - srScale := fbWidth / (int(float32(gh)*aspectRatio) * scale) - if srScale == 0 { - srScale = 1 - } - w = h * aspectRatio * float32(srScale) + if settings.Current.VideoSuperRes == "16:9" { + w = aspectRatio * h * fbw * 9 / 16 / fbh + } else if settings.Current.VideoSuperRes == "4:3" { + w = aspectRatio * h * fbw * 3 / 4 / fbh } else { - w = h * aspectRatio + w = h * float32(gw) / float32(gh) } - if w > fbw { - scale = fbWidth / int(float32(gh)*aspectRatio) + for w > fbw { + scale -= 1 h = float32(gh * scale) if scale == 0 { - h = fbw / aspectRatio - w = fbw + h = float32(gh) + } + if settings.Current.VideoSuperRes == "16:9" && scale > 0 { + w = aspectRatio * h * fbw * 9 / 16 / fbh + } else if settings.Current.VideoSuperRes == "4:3" && scale > 0 { + w = aspectRatio * h * fbw * 3 / 4 / fbh } else { - w = h * aspectRatio + w = fbw + h = fbw * float32(gh) / float32(gw) } } } else { h = fbh - if settings.Current.VideoSuperRes { - w = fbw + if settings.Current.VideoSuperRes == "16:9" { + w = aspectRatio * fbw * 9 / 16 + } else if settings.Current.VideoSuperRes == "4:3" { + w = aspectRatio * fbw * 3 / 4 } else { w = fbh * aspectRatio } if w > fbw { - h = fbw / aspectRatio w = fbw + if settings.Current.VideoSuperRes == "16:9" { + h = fbh * 16 / 9 / aspectRatio + } else if settings.Current.VideoSuperRes == "4:3" { + h = fbh * 16 / 9 / aspectRatio + } else { + h = fbw / aspectRatio + } } } // (C) donmor 2022 patch-1 END From 32f3c5f919fd2e94121baf7eb94d511bf3c88437 Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 25 Jun 2022 14:51:57 +0800 Subject: [PATCH 08/12] Minor: update go.mod --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index 8e2c558d..b3f792fa 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mholt/archiver/v3 v3.5.1 + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/nwaples/rardecode v1.1.2 // indirect github.com/pelletier/go-toml v1.9.4 github.com/pierrec/lz4/v4 v4.1.12 // indirect From 2e0184daa6be6ffb63ebc358d9d5bb70ee6b72ff Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 25 Jun 2022 14:52:22 +0800 Subject: [PATCH 09/12] Minor: update go.sum --- go.sum | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.sum b/go.sum index a7824bdf..af1feecf 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= From aa5143b3308bf82370b33c9401269e6d5b95614a Mon Sep 17 00:00:00 2001 From: donmor Date: Sun, 26 Jun 2022 00:52:50 +0800 Subject: [PATCH 10/12] Minor: fullscreen mode uses current video mode --- video/video.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/video/video.go b/video/video.go index 261086fe..b9b3b520 100644 --- a/video/video.go +++ b/video/video.go @@ -84,12 +84,10 @@ func (video *Video) SetShouldClose(b bool) { // Configure instanciates the video package func (video *Video) Configure(fullscreen bool) { var width, height int - var m *glfw.Monitor if fullscreen { - m = glfw.GetMonitors()[settings.Current.VideoMonitorIndex] - vms := m.GetVideoModes() - vm := vms[len(vms)-1] + m := glfw.GetMonitors()[settings.Current.VideoMonitorIndex] + vm := m.GetVideoMode() width = vm.Width height = vm.Height } else { @@ -98,7 +96,7 @@ func (video *Video) Configure(fullscreen bool) { } var err error - video.Window, err = glfw.CreateWindow(width, height, "Ludo", m, nil) + video.Window, err = glfw.CreateWindow(width, height, "Ludo", nil, nil) if err != nil { panic("Window creation failed:" + err.Error()) } From 459397c2e7510a9f377cd757bac6d823a67286b7 Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 4 Mar 2023 15:01:03 +0800 Subject: [PATCH 11/12] Fixing fullscreen --- video/video.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/video/video.go b/video/video.go index b9b3b520..a5751520 100644 --- a/video/video.go +++ b/video/video.go @@ -83,13 +83,17 @@ func (video *Video) SetShouldClose(b bool) { // Configure instanciates the video package func (video *Video) Configure(fullscreen bool) { - var width, height int + var width, height, refresh int + var m *glfw.Monitor if fullscreen { - m := glfw.GetMonitors()[settings.Current.VideoMonitorIndex] + m = glfw.GetMonitors()[settings.Current.VideoMonitorIndex] + // donmor: Just get the correct video mode here vm := m.GetVideoMode() width = vm.Width height = vm.Height + // donmor: Now we have refresh rate + refresh = vm.RefreshRate } else { width = 320 * 3 height = 180 * 3 @@ -97,6 +101,13 @@ func (video *Video) Configure(fullscreen bool) { var err error video.Window, err = glfw.CreateWindow(width, height, "Ludo", nil, nil) + if fullscreen { + // donmor: + // Set full screen mode separately with correct video mode + // Is it possible to set color bit depth? + mx, my := video.Window.GetPos() + video.Window.SetMonitor(m, mx, my, width, height, refresh) + } if err != nil { panic("Window creation failed:" + err.Error()) } From 9d6ecd641f45f58684f6b76f9a84ba2dffdece41 Mon Sep 17 00:00:00 2001 From: donmor Date: Sat, 4 Mar 2023 16:24:10 +0800 Subject: [PATCH 12/12] add some comments --- menu/menu.go | 4 ++++ menu/scene_history.go | 1 + menu/scene_playlist.go | 1 + menu/scene_settings.go | 7 +++++++ settings/defaults.go | 3 ++- video/font.go | 12 +++++++++--- video/video.go | 5 +++-- 7 files changed, 27 insertions(+), 6 deletions(-) diff --git a/menu/menu.go b/menu/menu.go index 47631f17..42911543 100644 --- a/menu/menu.go +++ b/menu/menu.go @@ -31,6 +31,7 @@ type Menu struct { // If a game is already running, it will warp the user to the quick menu. // If not, it will display the menu tabs. func Init(v *video.Video) *Menu { + // donmor: Now the h value is getting in use w, h := v.GetFramebufferSize() menu = &Menu{} @@ -38,11 +39,13 @@ func Init(v *video.Video) *Menu { menu.stack = []Scene{} menu.tweens = make(Tweens) menu.ratio = float32(w) / 1920 + // donmor: Added ratio2 for all HEIGHT values if we are under superres and using aspect correction if settings.Current.VideoSuperRes == "16:9" { menu.ratio2 = float32(h) / 1080 } else if settings.Current.VideoSuperRes == "4:3" { menu.ratio2 = float32(h) / 1440 } else { + // donmor: Just give a same value if aspect correction is disabled menu.ratio2 = menu.ratio } menu.icons = map[string]uint32{} @@ -71,6 +74,7 @@ func (m *Menu) Render(dt float32) { m.t += float64(dt * 8) w, h := m.GetFramebufferSize() m.ratio = float32(w) / 1920 + // donmor: Don't forget the recalculation :) if settings.Current.VideoSuperRes == "16:9" { menu.ratio2 = float32(h) / 1080 } else if settings.Current.VideoSuperRes == "4:3" { diff --git a/menu/scene_history.go b/menu/scene_history.go index e221e748..bdc09505 100644 --- a/menu/scene_history.go +++ b/menu/scene_history.go @@ -181,6 +181,7 @@ func (s *sceneHistory) render() { 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if e.path == state.GamePath && e.path != "" { + // donmor: TODO: Does anyone know how to draw an oval here? menu.DrawCircle( 680*menu.ratio, float32(h)*e.yp-14*menu.ratio2+fontOffset, diff --git a/menu/scene_playlist.go b/menu/scene_playlist.go index 25d2bbe4..bca9ddc2 100644 --- a/menu/scene_playlist.go +++ b/menu/scene_playlist.go @@ -221,6 +221,7 @@ func (s *scenePlaylist) render() { 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if e.path == state.GamePath && e.path != "" { + // donmor: TODO: Another place that needs an oval menu.DrawCircle( 680*menu.ratio, float32(h)*e.yp-14*menu.ratio2+fontOffset, diff --git a/menu/scene_settings.go b/menu/scene_settings.go index ef1d8829..b57e10f2 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -153,6 +153,7 @@ var widgets = map[string]func(*entry){ menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha/4)) w = 175 * menu.ratio * e.value().(float32) menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha)) + // donmor: TODO: Another place that needs an oval menu.DrawCircle(x+w, y+4*menu.ratio2, 38*float32(math.Sqrt(float64(menu.ratio*menu.ratio2))), textColor.Alpha(e.iconAlpha)) }, } @@ -169,12 +170,16 @@ var incrCallbacks = map[string]callbackIncrement{ menu.ContextReset() settings.Save() }, + // donmor: + // New option for integer scaling here "VideoIntScaling": func(f *structs.Field, direction int) { v := f.Value().(bool) v = !v f.Set(v) settings.Save() }, + // donmor: + // New option for aspect correction here (mostly used under super resolution) "VideoSuperRes": func(f *structs.Field, direction int) { filters := []string{"Disabled", "4:3", "16:9"} v := f.Value().(string) @@ -224,6 +229,8 @@ var incrCallbacks = map[string]callbackIncrement{ f.Set(v) settings.Save() }, + // donmor: + // New option for unicode font here (Can we get rid of this somedays by using unifont by default? It needs polishing, though) "VideoUniFont": func(f *structs.Field, direction int) { v := f.Value().(bool) v = !v diff --git a/settings/defaults.go b/settings/defaults.go index 4b86d36d..b620ad42 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -8,7 +8,8 @@ import ( func defaultSettings() Settings { return Settings{ - VideoFullscreen: false, + VideoFullscreen: false, + // donmor: All new features disabled by default VideoIntScaling: false, VideoSuperRes: "Disabled", VideoMonitorIndex: 0, diff --git a/video/font.go b/video/font.go index 3a7b2622..1dd6ef28 100644 --- a/video/font.go +++ b/video/font.go @@ -211,21 +211,23 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale int32, low, high rune, return f, nil } -// LoadUniFont builds a set of textures based on a ttf files gylphs +// donmor: LoadUniFont builds a set of textures out of a png gylphs func LoadUniFont(program uint32, r io.Reader, scale int32) (*Font, error) { var bMap image.Image var err error + // PNG image decoded here bMap, err = png.Decode(r) if err != nil { return nil, err } - low, high := 1, 65536 // 131072 if with plane 1 in the future + // 131072 if with plane 1 in the future + low, high := 1, 65536 // Make Font stuct type f := new(Font) f.fontChar = make([]*character, 0, high-low+1) - f.program = program // Set shader program + f.program = program // TODO: Can we use a basic one here? It looks blurry under super resolution f.SetColor(Color{R: 1, G: 1, B: 1, A: 1}) // Set default white hOffset, vOffset := 32, 64 // Blanking in unifont glyphs @@ -351,6 +353,7 @@ func (f *Font) UpdateResolution(windowWidth int, windowHeight int) { resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00")) gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) gl.UseProgram(0) + // donmor: Stretch the glyphs for super resolution f.xScale = float32(1) if settings.Current.VideoSuperRes == "16:9" { bw, bh := float32(windowWidth), float32(windowHeight) @@ -370,6 +373,7 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ return nil } + // donmor: Unifont allows char below 32, doesn't make much sense though lowChar := rune(0) if !unifont { lowChar = rune(32) @@ -386,6 +390,7 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ var coords []point + // donmor: Unifont is always integer-scaled uniScale := int(scale*5 + 0.01) uniXScale := int(f.xScale + 0.75) if f.xScale < 0.8 { @@ -438,6 +443,7 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ var x2 = xpos + w var y1 = ypos var y2 = ypos + h + // donmor: No padding for unifont padding := 0 if !unifont { padding = 1 diff --git a/video/video.go b/video/video.go index a5751520..091c6b3b 100644 --- a/video/video.go +++ b/video/video.go @@ -321,7 +321,7 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo aspectRatio = float32(video.Geom.BaseWidth) / float32(video.Geom.BaseHeight) } - // (C) donmor 2022 patch-1 BEGIN + // donmor: 2022 patch-1 BEGIN if settings.Current.VideoIntScaling { gw := video.Geom.BaseWidth gh := video.Geom.BaseHeight @@ -375,7 +375,8 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo } } } - // (C) donmor 2022 patch-1 END + // donmor: 2022 patch-1 END + // Now only God knows what I wrote here <:-/ // Place the content in the middle of the window. x = (fbw - w) / 2