8 #include "mf_justify.h"
9 #include "mf_kerning.h"
15 static gI16 mf_round_to_tab(
const struct mf_font_s *font,
20 tabw = mf_character_width(font,
'm') * MF_TABSIZE;
23 x += mf_character_width(font,
' ');
26 dx = x - x0 + font->baseline_x;
27 x += tabw - (dx % tabw);
33 static gI16 mf_round_to_prev_tab(
const struct mf_font_s *font,
38 tabw = mf_character_width(font,
'm') * MF_TABSIZE;
41 x -= mf_character_width(font,
' ');
44 dx = x0 - x + font->baseline_x;
45 x -= tabw - (dx % tabw);
51 gI16 mf_get_string_width(
const struct mf_font_s *font, mf_str text,
52 gU16 count,
bool kern)
60 while (count-- && *text)
62 c2 = mf_getchar(&text);
67 result = mf_round_to_tab(font, 0, result);
76 result += mf_compute_kerning(font, c1, c2);
78 result += mf_character_width(font, c2);
86 static gU16 strip_spaces(mf_str text, gU16 count, mf_char *last_char)
88 gU16 i = 0, result = 0;
94 while (count-- && *text)
97 tmp = mf_getchar(&text);
98 if (tmp !=
' ' && tmp != (mf_char)0xA0 && tmp !=
'\n' &&
99 tmp !=
'\r' && tmp !=
'\t')
117 static void render_left(
const struct mf_font_s *font,
119 mf_str text, gU16 count,
120 mf_character_callback_t callback,
126 x = x0 - font->baseline_x;
129 c2 = mf_getchar(&text);
134 x = mf_round_to_tab(font, x0, x);
143 x += mf_compute_kerning(font, c1, c2);
145 x += callback(x, y0, c2, state);
152 void mf_render_aligned(
const struct mf_font_s *font,
154 enum mf_align_t align,
155 mf_str text, gU16 count,
156 mf_character_callback_t callback,
160 count = strip_spaces(text, count, 0);
161 render_left(font, x0, y0, text, count, callback, state);
167 static void render_right(
const struct mf_font_s *font,
169 mf_str text, gU16 count,
170 mf_character_callback_t callback,
179 for (i = 0; i < count; i++)
182 x = x0 - font->baseline_x;
183 for (i = 0; i < count; i++)
187 c1 = mf_getchar(&tmp);
193 x = mf_round_to_prev_tab(font, x0, x);
202 x -= mf_character_width(font, c1);
206 x -= mf_compute_kerning(font, c1, c2);
208 callback(x, y0, c1, state);
213 void mf_render_aligned(
const struct mf_font_s *font,
215 enum mf_align_t align,
216 mf_str text, gU16 count,
217 mf_character_callback_t callback,
221 count = strip_spaces(text, count, 0);
223 if (align == MF_ALIGN_LEFT)
225 render_left(font, x0, y0, text, count, callback, state);
227 if (align == MF_ALIGN_CENTER)
229 string_width = mf_get_string_width(font, text, count,
false);
230 x0 -= string_width / 2;
231 render_left(font, x0, y0, text, count, callback, state);
233 else if (align == MF_ALIGN_RIGHT)
235 render_right(font, x0, y0, text, count, callback, state);
244 void mf_render_justified(
const struct mf_font_s *font,
245 gI16 x0, gI16 y0, gI16 width,
246 mf_str text, gU16 count,
247 mf_character_callback_t callback,
251 mf_render_aligned(font, x0, y0, MF_ALIGN_LEFT, text, count, callback, state);
258 static bool is_justify_space(gU16 c)
260 return c ==
' ' || c == 0xA0;
264 static gU16 count_spaces(mf_str text, gU16 count)
267 while (count-- && *text)
269 if (is_justify_space(mf_getchar(&text)))
275 void mf_render_justified(
const struct mf_font_s *font,
276 gI16 x0, gI16 y0, gI16 width,
277 mf_str text, gU16 count,
278 mf_character_callback_t callback,
281 gI16 string_width, adjustment;
285 count = strip_spaces(text, count, &last_char);
287 if (last_char ==
'\n' || last_char == 0)
290 render_left(font, x0, y0, text, count, callback, state);
294 string_width = mf_get_string_width(font, text, count,
false);
295 adjustment = width - string_width;
296 num_spaces = count_spaces(text, count);
302 x = x0 - font->baseline_x;
305 c2 = mf_getchar(&text);
311 x = mf_round_to_tab(font, x0, x);
312 adjustment -= x - tmp - mf_character_width(font,
'\t');
320 if (is_justify_space(c2))
322 tmp = (adjustment + num_spaces / 2) / num_spaces;
330 tmp = mf_compute_kerning(font, c1, c2);
335 x += callback(x, y0, c2, state);