Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Font outline does not line up using TLF_CENTERED or TLF_RIGHT — Gideros Forum

Font outline does not line up using TLF_CENTERED or TLF_RIGHT

EricCarrEricCarr Member
edited January 2019 in Bugs and issues
When converting to use outlines, I've discovered that unless I'm using normal TLF_LEFT, the outline text does not line up properly:

Has anyone else ran into this? Am I doing something wrong? I've seen it on all versions since outlining became available. I see it both on my desktop player and phone.

Sample code:
local fontO = TTFont.new("PressStart2P.ttf", 20,"", false,3)
local font = TTFont.new("PressStart2P.ttf", 20,"", false)
 
local function addText(t,x,y, o)
	local text = TextField.new(fontO, t,nil,o) text:setPosition(x,y)
	text:setTextColor(0)
	stage:addChild(text)
 
	text = TextField.new(font, t,nil,o) text:setPosition(x,y)
	text:setTextColor(0xff0000)
	stage:addChild(text)
end
 
addText("1",100,50, {flags=FontBase.TLF_CENTER})
addText("12345",100,150, {flags=FontBase.TLF_CENTER})
 
addText("1",100,250, {flags=FontBase.TLF_LEFT})
addText("12345",100,350, {flags=FontBase.TLF_LEFT})
 
addText("1",200,450, {flags=FontBase.TLF_RIGHT})
addText("12345",200,550, {flags=FontBase.TLF_RIGHT})


image.png
606 x 1108 - 21K
Tagged:

Comments

  • hgy29hgy29 Maintainer
    Yes, this is expected since the outlined version of the font is slightly larger than the original one. Centering or right aligning use the text width in the computation, final x values are then not exactly the same for both versions
  • So, calculating the width of the text does not take into account the extra padding?

    I would expect centering to be correct, and only right to be skewed.

    In right justified, why doesn't the black text line up exactly on the right line? It instead is slightly to the left. Seems like there is some correcting being applied but it isn't calculating right.

    Also, the difference between the two is different in centered and right justified, which again indicates different width calculated or something is off with the padding calculation.


  • Adding this simple test code afterward fixes it (where textO contains the extra padding):
            if o.flags == FontBase.TLF_CENTER then
    		local delta = textO:getWidth()-text:getWidth()
    		textO:setPosition(x+delta/2,y)
    	elseif o.flags == FontBase.TLF_RIGHT then
    		local delta = textO:getWidth()-text:getWidth()
    		textO:setPosition(x+delta,y)
    	end
    For centering, I have to shift it half the difference in width to the right.
    For right, I have to shift it the entire difference in width to the right.

    I would be great if this calculation would be part of the engine so we don't have to do the above on every setText operation in code, maybe an option when creating the textField?

    Thanks,
    Eric
  • hgy29hgy29 Maintainer
    Accepted Answer
    This is because freetype library adds itself the offset so that text is at the right place when using the same x location. For your suggestion, yes it would be good but current gideros api only deals with a single font at a time, and doesn’t have access to the other one to compute differences

    Likes: EricCarr

    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    Thinking of it, the best way would be to have a composite font type, so that the outlined and the base font version are drawn at the same time: no duplicate computations, no duplicate text field creation
    +1 -1 (+2 / -0 )Share on Facebook
  • I also see that when it wants to wrap the text and I prevent it by adding w=N or _NOWRAP, the offset is doubled. Agreed, composite is a great solution and probably best for a future update :) .

    For now I'll update my custom TextFieldO (drop in replacement that creates two textfield children, one with an outline) to always use _LEFT and use getWidth() to set the X position for centering/right whenever settext() is called.
  • In case it helps anyone, here is my custom class below. It turns out that if nowrap is turned on, or a width is applied, the outlined text gets skewed more for every space and less for every line break ("\n"). Hence the extra checks. One known issue - if you make the Width at just the right amount so the bigger outline wraps but the smaller regular font does not wrap, it won't catch that. But it solves all my use cases.
    TextFieldO = Core.class(Sprite)
    function TextFieldO:init(ignored, text, d, flags, color)
    	local s= self
    	s.to = TextField.new(fontO, text,d,flags)
    	s.t = TextField.new(font, text, d,flags)
    	s.t:setTextColor(color or 0xffffff)
     
    	s:addChild(s.to)
    	s:addChild(s.t)
    	s:updateLayout(text)	
    end
     
    function TextFieldO:setText(text)
    	self.to:setText(text)
    	self.t:setText(text)
    	self:updateLayout(text)
    end
     
    function TextFieldO:updateLayout(text)
    	text = "" .. text
    	local l = self.to:getLayout()
    	local flags = l.flags
     
    	local ow,w = self.to:getWidth(),  self.t:getWidth()
    	local delta = ow-w
     
    	if  (flags & FontBase.TLF_NOWRAP == FontBase.TLF_NOWRAP ) or l.w>0 then 
    		local mult = 1
    		for i=#text,1,-1 do
    			local c = string.sub(text,i,i) 
    			if c== " " then 
    				mult += 1
    			elseif c == "\n" then
    				mult -= 1
    			end
    		end
    		if mult <=1 then mult = 1 end 
    		delta*= mult
    	end
     
    	if flags & FontBase.TLF_CENTER == FontBase.TLF_CENTER then
    			self.to:setPosition(delta*0.5,0)
    	elseif flags & FontBase.TLF_RIGHT == FontBase.TLF_RIGHT then
    		self.to:setPosition(delta,0)
    	end
    end
     
    function TextFieldO:setTextColor(color)
    	self.t:setTextColor(color)
    end

    Likes: hgy29, Apollo14, pie, antix

    +1 -1 (+4 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    I have added on new font type in gideros for this purpose:
    local nf =  TTFont.new("OpenSans-ExtraBold.ttf", 50, str,true) --Normal
    local of = TTFont.new("OpenSans-ExtraBold.ttf", 50,str,true,3) --Outlined
    local cf= CompositeFont.new{
    { font=of, color=0x000000 }, --Draw outline in black
    { font=nf, x=1,y=2 }, --Draw normal text with an offset
    }
    +1 -1 (+4 / -0 )Share on Facebook
  • EricCarrEricCarr Member
    edited January 2019
    Awesome news hgy29! Can't wait to try it out!

    In case it helps, here is a "unit test" I made to test out the various font conditions:
    local fontO = TTFont.new("PressStart2P.ttf", 10,"", false,1)
    local font = TTFont.new("PressStart2P.ttf", 10,"", false)
     
    local function addText(t,x,y, o)
     
    	local text = TextFieldO.new(fontO, t,nil,o,0xffff00)  -- replace with composite
    	text:setPosition(x,y)
    	stage:addChild(text)
    end
     
    local y, delta =25, 25
    addText("WORLD\n1",150,y, {flags=FontBase.TLF_LEFT})	y+=delta
    addText("WORLD\n1",150,y, {flags=FontBase.TLF_RIGHT})	y+=delta
    addText("WORLD\n1",150,y, {flags=FontBase.TLF_CENTER })	y+=delta*2
     
    addText("WORLD 2",150,y, {flags=FontBase.TLF_LEFT})	y+=delta
    addText("WORLD 2",150,y, {flags=FontBase.TLF_RIGHT})	y+=delta
    addText("WORLD 2",150,y, {flags=FontBase.TLF_CENTER })	y+=delta*2
     
    addText("NOWRAP 3",150,y, {flags=FontBase.TLF_LEFT | FontBase.TLF_NOWRAP})	y+=delta/2
    addText("NOWRAP 3",150,y, {flags=FontBase.TLF_RIGHT | FontBase.TLF_NOWRAP})	y+=delta/2
    addText("NOWRAP 3",150,y, {flags=FontBase.TLF_CENTER | FontBase.TLF_NOWRAP})	y+=delta
     
    addText("NOWRAP with spaces",150,y, {flags=FontBase.TLF_CENTER | FontBase.TLF_NOWRAP})	y+=delta
    addText("NOWRAP spaces\nand a break",150,y, {flags=FontBase.TLF_CENTER | FontBase.TLF_NOWRAP})	y+=delta*1.5
     
    addText("BLOCK4",150,y, {flags=FontBase.TLF_LEFT | FontBase.TLF_NOWRAP})
    y+=delta/2
    addText("BLOCK4",150,y, {flags=FontBase.TLF_RIGHT | FontBase.TLF_NOWRAP})
    y+=delta/2
    addText("BLOCK4",150,y, {flags=FontBase.TLF_CENTER | FontBase.TLF_NOWRAP})
    y+=delta
     
    addText("WID1",50,y, {flags=FontBase.TLF_LEFT, w=100})	y+=delta/2
    addText("WID1",50,y, {flags=FontBase.TLF_RIGHT, w=100})	y+=delta/2
    addText("WID1",50,y, {flags=FontBase.TLF_CENTER,w=100})	y+=delta
     
    addText("WID 2",50,y, {flags=FontBase.TLF_LEFT, w=100})	y+=delta/2
    addText("WID 2",50,y, {flags=FontBase.TLF_RIGHT, w=100})	y+=delta/2
    addText("WID 2",50,y, {flags=FontBase.TLF_CENTER,w=100})	y+=delta
     
    -- Known issue - The outline font wraps but the (slightly smaller width) font does not.
    addText("WID 3",50,y, {flags=FontBase.TLF_LEFT, w=50})	y+=delta
    addText("WID 3",50,y, {flags=FontBase.TLF_RIGHT, w=50})	y+=delta
    addText("WID 3",50,y, {flags=FontBase.TLF_CENTER,w=50})	y+=delta
Sign In or Register to comment.