newText multiline, custom fonts some parts of the text are cut off

I know this has been asked afew times in other threads, but none are solved. 

For some fonts, when using multiline, the top, left or right of the text will be cut off. My attached image shows the “W” has been cut off at the left side. 

So far the only solution I found in the forum is to “remake” the font’s ttf

I understand that multiline text uses mask, so I guess a simple solution is to turn off textbox’s mask?

I tried 

local text2 = display.newText( textOptions2 ) text2:setMask(nil)

but it returns error. any suggestion how to turn off the mask?

If you were able to turn off the mask, you would get a solid rectangle.  Because these have to go into OpenGL, they have to be a texture image (i.e. a graphic).  Text is rendered as a colored rectangle with a mask applied to create the transparent areas.  The reason you get things cut off is because every device/os combination has their own font rendering APIs and they are not consistent.  When you use a custom font, they come from founderies that are of different quality.  A font like Arial or Helvetica has been well tested but Joe’s UbaUba Font may not have had as much testing on the different devices and you end up with stuff cut off if their font metrics are not quite right.

When you see this you can do things like add some spaces before the W or add a blank line at the top to move the text down in the box.  It’s a hack, yes, but the only other choice is to find a Font that’s better constructed and works better with the different device rendering engines.

Rob

Thanks Rob for the clarification!

Not sure if only the multi line textfield uses openGL, because for single line text field doesn’t have the problem. So I end up writing a new multi line script based on your blog entry http://coronalabs.com/blog/2013/04/16/lua-string-magic/

I break the string and insert them in multiple single line texts, then put them in one display group.

The downside is I can’t update the text after created, but that is fine for me.

I’ll share the code here. Probably will add in code to adjust line spacing and alignment in future. 

--------------------------------------------------------------- -- MULTI LINE TEXT --------------------------------------------------------------- function string:split( inSplitPattern, outResults ) if not outResults then outResults = { } end local theStart = 1 local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) while theSplitStart do table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) ) theStart = theSplitEnd + 1 theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) end table.insert( outResults, string.sub( self, theStart ) ) return outResults end local function multiText(textOptions) local textTable = string.split( textOptions.text, " " ) local tempTextGrp = display.newGroup() local tempT = "" local tempT2 = "" local lineGrp = display.newText(tempTextGrp, "", 0, 0, textOptions.font, textOptions.fontSize) local function addText(whatText) -------------------------------------- --insert to text field tempT2 = tempT tempT = tempT ..whatText.." " lineGrp.text = tempT if textOptions.width and lineGrp.width \> textOptions.width then --check width, if too wide, next line lineGrp.text = tempT2 tempT = whatText.." " lineGrp = display.newText(tempTextGrp, "", 0, 0, textOptions.font, textOptions.fontSize) end end for i = 1, #textTable do if textTable[i] == "" then addText(textTable[i]) else -------------------------------------- --take out \n local textTable2 = string.split( textTable[i], "\n" ) for j = 1, #textTable2 do addText(textTable2[j]) if j ~= #textTable2 then --add new line lineGrp = display.newText(tempTextGrp, "", 0, 0, textOptions.font, textOptions.fontSize) tempT = "" end end end end --arrange text --checkHighestHeight local tempHeight = 0 for j = 1, tempTextGrp.numChildren do if tempTextGrp[j].height \> tempHeight then tempHeight = tempTextGrp[j].height end end for j = 1, tempTextGrp.numChildren do tempTextGrp[j].y = tempHeight\*(j-1) local tempColor = textOptions.textColor if tempColor then tempTextGrp[j]:setFillColor(tempColor[1], tempColor[2], tempColor[3]) end end tempTextGrp.anchorX = 0.5 tempTextGrp.anchorY = 0.5 tempTextGrp.anchorChildren = true if textOptions.x then tempTextGrp.x = textOptions.x end if textOptions.y then tempTextGrp.y = textOptions.y end if textOptions.displayGrp then textOptions.displayGrp:insert(tempTextGrp) end return tempTextGrp end -------------------------------------------- --testing the text -------------------------------------------- local sayWhat = "TESTING\nThe quick brown fox jumps over the lazy dog" local testGroup = display.newGroup() local textOptions = { displayGrp=testGroup, text = sayWhat, x = display.contentCenterX, y = display.contentCenterY , width = 150, font = "Bromine", fontSize = 13, textColor = {0, 0, 0} } testGroup.myText = multiText(textOptions)

We use the same procedures for multi-line and single line. However, font metrics plays a bigger roll when you have multi-line.

Rob

If you were able to turn off the mask, you would get a solid rectangle.  Because these have to go into OpenGL, they have to be a texture image (i.e. a graphic).  Text is rendered as a colored rectangle with a mask applied to create the transparent areas.  The reason you get things cut off is because every device/os combination has their own font rendering APIs and they are not consistent.  When you use a custom font, they come from founderies that are of different quality.  A font like Arial or Helvetica has been well tested but Joe’s UbaUba Font may not have had as much testing on the different devices and you end up with stuff cut off if their font metrics are not quite right.

When you see this you can do things like add some spaces before the W or add a blank line at the top to move the text down in the box.  It’s a hack, yes, but the only other choice is to find a Font that’s better constructed and works better with the different device rendering engines.

Rob

Thanks Rob for the clarification!

Not sure if only the multi line textfield uses openGL, because for single line text field doesn’t have the problem. So I end up writing a new multi line script based on your blog entry http://coronalabs.com/blog/2013/04/16/lua-string-magic/

I break the string and insert them in multiple single line texts, then put them in one display group.

The downside is I can’t update the text after created, but that is fine for me.

I’ll share the code here. Probably will add in code to adjust line spacing and alignment in future. 

--------------------------------------------------------------- -- MULTI LINE TEXT --------------------------------------------------------------- function string:split( inSplitPattern, outResults ) if not outResults then outResults = { } end local theStart = 1 local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) while theSplitStart do table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) ) theStart = theSplitEnd + 1 theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) end table.insert( outResults, string.sub( self, theStart ) ) return outResults end local function multiText(textOptions) local textTable = string.split( textOptions.text, " " ) local tempTextGrp = display.newGroup() local tempT = "" local tempT2 = "" local lineGrp = display.newText(tempTextGrp, "", 0, 0, textOptions.font, textOptions.fontSize) local function addText(whatText) -------------------------------------- --insert to text field tempT2 = tempT tempT = tempT ..whatText.." " lineGrp.text = tempT if textOptions.width and lineGrp.width \> textOptions.width then --check width, if too wide, next line lineGrp.text = tempT2 tempT = whatText.." " lineGrp = display.newText(tempTextGrp, "", 0, 0, textOptions.font, textOptions.fontSize) end end for i = 1, #textTable do if textTable[i] == "" then addText(textTable[i]) else -------------------------------------- --take out \n local textTable2 = string.split( textTable[i], "\n" ) for j = 1, #textTable2 do addText(textTable2[j]) if j ~= #textTable2 then --add new line lineGrp = display.newText(tempTextGrp, "", 0, 0, textOptions.font, textOptions.fontSize) tempT = "" end end end end --arrange text --checkHighestHeight local tempHeight = 0 for j = 1, tempTextGrp.numChildren do if tempTextGrp[j].height \> tempHeight then tempHeight = tempTextGrp[j].height end end for j = 1, tempTextGrp.numChildren do tempTextGrp[j].y = tempHeight\*(j-1) local tempColor = textOptions.textColor if tempColor then tempTextGrp[j]:setFillColor(tempColor[1], tempColor[2], tempColor[3]) end end tempTextGrp.anchorX = 0.5 tempTextGrp.anchorY = 0.5 tempTextGrp.anchorChildren = true if textOptions.x then tempTextGrp.x = textOptions.x end if textOptions.y then tempTextGrp.y = textOptions.y end if textOptions.displayGrp then textOptions.displayGrp:insert(tempTextGrp) end return tempTextGrp end -------------------------------------------- --testing the text -------------------------------------------- local sayWhat = "TESTING\nThe quick brown fox jumps over the lazy dog" local testGroup = display.newGroup() local textOptions = { displayGrp=testGroup, text = sayWhat, x = display.contentCenterX, y = display.contentCenterY , width = 150, font = "Bromine", fontSize = 13, textColor = {0, 0, 0} } testGroup.myText = multiText(textOptions)

We use the same procedures for multi-line and single line. However, font metrics plays a bigger roll when you have multi-line.

Rob