diff --git a/cppsrc/U8g2lib.h b/cppsrc/U8g2lib.h index 9a7f9602..6492d43e 100644 --- a/cppsrc/U8g2lib.h +++ b/cppsrc/U8g2lib.h @@ -144,6 +144,12 @@ class U8G2 : public Print /* u8g2 */ +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + void setMaxClipWindow(void) { u8g2_SetMaxClipWindow(&u8g2); } + void setClipWindow(u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, u8g2_uint_t clip_x1, u8g2_uint_t clip_y1) { + u8g2_SetClipWindow(&u8g2, clip_x0, clip_y0, clip_x1, clip_y1 ); } +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + u8g2_uint_t getDisplayHeight(void) { return u8g2_GetDisplayHeight(&u8g2); } u8g2_uint_t getDisplayWidth(void) { return u8g2_GetDisplayWidth(&u8g2); } diff --git a/csrc/u8g2.h b/csrc/u8g2.h index 664e8df3..d607570d 100644 --- a/csrc/u8g2.h +++ b/csrc/u8g2.h @@ -82,6 +82,15 @@ */ #define U8G2_WITH_ONE_PIXEL_OPTIMIZATION +/* + Enable clip window support: + void u8g2_SetMaxClipWindow(u8g2_t *u8g2) + void u8g2_SetClipWindow(u8g2_t *u8g2, u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, u8g2_uint_t clip_x1, u8g2_uint_t clip_y1 ) + Setting a clip window will restrict all drawing to this window. + Clip window support requires about 200 bytes flash memory on AVR systems +*/ +//#define U8G2_WITH_CLIP_WINDOW_SUPPORT + /* The following macro enables the HVLine speed optimization. @@ -290,7 +299,7 @@ struct u8g2_struct u8g2_uint_t buf_y0; u8g2_uint_t buf_y1; - /* display dimensions in pixel for the user, calculated in u8g2_update_dimension_common(), used in u8g2_draw_hv_line_2dir() */ + /* display dimensions in pixel for the user, calculated in u8g2_update_dimension_common() */ u8g2_uint_t width; u8g2_uint_t height; @@ -302,6 +311,15 @@ struct u8g2_struct u8g2_uint_t user_y0; /* upper edge of the buffer */ u8g2_uint_t user_y1; /* lower edge of the buffer (excluded) */ +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + /* clip window */ + u8g2_uint_t clip_x0; /* left corner of the clip window */ + u8g2_uint_t clip_x1; /* right corner of the clip window (excluded) */ + u8g2_uint_t clip_y0; /* upper edge of the clip window */ + u8g2_uint_t clip_y1; /* lower edge of the clip window (excluded) */ +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + + /* information about the current font */ const uint8_t *font; /* current font for all text procedures */ // removed: const u8g2_kerning_t *kerning; /* can be NULL */ @@ -311,6 +329,11 @@ struct u8g2_struct u8g2_font_decode_t font_decode; /* new font decode structure */ u8g2_font_info_t font_info; /* new font info structure */ +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + /* 1 of there is an intersection between user_?? and clip_?? box */ + uint8_t is_page_clip_window_intersection; +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + uint8_t font_height_mode; int8_t font_ref_ascent; int8_t font_ref_descent; @@ -325,12 +348,6 @@ struct u8g2_struct // the following variable should be renamed to is_buffer_auto_clear uint8_t is_auto_page_clear; /* set to 0 to disable automatic clear of the buffer in firstPage() and nextPage() */ -// removed, there is now the new index table -//#ifdef __unix__ -// uint16_t last_unicode; -// const uint8_t *last_font_data; -//#endif - }; #define u8g2_GetU8x8(u8g2) ((u8x8_t *)(u8g2)) @@ -399,6 +416,9 @@ extern const u8g2_cb_t u8g2_cb_mirror; */ +void u8g2_SetMaxClipWindow(u8g2_t *u8g2); +void u8g2_SetClipWindow(u8g2_t *u8g2, u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, u8g2_uint_t clip_x1, u8g2_uint_t clip_y1 ); + void u8g2_SetupBuffer(u8g2_t *u8g2, uint8_t *buf, uint8_t tile_buf_height, u8g2_draw_ll_hvline_cb ll_hvline_cb, const u8g2_cb_t *u8g2_cb); void u8g2_SetDisplayRotation(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb); diff --git a/csrc/u8g2_hvline.c b/csrc/u8g2_hvline.c index 8ca947ba..a98374e2 100644 --- a/csrc/u8g2_hvline.c +++ b/csrc/u8g2_hvline.c @@ -45,6 +45,8 @@ #include "u8g2.h" #include +/*==========================================================*/ +/* intersection procedure */ /* Description: @@ -114,6 +116,10 @@ static uint8_t u8g2_clip_intersection2(u8g2_uint_t *ap, u8g2_uint_t *len, u8g2_u } + +/*==========================================================*/ +/* draw procedures */ + /* x,y Upper left position of the line within the pixel buffer len length of the line in pixel, len must not be 0 @@ -129,7 +135,7 @@ void u8g2_draw_hv_line_2dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uin /* clipping happens before the display rotation */ /* transform to pixel buffer coordinates */ - y -= u8g2->tile_curr_row*8; + y -= u8g2->pixel_curr_row; u8g2->ll_hvline(u8g2, x, y, len, dir); } @@ -146,48 +152,52 @@ void u8g2_DrawHVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len /* Make a call to the callback function (e.g. u8g2_draw_l90_r0). */ /* The callback may rotate the hv line */ /* after rotation this will call u8g2_draw_hv_line_4dir() */ - if ( len != 0 ) - { - /* convert to two directions */ - if ( len > 1 ) +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + if ( u8g2->is_page_clip_window_intersection != 0 ) +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + if ( len != 0 ) { - if ( dir == 2 ) + + /* convert to two directions */ + if ( len > 1 ) { - x -= len; - x++; + if ( dir == 2 ) + { + x -= len; + x++; + } + else if ( dir == 3 ) + { + y -= len; + y++; + } } - else if ( dir == 3 ) + dir &= 1; + + /* clip against the user window */ + if ( dir == 0 ) { - y -= len; - y++; + if ( y < u8g2->user_y0 ) + return; + if ( y >= u8g2->user_y1 ) + return; + if ( u8g2_clip_intersection2(&x, &len, u8g2->user_x0, u8g2->user_x1) == 0 ) + return; } + else + { + if ( x < u8g2->user_x0 ) + return; + if ( x >= u8g2->user_x1 ) + return; + if ( u8g2_clip_intersection2(&y, &len, u8g2->user_y0, u8g2->user_y1) == 0 ) + return; + } + + + u8g2->cb->draw_l90(u8g2, x, y, len, dir); } - dir &= 1; - - /* clip against the user window */ - if ( dir == 0 ) - { - if ( y < u8g2->user_y0 ) - return; - if ( y >= u8g2->user_y1 ) - return; - if ( u8g2_clip_intersection2(&x, &len, u8g2->user_x0, u8g2->user_x1) == 0 ) - return; - } - else - { - if ( x < u8g2->user_x0 ) - return; - if ( x >= u8g2->user_x1 ) - return; - if ( u8g2_clip_intersection2(&y, &len, u8g2->user_y0, u8g2->user_y1) == 0 ) - return; - } - - - u8g2->cb->draw_l90(u8g2, x, y, len, dir); - } } void u8g2_DrawHLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len) diff --git a/csrc/u8g2_setup.c b/csrc/u8g2_setup.c index 6fca20f5..ccd8395a 100644 --- a/csrc/u8g2_setup.c +++ b/csrc/u8g2_setup.c @@ -38,6 +38,30 @@ #include +/*============================================*/ + + +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT +void u8g2_SetMaxClipWindow(u8g2_t *u8g2) +{ + u8g2->clip_x0 = 0; + u8g2->clip_y0 = 0; + u8g2->clip_x1 = (u8g2_uint_t)~(u8g2_uint_t)0; + u8g2->clip_y1 = (u8g2_uint_t)~(u8g2_uint_t)0; +} +#endif + +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT +void u8g2_SetClipWindow(u8g2_t *u8g2, u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, u8g2_uint_t clip_x1, u8g2_uint_t clip_y1 ) +{ + u8g2->clip_x0 = clip_x0; + u8g2->clip_y0 = clip_y0; + u8g2->clip_x1 = clip_x1; + u8g2->clip_y1 = clip_y1; + u8g2->cb->update(u8g2); +} +#endif + /*============================================*/ /* This procedure is called after setting up the display (u8x8 structure). @@ -64,6 +88,9 @@ void u8g2_SetupBuffer(u8g2_t *u8g2, uint8_t *buf, uint8_t tile_buf_height, u8g2_ u8g2->is_auto_page_clear = 1; u8g2->cb = u8g2_cb; +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + u8g2_SetMaxClipWindow(u8g2); /* assign a clip window before the update() callback is called */ +#endif u8g2->cb->update(u8g2); u8g2_SetFontPosBaseline(u8g2); /* issue 195 */ @@ -96,13 +123,14 @@ void u8g2_SetDisplayRotation(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb) static void u8g2_update_dimension_common(u8g2_t *u8g2) { + const u8x8_display_info_t *display_info = u8g2_GetU8x8(u8g2)->display_info; u8g2_uint_t t; t = u8g2->tile_buf_height; t *= 8; u8g2->pixel_buf_height = t; - t = u8g2_GetU8x8(u8g2)->display_info->tile_width; + t = display_info->tile_width; #ifndef U8G2_16BIT if ( t >= 32 ) t = 31; @@ -116,8 +144,8 @@ static void u8g2_update_dimension_common(u8g2_t *u8g2) t = u8g2->tile_buf_height; /* handle the case, where the buffer is larger than the (remaining) part of the display */ - if ( t + u8g2->tile_curr_row > u8g2_GetU8x8(u8g2)->display_info->tile_height ) - t = u8g2_GetU8x8(u8g2)->display_info->tile_height - u8g2->tile_curr_row; + if ( t + u8g2->tile_curr_row > display_info->tile_height ) + t = display_info->tile_height - u8g2->tile_curr_row; t *= 8; u8g2->buf_y0 = u8g2->pixel_curr_row; @@ -126,17 +154,47 @@ static void u8g2_update_dimension_common(u8g2_t *u8g2) #ifdef U8G2_16BIT - u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_width; - u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_height; + u8g2->width = display_info->pixel_width; + u8g2->height = display_info->pixel_height; #else u8g2->width = 240; - if ( u8g2_GetU8x8(u8g2)->display_info->pixel_width <= 240 ) - u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_width; - u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_height; + if ( display_info->pixel_width <= 240 ) + u8g2->width = display_info->pixel_width; + u8g2->height = display_info->pixel_height; #endif } +/*==========================================================*/ +/* apply clip window */ + +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT +static void u8g2_apply_clip_window(u8g2_t *u8g2) +{ + /* check aganst the current user_??? window */ + if ( u8g2_IsIntersection(u8g2, u8g2->clip_x0, u8g2->clip_y0, u8g2->clip_x1, u8g2->clip_y1) == 0 ) + { + u8g2->is_page_clip_window_intersection = 0; + } + else + { + u8g2->is_page_clip_window_intersection = 1; + + if ( u8g2->user_x0 < u8g2->clip_x0 ) + u8g2->user_x0 = u8g2->clip_x0; + if ( u8g2->user_x1 > u8g2->clip_x1 ) + u8g2->user_x1 = u8g2->clip_x1; + if ( u8g2->user_y0 < u8g2->clip_y0 ) + u8g2->user_y0 = u8g2->clip_y0; + if ( u8g2->user_y1 > u8g2->clip_y1 ) + u8g2->user_y1 = u8g2->clip_y1; + } +} +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + +/*==========================================================*/ + + void u8g2_update_dimension_r0(u8g2_t *u8g2) { u8g2_update_dimension_common(u8g2); @@ -147,6 +205,10 @@ void u8g2_update_dimension_r0(u8g2_t *u8g2) u8g2->user_y0 = u8g2->buf_y0; u8g2->user_y1 = u8g2->buf_y1; +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + u8g2_apply_clip_window(u8g2); +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + // printf("x0=%d x1=%d y0=%d y1=%d\n", // u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1); } @@ -164,6 +226,9 @@ void u8g2_update_dimension_r1(u8g2_t *u8g2) u8g2->user_y0 = 0; u8g2->user_y1 = u8g2->height; /* pixel_buf_width replaced with height (which is the real pixel width) */ +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + u8g2_apply_clip_window(u8g2); +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ //printf("x0=%d x1=%d y0=%d y1=%d\n", // u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1); } @@ -182,6 +247,9 @@ void u8g2_update_dimension_r2(u8g2_t *u8g2) u8g2->user_y0 = u8g2->height - u8g2->buf_y1; u8g2->user_y1 = u8g2->height - u8g2->buf_y0; +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + u8g2_apply_clip_window(u8g2); +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ // printf("x0=%d x1=%d y0=%d y1=%d\n", // u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1); } @@ -203,6 +271,9 @@ void u8g2_update_dimension_r3(u8g2_t *u8g2) u8g2->user_y0 = 0; u8g2->user_y1 = u8g2->height; /* pixel_buf_width replaced with height (pixel_width) */ +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + u8g2_apply_clip_window(u8g2); +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ // printf("x0=%d x1=%d y0=%d y1=%d\n", // u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1); } diff --git a/sys/arduino/u8g2_page_buffer/HelloWorld/HelloWorld.ino b/sys/arduino/u8g2_page_buffer/HelloWorld/HelloWorld.ino index c08cca0d..6d02c6ee 100644 --- a/sys/arduino/u8g2_page_buffer/HelloWorld/HelloWorld.ino +++ b/sys/arduino/u8g2_page_buffer/HelloWorld/HelloWorld.ino @@ -38,6 +38,8 @@ 8440 152 420 9012 2334 HelloWorld.elf 8422 + 8470 + 8676 */