Issue #719 new

Things related to drawing text

hahawoo avatarhahawoo created an issue

Here's a proposal for a function that replaces love.graphics.print and love.graphics.printf, yay!

Basically, it:

  • Combines the functionality of print and printf.
  • Adds the functionality of aligning to a point, along with aligning within a "rectangle".
  • Is called text instead of print.
  • Has a default x and y of 0. (#638)

It has two variants:

love.graphics.text(string, x (0), y (0), alignmode ("left"), r, sx, sy, ox, oy, kx, ky)
love.graphics.text(string, x, y, wraplimit, alignmode ("left"), r, sx, sy, ox, oy, kx, ky)

Here are some examples:

Drawing text at 0, 0:

love.graphics.text("Some text.")

Drawing horizontally left-aligned text at a point, i.e. just like love.graphics.print:

love.graphics.text("Some text.", 12, 34)

Drawing text horizontally aligned to a point again, this time centered above "object":

love.graphics.text("Some text.", object.x, object.y - 20, "center")

Drawing left-aligned text which wraps at 100:

love.graphics.text("Some text.", 12, 34, 100)

Drawing left-aligned text rotated by 1 radian:

love.graphics.text("Some text.", 12, 34, "left", 1)

I prefer the name text to the name print because...

  • print is inconsistent with primitive drawing functions in that it's not named after what it draws; love.graphics.rectangle draws a rectangle, but love.graphics.print doesn't draw a "print".
  • print isn't necessarily an obvious name, unless one has previously come across the word "print" used to mean "outputting text", which surely is common since it's used in Lua, but still, drawing text with LOVE might be the first programming someone ever does, and I'd say for most people the word "print" invokes thoughts of paper.
  • printf is surely a somewhat confusing name to people who have never seen printf in another language, and if they have they might be expecting something like string.format.
  • text is one character shorter than print! :D

Please say if anything is unclear/insane!

Comments (11)

  1. Alex Szpakowski

    I think a more forward-looking text drawing API would probably have text objects (at least as an option), because if the text doesn't change every frame then it can be drawn much more efficiently, especially if it has some formatting applied. This is very important for mobile.

    print is inconsistent with primitive drawing functions in that it's not named after what it draws; love.graphics.rectangle draws a rectangle, but love.graphics.print doesn't draw a "print".

    Well, love.graphics.print isn't a primitive drawing function - love.graphics.draw doesn't draw a "draw" either. :P

    I'm not really convinced this is a significant improvement, more of a.. side-grade.

  2. hahawoo

    Hehehe, it is a bit of a side-grade, but I think it might be a slight improvement.

    And plus, I think maybe horizontally-aligned-to-a-point text might be interesting. love.graphics.print already does this, except it only left-aligns. So, adding the align mode argument "completes the thought" (and that's the first variant).

    Currently if you wanted non-wrapping centered text, I think you might have to do something like this:

    love.graphics.print('Some text!', x - love.graphics.getFont():getWidth('Some text!')/2, y)
    

    or this:

    love.graphics.printf('Some text!', x - LARGE_NUMBER/2, y, LARGE_NUMBER, 'center')
    

    (Oh yeah, and without printf, and with mkdir and ChainShape:setPrevVertex renamed, and not including the abbreviation "Max" or the acronym "FPS", or "X" or "Y" or "AABB" (Edit: or BezierCurve:eval), I think that possibly all function names would consist of actual words! Yaaaaaay!)

  3. Bart van Strien

    I am wondering what love.graphics.text("Some text.", object.x, object.y - 20, "center") is supposed to do.

    Also, I like the print/printf distinction, I don't think 'text' is a good name, and I think your proposed interface is ambiguous.

  4. hahawoo

    Assuming I haven't made any errors, this interface is what I'm proposing:

    function love.graphics.text(s, x, y, a, b, c, d, e, f, g, h, i)
        if x == nil then x = 0 end
        if y == nil then y = 0 end
    
        if type(a) == 'number' then
            local wraplimit, alignmode, r, sx, sy, ox, oy, kx, ky = a, b, c, d, e, f, g, h, i
            love.graphics.printf(s, x, y, wraplimit, alignmode, r, sx, sy, ox, oy, kx, ky)
    
        else
            local alignmode, r, sx, sy, ox, oy, kx, ky = a, b, c, d, e, f, g, h
    
            if alignmode == 'center' then
                x = x - love.graphics.getFont():getWidth(s)/2
            elseif alignmode == 'right' then
                x = x - love.graphics.getFont():getWidth(s)
            end
    
            love.graphics.print(s, x, y, r, sx, sy, ox, oy, kx, ky)
        end
    end
    

    And the current interface could be emulated by this:

    function love.graphics._print(s, x, y, ...)
        love.graphics.text(s, x, y, 'left', ...)
    end
    
    love.graphics._printf = love.graphics.text
    
  5. hahawoo

    A problem with this though is it would probably be the most "I have to look carefully at the arguments to see which variation is being used" function in the API.

  6. hahawoo

    Okay so this idea was insane. :D

    Combining functions which do similar things in an unambiguous way can still be confusing. As another example, love.graphics.polygon could function the same as love.graphics.rectangle when given four arguments, but this would surely be confusing.

    So, salvaging the other ideas:

    • love.graphics.print could have an argument for how to aligns to its x position (left, right, or center). This could be achieved in other ways though, so I'm not really thinking this is such a great idea, and it would be inconsistent with love.graphics.draw in a way.
    • I still prefer the name "text" to "print". As well as the reasons above:
      • It differentiates itself from Lua's print.
      • Well, it's true that love.graphics.draw doesn't draw a "draw". :P But still, love.graphics.draw can draw multiple things, and love.graphics.text would be named after what it draws. To note, it's kind of difficult to describe love.graphics.print without using the word "text"; drawing text is just kinda what it does.
    • Regardless of "print" vs "text", I don't think printf is a great name. What about... printWrap? That also doesn't seem like a great name. But, maybe it's more suitable. It describes what it does a bit more, it uses English words and is pronounceable.
  7. hahawoo

    "printf" is a familiar sound to me, I could pronounce it without really having to think about it, and I know that the "f" stands for format(ting/ted), but why is this the case for me?

    Well, I've heard the function of the same name in C spoken and its abbreviation explained. However, some people will see LÖVE's printf function and won't have had this previous experience, and for them it will surely be mysterious.

    Additionally, it seems that LÖVE's printf relies on a different interpretation of "formatted".

    http://en.wikipedia.org/wiki/printf redirects to "printf format string", which shows the printf function of some languages, and the kind of thing they do is what string.format does.

    So by "format", LÖVE's printf means "wraps and aligns within the wrapping width".

    Contrasting "printf" with, say, "textWrap", I think someone who is new to everything could kind of maybe possibly get an idea of what "textWrap" is about, but I'd say "printf" would leave them clueless.

    I'm thinking that using real, descriptive words is actually kind of "not scary" in a way. Like, if there was a function called setMetaAlphaShader and a function called ksdfsd, at least with setMetaAlphaShader you kind of know that it sets the meta alpha shader, whatever that means, but with ksdfsd you have no idea, so it's kind of scary.

  8. hahawoo

    Just to note, if there were text objects in LÖVE, the name "text" might be consistent with that, and perhaps the word "wrap" might be consistent with in a text object method?

  9. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.