Skip to content

Instantly share code, notes, and snippets.

@sn-0w
Created September 17, 2025 19:24
Show Gist options
  • Select an option

  • Save sn-0w/46baa6db41d2ba76aa255383cbef32db to your computer and use it in GitHub Desktop.

Select an option

Save sn-0w/46baa6db41d2ba76aa255383cbef32db to your computer and use it in GitHub Desktop.
This Lua Script reads out the Font names from all found Font files and displays them in a list ingame so you can preview and select the font you want to use faster!
local function ReadUShortBE(f)
local b1 = f:ReadByte() or 0
local b2 = f:ReadByte() or 0
return b1 * 256 + b2
end
local function ReadULongBE(f)
local b1 = f:ReadByte() or 0
local b2 = f:ReadByte() or 0
local b3 = f:ReadByte() or 0
local b4 = f:ReadByte() or 0
return b1 * 16777216 + b2 * 65536 + b3 * 256 + b4
end
function GetTTFFontName(filepath)
if not file.Exists(filepath, "GAME") then return nil, "File does not exist" end
local f = file.Open(filepath, "rb", "GAME")
if not f then return nil, "Could not open file" end
f:Seek(4)
local numTables = ReadUShortBE(f)
f:Seek(f:Tell() + 6) --we skip searchRange, entrySelector, rangeShift
local nameOffset, nameLength
for i = 1, numTables do
local tag = f:Read(4)
local checkSum = ReadULongBE(f)
local offset = ReadULongBE(f)
local length = ReadULongBE(f)
if tag == "name" then nameOffset, nameLength = offset, length end
end
if not nameOffset then return nil, "No name table" end
f:Seek(nameOffset)
local version = ReadUShortBE(f)
local count = ReadUShortBE(f)
local storageOffset = ReadUShortBE(f)
for i = 1, count do
local platformID = ReadUShortBE(f)
local encodingID = ReadUShortBE(f)
local languageID = ReadUShortBE(f)
local nameID = ReadUShortBE(f)
local length = ReadUShortBE(f)
local stringOffset = ReadUShortBE(f)
if nameID == 4 or nameID == 1 then
local pos = nameOffset + stringOffset + storageOffset
f:Seek(pos)
local raw = f:Read(length)
if platformID == 0 or platformID == 3 then
local out = {}
for j = 1, #raw, 2 do
local hi = raw:byte(j)
local lo = raw:byte(j + 1)
local code = hi * 256 + lo
if code > 0 and code < 128 then table.insert(out, string.char(code)) end
end
return table.concat(out)
else
return raw
end
end
end
return nil, "Font name not found"
end
local function ListFontFiles()
local fonts, _ = file.Find("resource/fonts/*", "GAME")
print("=== Found Font Files ===")
for _, font in ipairs(fonts) do
if string.match(font, "%.ttf$") then
local name, error = GetTTFFontName("resource/fonts/" .. font)
if name then
print(font .. " - " .. name)
else
print(font .. " (Error: " .. (error or "Unknown") .. ")")
end
end
end
end
concommand.Add("list_font_files", ListFontFiles)
local function OpenFontPreviewer()
local frame = vgui.Create("DFrame")
frame:SetSize(600, 800)
frame:Center()
frame:SetTitle("Font Previewer")
frame:MakePopup()
local textEntry = vgui.Create("DTextEntry", frame)
textEntry:Dock(TOP)
textEntry:SetPlaceholderText("Enter text to preview...")
textEntry:SetText("Sample Text")
local scroll = vgui.Create("DScrollPanel", frame)
scroll:Dock(FILL)
local fonts, _ = file.Find("resource/fonts/*", "GAME")
local createdFonts = {}
local function RefreshList()
scroll:Clear()
local displayText = textEntry:GetText()
local addedfonts = {}
for _, font in ipairs(fonts) do
if font:match("%.ttf$") then
local fontName, err = GetTTFFontName("resource/fonts/" .. font)
if fontName and #fontName < 24 and not table.HasValue(addedfonts, fontName) then
table.insert(addedfonts, fontName)
if not createdFonts[fontName] then
surface.CreateFont("Preview_" .. fontName, {
font = fontName,
size = 24,
weight = 500
})
createdFonts[fontName] = true
end
local panel = scroll:Add("DButton")
panel:Dock(TOP)
panel:SetTall(40)
panel:SetText("")
panel:DockMargin(0, 0, 0, 4)
panel.Paint = function(self, w, h)
surface.SetFont("Preview_" .. fontName)
surface.SetTextColor(255, 255, 255)
surface.SetTextPos(5, 10)
surface.DrawText(displayText .. " (" .. fontName .. ")")
end
panel.DoClick = function() print("Selected font: " .. fontName) end
else
local label = scroll:Add("DLabel")
label:Dock(TOP)
label:SetTall(20)
label:SetText(font .. " (Error: " .. (err or "Unknown") .. ")")
end
end
end
end
textEntry.OnChange = RefreshList
RefreshList()
end
concommand.Add("open_font_previewer", OpenFontPreviewer)
@GrayWolf64
Copy link

I also ported stb_truetype.h(source engine uses this) to Lua a while ago so you can try it out if you want something more than basic font info.
https://github.com/GrayWolf64/imgui-lua/blob/main/lua/imstb_truetype.lua
Btw not tested for general use cases but for imgui font system, since GMod surface.CreateFont() is too limited

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment