* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
		
			
				
	
	
		
			1162 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1162 lines
		
	
	
		
			34 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_long_t u8g2_string_width(u8g2_t* u8g2, const char* str) U8G2_NOINLINE;
 | 
						|
static u8g2_long_t u8g2_string_width(u8g2_t* u8g2, const char* str) {
 | 
						|
    uint16_t e;
 | 
						|
    u8g2_uint_t dx;
 | 
						|
    u8g2_long_t w;
 | 
						|
 | 
						|
    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_long_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
 | 
						|
}
 |