Krolyxon
Commit 3120783

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_8x8.c

493 lines · 11.8 KB · C

1/*
2
3 u8x8_8x8.c
4
5 font procedures, directly interfaces display procedures
6
7 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
8
9 Copyright (c) 2016, olikraus@gmail.com
10 All rights reserved.
11
12 Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14
15 * Redistributions of source code must retain the above copyright notice, this list
16 of conditions and the following disclaimer.
17
18 * Redistributions in binary form must reproduce the above copyright notice, this
19 list of conditions and the following disclaimer in the documentation and/or other
20 materials provided with the distribution.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
36*/
37
38#include "u8x8.h"
39
40#if defined(ESP8266)
41uint8_t u8x8_pgm_read_esp(const uint8_t * addr)
42{
43 uint32_t bytes;
44 bytes = *(uint32_t*)((uint32_t)addr & ~3);
45 return ((uint8_t*)&bytes)[(uint32_t)addr & 3];
46}
47#endif
48
49
50void u8x8_SetFont(u8x8_t *u8x8, const uint8_t *font_8x8)
51{
52 u8x8->font = font_8x8;
53}
54
55/*
56 Args:
57 u8x8: ptr to u8x8 structure
58 encoding: glyph for which the data is requested (must be between 0 and 255)
59 buf: pointer to 8 bytes
60*/
61void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf, uint8_t tile_offset) U8X8_NOINLINE;
62void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf, uint8_t tile_offset)
63{
64 uint8_t first, last, tiles, i;
65 uint16_t offset;
66 first = u8x8_pgm_read(u8x8->font+0);
67 last = u8x8_pgm_read(u8x8->font+1);
68 tiles = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
69 tiles *= u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
70
71 /* get the glyph bitmap from the font */
72 if ( first <= encoding && encoding <= last )
73 {
74 offset = encoding;
75 offset -= first;
76 offset *= tiles; /* new 2019 format */
77 offset += tile_offset; /* new 2019 format */
78 offset *= 8;
79 offset +=4; /* changed from 2 to 4, new 2019 format */
80 for( i = 0; i < 8; i++ )
81 {
82 buf[i] = u8x8_pgm_read(u8x8->font+offset);
83 offset++;
84 }
85 }
86 else
87 {
88 for( i = 0; i < 8; i++ )
89 {
90 buf[i] = 0;
91 }
92 }
93
94 /* invert the bitmap if required */
95 if ( u8x8->is_font_inverse_mode )
96 {
97 for( i = 0; i < 8; i++ )
98 {
99 buf[i] ^= 255;
100 }
101 }
102
103}
104
105void u8x8_DrawGlyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
106{
107 uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
108 uint8_t tv = u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
109 uint8_t xx, tile;
110 uint8_t buf[8];
111 th += x;
112 tv += y;
113 tile = 0;
114 do
115 {
116 xx = x;
117 do
118 {
119 u8x8_get_glyph_data(u8x8, encoding, buf, tile);
120 u8x8_DrawTile(u8x8, xx, y, 1, buf);
121 tile++;
122 xx++;
123 } while( xx < th );
124 y++;
125 } while( y < tv );
126}
127
128
129/*
130 Source: http://graphics.stanford.edu/~seander/bithacks.html
131 Section: Interleave bits by Binary Magic Numbers
132 Original codes is here:
133 static const unsigned int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF};
134 static const unsigned int S[] = {1, 2, 4, 8};
135
136 unsigned int x; // Interleave lower 16 bits of x and y, so the bits of x
137 unsigned int y; // are in the even positions and bits from y in the odd;
138 unsigned int z; // z gets the resulting 32-bit Morton Number.
139 // x and y must initially be less than 65536.
140
141 x = (x | (x << S[3])) & B[3];
142 x = (x | (x << S[2])) & B[2];
143 x = (x | (x << S[1])) & B[1];
144 x = (x | (x << S[0])) & B[0];
145
146 y = (y | (y << S[3])) & B[3];
147 y = (y | (y << S[2])) & B[2];
148 y = (y | (y << S[1])) & B[1];
149 y = (y | (y << S[0])) & B[0];
150
151 z = x | (y << 1);
152*/
153uint16_t u8x8_upscale_byte(uint8_t x)
154{
155 uint16_t y = x;
156 y |= (y << 4); // x = (x | (x << S[2])) & B[2];
157 y &= 0x0f0f;
158 y |= (y << 2); // x = (x | (x << S[1])) & B[1];
159 y &= 0x3333;
160 y |= (y << 1); // x = (x | (x << S[0])) & B[0];
161 y &= 0x5555;
162
163 y |= (y << 1); // z = x | (y << 1);
164 return y;
165}
166
167static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest) U8X8_NOINLINE;
168static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest)
169{
170 uint8_t i = 4;
171 do
172 {
173 *dest++ = *src;
174 *dest++ = *src++;
175 i--;
176 } while( i > 0 );
177}
178
179static void u8x8_draw_2x2_subglyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding, uint8_t tile)
180{
181 uint8_t i;
182 uint16_t t;
183 uint8_t buf[8];
184 uint8_t buf1[8];
185 uint8_t buf2[8];
186 u8x8_get_glyph_data(u8x8, encoding, buf, tile);
187 for( i = 0; i < 8; i ++ )
188 {
189 t = u8x8_upscale_byte(buf[i]);
190 buf1[i] = t >> 8;
191 buf2[i] = t & 255;
192 }
193 u8x8_upscale_buf(buf2, buf);
194 u8x8_DrawTile(u8x8, x, y, 1, buf);
195
196 u8x8_upscale_buf(buf2+4, buf);
197 u8x8_DrawTile(u8x8, x+1, y, 1, buf);
198
199 u8x8_upscale_buf(buf1, buf);
200 u8x8_DrawTile(u8x8, x, y+1, 1, buf);
201
202 u8x8_upscale_buf(buf1+4, buf);
203 u8x8_DrawTile(u8x8, x+1, y+1, 1, buf);
204}
205
206
207void u8x8_Draw2x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
208{
209 uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
210 uint8_t tv = u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
211 uint8_t xx, tile;
212 th *= 2;
213 th += x;
214 tv *= 2;
215 tv += y;
216 tile = 0;
217 do
218 {
219 xx = x;
220 do
221 {
222 u8x8_draw_2x2_subglyph(u8x8, xx, y, encoding, tile);
223 tile++;
224 xx+=2;
225 } while( xx < th );
226 y+=2;
227 } while( y < tv );
228}
229
230/* https://github.com/olikraus/u8g2/issues/474 */
231static void u8x8_draw_1x2_subglyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding, uint8_t tile)
232{
233 uint8_t i;
234 uint16_t t;
235 uint8_t buf[8];
236 uint8_t buf1[8];
237 uint8_t buf2[8];
238 u8x8_get_glyph_data(u8x8, encoding, buf, tile);
239 for( i = 0; i < 8; i ++ )
240 {
241 t = u8x8_upscale_byte(buf[i]);
242 buf1[i] = t >> 8;
243 buf2[i] = t & 255;
244 }
245 u8x8_DrawTile(u8x8, x, y, 1, buf2);
246 u8x8_DrawTile(u8x8, x, y+1, 1, buf1);
247}
248
249void u8x8_Draw1x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
250{
251 uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
252 uint8_t tv = u8x8_pgm_read(u8x8->font+3); /* new 2019 format */
253 uint8_t xx, tile;
254 th += x;
255 tv *= 2;
256 tv += y;
257 tile = 0;
258 do
259 {
260 xx = x;
261 do
262 {
263 u8x8_draw_1x2_subglyph(u8x8, xx, y, encoding, tile);
264 tile++;
265 xx++;
266 } while( xx < th );
267 y+=2;
268 } while( y < tv );
269}
270
271/*
272source: https://en.wikipedia.org/wiki/UTF-8
273Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
274 7 U+0000 U+007F 1 0xxxxxxx
27511 U+0080 U+07FF 2 110xxxxx 10xxxxxx
27616 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
27721 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
27826 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
27931 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
280
281
282*/
283
284/* reset the internal state machine */
285void u8x8_utf8_init(u8x8_t *u8x8)
286{
287 u8x8->utf8_state = 0; /* also reset during u8x8_SetupDefaults() */
288}
289
290uint16_t u8x8_ascii_next(U8X8_UNUSED u8x8_t *u8x8, uint8_t b)
291{
292 if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
293 return 0x0ffff; /* end of string detected*/
294 return b;
295}
296
297/*
298 pass a byte from an utf8 encoded string to the utf8 decoder state machine
299 returns
300 0x0fffe: no glyph, just continue
301 0x0ffff: end of string
302 anything else: The decoded encoding
303*/
304uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b)
305{
306 if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
307 return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
308 if ( u8x8->utf8_state == 0 )
309 {
310 if ( b >= 0xfc ) /* 6 byte sequence */
311 {
312 u8x8->utf8_state = 5;
313 b &= 1;
314 }
315 else if ( b >= 0xf8 )
316 {
317 u8x8->utf8_state = 4;
318 b &= 3;
319 }
320 else if ( b >= 0xf0 )
321 {
322 u8x8->utf8_state = 3;
323 b &= 7;
324 }
325 else if ( b >= 0xe0 )
326 {
327 u8x8->utf8_state = 2;
328 b &= 15;
329 }
330 else if ( b >= 0xc0 )
331 {
332 u8x8->utf8_state = 1;
333 b &= 0x01f;
334 }
335 else
336 {
337 /* do nothing, just use the value as encoding */
338 return b;
339 }
340 u8x8->encoding = b;
341 return 0x0fffe;
342 }
343 else
344 {
345 u8x8->utf8_state--;
346 /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
347 u8x8->encoding<<=6;
348 b &= 0x03f;
349 u8x8->encoding |= b;
350 if ( u8x8->utf8_state != 0 )
351 return 0x0fffe; /* nothing to do yet */
352 }
353 return u8x8->encoding;
354}
355
356
357
358static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
359static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
360{
361 uint16_t e;
362 uint8_t cnt = 0;
363 uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
364
365 u8x8_utf8_init(u8x8);
366 for(;;)
367 {
368 e = u8x8->next_cb(u8x8, (uint8_t)*s);
369 if ( e == 0x0ffff )
370 break;
371 s++;
372 if ( e != 0x0fffe )
373 {
374 u8x8_DrawGlyph(u8x8, x, y, e);
375 x+=th;
376 cnt++;
377 }
378 }
379 return cnt;
380}
381
382
383uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
384{
385 u8x8->next_cb = u8x8_ascii_next;
386 return u8x8_draw_string(u8x8, x, y, s);
387}
388
389uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
390{
391 u8x8->next_cb = u8x8_utf8_next;
392 return u8x8_draw_string(u8x8, x, y, s);
393}
394
395
396
397static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
398static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
399{
400 uint16_t e;
401 uint8_t cnt = 0;
402 uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
403
404 th <<= 1;
405
406 u8x8_utf8_init(u8x8);
407 for(;;)
408 {
409 e = u8x8->next_cb(u8x8, (uint8_t)*s);
410 if ( e == 0x0ffff )
411 break;
412 s++;
413 if ( e != 0x0fffe )
414 {
415 u8x8_Draw2x2Glyph(u8x8, x, y, e);
416 x+=th;
417 cnt++;
418 }
419 }
420 return cnt;
421}
422
423
424uint8_t u8x8_Draw2x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
425{
426 u8x8->next_cb = u8x8_ascii_next;
427 return u8x8_draw_2x2_string(u8x8, x, y, s);
428}
429
430uint8_t u8x8_Draw2x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
431{
432 u8x8->next_cb = u8x8_utf8_next;
433 return u8x8_draw_2x2_string(u8x8, x, y, s);
434}
435
436
437
438static uint8_t u8x8_draw_1x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
439static uint8_t u8x8_draw_1x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
440{
441 uint16_t e;
442 uint8_t cnt = 0;
443 uint8_t th = u8x8_pgm_read(u8x8->font+2); /* new 2019 format */
444 u8x8_utf8_init(u8x8);
445 for(;;)
446 {
447 e = u8x8->next_cb(u8x8, (uint8_t)*s);
448 if ( e == 0x0ffff )
449 break;
450 s++;
451 if ( e != 0x0fffe )
452 {
453 u8x8_Draw1x2Glyph(u8x8, x, y, e);
454 x+=th;
455 cnt++;
456 }
457 }
458 return cnt;
459}
460
461
462uint8_t u8x8_Draw1x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
463{
464 u8x8->next_cb = u8x8_ascii_next;
465 return u8x8_draw_1x2_string(u8x8, x, y, s);
466}
467
468uint8_t u8x8_Draw1x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
469{
470 u8x8->next_cb = u8x8_utf8_next;
471 return u8x8_draw_1x2_string(u8x8, x, y, s);
472}
473
474
475
476uint8_t u8x8_GetUTF8Len(u8x8_t *u8x8, const char *s)
477{
478 uint16_t e;
479 uint8_t cnt = 0;
480 u8x8_utf8_init(u8x8);
481 for(;;)
482 {
483 e = u8x8_utf8_next(u8x8, *s);
484 if ( e == 0x0ffff )
485 break;
486 s++;
487 if ( e != 0x0fffe )
488 cnt++;
489 }
490 return cnt;
491}
492
493