8 #include "mf_kerning.h"
17 struct kerning_state_s
19 gU8 edgepos[MF_KERNING_ZONES];
24 static void fit_leftedge(gI16 x, gI16 y, gU8 count, gU8 alpha,
27 struct kerning_state_s *s = state;
32 gU8 zone = y / s->zoneheight;
33 if (x < s->edgepos[zone])
39 static void fit_rightedge(gI16 x, gI16 y, gU8 count, gU8 alpha,
42 struct kerning_state_s *s = state;
46 gU8 zone = y / s->zoneheight;
48 if (x > s->edgepos[zone])
54 static bool do_kerning(mf_char c)
57 if (c ==
' ' || c ==
'\n' || c ==
'\r' || c ==
'\t')
62 if (c >=
'0' && c <=
'9')
69 static gI16 max16(gI16 a, gI16 b) {
return (a > b) ? a : b; }
70 static gI16 avg16(gI16 a, gI16 b) {
return (a + b) / 2; }
72 gI8 mf_compute_kerning(
const struct mf_font_s *font,
73 mf_char c1, mf_char c2)
75 struct kerning_state_s leftedge, rightedge;
76 gU8 w1, w2, i, min_space;
77 gI16 normal_space, adjust, max_adjust;
79 if (font->flags & MF_FONT_FLAG_MONOSPACE)
82 if (!do_kerning(c1) || !do_kerning(c2))
86 i = (font->height + MF_KERNING_ZONES - 1) / MF_KERNING_ZONES;
90 leftedge.zoneheight = rightedge.zoneheight = i;
91 for (i = 0; i < MF_KERNING_ZONES; i++)
93 leftedge.edgepos[i] = 255;
94 rightedge.edgepos[i] = 0;
98 w1 = mf_render_character(font, 0, 0, c1, fit_rightedge, &rightedge);
99 w2 = mf_render_character(font, 0, 0, c2, fit_leftedge, &leftedge);
103 for (i = 0; i < MF_KERNING_ZONES; i++)
106 if (leftedge.edgepos[i] == 255 || rightedge.edgepos[i] == 0)
109 space = w1 - rightedge.edgepos[i] + leftedge.edgepos[i];
110 if (space < min_space)
114 if (min_space == 255)
118 normal_space = avg16(w1, w2) * MF_KERNING_SPACE_PERCENT / 100;
119 normal_space += MF_KERNING_SPACE_PIXELS;
120 adjust = normal_space - min_space;
121 max_adjust = -max16(w1, w2) * MF_KERNING_LIMIT / 100;
123 if (adjust > 0) adjust = 0;
124 if (adjust < max_adjust) adjust = max_adjust;