.fnt file to image labels (Custom fonts in Studio)

the problem appears to be coming from the UI Layout thing, but i have 0 clue on how it works. i will try and look up the documentation

EDIT: scratch this, no matter what UI layout thing you put in there it results in the same thing, so its the code. ill try to look into it

EDIT2: it has something to do with the property Enum.SortOrder. Neither options work properly, though.

Yeah in that case I’ll look into it soon.

I made a small update to the original post and the example post in the initial reply and to the model available on the site that should fix this issue.

Lovely. Will find a use for this.

1 Like

alright, ill try it out. thank you for the fix!

okay, so it works, but now i have the alignment issues. i will try my best to sort it out myself. thank you very much!

I have come crawling back again, thin characters are very silly. Also i should note that im using a surfacegui, will this afect anything?

I believe this has to do with how Roblox handles resampling and such. You might be able to get around the issue if you change the ResampleMode of the image labels. SurfaceGuis could make the issue more prevalent if the SurfaceGui is far away or if the PixelsPerStud is low.

Love this system and it works good with my font. Although i am kinda confused on how to make it so i can position the ‘frame’ and put a size for the it inside of screengui.

1 Like

I wonder if Roblox will ever make their own way to upload custom fonts, great work btw

1 Like

Its me again. I tried using this again, and it worked perfectly. Don’t know what i did wrong the first time though. This works great! but do you have any idea on how I could keep the text centered? im finding this difficult.

Glad you got it fixed.

With your UIListLayout, set the HorizontalAlignment and VerticalAlignment to centre. This should anchor the text to the middle of the frame it is contained in.

image

1 Like

okay, thanks!! this works really well.

1 Like

hello again! i need assistance with changing the font size as i had the resolution of the original image much higher than i want it to be. I want it to be in pixels but i can’t seem to figure out how to change the size. Can you help please? thanks

1 Like

Hi, for some reason when I use my font, the size of everything becomes zero.
Here’s the source code:

local s = [[info face="Aqua" size=72 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=1,1
common lineHeight=72 base=48 scaleW=171 scaleH=172 pages=1 packed=0
page id=0 file="Unnamed.png"
chars count=28
char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=0 xadvance=19 page=0 chnl=15
char id=39 x=154 y=32 width=9 height=9 xoffset=1 yoffset=20 xadvance=11 page=0 chnl=15
char id=65 x=0 y=105 width=34 height=36 xoffset=0 yoffset=9 xadvance=35 page=0 chnl=15
char id=66 x=74 y=61 width=26 height=36 xoffset=0 yoffset=8 xadvance=27 page=0 chnl=15
char id=67 x=74 y=98 width=26 height=35 xoffset=0 yoffset=7 xadvance=27 page=0 chnl=15
char id=68 x=42 y=102 width=28 height=36 xoffset=0 yoffset=7 xadvance=29 page=0 chnl=15
char id=69 x=130 y=101 width=22 height=35 xoffset=0 yoffset=8 xadvance=23 page=0 chnl=15
char id=70 x=42 y=139 width=19 height=33 xoffset=0 yoffset=9 xadvance=20 page=0 chnl=15
char id=71 x=42 y=0 width=31 height=35 xoffset=0 yoffset=9 xadvance=32 page=0 chnl=15
char id=72 x=42 y=36 width=31 height=34 xoffset=0 yoffset=9 xadvance=32 page=0 chnl=15
char id=73 x=130 y=137 width=19 height=30 xoffset=0 yoffset=11 xadvance=20 page=0 chnl=15
char id=74 x=42 y=71 width=30 height=30 xoffset=0 yoffset=10 xadvance=30 page=0 chnl=15
char id=75 x=103 y=133 width=24 height=34 xoffset=0 yoffset=9 xadvance=25 page=0 chnl=15
char id=76 x=130 y=35 width=23 height=33 xoffset=0 yoffset=10 xadvance=23 page=0 chnl=15
char id=77 x=0 y=142 width=34 height=30 xoffset=0 yoffset=10 xadvance=35 page=0 chnl=15
char id=78 x=74 y=30 width=27 height=30 xoffset=0 yoffset=10 xadvance=28 page=0 chnl=15
char id=79 x=0 y=70 width=35 height=34 xoffset=0 yoffset=10 xadvance=36 page=0 chnl=15
char id=80 x=103 y=95 width=24 height=37 xoffset=0 yoffset=6 xadvance=25 page=0 chnl=15
char id=81 x=0 y=32 width=39 height=37 xoffset=0 yoffset=5 xadvance=40 page=0 chnl=15
char id=82 x=130 y=0 width=23 height=34 xoffset=0 yoffset=6 xadvance=24 page=0 chnl=15
char id=83 x=154 y=0 width=17 height=31 xoffset=0 yoffset=8 xadvance=18 page=0 chnl=15
char id=84 x=74 y=134 width=26 height=32 xoffset=0 yoffset=8 xadvance=27 page=0 chnl=15
char id=85 x=74 y=0 width=28 height=29 xoffset=0 yoffset=13 xadvance=29 page=0 chnl=15
char id=86 x=130 y=69 width=23 height=31 xoffset=0 yoffset=13 xadvance=24 page=0 chnl=15
char id=87 x=0 y=0 width=41 height=31 xoffset=0 yoffset=13 xadvance=43 page=0 chnl=15
char id=88 x=103 y=0 width=26 height=32 xoffset=1 yoffset=12 xadvance=28 page=0 chnl=15
char id=89 x=103 y=33 width=26 height=31 xoffset=0 yoffset=11 xadvance=26 page=0 chnl=15
char id=90 x=103 y=65 width=25 height=29 xoffset=0 yoffset=13 xadvance=25 page=0 chnl=15
]]

local fontMap = 'rbxassetid://15540813455'

-----

local info = {}

info.fontInfo = {}
info.characterTable = {}
info.kernings = {}

local init, _ = s:find('kernings')
if init then
	local kernings = s:sub(init, s:len()):split('\n')

	local kerningsTable = info.kernings

	for i,v in ipairs(kernings) do
		local first, second, amount = v:match('kerning first=([%-?%.?%d?]+) second=([%-?%.?%d?]+) amount=([%-?%.?%d?]+)')
		if first then
			kerningsTable[utf8.char(first)] = kerningsTable[utf8.char(first)] or {}
			kerningsTable[utf8.char(first)][utf8.char(second)] = amount
		end
	end
	s = s:sub(1, init - 1)
end
local split = s:split('\n')

local characterTable = info.characterTable

for i = 3, 1, -1 do
	local infoThisIteration = split[i]:split(' ')
	for i,v in ipairs(infoThisIteration) do
		local field, value = unpack(v:split('='))
		if field and value then
			field, value = field:gsub('"', ''), value:gsub('"', '')
			info.fontInfo[field] = tonumber(value) or value
		end
	end
	table.remove(split, i)
end
table.remove(split, 1)

for i = #split, 1, -1 do
	local v = split[i]
	local charId, x, y, width, height, xOffset, yOffset, xAdvance, page, chnl = v:match('char id=([%-?%.?%d?]+) x=([%-?%.?%d?]+) y=([%-?%.?%d?]+) width=([%-?%.?%d?]+) height=([%-?%.?%d?]+) xoffset=([%-?%.?%d?]+) yoffset=([%-?%.?%d?]+) xadvance=([%-?%.?%d?]+) page=([%-?%.?%d?]+) chnl=([%-?%.?%d?]+)')
	if charId then
		table.remove(split,i)
		table.insert(characterTable, {
			charId = charId;
			x = x;
			y = y;
			width = width;
			height = height;
			xOffset = xOffset;
			yOffset = yOffset;
			xAdvance = xAdvance;
			page = page;
			chnl = chnl
		})
	end
end

local size = 72

local stringFolder = Instance.new('Folder')
stringFolder.Name = info.fontInfo.face
stringFolder.Parent = script

for i,v in ipairs(characterTable) do
	local mainFrame = Instance.new('Frame')
	mainFrame.Size = UDim2.fromOffset(v.xAdvance or v.width, size)
	mainFrame.BackgroundTransparency = 1
	mainFrame.Name = utf8.char(v.charId)
	mainFrame.BackgroundTransparency = 1
	local newLabel = Instance.new('ImageLabel')
	newLabel.Image = fontMap
	newLabel.Size = UDim2.fromOffset(v.width, v.height)
	newLabel.Parent = mainFrame
	newLabel.Name = utf8.char(v.charId)
	newLabel.Position = UDim2.fromOffset(v.xOffset, v.yOffset)
	newLabel.ImageRectSize = Vector2.new(v.width, v.height)
	newLabel.ImageRectOffset = Vector2.new(v.x, v.y)
	newLabel.Parent = mainFrame
	newLabel.BackgroundTransparency = 1
	newLabel.ScaleType = Enum.ScaleType.Fit
	newLabel.BackgroundTransparency = 1
	mainFrame.Parent = stringFolder
end

-----

local function feed(str: string)
	-- example feed function:

	-- first off, we have a function that will return a table of graphemes
	local splitString = (function()
		local graphemes = {}
		for i,v in utf8.graphemes(str) do -- for each of the graphemes,
			table.insert(graphemes, str:sub(i,v)) -- we have to use string.sub because utf8 returns a pair where i is the beginning of the grapheme and v is the end of the grapheme. We must use this because we're working with a non-ASCII character (№).
		end
		return graphemes -- returns the table of graphemes
	end)() -- ensure you call this function so it actually assigns the graphemes table to the splitString variable
	local newFrame = Instance.new('Frame') -- create a new frame that will store the glyphs
	
	local newUIListLayout = Instance.new('UIListLayout')
	newUIListLayout.Parent = newFrame
	newUIListLayout.SortOrder = Enum.SortOrder.LayoutOrder -- we don't want them to be aligned vertically
	newUIListLayout.FillDirection = Enum.FillDirection.Horizontal -- align them horizontally from left to right
	newUIListLayout.Padding = UDim.new(0,0) -- we don't want any padding
	
	for i,v in ipairs(splitString) do -- where i is the index and v is the glyph
		local thisLetter = stringFolder:FindFirstChild(v) -- look inside the folder for a frame with the glyph's name
		if thisLetter then -- if it found a frame with this name,
			local newLetter = thisLetter:Clone() -- clone it and parent it to the frame
			newLetter.LayoutOrder = i
			newLetter.Parent = newFrame
			
			local next = splitString[i + 1] -- look for the next character to handle kernings
			if next then
				local kerningThisLetter = info.kernings[v] -- inside the kernings table, look for the kerning for this letter and the next letter
				if kerningThisLetter then -- if there is a kerning table for this letter then
					local kerningNextLetter = kerningThisLetter[next] -- if inside that kerning table there is a kerning for the next letter
					if kerningNextLetter then -- if there's a kerning then
						--newFrame.Size -= UDim2.fromOffset(0,kerningNextLetter) -- subtract it from the frame's size, not the actual letter label's size because we don't want to clip the letter
					end
				end
			end
		end
	end
	return newFrame
end
wait(5)
local new = feed('wow custom fonts so cool right')
new.Parent = game.StarterGui.ScreenGui

print(new)

The frame comes out, it just has the size set to zero.
Aqua

EDIT: I noticed something odd, this is how your example code looks:


And this is how my code looks:
image

1 Like

Hey, sorry for the late response, I saw your message earlier but forgot to respond lol

For individual letters, you can resize the font size and line heights. It’ll be on the lefthand side. Use the font size one.

image

As for resizing the entire image, you can untick Auto-Pack and optionally tick Fixed Size. This will allow you to change the size of your image in the text boxes.

image

If your image is too small (ie all the characters can’t fit), you’ll get an error in red at the top of your screen.

image


Hey, this is because you’re passing lowercase letters to your feed function, your fontmap only has uppercase characters.

At the end, swap “wow custom fonts so cool right” with “WOW CUSTOM FONTS SO COOL RIGHT” and you should get your expected result.

I’m facepalming so hard right now at my own stupidity.
Thank you so much.

1 Like

Sorry to bother you again, still learning this, but I’m trying to figure out the “size” variable

local size = 1000

local stringFolder = Instance.new('Folder')
stringFolder.Name = info.fontInfo.face
stringFolder.Parent = script

No matter what I change it to, nothing changes. Any idea how to resize the text?

Edit:
Nevermind, I found out there was no built-in resizing method, so I just did this:


local textSize = 2

for i,v in ipairs(characterTable) do
	local mainFrame = Instance.new('Frame')
	mainFrame.Size = UDim2.fromOffset(v.xAdvance*textSize or v.width*textSize, size)
	mainFrame.BackgroundTransparency = 1
	mainFrame.Name = utf8.char(v.charId)
	mainFrame.BackgroundTransparency = 1
	local newLabel = Instance.new('ImageLabel')
	newLabel.Image = fontMap
	newLabel.Size = UDim2.fromOffset(v.width*textSize, v.height*textSize)
	newLabel.Parent = mainFrame
	newLabel.Name = utf8.char(v.charId)
	newLabel.Position = UDim2.fromOffset(v.xOffset, v.yOffset)
	newLabel.ImageRectSize = Vector2.new(v.width, v.height)
	newLabel.ImageRectOffset = Vector2.new(v.x, v.y)
	newLabel.Parent = mainFrame
	newLabel.BackgroundTransparency = 1
	newLabel.ScaleType = Enum.ScaleType.Fit
	newLabel.BackgroundTransparency = 1
	mainFrame.Parent = stringFolder
end
2 Likes

Sorry for the late response. I’ll add scaling when I get time which should allow people to resize the letters. Glad you got it figured out tho

1 Like

i edited your scripts to fix this already, sizing works now for me.

1 Like