 5c81bb8abc
			
		
	
	
		5c81bb8abc
		
			
		
	
	
	
	
		
			
			* add u8g2 and ui libs * add display driver and usage example * not init display in test mode * change todo text * fix removed code * Target f2 (#107) * add ioc for flipperzero f2 * add generated f1 files to f2 * regenerate cubemx * invert initial state of led * blink backligh * shutdown backlight on idle
		
			
				
	
	
		
			1292 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1292 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| 
 | |
|   u8g2_font.c
 | |
| 
 | |
|   Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
 | |
| 
 | |
|   Copyright (c) 2016, olikraus@gmail.com
 | |
|   All rights reserved.
 | |
| 
 | |
|   Redistribution and use in source and binary forms, with or without modification, 
 | |
|   are permitted provided that the following conditions are met:
 | |
| 
 | |
|   * Redistributions of source code must retain the above copyright notice, this list 
 | |
|     of conditions and the following disclaimer.
 | |
|     
 | |
|   * Redistributions in binary form must reproduce the above copyright notice, this 
 | |
|     list of conditions and the following disclaimer in the documentation and/or other 
 | |
|     materials provided with the distribution.
 | |
| 
 | |
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
 | |
|   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 | |
|   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 | |
|   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 | |
|   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 | |
|   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 | |
|   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
 | |
|   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 | |
|   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 | |
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 | |
|   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 | |
|   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 | |
|   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 | |
| 
 | |
| */
 | |
| 
 | |
| #include "u8g2.h"
 | |
| 
 | |
| /* size of the font data structure, there is no struct or class... */
 | |
| /* this is the size for the new font format */
 | |
| #define U8G2_FONT_DATA_STRUCT_SIZE 23
 | |
| 
 | |
| /*
 | |
|   font data:
 | |
| 
 | |
|   offset	bytes	description
 | |
|   0		1		glyph_cnt		number of glyphs
 | |
|   1		1		bbx_mode	0: proportional, 1: common height, 2: monospace, 3: multiple of 8
 | |
|   2		1		bits_per_0	glyph rle parameter
 | |
|   3		1		bits_per_1	glyph rle parameter
 | |
| 
 | |
|   4		1		bits_per_char_width		glyph rle parameter
 | |
|   5		1		bits_per_char_height	glyph rle parameter
 | |
|   6		1		bits_per_char_x		glyph rle parameter
 | |
|   7		1		bits_per_char_y		glyph rle parameter
 | |
|   8		1		bits_per_delta_x		glyph rle parameter
 | |
| 
 | |
|   9		1		max_char_width
 | |
|   10		1		max_char_height
 | |
|   11		1		x offset
 | |
|   12		1		y offset (descent)
 | |
|   
 | |
|   13		1		ascent (capital A)
 | |
|   14		1		descent (lower g)
 | |
|   15		1		ascent '('
 | |
|   16		1		descent ')'
 | |
|   
 | |
|   17		1		start pos 'A' high byte
 | |
|   18		1		start pos 'A' low byte
 | |
| 
 | |
|   19		1		start pos 'a' high byte
 | |
|   20		1		start pos 'a' low byte
 | |
| 
 | |
|   21		1		start pos unicode high byte
 | |
|   22		1		start pos unicode low byte
 | |
| 
 | |
|   Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
 | |
| 
 | |
|   Font build mode 0:		
 | |
|     - "t"
 | |
|     - Ref height mode: U8G2_FONT_HEIGHT_MODE_TEXT, U8G2_FONT_HEIGHT_MODE_XTEXT or U8G2_FONT_HEIGHT_MODE_ALL
 | |
|     - use in transparent mode only (does not look good in solid mode)
 | |
|     - most compact format
 | |
|     - different font heights possible
 | |
|     
 | |
|   Font build mode 1:		
 | |
|     - "h"
 | |
|     - Ref height mode: U8G2_FONT_HEIGHT_MODE_ALL
 | |
|     - transparent or solid mode
 | |
|     - The height of the glyphs depend on the largest glyph in the font. This means font height depends on postfix "r", "f" and "n".
 | |
| 
 | |
| */
 | |
| 
 | |
| /* use case: What is the width and the height of the minimal box into which string s fints? */
 | |
| void u8g2_font_GetStrSize(const void *font, const char *s, u8g2_uint_t *width, u8g2_uint_t *height);
 | |
| void u8g2_font_GetStrSizeP(const void *font, const char *s, u8g2_uint_t *width, u8g2_uint_t *height);
 | |
| 
 | |
| /* use case: lower left edge of a minimal box is known, what is the correct x, y position for the string draw procedure */
 | |
| void u8g2_font_AdjustXYToDraw(const void *font, const char *s, u8g2_uint_t *x, u8g2_uint_t *y);
 | |
| void u8g2_font_AdjustXYToDrawP(const void *font, const char *s, u8g2_uint_t *x, u8g2_uint_t *y);
 | |
| 
 | |
| /* use case: Baseline origin known, return minimal box */
 | |
| 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);
 | |
| 
 | |
| /* procedures */
 | |
| 
 | |
| /*========================================================================*/
 | |
| /* low level byte and word access */
 | |
| 
 | |
| /* removed NOINLINE, because it leads to smaller code, might also be faster */
 | |
| //static uint8_t u8g2_font_get_byte(const uint8_t *font, uint8_t offset) U8G2_NOINLINE;
 | |
| static uint8_t u8g2_font_get_byte(const uint8_t *font, uint8_t offset)
 | |
| {
 | |
|   font += offset;
 | |
|   return u8x8_pgm_read( font );  
 | |
| }
 | |
| 
 | |
| static uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset) U8G2_NOINLINE; 
 | |
| static uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset)
 | |
| {
 | |
|     uint16_t pos;
 | |
|     font += offset;
 | |
|     pos = u8x8_pgm_read( font );
 | |
|     font++;
 | |
|     pos <<= 8;
 | |
|     pos += u8x8_pgm_read( font);
 | |
|     return pos;
 | |
| }
 | |
| 
 | |
| /*========================================================================*/
 | |
| /* new font format */
 | |
| void u8g2_read_font_info(u8g2_font_info_t *font_info, const uint8_t *font)
 | |
| {
 | |
|   /* offset 0 */
 | |
|   font_info->glyph_cnt = u8g2_font_get_byte(font, 0);
 | |
|   font_info->bbx_mode = u8g2_font_get_byte(font, 1);
 | |
|   font_info->bits_per_0 = u8g2_font_get_byte(font, 2);
 | |
|   font_info->bits_per_1 = u8g2_font_get_byte(font, 3);
 | |
|   
 | |
|   /* offset 4 */
 | |
|   font_info->bits_per_char_width = u8g2_font_get_byte(font, 4);
 | |
|   font_info->bits_per_char_height = u8g2_font_get_byte(font, 5);
 | |
|   font_info->bits_per_char_x = u8g2_font_get_byte(font, 6);
 | |
|   font_info->bits_per_char_y = u8g2_font_get_byte(font, 7);
 | |
|   font_info->bits_per_delta_x = u8g2_font_get_byte(font, 8);
 | |
|   
 | |
|   /* offset 9 */
 | |
|   font_info->max_char_width = u8g2_font_get_byte(font, 9);
 | |
|   font_info->max_char_height = u8g2_font_get_byte(font, 10);
 | |
|   font_info->x_offset = u8g2_font_get_byte(font, 11);
 | |
|   font_info->y_offset = u8g2_font_get_byte(font, 12);
 | |
|   
 | |
|   /* offset 13 */
 | |
|   font_info->ascent_A = u8g2_font_get_byte(font, 13);
 | |
|   font_info->descent_g = u8g2_font_get_byte(font, 14);
 | |
|   font_info->ascent_para = u8g2_font_get_byte(font, 15);
 | |
|   font_info->descent_para = u8g2_font_get_byte(font, 16);
 | |
|   
 | |
|   /* offset 17 */
 | |
|   font_info->start_pos_upper_A = u8g2_font_get_word(font, 17);
 | |
|   font_info->start_pos_lower_a = u8g2_font_get_word(font, 19); 
 | |
|   
 | |
|   /* offset 21 */
 | |
| #ifdef U8G2_WITH_UNICODE
 | |
|   font_info->start_pos_unicode = u8g2_font_get_word(font, 21); 
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| /* calculate the overall length of the font, only used to create the picture for the google wiki */
 | |
| size_t u8g2_GetFontSize(const uint8_t *font_arg)
 | |
| {
 | |
|   uint16_t e;
 | |
|   const uint8_t *font = font_arg;
 | |
|   font += U8G2_FONT_DATA_STRUCT_SIZE;
 | |
|   
 | |
|   for(;;)
 | |
|   {
 | |
|     if ( u8x8_pgm_read( font + 1 ) == 0 )
 | |
|       break;
 | |
|     font += u8x8_pgm_read( font + 1 );
 | |
|   }
 | |
|   
 | |
|   /* continue with unicode section */
 | |
|   font += 2;
 | |
| 
 | |
|   /* skip unicode lookup table */
 | |
|   font += u8g2_font_get_word(font, 0);
 | |
|   
 | |
|   for(;;)
 | |
|   {
 | |
|     e = u8x8_pgm_read( font );
 | |
|     e <<= 8;
 | |
|     e |= u8x8_pgm_read( font + 1 );
 | |
|     if ( e == 0 )
 | |
|       break;
 | |
|     font += u8x8_pgm_read( font + 2 );    
 | |
|   }
 | |
|   
 | |
|   return (font - font_arg) + 2;
 | |
| }
 | |
| 
 | |
| /*========================================================================*/
 | |
| /* u8g2 interface, font access */
 | |
| 
 | |
| uint8_t u8g2_GetFontBBXWidth(u8g2_t *u8g2)
 | |
| {
 | |
|   return u8g2->font_info.max_char_width;		/* new font info structure */
 | |
| }
 | |
| 
 | |
| uint8_t u8g2_GetFontBBXHeight(u8g2_t *u8g2)
 | |
| {
 | |
|   return u8g2->font_info.max_char_height;		/* new font info structure */
 | |
| }
 | |
| 
 | |
| int8_t u8g2_GetFontBBXOffX(u8g2_t *u8g2) U8G2_NOINLINE;
 | |
| int8_t u8g2_GetFontBBXOffX(u8g2_t *u8g2)
 | |
| {
 | |
|   return u8g2->font_info.x_offset;		/* new font info structure */
 | |
| }
 | |
| 
 | |
| int8_t u8g2_GetFontBBXOffY(u8g2_t *u8g2) U8G2_NOINLINE;
 | |
| int8_t u8g2_GetFontBBXOffY(u8g2_t *u8g2)
 | |
| {
 | |
|   return u8g2->font_info.y_offset;		/* new font info structure */
 | |
| }
 | |
| 
 | |
| uint8_t u8g2_GetFontCapitalAHeight(u8g2_t *u8g2) U8G2_NOINLINE; 
 | |
| uint8_t u8g2_GetFontCapitalAHeight(u8g2_t *u8g2)
 | |
| {
 | |
|   return u8g2->font_info.ascent_A;		/* new font info structure */
 | |
| }
 | |
| 
 | |
| /*========================================================================*/
 | |
| /* glyph handling */
 | |
| 
 | |
| /* optimized */
 | |
| uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt) 
 | |
| {
 | |
|   uint8_t val;
 | |
|   uint8_t bit_pos = f->decode_bit_pos;
 | |
|   uint8_t bit_pos_plus_cnt;
 | |
|   
 | |
|   //val = *(f->decode_ptr);
 | |
|   val = u8x8_pgm_read( f->decode_ptr );  
 | |
|   
 | |
|   val >>= bit_pos;
 | |
|   bit_pos_plus_cnt = bit_pos;
 | |
|   bit_pos_plus_cnt += cnt;
 | |
|   if ( bit_pos_plus_cnt >= 8 )
 | |
|   {
 | |
|     uint8_t s = 8;
 | |
|     s -= bit_pos;
 | |
|     f->decode_ptr++;
 | |
|     //val |= *(f->decode_ptr) << (8-bit_pos);
 | |
|     val |= u8x8_pgm_read( f->decode_ptr ) << (s);
 | |
|     //bit_pos -= 8;
 | |
|     bit_pos_plus_cnt -= 8;
 | |
|   }
 | |
|   val &= (1U<<cnt)-1;
 | |
|   //bit_pos += cnt;
 | |
|   
 | |
|   f->decode_bit_pos = bit_pos_plus_cnt;
 | |
|   return val;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|     2 bit --> cnt = 2
 | |
|       -2,-1,0. 1
 | |
| 
 | |
|     3 bit --> cnt = 3
 | |
|       -2,-1,0. 1
 | |
|       -4,-3,-2,-1,0,1,2,3
 | |
| 
 | |
|       if ( x < 0 )
 | |
| 	r = bits(x-1)+1;
 | |
|     else
 | |
| 	r = bits(x)+1;
 | |
| 
 | |
| */
 | |
| /* optimized */
 | |
| int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cnt)
 | |
| {
 | |
|   int8_t v, d;
 | |
|   v = (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt);
 | |
|   d = 1;
 | |
|   cnt--;
 | |
|   d <<= cnt;
 | |
|   v -= d;
 | |
|   return v;
 | |
|   //return (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt) - ((1<<cnt)>>1);
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
| u8g2_uint_t u8g2_add_vector_y(u8g2_uint_t dy, int8_t x, int8_t y, uint8_t dir)
 | |
| {
 | |
|   switch(dir)
 | |
|   {
 | |
|     case 0:
 | |
|       dy += y;
 | |
|       break;
 | |
|     case 1:
 | |
|       dy += x;
 | |
|       break;
 | |
|     case 2:
 | |
|       dy -= y;
 | |
|       break;
 | |
|     default:
 | |
|       dy -= x;
 | |
|       break;      
 | |
|   }
 | |
|   return dy;
 | |
| }
 | |
| 
 | |
| u8g2_uint_t u8g2_add_vector_x(u8g2_uint_t dx, int8_t x, int8_t y, uint8_t dir)
 | |
| {
 | |
|   switch(dir)
 | |
|   {
 | |
|     case 0:
 | |
|       dx += x;
 | |
|       break;
 | |
|     case 1:
 | |
|       dx -= y;
 | |
|       break;
 | |
|     case 2:
 | |
|       dx -= x;
 | |
|       break;
 | |
|     default:
 | |
|       dx += y;
 | |
|       break;      
 | |
|   }
 | |
|   return dx;
 | |
| }
 | |
| 
 | |
| /*
 | |
| // does not make sense, 50 bytes more required on avr
 | |
| void u8g2_add_vector(u8g2_uint_t *xp, u8g2_uint_t *yp, int8_t x, int8_t y, uint8_t dir)
 | |
| {
 | |
|   u8g2_uint_t x_ = *xp;
 | |
|   u8g2_uint_t y_ = *yp;
 | |
|   switch(dir)
 | |
|   {
 | |
|     case 0:
 | |
|       y_ += y;
 | |
|       x_ += x;
 | |
|       break;
 | |
|     case 1:
 | |
|       y_ += x;
 | |
|       x_ -= y;
 | |
|       break;
 | |
|     case 2:
 | |
|       y_ -= y;
 | |
|       x_ -= x;
 | |
|       break;
 | |
|     default:
 | |
|       y_ -= x;
 | |
|       x_ += y;
 | |
|       break;      
 | |
|   }
 | |
|   *xp = x_;
 | |
|   *yp = y_;
 | |
| }
 | |
| */
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Description:
 | |
|     Draw a run-length area of the glyph. "len" can have any size and the line
 | |
|     length has to be wrapped at the glyph border.
 | |
|   Args:
 | |
|     len: 					Length of the line
 | |
|     is_foreground			foreground/background?
 | |
|     u8g2->font_decode.target_x		X position
 | |
|     u8g2->font_decode.target_y		Y position
 | |
|     u8g2->font_decode.is_transparent	Transparent mode
 | |
|   Return:
 | |
|     -
 | |
|   Calls:
 | |
|     u8g2_Draw90Line()
 | |
|   Called by:
 | |
|     u8g2_font_decode_glyph()
 | |
| */
 | |
| /* optimized */
 | |
| void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground)
 | |
| {
 | |
|   uint8_t cnt;	/* total number of remaining pixels, which have to be drawn */
 | |
|   uint8_t rem; 	/* remaining pixel to the right edge of the glyph */
 | |
|   uint8_t current;	/* number of pixels, which need to be drawn for the draw procedure */
 | |
|     /* current is either equal to cnt or equal to rem */
 | |
|   
 | |
|   /* local coordinates of the glyph */
 | |
|   uint8_t lx,ly;
 | |
|   
 | |
|   /* target position on the screen */
 | |
|   u8g2_uint_t x, y;
 | |
|   
 | |
|   u8g2_font_decode_t *decode = &(u8g2->font_decode);
 | |
|   
 | |
|   cnt = len;
 | |
|   
 | |
|   /* get the local position */
 | |
|   lx = decode->x;
 | |
|   ly = decode->y;
 | |
|   
 | |
|   for(;;)
 | |
|   {
 | |
|     /* calculate the number of pixel to the right edge of the glyph */
 | |
|     rem = decode->glyph_width;
 | |
|     rem -= lx;
 | |
|     
 | |
|     /* calculate how many pixel to draw. This is either to the right edge */
 | |
|     /* or lesser, if not enough pixel are left */
 | |
|     current = rem;
 | |
|     if ( cnt < rem )
 | |
|       current = cnt;
 | |
|     
 | |
|     
 | |
|     /* now draw the line, but apply the rotation around the glyph target position */
 | |
|     //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
 | |
| 
 | |
|     /* get target position */
 | |
|     x = decode->target_x;
 | |
|     y = decode->target_y;
 | |
| 
 | |
|     /* apply rotation */
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
|     
 | |
|     x = u8g2_add_vector_x(x, lx, ly, decode->dir);
 | |
|     y = u8g2_add_vector_y(y, lx, ly, decode->dir);
 | |
|     
 | |
|     //u8g2_add_vector(&x, &y, lx, ly, decode->dir);
 | |
|     
 | |
| #else
 | |
|     x += lx;
 | |
|     y += ly;
 | |
| #endif
 | |
|     
 | |
|     /* draw foreground and background (if required) */
 | |
|     if ( is_foreground )
 | |
|     {
 | |
|       u8g2->draw_color = decode->fg_color;			/* draw_color will be restored later */
 | |
|       u8g2_DrawHVLine(u8g2, 
 | |
| 	x, 
 | |
| 	y, 
 | |
| 	current, 
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
| 	/* dir */ decode->dir
 | |
| #else
 | |
| 	0
 | |
| #endif
 | |
|       );
 | |
|     }
 | |
|     else if ( decode->is_transparent == 0 )    
 | |
|     {
 | |
|       u8g2->draw_color = decode->bg_color;			/* draw_color will be restored later */
 | |
|       u8g2_DrawHVLine(u8g2, 
 | |
| 	x, 
 | |
| 	y, 
 | |
| 	current, 
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
| 	/* dir */ decode->dir
 | |
| #else
 | |
| 	0
 | |
| #endif
 | |
|       );   
 | |
|     }
 | |
|     
 | |
|     /* check, whether the end of the run length code has been reached */
 | |
|     if ( cnt < rem )
 | |
|       break;
 | |
|     cnt -= rem;
 | |
|     lx = 0;
 | |
|     ly++;
 | |
|   }
 | |
|   lx += cnt;
 | |
|   
 | |
|   decode->x = lx;
 | |
|   decode->y = ly;
 | |
|   
 | |
| }
 | |
| 
 | |
| static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
 | |
| {
 | |
|   u8g2_font_decode_t *decode = &(u8g2->font_decode);
 | |
|   decode->decode_ptr = glyph_data;
 | |
|   decode->decode_bit_pos = 0;
 | |
|   
 | |
|   /* 8 Nov 2015, this is already done in the glyph data search procedure */
 | |
|   /*
 | |
|   decode->decode_ptr += 1;
 | |
|   decode->decode_ptr += 1;
 | |
|   */
 | |
|   
 | |
|   decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
 | |
|   decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode,u8g2->font_info.bits_per_char_height);
 | |
|   
 | |
|   decode->fg_color = u8g2->draw_color;
 | |
|   decode->bg_color = (decode->fg_color == 0 ? 1 : 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Description:
 | |
|     Decode and draw a glyph.
 | |
|   Args:
 | |
|     glyph_data: 					Pointer to the compressed glyph data of the font
 | |
|     u8g2->font_decode.target_x		X position
 | |
|     u8g2->font_decode.target_y		Y position
 | |
|     u8g2->font_decode.is_transparent	Transparent mode
 | |
|   Return:
 | |
|     Width (delta x advance) of the glyph.
 | |
|   Calls:
 | |
|     u8g2_font_decode_len()
 | |
| */
 | |
| /* optimized */
 | |
| int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data)
 | |
| {
 | |
|   uint8_t a, b;
 | |
|   int8_t x, y;
 | |
|   int8_t d;
 | |
|   int8_t h;
 | |
|   u8g2_font_decode_t *decode = &(u8g2->font_decode);
 | |
|     
 | |
|   u8g2_font_setup_decode(u8g2, glyph_data);
 | |
|   h = u8g2->font_decode.glyph_height;
 | |
|   
 | |
|   x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
 | |
|   y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
 | |
|   d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
 | |
|   
 | |
|   if ( decode->glyph_width > 0 )
 | |
|   {
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
|     decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
 | |
|     decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
 | |
|     
 | |
|     //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
 | |
| 
 | |
| #else
 | |
|     decode->target_x += x;
 | |
|     decode->target_y -= h+y;
 | |
| #endif
 | |
|     //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
 | |
| 
 | |
| #ifdef U8G2_WITH_INTERSECTION
 | |
|     {
 | |
|       u8g2_uint_t x0, x1, y0, y1;
 | |
|       x0 = decode->target_x;
 | |
|       y0 = decode->target_y;
 | |
|       x1 = x0;
 | |
|       y1 = y0;
 | |
|       
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
|       switch(decode->dir)
 | |
|       {
 | |
| 	case 0:
 | |
| 	    x1 += decode->glyph_width;
 | |
| 	    y1 += h;
 | |
| 	    break;
 | |
| 	case 1:
 | |
| 	    x0 -= h;
 | |
| 	    x0++;	/* shift down, because of assymetric boundaries for the interseciton test */
 | |
| 	    x1++;
 | |
| 	    y1 += decode->glyph_width;
 | |
| 	    break;
 | |
| 	case 2:
 | |
| 	    x0 -= decode->glyph_width;
 | |
| 	    x0++;	/* shift down, because of assymetric boundaries for the interseciton test */
 | |
| 	    x1++;
 | |
| 	    y0 -= h;
 | |
| 	    y0++;	/* shift down, because of assymetric boundaries for the interseciton test */
 | |
| 	    y1++;
 | |
| 	    break;	  
 | |
| 	case 3:
 | |
| 	    x1 += h;
 | |
| 	    y0 -= decode->glyph_width;
 | |
| 	    y0++;	/* shift down, because of assymetric boundaries for the interseciton test */
 | |
| 	    y1++;
 | |
| 	    break;	  
 | |
|       }
 | |
| #else /* U8G2_WITH_FONT_ROTATION */
 | |
|       x1 += decode->glyph_width;
 | |
|       y1 += h;      
 | |
| #endif
 | |
|       
 | |
|       if ( u8g2_IsIntersection(u8g2, x0, y0, x1, y1) == 0 ) 
 | |
| 	return d;
 | |
|     }
 | |
| #endif /* U8G2_WITH_INTERSECTION */
 | |
|    
 | |
|     /* reset local x/y position */
 | |
|     decode->x = 0;
 | |
|     decode->y = 0;
 | |
|     
 | |
|     /* decode glyph */
 | |
|     for(;;)
 | |
|     {
 | |
|       a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
 | |
|       b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
 | |
|       do
 | |
|       {
 | |
| 	u8g2_font_decode_len(u8g2, a, 0);
 | |
| 	u8g2_font_decode_len(u8g2, b, 1);
 | |
|       } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
 | |
| 
 | |
|       if ( decode->y >= h )
 | |
| 	break;
 | |
|     }
 | |
|     
 | |
|     /* restore the u8g2 draw color, because this is modified by the decode algo */
 | |
|     u8g2->draw_color = decode->fg_color;
 | |
|   }
 | |
|   return d;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Description:
 | |
|     Find the starting point of the glyph data.
 | |
|   Args:
 | |
|     encoding: Encoding (ASCII or Unicode) of the glyph
 | |
|   Return:
 | |
|     Address of the glyph data or NULL, if the encoding is not avialable in the font.
 | |
| */
 | |
| const uint8_t *u8g2_font_get_glyph_data(u8g2_t *u8g2, uint16_t encoding)
 | |
| {
 | |
|   const uint8_t *font = u8g2->font;
 | |
|   font += U8G2_FONT_DATA_STRUCT_SIZE;
 | |
| 
 | |
|   
 | |
|   if ( encoding <= 255 )
 | |
|   {
 | |
|     if ( encoding >= 'a' )
 | |
|     {
 | |
|       font += u8g2->font_info.start_pos_lower_a;
 | |
|     }
 | |
|     else if ( encoding >= 'A' )
 | |
|     {
 | |
|       font += u8g2->font_info.start_pos_upper_A;
 | |
|     }
 | |
|     
 | |
|     for(;;)
 | |
|     {
 | |
|       if ( u8x8_pgm_read( font + 1 ) == 0 )
 | |
| 	break;
 | |
|       if ( u8x8_pgm_read( font ) == encoding )
 | |
|       {
 | |
| 	return font+2;	/* skip encoding and glyph size */
 | |
|       }
 | |
|       font += u8x8_pgm_read( font + 1 );
 | |
|     }
 | |
|   }
 | |
| #ifdef U8G2_WITH_UNICODE
 | |
|   else
 | |
|   {
 | |
|     uint16_t e;
 | |
|     const uint8_t *unicode_lookup_table;
 | |
|     
 | |
| // removed, there is now the new index table
 | |
| //#ifdef  __unix__
 | |
| //    if ( u8g2->last_font_data != NULL && encoding >= u8g2->last_unicode )
 | |
| //    {
 | |
| //	font = u8g2->last_font_data;
 | |
| //    }
 | |
| //    else
 | |
| //#endif 
 | |
| 
 | |
|     font += u8g2->font_info.start_pos_unicode;
 | |
|     unicode_lookup_table = font; 
 | |
|   
 | |
|     /* issue 596: search for the glyph start in the unicode lookup table */
 | |
|     do
 | |
|     {
 | |
|       font += u8g2_font_get_word(unicode_lookup_table, 0);
 | |
|       e = u8g2_font_get_word(unicode_lookup_table, 2);
 | |
|       unicode_lookup_table+=4;
 | |
|     } while( e < encoding );
 | |
|     
 | |
|   
 | |
|     for(;;)
 | |
|     {
 | |
|       e = u8x8_pgm_read( font );
 | |
|       e <<= 8;
 | |
|       e |= u8x8_pgm_read( font + 1 );
 | |
|   
 | |
| // removed, there is now the new index table  
 | |
| //#ifdef  __unix__
 | |
| //      if ( encoding < e )
 | |
| //        break;
 | |
| //#endif 
 | |
| 
 | |
|       if ( e == 0 )
 | |
| 	break;
 | |
|   
 | |
|       if ( e == encoding )
 | |
|       {
 | |
| // removed, there is now the new index table
 | |
| //#ifdef  __unix__
 | |
| //	u8g2->last_font_data = font;
 | |
| //	u8g2->last_unicode = encoding;
 | |
| //#endif 
 | |
| 	return font+3;	/* skip encoding and glyph size */
 | |
|       }
 | |
|       font += u8x8_pgm_read( font + 2 );
 | |
|     }  
 | |
|   }
 | |
| #endif
 | |
|   
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| static u8g2_uint_t u8g2_font_draw_glyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
 | |
| {
 | |
|   u8g2_uint_t dx = 0;
 | |
|   u8g2->font_decode.target_x = x;
 | |
|   u8g2->font_decode.target_y = y;
 | |
|   //u8g2->font_decode.is_transparent = is_transparent; this is already set
 | |
|   //u8g2->font_decode.dir = dir;
 | |
|   const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
 | |
|   if ( glyph_data != NULL )
 | |
|   {
 | |
|     dx = u8g2_font_decode_glyph(u8g2, glyph_data);
 | |
|   }
 | |
|   return dx;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| uint8_t u8g2_IsGlyph(u8g2_t *u8g2, uint16_t requested_encoding)
 | |
| {
 | |
|   /* updated to new code */
 | |
|   if ( u8g2_font_get_glyph_data(u8g2, requested_encoding) != NULL )
 | |
|     return 1;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /* side effect: updates u8g2->font_decode and u8g2->glyph_x_offset */
 | |
| int8_t u8g2_GetGlyphWidth(u8g2_t *u8g2, uint16_t requested_encoding)
 | |
| {
 | |
|   const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, requested_encoding);
 | |
|   if ( glyph_data == NULL )
 | |
|     return 0; 
 | |
|   
 | |
|   u8g2_font_setup_decode(u8g2, glyph_data);
 | |
|   u8g2->glyph_x_offset = u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_x);
 | |
|   u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_y);
 | |
|   
 | |
|   /* glyph width is here: u8g2->font_decode.glyph_width */
 | |
| 
 | |
|   return u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_delta_x);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   set one of:
 | |
|     U8G2_FONT_MODE_TRANSPARENT
 | |
|     U8G2_FONT_MODE_SOLID
 | |
|     U8G2_FONT_MODE_NONE
 | |
|   This has been changed for the new font procedures  
 | |
| */
 | |
| void u8g2_SetFontMode(u8g2_t *u8g2, uint8_t is_transparent)
 | |
| {
 | |
|   u8g2->font_decode.is_transparent = is_transparent;		// new font procedures
 | |
| }
 | |
| 
 | |
| u8g2_uint_t u8g2_DrawGlyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
 | |
| {
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
|   switch(u8g2->font_decode.dir)
 | |
|   {
 | |
|     case 0:
 | |
|       y += u8g2->font_calc_vref(u8g2);
 | |
|       break;
 | |
|     case 1:
 | |
|       x -= u8g2->font_calc_vref(u8g2);
 | |
|       break;
 | |
|     case 2:
 | |
|       y -= u8g2->font_calc_vref(u8g2);
 | |
|       break;
 | |
|     case 3:
 | |
|       x += u8g2->font_calc_vref(u8g2);
 | |
|       break;
 | |
|   }
 | |
| #else
 | |
|   y += u8g2->font_calc_vref(u8g2);
 | |
| #endif
 | |
|   return u8g2_font_draw_glyph(u8g2, x, y, encoding);
 | |
| }
 | |
| 
 | |
| static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str) U8G2_NOINLINE;
 | |
| static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
 | |
| {
 | |
|   uint16_t e;
 | |
|   u8g2_uint_t delta, sum;
 | |
|   u8x8_utf8_init(u8g2_GetU8x8(u8g2));
 | |
|   sum = 0;
 | |
|   for(;;)
 | |
|   {
 | |
|     e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|     if ( e == 0x0ffff )
 | |
|       break;
 | |
|     str++;
 | |
|     if ( e != 0x0fffe )
 | |
|     {
 | |
|       delta = u8g2_DrawGlyph(u8g2, x, y, e);
 | |
|     
 | |
| #ifdef U8G2_WITH_FONT_ROTATION
 | |
|       switch(u8g2->font_decode.dir)
 | |
|       {
 | |
| 	case 0:
 | |
| 	  x += delta;
 | |
| 	  break;
 | |
| 	case 1:
 | |
| 	  y += delta;
 | |
| 	  break;
 | |
| 	case 2:
 | |
| 	  x -= delta;
 | |
| 	  break;
 | |
| 	case 3:
 | |
| 	  y -= delta;
 | |
| 	  break;
 | |
|       }
 | |
|       
 | |
|       /*
 | |
|       // requires 10 bytes more on avr
 | |
|       x = u8g2_add_vector_x(x, delta, 0, u8g2->font_decode.dir);
 | |
|       y = u8g2_add_vector_y(y, delta, 0, u8g2->font_decode.dir);
 | |
|       */
 | |
| 
 | |
| #else
 | |
|       x += delta;
 | |
| #endif
 | |
| 
 | |
|       sum += delta;    
 | |
|     }
 | |
|   }
 | |
|   return sum;
 | |
| }
 | |
| 
 | |
| u8g2_uint_t u8g2_DrawStr(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_ascii_next;
 | |
|   return u8g2_draw_string(u8g2, x, y, str);
 | |
| }
 | |
| 
 | |
| /*
 | |
| source: https://en.wikipedia.org/wiki/UTF-8
 | |
| Bits	from 		to			bytes	Byte 1 		Byte 2 		Byte 3 		Byte 4 		Byte 5 		Byte 6
 | |
|   7 	U+0000 		U+007F 		1 		0xxxxxxx
 | |
| 11 	U+0080 		U+07FF 		2 		110xxxxx 	10xxxxxx
 | |
| 16 	U+0800 		U+FFFF 		3 		1110xxxx 	10xxxxxx 	10xxxxxx
 | |
| 21 	U+10000 	U+1FFFFF 	4 		11110xxx 	10xxxxxx 	10xxxxxx 	10xxxxxx
 | |
| 26 	U+200000 	U+3FFFFFF 	5 		111110xx 	10xxxxxx 	10xxxxxx 	10xxxxxx 	10xxxxxx
 | |
| 31 	U+4000000 	U+7FFFFFFF 	6 		1111110x 	10xxxxxx 	10xxxxxx 	10xxxxxx 	10xxxxxx 	10xxxxxx  
 | |
| */
 | |
| u8g2_uint_t u8g2_DrawUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_utf8_next;
 | |
|   return u8g2_draw_string(u8g2, x, y, str);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 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)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_utf8_next;
 | |
|   uint16_t e_prev = 0x0ffff;
 | |
|   uint16_t e;
 | |
|   u8g2_uint_t delta, sum, k;
 | |
|   u8x8_utf8_init(u8g2_GetU8x8(u8g2));
 | |
|   sum = 0;
 | |
|   for(;;)
 | |
|   {
 | |
|     e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|     if ( e == 0x0ffff )
 | |
|       break;
 | |
|     str++;
 | |
|     if ( e != 0x0fffe )
 | |
|     {
 | |
|       delta = u8g2_GetGlyphWidth(u8g2, e);
 | |
| 	    
 | |
|       if ( to_left )
 | |
|       {
 | |
|         k = u8g2_GetKerning(u8g2, kerning, e, e_prev);
 | |
| 	delta -= k;
 | |
| 	x -= delta;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         k = u8g2_GetKerning(u8g2, kerning, e_prev, e);
 | |
| 	delta -= k;
 | |
|       }
 | |
|       e_prev = e;
 | |
| 
 | |
|       u8g2_DrawGlyph(u8g2, x, y, e);
 | |
|       if ( to_left )
 | |
|       {
 | |
|       }
 | |
|       else
 | |
|       {
 | |
| 	x += delta;
 | |
| 	x -= k;
 | |
|       }
 | |
|       
 | |
|       sum += delta;    
 | |
|     }
 | |
|   }
 | |
|   return sum;
 | |
| }
 | |
| 
 | |
| 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)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_utf8_next;
 | |
|   uint16_t e_prev = 0x0ffff;
 | |
|   uint16_t e;
 | |
|   u8g2_uint_t delta, sum, k;
 | |
|   u8x8_utf8_init(u8g2_GetU8x8(u8g2));
 | |
|   sum = 0;
 | |
|   for(;;)
 | |
|   {
 | |
|     e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|     if ( e == 0x0ffff )
 | |
|       break;
 | |
|     str++;
 | |
|     if ( e != 0x0fffe )
 | |
|     {
 | |
|       delta = u8g2_GetGlyphWidth(u8g2, e);
 | |
| 	    
 | |
|       if ( to_left )
 | |
|       {
 | |
|         k = u8g2_GetKerningByTable(u8g2, kerning_table, e, e_prev);
 | |
| 	delta -= k;
 | |
| 	x -= delta;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         k = u8g2_GetKerningByTable(u8g2, kerning_table, e_prev, e);
 | |
| 	delta -= k;
 | |
|       }
 | |
|       e_prev = e;
 | |
| 
 | |
|       if ( to_left )
 | |
|       {
 | |
|       }
 | |
|       else
 | |
|       {
 | |
| 	x += delta;
 | |
|       }
 | |
|       u8g2_DrawGlyph(u8g2, x, y, e);
 | |
|       if ( to_left )
 | |
|       {
 | |
|       }
 | |
|       else
 | |
|       {
 | |
| 	//x += delta;
 | |
| 	//x -= k;
 | |
|       }
 | |
|       
 | |
|       sum += delta;    
 | |
|     }
 | |
|   }
 | |
|   return sum;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /*===============================================*/
 | |
| 
 | |
| /* set ascent/descent for reference point calculation */
 | |
| 
 | |
| void u8g2_UpdateRefHeight(u8g2_t *u8g2)
 | |
| {
 | |
|   if ( u8g2->font == NULL )
 | |
|     return;
 | |
|   u8g2->font_ref_ascent = u8g2->font_info.ascent_A;
 | |
|   u8g2->font_ref_descent = u8g2->font_info.descent_g;
 | |
|   if ( u8g2->font_height_mode == U8G2_FONT_HEIGHT_MODE_TEXT )
 | |
|   {
 | |
|   }
 | |
|   else if ( u8g2->font_height_mode == U8G2_FONT_HEIGHT_MODE_XTEXT )
 | |
|   {
 | |
|     if ( u8g2->font_ref_ascent < u8g2->font_info.ascent_para )
 | |
|       u8g2->font_ref_ascent = u8g2->font_info.ascent_para;
 | |
|     if ( u8g2->font_ref_descent > u8g2->font_info.descent_para )
 | |
|       u8g2->font_ref_descent = u8g2->font_info.descent_para;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if ( u8g2->font_ref_ascent < u8g2->font_info.max_char_height+u8g2->font_info.y_offset )
 | |
|       u8g2->font_ref_ascent = u8g2->font_info.max_char_height+u8g2->font_info.y_offset;
 | |
|     if ( u8g2->font_ref_descent > u8g2->font_info.y_offset )
 | |
|       u8g2->font_ref_descent = u8g2->font_info.y_offset;
 | |
|   }  
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontRefHeightText(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_height_mode = U8G2_FONT_HEIGHT_MODE_TEXT;
 | |
|   u8g2_UpdateRefHeight(u8g2);
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontRefHeightExtendedText(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_height_mode = U8G2_FONT_HEIGHT_MODE_XTEXT;
 | |
|   u8g2_UpdateRefHeight(u8g2);
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontRefHeightAll(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_height_mode = U8G2_FONT_HEIGHT_MODE_ALL;
 | |
|   u8g2_UpdateRefHeight(u8g2);
 | |
| }
 | |
| 
 | |
| /*===============================================*/
 | |
| /* callback procedures to correct the y position */
 | |
| 
 | |
| u8g2_uint_t u8g2_font_calc_vref_font(U8X8_UNUSED u8g2_t *u8g2)
 | |
| {
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontPosBaseline(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_calc_vref = u8g2_font_calc_vref_font;
 | |
| }
 | |
| 
 | |
| 
 | |
| u8g2_uint_t u8g2_font_calc_vref_bottom(u8g2_t *u8g2)
 | |
| {
 | |
|   return (u8g2_uint_t)(u8g2->font_ref_descent);
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontPosBottom(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_calc_vref = u8g2_font_calc_vref_bottom;
 | |
| }
 | |
| 
 | |
| u8g2_uint_t u8g2_font_calc_vref_top(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2_uint_t tmp;
 | |
|   /* reference pos is one pixel above the upper edge of the reference glyph */
 | |
|   tmp = (u8g2_uint_t)(u8g2->font_ref_ascent);
 | |
|   tmp++;
 | |
|   return tmp;
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontPosTop(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_calc_vref = u8g2_font_calc_vref_top;
 | |
| }
 | |
| 
 | |
| u8g2_uint_t u8g2_font_calc_vref_center(u8g2_t *u8g2)
 | |
| {
 | |
|   int8_t tmp;
 | |
|   tmp = u8g2->font_ref_ascent;
 | |
|   tmp -= u8g2->font_ref_descent;
 | |
|   tmp /= 2;
 | |
|   tmp += u8g2->font_ref_descent;  
 | |
|   return tmp;
 | |
| }
 | |
| 
 | |
| void u8g2_SetFontPosCenter(u8g2_t *u8g2)
 | |
| {
 | |
|   u8g2->font_calc_vref = u8g2_font_calc_vref_center;
 | |
| }
 | |
| 
 | |
| /*===============================================*/
 | |
| 
 | |
| void u8g2_SetFont(u8g2_t *u8g2, const uint8_t  *font)
 | |
| {
 | |
|   if ( u8g2->font != font )
 | |
|   {
 | |
| //#ifdef  __unix__
 | |
| //	u8g2->last_font_data = NULL;
 | |
| //	u8g2->last_unicode = 0x0ffff;
 | |
| //#endif 
 | |
|     u8g2->font = font;
 | |
|     u8g2_read_font_info(&(u8g2->font_info), font);
 | |
|     u8g2_UpdateRefHeight(u8g2);
 | |
|     /* u8g2_SetFontPosBaseline(u8g2); */ /* removed with issue 195 */
 | |
|   }
 | |
| }
 | |
| 
 | |
| /*===============================================*/
 | |
| 
 | |
| static uint8_t u8g2_is_all_valid(u8g2_t *u8g2, const char *str) U8G2_NOINLINE;
 | |
| static uint8_t u8g2_is_all_valid(u8g2_t *u8g2, const char *str)
 | |
| {
 | |
|   uint16_t e;
 | |
|   u8x8_utf8_init(u8g2_GetU8x8(u8g2));
 | |
|   for(;;)
 | |
|   {
 | |
|     e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|     if ( e == 0x0ffff )
 | |
|       break;
 | |
|     str++;
 | |
|     if ( e != 0x0fffe )
 | |
|     {
 | |
|       if ( u8g2_font_get_glyph_data(u8g2, e) == NULL )
 | |
| 	return 0;
 | |
|     }
 | |
|   }
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| uint8_t u8g2_IsAllValidUTF8(u8g2_t *u8g2, const char *str)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_utf8_next;
 | |
|   return u8g2_is_all_valid(u8g2, str);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* string calculation is stilll not 100% perfect as it addes the initial string offset to the overall size */
 | |
| static u8g2_uint_t u8g2_string_width(u8g2_t *u8g2, const char *str) U8G2_NOINLINE;
 | |
| static u8g2_uint_t u8g2_string_width(u8g2_t *u8g2, const char *str)
 | |
| {
 | |
|   uint16_t e;
 | |
|   u8g2_uint_t  w, dx;
 | |
|   
 | |
|   u8g2->font_decode.glyph_width = 0;
 | |
|   u8x8_utf8_init(u8g2_GetU8x8(u8g2));
 | |
|   
 | |
|   /* reset the total width to zero, this will be expanded during calculation */
 | |
|   w = 0;
 | |
|   dx = 0;
 | |
| 
 | |
|   // printf("str=<%s>\n", str);
 | |
| 	
 | |
|   for(;;)
 | |
|   {
 | |
|     e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|     if ( e == 0x0ffff )
 | |
|       break;
 | |
|     str++;
 | |
|     if ( e != 0x0fffe )
 | |
|     {
 | |
|       dx = u8g2_GetGlyphWidth(u8g2, e);		/* delta x value of the glyph */
 | |
|       w += dx;
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /* adjust the last glyph, check for issue #16: do not adjust if width is 0 */
 | |
|   if ( u8g2->font_decode.glyph_width != 0 )
 | |
|   {
 | |
|     w -= dx;
 | |
|     w += u8g2->font_decode.glyph_width;  /* the real pixel width of the glyph, sideeffect of GetGlyphWidth */
 | |
|     /* issue #46: we have to add the x offset also */
 | |
|     w += u8g2->glyph_x_offset;	/* this value is set as a side effect of u8g2_GetGlyphWidth() */
 | |
|   }
 | |
|   // printf("w=%d \n", w);
 | |
|   
 | |
|   return w;  
 | |
| }
 | |
| 
 | |
| static void u8g2_GetGlyphHorizontalProperties(u8g2_t *u8g2, uint16_t requested_encoding, uint8_t *w, int8_t *ox, int8_t *dx)
 | |
| {
 | |
|   const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, requested_encoding);
 | |
|   if ( glyph_data == NULL )
 | |
|     return; 
 | |
|   
 | |
|   u8g2_font_setup_decode(u8g2, glyph_data);
 | |
|   *w = u8g2->font_decode.glyph_width;
 | |
|   *ox =  u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_x);
 | |
|   u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_y);
 | |
|   *dx = u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_delta_x);
 | |
| }
 | |
| 
 | |
| /* u8g compatible GetStrX function */
 | |
| int8_t u8g2_GetStrX(u8g2_t *u8g2, const char *s)
 | |
| {
 | |
|   uint8_t w;
 | |
|   int8_t ox, dx;
 | |
|   u8g2_GetGlyphHorizontalProperties(u8g2, *s, &w, &ox, &dx);
 | |
|   return ox;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static u8g2_uint_t u8g2_calculate_exact_string_width(u8g2_t *u8g2, const char *str)
 | |
| {
 | |
| 
 | |
|   u8g2_uint_t  w;
 | |
|   uint16_t enc;
 | |
|   uint8_t gw; 
 | |
|   int8_t ox, dx;
 | |
|   
 | |
|   /* reset the total minimal width to zero, this will be expanded during calculation */
 | |
|   w = 0;
 | |
|     
 | |
|   
 | |
|   /* check for empty string, width is already 0 */
 | |
|   do
 | |
|   {
 | |
|     enc = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|     str++;
 | |
|   } while( enc == 0x0fffe );
 | |
|   
 | |
|   if ( enc== 0x0ffff )
 | |
|      return w;
 | |
|   
 | |
|   /* get the glyph information of the first char. This must be valid, because we already checked for the empty string */
 | |
|   /* if *s is not inside the font, then the cached parameters of the glyph are all zero */
 | |
|   u8g2_GetGlyphHorizontalProperties(u8g2, enc, &gw, &ox, &dx);  
 | |
| 
 | |
|   /* strlen(s) == 1:       width = width(s[0]) */
 | |
|   /* strlen(s) == 2:       width = - offx(s[0]) + deltax(s[0]) + offx(s[1]) + width(s[1]) */
 | |
|   /* strlen(s) == 3:       width = - offx(s[0]) + deltax(s[0]) + deltax(s[1]) + offx(s[2]) + width(s[2]) */
 | |
|   
 | |
|   /* assume that the string has size 2 or more, than start with negative offset-x */
 | |
|   /* for string with size 1, this will be nullified after the loop */
 | |
|   w = -ox;  
 | |
|   for(;;)
 | |
|   {
 | |
|     
 | |
|     /* check and stop if the end of the string is reached */
 | |
|     do
 | |
|     {
 | |
|       enc = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
 | |
|       str++;
 | |
|     } while( enc == 0x0fffe );
 | |
|     if ( enc== 0x0ffff )
 | |
|       break;
 | |
| 
 | |
|     u8g2_GetGlyphHorizontalProperties(u8g2, enc, &gw, &ox, &dx);  
 | |
|     
 | |
|     /* if there are still more characters, add the delta to the next glyph */
 | |
|     w += dx;    
 | |
|   }
 | |
|   
 | |
|   /* finally calculate the width of the last char */
 | |
|   /* here is another exception, if the last char is a black, use the dx value instead */
 | |
|   if ( enc != ' ' )
 | |
|   {
 | |
|     /* if g was not updated in the for loop (strlen() == 1), then the initial offset x gets removed */
 | |
|     w += gw;
 | |
|     w += ox;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     w += dx;
 | |
|   }
 | |
|   
 | |
|   
 | |
|   return w;
 | |
| 	
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| u8g2_uint_t u8g2_GetStrWidth(u8g2_t *u8g2, const char *s)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_ascii_next;
 | |
|   return u8g2_string_width(u8g2, s);
 | |
| }
 | |
| 
 | |
| u8g2_uint_t u8g2_GetExactStrWidth(u8g2_t *u8g2, const char *s)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_ascii_next;
 | |
|   return u8g2_calculate_exact_string_width(u8g2, s);
 | |
| }
 | |
| 
 | |
| /*
 | |
| source: https://en.wikipedia.org/wiki/UTF-8
 | |
| Bits	from 		to			bytes	Byte 1 		Byte 2 		Byte 3 		Byte 4 		Byte 5 		Byte 6
 | |
|   7 	U+0000 		U+007F 		1 		0xxxxxxx
 | |
| 11 	U+0080 		U+07FF 		2 		110xxxxx 	10xxxxxx
 | |
| 16 	U+0800 		U+FFFF 		3 		1110xxxx 	10xxxxxx 	10xxxxxx
 | |
| 21 	U+10000 	U+1FFFFF 	4 		11110xxx 	10xxxxxx 	10xxxxxx 	10xxxxxx
 | |
| 26 	U+200000 	U+3FFFFFF 	5 		111110xx 	10xxxxxx 	10xxxxxx 	10xxxxxx 	10xxxxxx
 | |
| 31 	U+4000000 	U+7FFFFFFF 	6 		1111110x 	10xxxxxx 	10xxxxxx 	10xxxxxx 	10xxxxxx 	10xxxxxx  
 | |
| */
 | |
| u8g2_uint_t u8g2_GetUTF8Width(u8g2_t *u8g2, const char *str)
 | |
| {
 | |
|   u8g2->u8x8.next_cb = u8x8_utf8_next;
 | |
|   return u8g2_string_width(u8g2, str);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void u8g2_SetFontDirection(u8g2_t *u8g2, uint8_t dir)
 | |
| {
 | |
| #ifdef U8G2_WITH_FONT_ROTATION  
 | |
|   u8g2->font_decode.dir = dir;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 |