• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lexus2k / lcdgfx / 14124572239

28 Mar 2025 08:05AM UTC coverage: 30.326% (-0.06%) from 30.385%
14124572239

push

github

lexus2k
Fixing makefile

158 of 521 relevant lines covered (30.33%)

82.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

40.0
/src/canvas/font.cpp
1
/*
2
    MIT License
3

4
    Copyright (c) 2019-2021, Alexey Dynda
5

6
    Permission is hereby granted, free of charge, to any person obtaining a copy
7
    of this software and associated documentation files (the "Software"), to deal
8
    in the Software without restriction, including without limitation the rights
9
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
    copies of the Software, and to permit persons to whom the Software is
11
    furnished to do so, subject to the following conditions:
12

13
    The above copyright notice and this permission notice shall be included in all
14
    copies or substantial portions of the Software.
15

16
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
    SOFTWARE.
23
*/
24

25
#include "font.h"
26
#include "canvas/internal/canvas_types_int.h"
27

28
enum
29
{
30
    SSD1306_OLD_FIXED_FORMAT = 0x00,
31
    SSD1306_NEW_FIXED_FORMAT = 0x01,
32
    SSD1306_NEW_FORMAT = 0x02,
33
    SSD1306_SQUIX_FORMAT = 0x03,
34
};
35

36
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
37
uint8_t g_ssd1306_unicode2 = 1;
38
#endif
39
NanoFont g_canvas_font;
40

41
static const uint8_t *ssd1306_readUnicodeRecord(SUnicodeBlockRecord *r, const uint8_t *p)
20✔
42
{
43
    r->start_code = ((static_cast<uint16_t>(pgm_read_byte(&p[0])) << 8)) | static_cast<uint16_t>(pgm_read_byte(&p[1]));
20✔
44
    r->count = pgm_read_byte(&p[2]);
20✔
45
    return (r->count > 0) ? (&p[3]) : nullptr;
20✔
46
}
47

48
//////////////////////////////////////////////////////////////////////////////////////////////////
49
/// OLD FORMAT: 1.7.6 and below
50
/// OLD FORMAT is supported by old and latest versions of ssd1306 library
51

52
static const uint8_t *ssd1306_getCharGlyph(const SFixedFontInfo &font, char ch)
133✔
53
{
54
    return &font.primary_table[(ch - font.h.ascii_offset) * font.glyph_size +
266✔
55
                               (font.h.type == 0x01 ? sizeof(SUnicodeBlockRecord) : 0)];
133✔
56
}
57

58
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
59
static const uint8_t *ssd1306_searchCharGlyph(const SFixedFontInfo &font, const uint8_t *unicode_table,
×
60
                                              uint16_t unicode)
61
{
62
    SUnicodeBlockRecord r;
×
63
    const uint8_t *data = unicode_table;
×
64
    // looking for required unicode table
65
    while ( 1 )
×
66
    {
67
        ssd1306_readUnicodeRecord(&r, data);
×
68
        if ( r.count == 0 )
×
69
        {
70
            break;
71
        }
72
        data += sizeof(SUnicodeBlockRecord);
×
73
        if ( (unicode >= r.start_code) && (unicode < (r.start_code + r.count)) )
×
74
        {
75
            break;
76
        }
77
        data += r.count * font.glyph_size;
×
78
    }
79
    if ( r.count == 0 )
×
80
    {
81
        // Sorry, no glyph found for the specified character
82
        return NULL;
83
    }
84
    return &data[(unicode - r.start_code) * font.glyph_size];
×
85
}
86
#endif
87

88
static const uint8_t *ssd1306_getU16CharGlyph(const SFixedFontInfo &font, uint16_t unicode)
133✔
89
{
90
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
91
    if ( g_ssd1306_unicode2 )
133✔
92
    {
93
        const uint8_t *glyph = NULL;
133✔
94
        if ( (unicode < 128) && (font.h.type == 0x00) && (font.primary_table != NULL) )
133✔
95
        {
96
            return ssd1306_getCharGlyph(font, unicode);
133✔
97
        }
98
        if ( font.primary_table )
×
99
        {
100
            glyph = ssd1306_searchCharGlyph(font, font.primary_table, unicode);
×
101
        }
102
        if ( !glyph && font.secondary_table )
×
103
        {
104
            glyph = ssd1306_searchCharGlyph(font, font.secondary_table, unicode);
×
105
        }
106
        if ( !glyph )
×
107
        {
108
            return ssd1306_getCharGlyph(font, font.h.ascii_offset);
×
109
        }
110
        return glyph;
×
111
    }
112
    else
113
#endif
114
    {
115
        return ssd1306_getCharGlyph(font, unicode);
×
116
    }
117
}
118

119
static void _ssd1306_oldFormatGetBitmap(const SFixedFontInfo &font, uint16_t unicode, SCharInfo *info)
133✔
120
{
121
    if ( info )
133✔
122
    {
123
        info->width = font.h.width;
133✔
124
        info->height = font.h.height;
133✔
125
        info->spacing = font.spacing;
133✔
126
        info->glyph = ssd1306_getU16CharGlyph(font, unicode);
133✔
127
    }
128
}
133✔
129

130
void NanoFont::loadFixedFont(const uint8_t *progmemFont)
2✔
131
{
132
    m_fixedFont.h.type = pgm_read_byte(&progmemFont[0]);
2✔
133
    m_fixedFont.h.width = pgm_read_byte(&progmemFont[1]);
2✔
134
    m_fixedFont.h.height = pgm_read_byte(&progmemFont[2]);
2✔
135
    m_fixedFont.h.ascii_offset = pgm_read_byte(&progmemFont[3]);
2✔
136
    m_fixedFont.primary_table = progmemFont + 4;
2✔
137
    m_getCharBitmap = _ssd1306_oldFormatGetBitmap;
2✔
138
    m_fixedFont.pages = (m_fixedFont.h.height + 7) >> 3;
2✔
139
    m_fixedFont.glyph_size = m_fixedFont.pages * m_fixedFont.h.width;
2✔
140
    m_fixedFont.spacing = 0;
2✔
141
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
142
    m_fixedFont.secondary_table = NULL;
2✔
143
#endif
144
}
2✔
145

146
//////////////////////////////////////////////////////////////////////////////////////////////////
147
/// NEW FORMAT: 1.7.8 and later
148
/// NEW FORMAT is supported only by latest versions of ssd1306 library
149

150
static void _ssd1306_newFormatGetBitmap(const SFixedFontInfo &font, uint16_t unicode, SCharInfo *info)
20✔
151
{
152
    if ( info )
20✔
153
    {
154
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
155
        uint8_t table_index = 0;
20✔
156
#endif
157
        const uint8_t *data = font.primary_table;
20✔
158
        while ( data )
20✔
159
        {
160
            SUnicodeBlockRecord r;
20✔
161
            data = ssd1306_readUnicodeRecord(&r, data);
20✔
162
            if ( !data )
20✔
163
            {
164
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
165
                if ( table_index == 0 )
×
166
                {
167
                    table_index++;
×
168
                    data = font.secondary_table;
×
169
                    continue;
×
170
                }
171
#endif
172
                break;
20✔
173
            }
174
            /* Check that unicode in the section being processed */
175
            if ( (unicode < r.start_code) || (unicode >= (r.start_code + r.count)) )
20✔
176
            {
177
                // skip jump table
178
                data += static_cast<uint16_t>(r.count) * 4;
×
179
                // skip block bitmap data
180
                uint16_t offset = ((static_cast<uint16_t>(pgm_read_byte(&data[0])) << 8) |
×
181
                                   static_cast<uint16_t>(pgm_read_byte(&data[1]))) +
×
182
                                  2;
×
183
                //                printf("JMP OFFSET: %d\n", offset);
184
                data += offset;
×
185
                //                printf("JMP DONE: %02X %02X %02X\n", data[0], data[1], data[2]);
186
                continue;
×
187
            }
×
188
            /* At this point data points to jump table (offset|offset|bytes|width) */
189
            unicode -= r.start_code;
20✔
190
            data += unicode * 4;
20✔
191
            uint16_t offset = (pgm_read_byte(&data[0]) << 8) | (pgm_read_byte(&data[1]));
20✔
192
            uint8_t glyph_width = pgm_read_byte(&data[2]);
20✔
193
            uint8_t glyph_height = pgm_read_byte(&data[3]);
20✔
194
            info->width = glyph_width;
20✔
195
            info->height = glyph_height;
20✔
196
            info->spacing = glyph_width ? font.spacing : (font.h.width >> 1);
20✔
197
            info->glyph = data + (r.count - unicode) * 4 + 2 + offset;
20✔
198
            break;
20✔
199
        }
200
        if ( !info->glyph )
20✔
201
        {
202
            info->width = 0;
×
203
            info->height = 0;
×
204
            info->spacing = font.h.width >> 1;
×
205
            info->glyph = font.primary_table;
×
206
        }
207
    }
208
}
20✔
209

210
void NanoFont::loadFreeFont(const uint8_t *progmemFont)
1✔
211
{
212
    m_fixedFont.h.type = pgm_read_byte(&progmemFont[0]);
1✔
213
    m_fixedFont.h.width = pgm_read_byte(&progmemFont[1]);
1✔
214
    m_fixedFont.h.height = pgm_read_byte(&progmemFont[2]);
1✔
215
    m_fixedFont.h.ascii_offset = pgm_read_byte(&progmemFont[3]);
1✔
216
    m_fixedFont.primary_table = progmemFont + 4;
1✔
217
    m_getCharBitmap = _ssd1306_newFormatGetBitmap;
1✔
218
    m_fixedFont.spacing = 1;
1✔
219
    m_fixedFont.pages = (m_fixedFont.h.height + 7) >> 3;
1✔
220
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
221
    m_fixedFont.secondary_table = NULL;
1✔
222
#endif
223
}
1✔
224

225
void NanoFont::loadSecondaryFont(const uint8_t *progmemUnicode)
×
226
{
227
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
228
    m_fixedFont.secondary_table = progmemUnicode;
×
229
    if ( m_fixedFont.secondary_table != NULL )
×
230
    {
231
        m_fixedFont.secondary_table += sizeof(SFontHeaderRecord);
×
232
    }
233
#endif
234
}
×
235

236
void NanoFont::loadFixedFont_oldStyle(const uint8_t *progmemFont)
×
237
{
238
    m_fixedFont.h.type = pgm_read_byte(&progmemFont[0]);
×
239
    m_fixedFont.h.width = pgm_read_byte(&progmemFont[1]);
×
240
    m_fixedFont.h.height = pgm_read_byte(&progmemFont[2]);
×
241
    m_fixedFont.h.ascii_offset = pgm_read_byte(&progmemFont[3]);
×
242
    m_fixedFont.primary_table = progmemFont + 4;
×
243
    m_fixedFont.pages = (m_fixedFont.h.height + 7) >> 3;
×
244
    m_fixedFont.glyph_size = m_fixedFont.pages * m_fixedFont.h.width;
×
245
    m_fixedFont.spacing = 0;
×
246
}
×
247

248
//////////////////////////////////////////////////////////////////////////////////////////////////
249
/// SQUIX FORMAT: 1.7.8 and later
250
/// SQUIX FORMAT is not fully supported. Use it at your own risk
251

252
static void _ssd1306_squixFormatGetBitmap(const SFixedFontInfo &font, uint16_t unicode, SCharInfo *info)
×
253
{
254
    if ( info )
×
255
    {
256
        const uint8_t *data = font.primary_table;
×
257
        /* Check that unicode in the section being processed */
258
        if ( !data || (unicode < font.h.ascii_offset) || (unicode >= (font.h.ascii_offset + font.count)) )
×
259
        {
260
            info->width = 0;
×
261
            info->height = 0;
×
262
            info->spacing = font.h.width >> 1;
×
263
            info->glyph = font.primary_table;
×
264
            return;
×
265
        }
266
        /* At this point data points to jump table (offset|offset|bytes|width) */
267
        const uint8_t *bitmap_data = data + (uint16_t)font.count * 4;
×
268
        unicode -= font.h.ascii_offset;
×
269
        data += (unicode * 4);
×
270
        uint16_t offset = (pgm_read_byte(&data[0]) << 8) | pgm_read_byte(&data[1]);
×
271
        uint8_t glyph_bytes = pgm_read_byte(&data[2]);
×
272
        //        uint8_t width = pgm_read_byte(&data[3]);
273
        info->width = glyph_bytes; //(glyph_bytes + font.pages - 1)  / font.pages;
×
274
        info->height = font.h.height / 2;
×
275
        info->spacing = font.spacing;
×
276
        //        uint8_t index=0;
277
        info->glyph = bitmap_data;
×
278
        if ( offset != 0xFFFF )
×
279
        {
280
            info->glyph += offset;
×
281
        }
282
    }
283
}
284

285
void NanoFont::loadSquixFont(const uint8_t *progmemFont)
×
286
{
287
    m_fixedFont.h.type = SSD1306_SQUIX_FORMAT;
×
288
    m_fixedFont.h.width = pgm_read_byte(&progmemFont[0]);
×
289
    m_fixedFont.h.height = pgm_read_byte(&progmemFont[1]);
×
290
    m_fixedFont.h.ascii_offset = pgm_read_byte(&progmemFont[2]);
×
291
    m_fixedFont.count = pgm_read_byte(&progmemFont[3]);
×
292
    m_fixedFont.primary_table = progmemFont + 4;
×
293
    m_getCharBitmap = _ssd1306_squixFormatGetBitmap;
×
294
    m_fixedFont.pages = (m_fixedFont.h.height + 7) >> 3;
×
295
    m_fixedFont.glyph_size = m_fixedFont.pages * m_fixedFont.h.width;
×
296
    m_fixedFont.spacing = 1;
×
297
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
298
    m_fixedFont.secondary_table = NULL;
×
299
#endif
300
}
×
301

302
void NanoFont::getCharBitmap(uint16_t ch, SCharInfo *info)
153✔
303
{
304
    m_getCharBitmap(m_fixedFont, ch, info);
153✔
305
}
153✔
306

307
lcduint_t NanoFont::getTextSize(const char *text, lcduint_t *height)
×
308
{
309
    lcduint_t width = 0;
×
310
    while ( *text )
×
311
    {
312
        if ( *text == '\r' || *text == '\n' )
×
313
        {
314
            break;
315
        }
316
        uint16_t unicode = unicode16FromUtf8(*text);
×
317
        if ( unicode != SSD1306_MORE_CHARS_REQUIRED )
×
318
        {
319
            SCharInfo char_info;
×
320
            getCharBitmap(unicode, &char_info);
×
321
            width += char_info.width + char_info.spacing;
×
322
            if ( height )
×
323
                *height = char_info.height;
×
324
        }
325
        text++;
×
326
    }
327
    return width;
×
328
}
329

330
uint16_t NanoFont::unicode16FromUtf8(uint8_t ch)
153✔
331
{
332
#ifdef CONFIG_SSD1306_UNICODE_ENABLE
333
    if(ch & 0x80)
153✔
334
    {
335
        static uint16_t unicode = 0;
×
336
        static uint8_t rest = 0;
×
337
        if(ch & 0x40)
×
338
        {
339
            uint8_t mask = 0x1f;
×
340
            rest = 1;
×
341
            while( ((~mask) & ch) == ((~mask) & 0xff) ) mask >>= 1, ++rest;
×
342
            unicode = ch & mask;
×
343
            return SSD1306_MORE_CHARS_REQUIRED;
×
344
        }
345
        else
346
        {
347
            unicode = (unicode << 6) | (ch & 0x3f);
×
348
            return (--rest) ? SSD1306_MORE_CHARS_REQUIRED : unicode;
×
349
        }
350
    }
351
    return ch;
153✔
352
#else
353
    return ch;
354
#endif
355
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc