I really appreciate all the great text formatting options — thanks! One option I'd love to see added is paragraph spacing. This could be passed as an optional argument to playdate.graphics.drawText and friends, and/or set via e.g. playdate.graphics.font:setParagraphSpacing(). This would manifest as extra space (increased leading) before the next line following a hard-coded \n within the provided text.
This would make it convenient to manage small blocks of stylized text without needing to manually account for the size of each line/paragraph they contain. Some examples:
Longer form text, with multiple paragraphs of prose
Short lists, to add extra space between list items
Title + description blocks, where the title might be bolded, followed by a small gap, followed by one or more lines of wrapped text
I've already hacked together a small change to _layoutTextInRect in CoreLibs/graphics.lua which achieves the effect, which I can share if helpful. It's quite straightforward since the inner loop already iterates over each hard-broken line — just add the appropriate paragraphSpacing at the very end of each loop. However, since I couldn't set a property on the font object itself, I cheated and just set playdate.graphics.paragraphSpacing in order to get the desired value into that function cheaply. Would be great to have official support!
As far as parameterizing it, I'm not sure which approach to specifying paragraph spacing makes the most sense, but I'd accept any of:
An additive value (added to leading)
An override value (used instead of standard leading)
A multiplier (e.g. 1.5 would yield space equal to lineHeight * 1.5 between paragraphs)
Oh, sure! There's a _layoutTextInRect helper inside graphics.lua (in CoreLibs). The last for loop in that function does the bulk of the layout work, line by line. I just inserted this immediately before the end termination for that loop:
if i < #lines then
y += (playdate.graphics.paragraphSpacing or 0)
end
Then, to make use of it, I just set playdate.graphics.paragraphSpacing = 6 (or whatever), and subsequent calls to any of the text layout functions observe that value.
Here's what it looks like in context. Line 505 is the last line of _layoutTextInRect.
This is great, thank you for sharing. This will be my first time going "deeper" under the hood like this. Being a novice, I think I see what I should do, but would you mind telling me if I'm off anywhere in my logic?
I see your graphics.lua file is in your source folder. I'm going to make an assumption that I need to make a copy of the graphics.lua file and put it my project source folder so that the override will be in the proper "context" code wise.
In the project, when we call a graphics action, it would normally pull from that original graphics.lua file, but since we have a copy of it in our source folder, that is the primary source used instead. Is that accurate?
Next, will this apply project wide, or is it something akin to a variable that I could selectively add in per TextInRect call?
You don't have to copy it into your source folder. For a while I did not, but if you don't copy then you need to reapply the change every time you update the SDK version. (Of course, if you copy, then you don't pull in changes from the update unless you go through those same steps, but if you're okay locking to whatever version you have at hand now, then copying is easier.)
I keep mine at source/overrides/graphics.lua, and then import it explicitly with import "overrides/graphics". If you do this, it will replace the one provided by CoreLibs and apply project wide.
Ahh, ok. I got it now. That actually helps me understand why we do import "CoreLibs/..." that's us pulling in the SDK version of the file. Hence why updates to the SDK would wipe out the change.
I like the idea of making an override file and just independently updating that with SDK updates. Keeps it "in view" and would help remind me of the why. I fall into the trap of 'out of sight, out of mind' WAY too easily haha.