Forum Discussion

cheungj's avatar
cheungj
Visitor
12 years ago

Issues with roFont.getOneLineWidth

Has anyone encountered an issue with roFont.getOneLineWidth(string, max size) not returning the right width for a particular string for specific fonts

essentially what I have is an image canvas with a layer that has a piece of text that is only suppose to be on one line. the font is set but the fontsize is dynamic.

so for a particular font size say 50 what happens is when i use the roFont.getOneLineWidth it returns a rectangle width which is smaller then it is to fit the text on one line so it word wraps. has anyone encountered an issue like this with that method before?

8 Replies

  • destruk's avatar
    destruk
    Streaming Star
    Yes, if the area you are writing your text to is too narrow to fit on one line, it wraps the text to fit, so if you check the height value as well you can get the actual size/area it is using. You can avoid the issue by using a fixed-width font instead of proportional, and using a set font size instead of a variable font size selection, and that way you could simply count the number of standard characters you have in the line rather than checking width and individual character metrics.
  • Destruk, I don't think that's the case. ifFont.GetOneLineHeight takes no parameters so it can't return the height of a specific wrapped string. GetOneLineWidth also doesn't take any wrapping into account. I'm not aware of any cases where GetOneLineWidth would return less than the space required to draw the string as one line, unless it's larger than the MaxWidth parameter. Can you provide an example?

    --Mark
  • destruk's avatar
    destruk
    Streaming Star
    I was using .Size.W and .Side.H for that.
    Maybe getonelinewidth and getonelineheight is handled differently.
  • Certainly I have example right here

    fontsize is dynamic integer
    Stringvalue = "Hello foo foo enjoy"

    font = m.fonts.GetFont("BPreplay",fontSize,true,false)
    txtRect.w = font.GetOneLineWidth(stringvalue, canvas.w*2)

    so when i print out the txtRect.w its smaller then what the text requires to fit on oneline. Should I provide an offset so it has additional padding or space?
  • Ok, I tried these commands in the debugger:

    BrightScript Debugger> reg = CreateObject("roFontRegistry")
    BrightScript Debugger> font = reg.GetDefaultFont()
    BrightScript Debugger> s = "Hello foo foo enjoy"
    BrightScript Debugger> w = font.GetOneLineWidth(s, 10000)
    BrightScript Debugger> ?w
    336
    BrightScript Debugger> screen = CreateObject("roscreen")
    BrightScript Debugger> screen.DrawText(s, 100,100,&hffffffff,font)
    BrightScript Debugger> screen.DrawRect(100,140,336,32, &hffff00ff)
    BrightScript Debugger> screen.Finish()

    This drew the text and then drew a yellow rectangle that exactly matches the width of the text, so it seems to be working here. Can you reproduce your problem with the default font? If not, perhaps there is a problem with your font file. If you can reproduce with the default font, please post the complete source.

    --Mark
  • Could you clarify what you mean by "It does not take into account the font face, bold or italic"? This example shows that it returns different results when bold is used:

    BrightScript Debugger> reg = CreateObject("roFontRegistry")
    BrightScript Debugger> font1 = reg.GetDefaultFont(32,false,false)
    BrightScript Debugger> font2 = reg.GetDefaultFont(32,true,false)
    BrightScript Debugger> ?font1.GetOneLineWidth("this string", 10000)
    146
    BrightScript Debugger> ?font2.GetOneLineWidth("this string", 10000)
    166


    I will look into the issue with SD.

    --Mark
  • Thanks for posting that. I've modified it to use roScreen rather than roImageCanvas and it seems to work perfectly (except possibly for a slight overdraw with italic). So the issue seems to be with roImageCanvas. I don't know much about roImageCanvas but I'll pass this along to the right people. The GetOneLine* functions were intended to be used with roScreen so I'm not sure if they're supposed to work with roImageCanvas. roScreen is really a better choice if you're trying to do pixel-accurate drawing.

    Here's the roScreen version of your code.


    function main()
    reg = CreateObject("roFontRegistry")
    scr = CreateObject("roScreen")
    port = CreateObject( "roMessagePort" )
    scr.SetMessagePort( port )
    usage = "Left/Right chg Face, Up/Dn chg Size, FF/REW chg Fudge Factor"
    size = 35
    s = "Hello foo foo enjoy"
    loop = true
    mode = 0
    fudge = 1.0

    while loop
    scr.Clear(&hFF808080)

    bold = Int(mode/2)
    italic = mode mod 2

    f = reg.GetDefaultFont( size, bold, italic )
    w = Int( f.GetOneLineWidth( s, 10000 ) * fudge )
    h = f.GetOneLineHeight()

    txt = "w = "+w.ToStr()+" h = "+h.ToStr()

    scr.DrawRect(100, 200, w, h, &hFFFFFFFF)
    scr.DrawText(s, 100, 200, &h00FFFFFF, f)
    scr.DrawText(txt, 100, 40, &h000000FF, f)
    scr.DrawText(usage, 100, 300, &h000000FF, f)
    scr.Finish()

    while true
    msg = wait( 0, port )
    if msg <> invalid and type(msg) = "roUniversalControlEvent" then
    i = msg.GetInt()
    if i = 2 ' up
    size = size + 1
    exit while
    elseif i = 3 ' down
    size = size - 1
    exit while
    elseif i = 4 ' left
    mode = (mode+1) mod 4
    exit while
    elseif i = 5 ' right
    mode = (mode-1) mod 4
    exit while
    elseif i = 6 ' select
    exit while
    elseif i = 8 ' reverse
    fudge = fudge * 0.99
    exit while
    elseif i = 9 ' forward
    fudge = fudge * 1.01
    exit while
    end if
    end if
    end while

    end while

    End Function

    --Mark
  • DrawText doesn't wrap, it just draws a single line of text. If you want it to wrap you have to break it up into lines yourself and call DrawText for each line. I posted some code to do this a couple of days ago.

    --Mark