Skip to content

Commit a37aee4

Browse files
committed
Added support for vertically aligning the words on a line
Fixes #55
1 parent 2abb584 commit a37aee4

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

README.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ The `settings` table can contain the following values:
152152
* `shadow` (vector4) - The default shadow color of text. Will be transparent if not specified.
153153
* `outline` (vector4) - The default outline color of text. Will be transparent if not specified.
154154
* `align` (hash) - One of `richtext.ALIGN_LEFT`, `richtext.ALIGN_CENTER`, `richtext.ALIGN_RIGHT` and `richtext.ALIGN_JUSTIFY`. Defaults to `richtext.ALIGN_LEFT`. Defines how the words of a line of text are positioned in relation the provided `position`. Width must be specified for `richtext.ALIGN_JUSTIFY`.
155+
* `valign` (hash) - One of `richtext.VALIGN_TOP`, `richtext.VALIGN_MIDDLE` and `richtext.VALIGN_BOTTOM`. Defaults to `richtext.VALIGN_TOP`. Defines how the words of a line of text are positioned vertically on the line.
155156
* `line_spacing` (number) - Value to multiply line height with. Set to a value lower than 1.0 to reduce space between lines and a value higher than 1.0 to increase space between lines. Defaults to 1.0.
156157
* `paragraph_spacing` (number) - Space to leave after lines with where `<p>` tags end. Relative to the line height. Defaults to 0.5 lines.
157158
* `image_pixel_grid_snap` (boolean) - Set to true to position image on full pixels (positions rounded to nearest integer) to avoid effects of anti-aliasing. Defaults to false.
@@ -280,10 +281,20 @@ Center text. The words of a line are centered on the specified position (see `ri
280281
### richtext.ALIGN_RIGHT
281282
Right-align text. The words of a line ends at the specified position (see `richtext.create` settings above).
282283

283-
### richtext.ALIGN_JUSTIFT
284+
### richtext.ALIGN_JUSTIFY
284285
Justify text. The words of a line start at the specified position and are spaced such that the last character of the last word ends at the right edge of the line bounds (see `richtext.create` settings above).
285286

286287

288+
### richtext.VALIGN_TOP
289+
Vertically align the words on a line so that the top of the words on the line align.
290+
291+
### richtext.VALIGN_MIDDLE
292+
Vertically align the words on a line so that the middle of the words on the line align.
293+
294+
### richtext.VALIGN_BOTTOM
295+
Vertically align the words on a line so that the bottom of the words on the line align.
296+
297+
287298
# Credits
288299
* Smiley icons in example app from [Flaticons](https://www.flaticon.com/packs/smileys-3)
289300
* UTF8 decoding from [utf8.lua](https://github.com/Stepets/utf8.lua)

richtext/richtext.lua

+29-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ M.ALIGN_LEFT = hash("ALIGN_LEFT")
88
M.ALIGN_RIGHT = hash("ALIGN_RIGHT")
99
M.ALIGN_JUSTIFY = hash("ALIGN_JUSTIFY")
1010

11+
M.VALIGN_TOP = hash("VALIGN_TOP")
12+
M.VALIGN_MIDDLE = hash("VALIGN_MIDDLE")
13+
M.VALIGN_BOTTOM = hash("VALIGN_BOTTOM")
14+
1115

1216
local V4_ZERO = vmath.vector4(0)
1317
local V4_ONE = vmath.vector4(1)
@@ -277,7 +281,6 @@ local function create_node(word, parent, font, node, metrics)
277281
else
278282
node, metrics = create_text_node(word, font, metrics)
279283
end
280-
gui.set_pivot(node, gui.PIVOT_NW)
281284
gui.set_parent(node, parent)
282285
gui.set_inherit_alpha(node, true)
283286
return node, metrics
@@ -312,6 +315,7 @@ function M.create(text, font, settings)
312315
assert(font, "You must provide a font")
313316
settings = settings or {}
314317
settings.align = settings.align or M.ALIGN_LEFT
318+
settings.valign = settings.valign or M.VALIGN_TOP
315319
settings.fonts = settings.fonts or {}
316320
settings.fonts[font] = settings.fonts[font] or { regular = hash(font) }
317321
settings.layers = settings.layers or {}
@@ -329,7 +333,20 @@ function M.create(text, font, settings)
329333
if settings.align == M.ALIGN_JUSTIFY and not settings.width then
330334
error("Width must be specified if text should be justified")
331335
end
332-
336+
337+
local line_increment_before = 0
338+
local line_increment_after = 1
339+
local pivot = gui.PIVOT_NW
340+
if settings.valign == M.VALIGN_MIDDLE then
341+
line_increment_before = 0.5
342+
line_increment_after = 0.5
343+
pivot = gui.PIVOT_W
344+
elseif settings.valign == M.VALIGN_BOTTOM then
345+
line_increment_before = 1
346+
line_increment_after = 0
347+
pivot = gui.PIVOT_SW
348+
end
349+
333350
-- default settings for a word
334351
-- will be assigned to each word unless tags override the values
335352
local word_settings = {
@@ -380,6 +397,7 @@ function M.create(text, font, settings)
380397

381398
if overflow and not word.nobr then
382399
-- overflow, position the words that fit on the line
400+
text_metrics.height = text_metrics.height + (line_height * line_increment_before * settings.line_spacing)
383401
position.x = settings.position.x
384402
position.y = settings.position.y - text_metrics.height
385403
position_words(line_words, line_width, line_height, position, settings)
@@ -389,7 +407,7 @@ function M.create(text, font, settings)
389407

390408
-- update text metrics
391409
text_metrics.width = math.max(text_metrics.width, line_width)
392-
text_metrics.height = text_metrics.height + (line_height * settings.line_spacing) + paragraph_spacing
410+
text_metrics.height = text_metrics.height + (line_height * line_increment_after * settings.line_spacing) + paragraph_spacing
393411
line_width = word_metrics.total_width
394412
line_height = word_metrics.height
395413
paragraph_spacing = 0
@@ -410,6 +428,7 @@ function M.create(text, font, settings)
410428

411429
if should_create_node then
412430
word.node, word.metrics = create_node(word, settings.parent, font_for_word, node, word_metrics)
431+
gui.set_pivot(word.node, pivot)
413432

414433
-- assign layer
415434
local layer = get_layer(word, settings.layers)
@@ -434,12 +453,13 @@ function M.create(text, font, settings)
434453
-- handle line break
435454
if word.linebreak then
436455
-- position all words on the line up until the linebreak
456+
text_metrics.height = text_metrics.height + (line_height * line_increment_before * settings.line_spacing)
437457
position.x = settings.position.x
438458
position.y = settings.position.y - text_metrics.height
439459
position_words(line_words, line_width, line_height, position, settings)
440460

441461
-- update text metrics
442-
text_metrics.height = text_metrics.height + (line_height * settings.line_spacing) + paragraph_spacing
462+
text_metrics.height = text_metrics.height + (line_height * line_increment_after * settings.line_spacing) + paragraph_spacing
443463
line_height = word_metrics.height
444464
line_width = 0
445465
paragraph_spacing = 0
@@ -448,10 +468,11 @@ function M.create(text, font, settings)
448468

449469
-- position remaining words
450470
if #line_words > 0 then
471+
text_metrics.height = text_metrics.height + (line_height * line_increment_before * settings.line_spacing)
451472
position.x = settings.position.x
452473
position.y = settings.position.y - text_metrics.height
453474
position_words(line_words, line_width, line_height, position, settings)
454-
text_metrics.height = text_metrics.height + line_height
475+
text_metrics.height = text_metrics.height + (line_height * line_increment_after * settings.line_spacing)
455476
end
456477

457478
-- compact words table
@@ -571,13 +592,15 @@ function M.characters(word)
571592
local parent = gui.get_parent(word.node)
572593
local font = gui.get_font(word.node)
573594
local layer = gui.get_layer(word.node)
595+
local pivot = gui.get_pivot(word.node)
574596

575597
local word_length = utf8.len(word.text)
576598

577599
-- exit early if word is a single character or empty
578600
if word_length <= 1 then
579601
local char = deepcopy(word)
580602
char.node, char.metrics = create_node(char, parent, font)
603+
gui.set_pivot(char.node, pivot)
581604
gui.set_position(char.node, gui.get_position(word.node))
582605
gui.set_layer(char.node, layer)
583606
return { char }
@@ -594,6 +617,7 @@ function M.characters(word)
594617
char.text = utf8.sub(word.text, i, i)
595618
char.node, char.metrics = create_node(char, parent, font)
596619
gui.set_layer(char.node, layer)
620+
gui.set_pivot(char.node, pivot)
597621

598622
local sub_metrics = get_text_metrics(word, font, utf8.sub(word.text, 1, i))
599623
position.x = position_x + sub_metrics.width - char.metrics.width

0 commit comments

Comments
 (0)