µGFX  2.9
version 2.9
mf_bwfont.c
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.io/license.html
6  */
7 
8 #include "mf_bwfont.h"
9 
10 #ifndef MF_NO_COMPILE
11 
12 #include <stdbool.h>
13 
14 /* Find the character range and index that contains a given glyph.. */
15 static const struct mf_bwfont_char_range_s *find_char_range(
16  const struct mf_bwfont_s *font, gU16 character, gU16 *index_ret)
17 {
18  unsigned i, index;
19  const struct mf_bwfont_char_range_s *range;
20  for (i = 0; i < font->char_range_count; i++)
21  {
22  range = &font->char_ranges[i];
23  index = character - range->first_char;
24  if (character >= range->first_char && index < range->char_count)
25  {
26  *index_ret = index;
27  return range;
28  }
29  }
30 
31  return 0;
32 }
33 
34 static gU8 get_width(const struct mf_bwfont_char_range_s *r, gU16 index)
35 {
36  if (r->width)
37  {
38  return r->width + r->offset_x;
39  }
40  else
41  {
42  return r->glyph_widths[index];
43  }
44 }
45 
46 static gU8 render_char(const struct mf_bwfont_char_range_s *r,
47  gI16 x0, gI16 y0, gU16 index,
48  mf_pixel_callback_t callback,
49  void *state)
50 {
51  const gU8 *data, *p;
52  gU8 stride, runlen;
53  gU8 x, y, height, num_cols;
54  gU8 bit, byte, mask;
55  bool oldstate, newstate;
56 
57  if (r->width)
58  {
59  data = r->glyph_data + r->width * index * r->height_bytes;
60  num_cols = r->width;
61  }
62  else
63  {
64  data = r->glyph_data + r->glyph_offsets[index] * r->height_bytes;
65  num_cols = r->glyph_offsets[index + 1] - r->glyph_offsets[index];
66  }
67 
68  stride = r->height_bytes;
69  height = r->height_pixels;
70  y0 += r->offset_y;
71  x0 += r->offset_x;
72  bit = 0;
73  byte = 0;
74 
75  for (y = 0; y < height; y++)
76  {
77  mask = (1 << bit);
78 
79  oldstate = false;
80  runlen = 0;
81  p = data + byte;
82  for (x = 0; x < num_cols; x++, p += stride)
83  {
84  newstate = *p & mask;
85  if (newstate != oldstate)
86  {
87  if (oldstate && runlen)
88  {
89  callback(x0 + x - runlen, y0 + y, runlen, 255, state);
90  }
91 
92  oldstate = newstate;
93  runlen = 0;
94  }
95 
96  runlen++;
97  }
98 
99  if (oldstate && runlen)
100  {
101  callback(x0 + x - runlen, y0 + y, runlen, 255, state);
102  }
103 
104  bit++;
105  if (bit > 7)
106  {
107  bit = 0;
108  byte++;
109  }
110  }
111 
112  return get_width(r, index);
113 }
114 
115 gU8 mf_bwfont_render_character(const struct mf_font_s *font,
116  gI16 x0, gI16 y0,
117  gU16 character,
118  mf_pixel_callback_t callback,
119  void *state)
120 {
121  const struct mf_bwfont_s *bwfont = (const struct mf_bwfont_s*)font;
122  const struct mf_bwfont_char_range_s *range;
123  gU16 index;
124 
125  range = find_char_range(bwfont, character, &index);
126  if (!range)
127  return 0;
128 
129  return render_char(range, x0, y0, index, callback, state);
130 }
131 
132 gU8 mf_bwfont_character_width(const struct mf_font_s *font,
133  gU16 character)
134 {
135  const struct mf_bwfont_s *bwfont = (const struct mf_bwfont_s*)font;
136  const struct mf_bwfont_char_range_s *range;
137  gU16 index;
138 
139  range = find_char_range(bwfont, character, &index);
140  if (!range)
141  return 0;
142 
143  return get_width(range, index);
144 }
145 
146 #endif //MF_NO_COMPILE