u8g2_font.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. /*
  2. u8g2_font.c
  3. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
  4. Copyright (c) 2016, olikraus@gmail.com
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice, this list
  9. of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice, this
  11. list of conditions and the following disclaimer in the documentation and/or other
  12. materials provided with the distribution.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  14. CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  15. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  16. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  25. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "u8g2.h"
  28. /* size of the font data structure, there is no struct or class... */
  29. /* this is the size for the new font format */
  30. #define U8G2_FONT_DATA_STRUCT_SIZE 23
  31. /*
  32. font data:
  33. offset bytes description
  34. 0 1 glyph_cnt number of glyphs
  35. 1 1 bbx_mode 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
  36. 2 1 bits_per_0 glyph rle parameter
  37. 3 1 bits_per_1 glyph rle parameter
  38. 4 1 bits_per_char_width glyph rle parameter
  39. 5 1 bits_per_char_height glyph rle parameter
  40. 6 1 bits_per_char_x glyph rle parameter
  41. 7 1 bits_per_char_y glyph rle parameter
  42. 8 1 bits_per_delta_x glyph rle parameter
  43. 9 1 max_char_width
  44. 10 1 max_char_height
  45. 11 1 x offset
  46. 12 1 y offset (descent)
  47. 13 1 ascent (capital A)
  48. 14 1 descent (lower g)
  49. 15 1 ascent '('
  50. 16 1 descent ')'
  51. 17 1 start pos 'A' high byte
  52. 18 1 start pos 'A' low byte
  53. 19 1 start pos 'a' high byte
  54. 20 1 start pos 'a' low byte
  55. 21 1 start pos unicode high byte
  56. 22 1 start pos unicode low byte
  57. Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
  58. Font build mode 0:
  59. - "t"
  60. - Ref height mode: U8G2_FONT_HEIGHT_MODE_TEXT, U8G2_FONT_HEIGHT_MODE_XTEXT or U8G2_FONT_HEIGHT_MODE_ALL
  61. - use in transparent mode only (does not look good in solid mode)
  62. - most compact format
  63. - different font heights possible
  64. Font build mode 1:
  65. - "h"
  66. - Ref height mode: U8G2_FONT_HEIGHT_MODE_ALL
  67. - transparent or solid mode
  68. - The height of the glyphs depend on the largest glyph in the font. This means font height depends on postfix "r", "f" and "n".
  69. */
  70. /* use case: What is the width and the height of the minimal box into which string s fints? */
  71. void u8g2_font_GetStrSize(const void *font, const char *s, u8g2_uint_t *width, u8g2_uint_t *height);
  72. void u8g2_font_GetStrSizeP(const void *font, const char *s, u8g2_uint_t *width, u8g2_uint_t *height);
  73. /* use case: lower left edge of a minimal box is known, what is the correct x, y position for the string draw procedure */
  74. void u8g2_font_AdjustXYToDraw(const void *font, const char *s, u8g2_uint_t *x, u8g2_uint_t *y);
  75. void u8g2_font_AdjustXYToDrawP(const void *font, const char *s, u8g2_uint_t *x, u8g2_uint_t *y);
  76. /* use case: Baseline origin known, return minimal box */
  77. void u8g2_font_GetStrMinBox(u8g2_t *u8g2, const void *font, const char *s, u8g2_uint_t *x, u8g2_uint_t *y, u8g2_uint_t *width, u8g2_uint_t *height);
  78. /* procedures */
  79. /*========================================================================*/
  80. /* low level byte and word access */
  81. /* removed NOINLINE, because it leads to smaller code, might also be faster */
  82. //static uint8_t u8g2_font_get_byte(const uint8_t *font, uint8_t offset) U8G2_NOINLINE;
  83. static uint8_t u8g2_font_get_byte(const uint8_t *font, uint8_t offset)
  84. {
  85. font += offset;
  86. return u8x8_pgm_read( font );
  87. }
  88. static uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset) U8G2_NOINLINE;
  89. static uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset)
  90. {
  91. uint16_t pos;
  92. font += offset;
  93. pos = u8x8_pgm_read( font );
  94. font++;
  95. pos <<= 8;
  96. pos += u8x8_pgm_read( font);
  97. return pos;
  98. }
  99. /*========================================================================*/
  100. /* new font format */
  101. void u8g2_read_font_info(u8g2_font_info_t *font_info, const uint8_t *font)
  102. {
  103. /* offset 0 */
  104. font_info->glyph_cnt = u8g2_font_get_byte(font, 0);
  105. font_info->bbx_mode = u8g2_font_get_byte(font, 1);
  106. font_info->bits_per_0 = u8g2_font_get_byte(font, 2);
  107. font_info->bits_per_1 = u8g2_font_get_byte(font, 3);
  108. /* offset 4 */
  109. font_info->bits_per_char_width = u8g2_font_get_byte(font, 4);
  110. font_info->bits_per_char_height = u8g2_font_get_byte(font, 5);
  111. font_info->bits_per_char_x = u8g2_font_get_byte(font, 6);
  112. font_info->bits_per_char_y = u8g2_font_get_byte(font, 7);
  113. font_info->bits_per_delta_x = u8g2_font_get_byte(font, 8);
  114. /* offset 9 */
  115. font_info->max_char_width = u8g2_font_get_byte(font, 9);
  116. font_info->max_char_height = u8g2_font_get_byte(font, 10);
  117. font_info->x_offset = u8g2_font_get_byte(font, 11);
  118. font_info->y_offset = u8g2_font_get_byte(font, 12);
  119. /* offset 13 */
  120. font_info->ascent_A = u8g2_font_get_byte(font, 13);
  121. font_info->descent_g = u8g2_font_get_byte(font, 14);
  122. font_info->ascent_para = u8g2_font_get_byte(font, 15);
  123. font_info->descent_para = u8g2_font_get_byte(font, 16);
  124. /* offset 17 */
  125. font_info->start_pos_upper_A = u8g2_font_get_word(font, 17);
  126. font_info->start_pos_lower_a = u8g2_font_get_word(font, 19);
  127. /* offset 21 */
  128. #ifdef U8G2_WITH_UNICODE
  129. font_info->start_pos_unicode = u8g2_font_get_word(font, 21);
  130. #endif
  131. }
  132. /* calculate the overall length of the font, only used to create the picture for the google wiki */
  133. size_t u8g2_GetFontSize(const uint8_t *font_arg)
  134. {
  135. uint16_t e;
  136. const uint8_t *font = font_arg;
  137. font += U8G2_FONT_DATA_STRUCT_SIZE;
  138. for(;;)
  139. {
  140. if ( u8x8_pgm_read( font + 1 ) == 0 )
  141. break;
  142. font += u8x8_pgm_read( font + 1 );
  143. }
  144. /* continue with unicode section */
  145. font += 2;
  146. /* skip unicode lookup table */
  147. font += u8g2_font_get_word(font, 0);
  148. for(;;)
  149. {
  150. e = u8x8_pgm_read( font );
  151. e <<= 8;
  152. e |= u8x8_pgm_read( font + 1 );
  153. if ( e == 0 )
  154. break;
  155. font += u8x8_pgm_read( font + 2 );
  156. }
  157. return (font - font_arg) + 2;
  158. }
  159. /*========================================================================*/
  160. /* u8g2 interface, font access */
  161. uint8_t u8g2_GetFontBBXWidth(u8g2_t *u8g2)
  162. {
  163. return u8g2->font_info.max_char_width; /* new font info structure */
  164. }
  165. uint8_t u8g2_GetFontBBXHeight(u8g2_t *u8g2)
  166. {
  167. return u8g2->font_info.max_char_height; /* new font info structure */
  168. }
  169. int8_t u8g2_GetFontBBXOffX(u8g2_t *u8g2) U8G2_NOINLINE;
  170. int8_t u8g2_GetFontBBXOffX(u8g2_t *u8g2)
  171. {
  172. return u8g2->font_info.x_offset; /* new font info structure */
  173. }
  174. int8_t u8g2_GetFontBBXOffY(u8g2_t *u8g2) U8G2_NOINLINE;
  175. int8_t u8g2_GetFontBBXOffY(u8g2_t *u8g2)
  176. {
  177. return u8g2->font_info.y_offset; /* new font info structure */
  178. }
  179. uint8_t u8g2_GetFontCapitalAHeight(u8g2_t *u8g2) U8G2_NOINLINE;
  180. uint8_t u8g2_GetFontCapitalAHeight(u8g2_t *u8g2)
  181. {
  182. return u8g2->font_info.ascent_A; /* new font info structure */
  183. }
  184. /*========================================================================*/
  185. /* glyph handling */
  186. /* optimized */
  187. uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt)
  188. {
  189. uint8_t val;
  190. uint8_t bit_pos = f->decode_bit_pos;
  191. uint8_t bit_pos_plus_cnt;
  192. //val = *(f->decode_ptr);
  193. val = u8x8_pgm_read( f->decode_ptr );
  194. val >>= bit_pos;
  195. bit_pos_plus_cnt = bit_pos;
  196. bit_pos_plus_cnt += cnt;
  197. if ( bit_pos_plus_cnt >= 8 )
  198. {
  199. uint8_t s = 8;
  200. s -= bit_pos;
  201. f->decode_ptr++;
  202. //val |= *(f->decode_ptr) << (8-bit_pos);
  203. val |= u8x8_pgm_read( f->decode_ptr ) << (s);
  204. //bit_pos -= 8;
  205. bit_pos_plus_cnt -= 8;
  206. }
  207. val &= (1U<<cnt)-1;
  208. //bit_pos += cnt;
  209. f->decode_bit_pos = bit_pos_plus_cnt;
  210. return val;
  211. }
  212. /*
  213. 2 bit --> cnt = 2
  214. -2,-1,0. 1
  215. 3 bit --> cnt = 3
  216. -2,-1,0. 1
  217. -4,-3,-2,-1,0,1,2,3
  218. if ( x < 0 )
  219. r = bits(x-1)+1;
  220. else
  221. r = bits(x)+1;
  222. */
  223. /* optimized */
  224. int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cnt)
  225. {
  226. int8_t v, d;
  227. v = (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt);
  228. d = 1;
  229. cnt--;
  230. d <<= cnt;
  231. v -= d;
  232. return v;
  233. //return (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt) - ((1<<cnt)>>1);
  234. }
  235. #ifdef U8G2_WITH_FONT_ROTATION
  236. u8g2_uint_t u8g2_add_vector_y(u8g2_uint_t dy, int8_t x, int8_t y, uint8_t dir)
  237. {
  238. switch(dir)
  239. {
  240. case 0:
  241. dy += y;
  242. break;
  243. case 1:
  244. dy += x;
  245. break;
  246. case 2:
  247. dy -= y;
  248. break;
  249. default:
  250. dy -= x;
  251. break;
  252. }
  253. return dy;
  254. }
  255. u8g2_uint_t u8g2_add_vector_x(u8g2_uint_t dx, int8_t x, int8_t y, uint8_t dir)
  256. {
  257. switch(dir)
  258. {
  259. case 0:
  260. dx += x;
  261. break;
  262. case 1:
  263. dx -= y;
  264. break;
  265. case 2:
  266. dx -= x;
  267. break;
  268. default:
  269. dx += y;
  270. break;
  271. }
  272. return dx;
  273. }
  274. /*
  275. // does not make sense, 50 bytes more required on avr
  276. void u8g2_add_vector(u8g2_uint_t *xp, u8g2_uint_t *yp, int8_t x, int8_t y, uint8_t dir)
  277. {
  278. u8g2_uint_t x_ = *xp;
  279. u8g2_uint_t y_ = *yp;
  280. switch(dir)
  281. {
  282. case 0:
  283. y_ += y;
  284. x_ += x;
  285. break;
  286. case 1:
  287. y_ += x;
  288. x_ -= y;
  289. break;
  290. case 2:
  291. y_ -= y;
  292. x_ -= x;
  293. break;
  294. default:
  295. y_ -= x;
  296. x_ += y;
  297. break;
  298. }
  299. *xp = x_;
  300. *yp = y_;
  301. }
  302. */
  303. #endif
  304. /*
  305. Description:
  306. Draw a run-length area of the glyph. "len" can have any size and the line
  307. length has to be wrapped at the glyph border.
  308. Args:
  309. len: Length of the line
  310. is_foreground foreground/background?
  311. u8g2->font_decode.target_x X position
  312. u8g2->font_decode.target_y Y position
  313. u8g2->font_decode.is_transparent Transparent mode
  314. Return:
  315. -
  316. Calls:
  317. u8g2_Draw90Line()
  318. Called by:
  319. u8g2_font_decode_glyph()
  320. */
  321. /* optimized */
  322. void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground)
  323. {
  324. uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
  325. uint8_t rem; /* remaining pixel to the right edge of the glyph */
  326. uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
  327. /* current is either equal to cnt or equal to rem */
  328. /* local coordinates of the glyph */
  329. uint8_t lx,ly;
  330. /* target position on the screen */
  331. u8g2_uint_t x, y;
  332. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  333. cnt = len;
  334. /* get the local position */
  335. lx = decode->x;
  336. ly = decode->y;
  337. for(;;)
  338. {
  339. /* calculate the number of pixel to the right edge of the glyph */
  340. rem = decode->glyph_width;
  341. rem -= lx;
  342. /* calculate how many pixel to draw. This is either to the right edge */
  343. /* or lesser, if not enough pixel are left */
  344. current = rem;
  345. if ( cnt < rem )
  346. current = cnt;
  347. /* now draw the line, but apply the rotation around the glyph target position */
  348. //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
  349. /* get target position */
  350. x = decode->target_x;
  351. y = decode->target_y;
  352. /* apply rotation */
  353. #ifdef U8G2_WITH_FONT_ROTATION
  354. x = u8g2_add_vector_x(x, lx, ly, decode->dir);
  355. y = u8g2_add_vector_y(y, lx, ly, decode->dir);
  356. //u8g2_add_vector(&x, &y, lx, ly, decode->dir);
  357. #else
  358. x += lx;
  359. y += ly;
  360. #endif
  361. /* draw foreground and background (if required) */
  362. if ( is_foreground )
  363. {
  364. u8g2->draw_color = decode->fg_color; /* draw_color will be restored later */
  365. u8g2_DrawHVLine(u8g2,
  366. x,
  367. y,
  368. current,
  369. #ifdef U8G2_WITH_FONT_ROTATION
  370. /* dir */ decode->dir
  371. #else
  372. 0
  373. #endif
  374. );
  375. }
  376. else if ( decode->is_transparent == 0 )
  377. {
  378. u8g2->draw_color = decode->bg_color; /* draw_color will be restored later */
  379. u8g2_DrawHVLine(u8g2,
  380. x,
  381. y,
  382. current,
  383. #ifdef U8G2_WITH_FONT_ROTATION
  384. /* dir */ decode->dir
  385. #else
  386. 0
  387. #endif
  388. );
  389. }
  390. /* check, whether the end of the run length code has been reached */
  391. if ( cnt < rem )
  392. break;
  393. cnt -= rem;
  394. lx = 0;
  395. ly++;
  396. }
  397. lx += cnt;
  398. decode->x = lx;
  399. decode->y = ly;
  400. }
  401. static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
  402. {
  403. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  404. decode->decode_ptr = glyph_data;
  405. decode->decode_bit_pos = 0;
  406. /* 8 Nov 2015, this is already done in the glyph data search procedure */
  407. /*
  408. decode->decode_ptr += 1;
  409. decode->decode_ptr += 1;
  410. */
  411. decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
  412. decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode,u8g2->font_info.bits_per_char_height);
  413. decode->fg_color = u8g2->draw_color;
  414. decode->bg_color = (decode->fg_color == 0 ? 1 : 0);
  415. }
  416. /*
  417. Description:
  418. Decode and draw a glyph.
  419. Args:
  420. glyph_data: Pointer to the compressed glyph data of the font
  421. u8g2->font_decode.target_x X position
  422. u8g2->font_decode.target_y Y position
  423. u8g2->font_decode.is_transparent Transparent mode
  424. Return:
  425. Width (delta x advance) of the glyph.
  426. Calls:
  427. u8g2_font_decode_len()
  428. */
  429. /* optimized */
  430. int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data)
  431. {
  432. uint8_t a, b;
  433. int8_t x, y;
  434. int8_t d;
  435. int8_t h;
  436. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  437. u8g2_font_setup_decode(u8g2, glyph_data);
  438. h = u8g2->font_decode.glyph_height;
  439. x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
  440. y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
  441. d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
  442. if ( decode->glyph_width > 0 )
  443. {
  444. #ifdef U8G2_WITH_FONT_ROTATION
  445. decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
  446. decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
  447. //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
  448. #else
  449. decode->target_x += x;
  450. decode->target_y -= h+y;
  451. #endif
  452. //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
  453. #ifdef U8G2_WITH_INTERSECTION
  454. {
  455. u8g2_uint_t x0, x1, y0, y1;
  456. x0 = decode->target_x;
  457. y0 = decode->target_y;
  458. x1 = x0;
  459. y1 = y0;
  460. #ifdef U8G2_WITH_FONT_ROTATION
  461. switch(decode->dir)
  462. {
  463. case 0:
  464. x1 += decode->glyph_width;
  465. y1 += h;
  466. break;
  467. case 1:
  468. x0 -= h;
  469. x0++; /* shift down, because of assymetric boundaries for the interseciton test */
  470. x1++;
  471. y1 += decode->glyph_width;
  472. break;
  473. case 2:
  474. x0 -= decode->glyph_width;
  475. x0++; /* shift down, because of assymetric boundaries for the interseciton test */
  476. x1++;
  477. y0 -= h;
  478. y0++; /* shift down, because of assymetric boundaries for the interseciton test */
  479. y1++;
  480. break;
  481. case 3:
  482. x1 += h;
  483. y0 -= decode->glyph_width;
  484. y0++; /* shift down, because of assymetric boundaries for the interseciton test */
  485. y1++;
  486. break;
  487. }
  488. #else /* U8G2_WITH_FONT_ROTATION */
  489. x1 += decode->glyph_width;
  490. y1 += h;
  491. #endif
  492. if ( u8g2_IsIntersection(u8g2, x0, y0, x1, y1) == 0 )
  493. return d;
  494. }
  495. #endif /* U8G2_WITH_INTERSECTION */
  496. /* reset local x/y position */
  497. decode->x = 0;
  498. decode->y = 0;
  499. /* decode glyph */
  500. for(;;)
  501. {
  502. a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
  503. b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
  504. do
  505. {
  506. u8g2_font_decode_len(u8g2, a, 0);
  507. u8g2_font_decode_len(u8g2, b, 1);
  508. } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
  509. if ( decode->y >= h )
  510. break;
  511. }
  512. /* restore the u8g2 draw color, because this is modified by the decode algo */
  513. u8g2->draw_color = decode->fg_color;
  514. }
  515. return d;
  516. }
  517. /*
  518. Description:
  519. Find the starting point of the glyph data.
  520. Args:
  521. encoding: Encoding (ASCII or Unicode) of the glyph
  522. Return:
  523. Address of the glyph data or NULL, if the encoding is not avialable in the font.
  524. */
  525. const uint8_t *u8g2_font_get_glyph_data(u8g2_t *u8g2, uint16_t encoding)
  526. {
  527. const uint8_t *font = u8g2->font;
  528. font += U8G2_FONT_DATA_STRUCT_SIZE;
  529. if ( encoding <= 255 )
  530. {
  531. if ( encoding >= 'a' )
  532. {
  533. font += u8g2->font_info.start_pos_lower_a;
  534. }
  535. else if ( encoding >= 'A' )
  536. {
  537. font += u8g2->font_info.start_pos_upper_A;
  538. }
  539. for(;;)
  540. {
  541. if ( u8x8_pgm_read( font + 1 ) == 0 )
  542. break;
  543. if ( u8x8_pgm_read( font ) == encoding )
  544. {
  545. return font+2; /* skip encoding and glyph size */
  546. }
  547. font += u8x8_pgm_read( font + 1 );
  548. }
  549. }
  550. #ifdef U8G2_WITH_UNICODE
  551. else
  552. {
  553. uint16_t e;
  554. const uint8_t *unicode_lookup_table;
  555. // removed, there is now the new index table
  556. //#ifdef __unix__
  557. // if ( u8g2->last_font_data != NULL && encoding >= u8g2->last_unicode )
  558. // {
  559. // font = u8g2->last_font_data;
  560. // }
  561. // else
  562. //#endif
  563. font += u8g2->font_info.start_pos_unicode;
  564. unicode_lookup_table = font;
  565. /* issue 596: search for the glyph start in the unicode lookup table */
  566. do
  567. {
  568. font += u8g2_font_get_word(unicode_lookup_table, 0);
  569. e = u8g2_font_get_word(unicode_lookup_table, 2);
  570. unicode_lookup_table+=4;
  571. } while( e < encoding );
  572. for(;;)
  573. {
  574. e = u8x8_pgm_read( font );
  575. e <<= 8;
  576. e |= u8x8_pgm_read( font + 1 );
  577. // removed, there is now the new index table
  578. //#ifdef __unix__
  579. // if ( encoding < e )
  580. // break;
  581. //#endif
  582. if ( e == 0 )
  583. break;
  584. if ( e == encoding )
  585. {
  586. // removed, there is now the new index table
  587. //#ifdef __unix__
  588. // u8g2->last_font_data = font;
  589. // u8g2->last_unicode = encoding;
  590. //#endif
  591. return font+3; /* skip encoding and glyph size */
  592. }
  593. font += u8x8_pgm_read( font + 2 );
  594. }
  595. }
  596. #endif
  597. return NULL;
  598. }
  599. static u8g2_uint_t u8g2_font_draw_glyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
  600. {
  601. u8g2_uint_t dx = 0;
  602. u8g2->font_decode.target_x = x;
  603. u8g2->font_decode.target_y = y;
  604. //u8g2->font_decode.is_transparent = is_transparent; this is already set
  605. //u8g2->font_decode.dir = dir;
  606. const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
  607. if ( glyph_data != NULL )
  608. {
  609. dx = u8g2_font_decode_glyph(u8g2, glyph_data);
  610. }
  611. return dx;
  612. }
  613. uint8_t u8g2_IsGlyph(u8g2_t *u8g2, uint16_t requested_encoding)
  614. {
  615. /* updated to new code */
  616. if ( u8g2_font_get_glyph_data(u8g2, requested_encoding) != NULL )
  617. return 1;
  618. return 0;
  619. }
  620. /* side effect: updates u8g2->font_decode and u8g2->glyph_x_offset */
  621. int8_t u8g2_GetGlyphWidth(u8g2_t *u8g2, uint16_t requested_encoding)
  622. {
  623. const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, requested_encoding);
  624. if ( glyph_data == NULL )
  625. return 0;
  626. u8g2_font_setup_decode(u8g2, glyph_data);
  627. u8g2->glyph_x_offset = u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_x);
  628. u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_y);
  629. /* glyph width is here: u8g2->font_decode.glyph_width */
  630. return u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_delta_x);
  631. }
  632. /*
  633. set one of:
  634. U8G2_FONT_MODE_TRANSPARENT
  635. U8G2_FONT_MODE_SOLID
  636. U8G2_FONT_MODE_NONE
  637. This has been changed for the new font procedures
  638. */
  639. void u8g2_SetFontMode(u8g2_t *u8g2, uint8_t is_transparent)
  640. {
  641. u8g2->font_decode.is_transparent = is_transparent; // new font procedures
  642. }
  643. u8g2_uint_t u8g2_DrawGlyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
  644. {
  645. #ifdef U8G2_WITH_FONT_ROTATION
  646. switch(u8g2->font_decode.dir)
  647. {
  648. case 0:
  649. y += u8g2->font_calc_vref(u8g2);
  650. break;
  651. case 1:
  652. x -= u8g2->font_calc_vref(u8g2);
  653. break;
  654. case 2:
  655. y -= u8g2->font_calc_vref(u8g2);
  656. break;
  657. case 3:
  658. x += u8g2->font_calc_vref(u8g2);
  659. break;
  660. }
  661. #else
  662. y += u8g2->font_calc_vref(u8g2);
  663. #endif
  664. return u8g2_font_draw_glyph(u8g2, x, y, encoding);
  665. }
  666. static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str) U8G2_NOINLINE;
  667. static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
  668. {
  669. uint16_t e;
  670. u8g2_uint_t delta, sum;
  671. u8x8_utf8_init(u8g2_GetU8x8(u8g2));
  672. sum = 0;
  673. for(;;)
  674. {
  675. e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  676. if ( e == 0x0ffff )
  677. break;
  678. str++;
  679. if ( e != 0x0fffe )
  680. {
  681. delta = u8g2_DrawGlyph(u8g2, x, y, e);
  682. #ifdef U8G2_WITH_FONT_ROTATION
  683. switch(u8g2->font_decode.dir)
  684. {
  685. case 0:
  686. x += delta;
  687. break;
  688. case 1:
  689. y += delta;
  690. break;
  691. case 2:
  692. x -= delta;
  693. break;
  694. case 3:
  695. y -= delta;
  696. break;
  697. }
  698. /*
  699. // requires 10 bytes more on avr
  700. x = u8g2_add_vector_x(x, delta, 0, u8g2->font_decode.dir);
  701. y = u8g2_add_vector_y(y, delta, 0, u8g2->font_decode.dir);
  702. */
  703. #else
  704. x += delta;
  705. #endif
  706. sum += delta;
  707. }
  708. }
  709. return sum;
  710. }
  711. u8g2_uint_t u8g2_DrawStr(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
  712. {
  713. u8g2->u8x8.next_cb = u8x8_ascii_next;
  714. return u8g2_draw_string(u8g2, x, y, str);
  715. }
  716. /*
  717. source: https://en.wikipedia.org/wiki/UTF-8
  718. Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
  719. 7 U+0000 U+007F 1 0xxxxxxx
  720. 11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
  721. 16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
  722. 21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  723. 26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  724. 31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  725. */
  726. u8g2_uint_t u8g2_DrawUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
  727. {
  728. u8g2->u8x8.next_cb = u8x8_utf8_next;
  729. return u8g2_draw_string(u8g2, x, y, str);
  730. }
  731. u8g2_uint_t u8g2_DrawExtendedUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, u8g2_kerning_t *kerning, const char *str)
  732. {
  733. u8g2->u8x8.next_cb = u8x8_utf8_next;
  734. uint16_t e_prev = 0x0ffff;
  735. uint16_t e;
  736. u8g2_uint_t delta, sum, k;
  737. u8x8_utf8_init(u8g2_GetU8x8(u8g2));
  738. sum = 0;
  739. for(;;)
  740. {
  741. e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  742. if ( e == 0x0ffff )
  743. break;
  744. str++;
  745. if ( e != 0x0fffe )
  746. {
  747. delta = u8g2_GetGlyphWidth(u8g2, e);
  748. if ( to_left )
  749. {
  750. k = u8g2_GetKerning(u8g2, kerning, e, e_prev);
  751. delta -= k;
  752. x -= delta;
  753. }
  754. else
  755. {
  756. k = u8g2_GetKerning(u8g2, kerning, e_prev, e);
  757. delta -= k;
  758. }
  759. e_prev = e;
  760. u8g2_DrawGlyph(u8g2, x, y, e);
  761. if ( to_left )
  762. {
  763. }
  764. else
  765. {
  766. x += delta;
  767. x -= k;
  768. }
  769. sum += delta;
  770. }
  771. }
  772. return sum;
  773. }
  774. u8g2_uint_t u8g2_DrawExtUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, const uint16_t *kerning_table, const char *str)
  775. {
  776. u8g2->u8x8.next_cb = u8x8_utf8_next;
  777. uint16_t e_prev = 0x0ffff;
  778. uint16_t e;
  779. u8g2_uint_t delta, sum, k;
  780. u8x8_utf8_init(u8g2_GetU8x8(u8g2));
  781. sum = 0;
  782. for(;;)
  783. {
  784. e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  785. if ( e == 0x0ffff )
  786. break;
  787. str++;
  788. if ( e != 0x0fffe )
  789. {
  790. delta = u8g2_GetGlyphWidth(u8g2, e);
  791. if ( to_left )
  792. {
  793. k = u8g2_GetKerningByTable(u8g2, kerning_table, e, e_prev);
  794. delta -= k;
  795. x -= delta;
  796. }
  797. else
  798. {
  799. k = u8g2_GetKerningByTable(u8g2, kerning_table, e_prev, e);
  800. delta -= k;
  801. }
  802. e_prev = e;
  803. if ( to_left )
  804. {
  805. }
  806. else
  807. {
  808. x += delta;
  809. }
  810. u8g2_DrawGlyph(u8g2, x, y, e);
  811. if ( to_left )
  812. {
  813. }
  814. else
  815. {
  816. //x += delta;
  817. //x -= k;
  818. }
  819. sum += delta;
  820. }
  821. }
  822. return sum;
  823. }
  824. /*===============================================*/
  825. /* set ascent/descent for reference point calculation */
  826. void u8g2_UpdateRefHeight(u8g2_t *u8g2)
  827. {
  828. if ( u8g2->font == NULL )
  829. return;
  830. u8g2->font_ref_ascent = u8g2->font_info.ascent_A;
  831. u8g2->font_ref_descent = u8g2->font_info.descent_g;
  832. if ( u8g2->font_height_mode == U8G2_FONT_HEIGHT_MODE_TEXT )
  833. {
  834. }
  835. else if ( u8g2->font_height_mode == U8G2_FONT_HEIGHT_MODE_XTEXT )
  836. {
  837. if ( u8g2->font_ref_ascent < u8g2->font_info.ascent_para )
  838. u8g2->font_ref_ascent = u8g2->font_info.ascent_para;
  839. if ( u8g2->font_ref_descent > u8g2->font_info.descent_para )
  840. u8g2->font_ref_descent = u8g2->font_info.descent_para;
  841. }
  842. else
  843. {
  844. if ( u8g2->font_ref_ascent < u8g2->font_info.max_char_height+u8g2->font_info.y_offset )
  845. u8g2->font_ref_ascent = u8g2->font_info.max_char_height+u8g2->font_info.y_offset;
  846. if ( u8g2->font_ref_descent > u8g2->font_info.y_offset )
  847. u8g2->font_ref_descent = u8g2->font_info.y_offset;
  848. }
  849. }
  850. void u8g2_SetFontRefHeightText(u8g2_t *u8g2)
  851. {
  852. u8g2->font_height_mode = U8G2_FONT_HEIGHT_MODE_TEXT;
  853. u8g2_UpdateRefHeight(u8g2);
  854. }
  855. void u8g2_SetFontRefHeightExtendedText(u8g2_t *u8g2)
  856. {
  857. u8g2->font_height_mode = U8G2_FONT_HEIGHT_MODE_XTEXT;
  858. u8g2_UpdateRefHeight(u8g2);
  859. }
  860. void u8g2_SetFontRefHeightAll(u8g2_t *u8g2)
  861. {
  862. u8g2->font_height_mode = U8G2_FONT_HEIGHT_MODE_ALL;
  863. u8g2_UpdateRefHeight(u8g2);
  864. }
  865. /*===============================================*/
  866. /* callback procedures to correct the y position */
  867. u8g2_uint_t u8g2_font_calc_vref_font(U8X8_UNUSED u8g2_t *u8g2)
  868. {
  869. return 0;
  870. }
  871. void u8g2_SetFontPosBaseline(u8g2_t *u8g2)
  872. {
  873. u8g2->font_calc_vref = u8g2_font_calc_vref_font;
  874. }
  875. u8g2_uint_t u8g2_font_calc_vref_bottom(u8g2_t *u8g2)
  876. {
  877. return (u8g2_uint_t)(u8g2->font_ref_descent);
  878. }
  879. void u8g2_SetFontPosBottom(u8g2_t *u8g2)
  880. {
  881. u8g2->font_calc_vref = u8g2_font_calc_vref_bottom;
  882. }
  883. u8g2_uint_t u8g2_font_calc_vref_top(u8g2_t *u8g2)
  884. {
  885. u8g2_uint_t tmp;
  886. /* reference pos is one pixel above the upper edge of the reference glyph */
  887. tmp = (u8g2_uint_t)(u8g2->font_ref_ascent);
  888. tmp++;
  889. return tmp;
  890. }
  891. void u8g2_SetFontPosTop(u8g2_t *u8g2)
  892. {
  893. u8g2->font_calc_vref = u8g2_font_calc_vref_top;
  894. }
  895. u8g2_uint_t u8g2_font_calc_vref_center(u8g2_t *u8g2)
  896. {
  897. int8_t tmp;
  898. tmp = u8g2->font_ref_ascent;
  899. tmp -= u8g2->font_ref_descent;
  900. tmp /= 2;
  901. tmp += u8g2->font_ref_descent;
  902. return tmp;
  903. }
  904. void u8g2_SetFontPosCenter(u8g2_t *u8g2)
  905. {
  906. u8g2->font_calc_vref = u8g2_font_calc_vref_center;
  907. }
  908. /*===============================================*/
  909. void u8g2_SetFont(u8g2_t *u8g2, const uint8_t *font)
  910. {
  911. if ( u8g2->font != font )
  912. {
  913. //#ifdef __unix__
  914. // u8g2->last_font_data = NULL;
  915. // u8g2->last_unicode = 0x0ffff;
  916. //#endif
  917. u8g2->font = font;
  918. u8g2_read_font_info(&(u8g2->font_info), font);
  919. u8g2_UpdateRefHeight(u8g2);
  920. /* u8g2_SetFontPosBaseline(u8g2); */ /* removed with issue 195 */
  921. }
  922. }
  923. /*===============================================*/
  924. static uint8_t u8g2_is_all_valid(u8g2_t *u8g2, const char *str) U8G2_NOINLINE;
  925. static uint8_t u8g2_is_all_valid(u8g2_t *u8g2, const char *str)
  926. {
  927. uint16_t e;
  928. u8x8_utf8_init(u8g2_GetU8x8(u8g2));
  929. for(;;)
  930. {
  931. e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  932. if ( e == 0x0ffff )
  933. break;
  934. str++;
  935. if ( e != 0x0fffe )
  936. {
  937. if ( u8g2_font_get_glyph_data(u8g2, e) == NULL )
  938. return 0;
  939. }
  940. }
  941. return 1;
  942. }
  943. uint8_t u8g2_IsAllValidUTF8(u8g2_t *u8g2, const char *str)
  944. {
  945. u8g2->u8x8.next_cb = u8x8_utf8_next;
  946. return u8g2_is_all_valid(u8g2, str);
  947. }
  948. /* string calculation is stilll not 100% perfect as it addes the initial string offset to the overall size */
  949. static u8g2_uint_t u8g2_string_width(u8g2_t *u8g2, const char *str) U8G2_NOINLINE;
  950. static u8g2_uint_t u8g2_string_width(u8g2_t *u8g2, const char *str)
  951. {
  952. uint16_t e;
  953. u8g2_uint_t w, dx;
  954. u8g2->font_decode.glyph_width = 0;
  955. u8x8_utf8_init(u8g2_GetU8x8(u8g2));
  956. /* reset the total width to zero, this will be expanded during calculation */
  957. w = 0;
  958. dx = 0;
  959. // printf("str=<%s>\n", str);
  960. for(;;)
  961. {
  962. e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  963. if ( e == 0x0ffff )
  964. break;
  965. str++;
  966. if ( e != 0x0fffe )
  967. {
  968. dx = u8g2_GetGlyphWidth(u8g2, e); /* delta x value of the glyph */
  969. w += dx;
  970. }
  971. }
  972. /* adjust the last glyph, check for issue #16: do not adjust if width is 0 */
  973. if ( u8g2->font_decode.glyph_width != 0 )
  974. {
  975. w -= dx;
  976. w += u8g2->font_decode.glyph_width; /* the real pixel width of the glyph, sideeffect of GetGlyphWidth */
  977. /* issue #46: we have to add the x offset also */
  978. w += u8g2->glyph_x_offset; /* this value is set as a side effect of u8g2_GetGlyphWidth() */
  979. }
  980. // printf("w=%d \n", w);
  981. return w;
  982. }
  983. static void u8g2_GetGlyphHorizontalProperties(u8g2_t *u8g2, uint16_t requested_encoding, uint8_t *w, int8_t *ox, int8_t *dx)
  984. {
  985. const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, requested_encoding);
  986. if ( glyph_data == NULL )
  987. return;
  988. u8g2_font_setup_decode(u8g2, glyph_data);
  989. *w = u8g2->font_decode.glyph_width;
  990. *ox = u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_x);
  991. u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_y);
  992. *dx = u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_delta_x);
  993. }
  994. /* u8g compatible GetStrX function */
  995. int8_t u8g2_GetStrX(u8g2_t *u8g2, const char *s)
  996. {
  997. uint8_t w;
  998. int8_t ox, dx;
  999. u8g2_GetGlyphHorizontalProperties(u8g2, *s, &w, &ox, &dx);
  1000. return ox;
  1001. }
  1002. static u8g2_uint_t u8g2_calculate_exact_string_width(u8g2_t *u8g2, const char *str)
  1003. {
  1004. u8g2_uint_t w;
  1005. uint16_t enc;
  1006. uint8_t gw;
  1007. int8_t ox, dx;
  1008. /* reset the total minimal width to zero, this will be expanded during calculation */
  1009. w = 0;
  1010. /* check for empty string, width is already 0 */
  1011. do
  1012. {
  1013. enc = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  1014. str++;
  1015. } while( enc == 0x0fffe );
  1016. if ( enc== 0x0ffff )
  1017. return w;
  1018. /* get the glyph information of the first char. This must be valid, because we already checked for the empty string */
  1019. /* if *s is not inside the font, then the cached parameters of the glyph are all zero */
  1020. u8g2_GetGlyphHorizontalProperties(u8g2, enc, &gw, &ox, &dx);
  1021. /* strlen(s) == 1: width = width(s[0]) */
  1022. /* strlen(s) == 2: width = - offx(s[0]) + deltax(s[0]) + offx(s[1]) + width(s[1]) */
  1023. /* strlen(s) == 3: width = - offx(s[0]) + deltax(s[0]) + deltax(s[1]) + offx(s[2]) + width(s[2]) */
  1024. /* assume that the string has size 2 or more, than start with negative offset-x */
  1025. /* for string with size 1, this will be nullified after the loop */
  1026. w = -ox;
  1027. for(;;)
  1028. {
  1029. /* check and stop if the end of the string is reached */
  1030. do
  1031. {
  1032. enc = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
  1033. str++;
  1034. } while( enc == 0x0fffe );
  1035. if ( enc== 0x0ffff )
  1036. break;
  1037. u8g2_GetGlyphHorizontalProperties(u8g2, enc, &gw, &ox, &dx);
  1038. /* if there are still more characters, add the delta to the next glyph */
  1039. w += dx;
  1040. }
  1041. /* finally calculate the width of the last char */
  1042. /* here is another exception, if the last char is a black, use the dx value instead */
  1043. if ( enc != ' ' )
  1044. {
  1045. /* if g was not updated in the for loop (strlen() == 1), then the initial offset x gets removed */
  1046. w += gw;
  1047. w += ox;
  1048. }
  1049. else
  1050. {
  1051. w += dx;
  1052. }
  1053. return w;
  1054. }
  1055. u8g2_uint_t u8g2_GetStrWidth(u8g2_t *u8g2, const char *s)
  1056. {
  1057. u8g2->u8x8.next_cb = u8x8_ascii_next;
  1058. return u8g2_string_width(u8g2, s);
  1059. }
  1060. u8g2_uint_t u8g2_GetExactStrWidth(u8g2_t *u8g2, const char *s)
  1061. {
  1062. u8g2->u8x8.next_cb = u8x8_ascii_next;
  1063. return u8g2_calculate_exact_string_width(u8g2, s);
  1064. }
  1065. /*
  1066. source: https://en.wikipedia.org/wiki/UTF-8
  1067. Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
  1068. 7 U+0000 U+007F 1 0xxxxxxx
  1069. 11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
  1070. 16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
  1071. 21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  1072. 26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  1073. 31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  1074. */
  1075. u8g2_uint_t u8g2_GetUTF8Width(u8g2_t *u8g2, const char *str)
  1076. {
  1077. u8g2->u8x8.next_cb = u8x8_utf8_next;
  1078. return u8g2_string_width(u8g2, str);
  1079. }
  1080. void u8g2_SetFontDirection(u8g2_t *u8g2, uint8_t dir)
  1081. {
  1082. #ifdef U8G2_WITH_FONT_ROTATION
  1083. u8g2->font_decode.dir = dir;
  1084. #endif
  1085. }