From 7b66f6a82e86c89d4e3aadcf51dba4b51dac86fe Mon Sep 17 00:00:00 2001 From: anod <182859762@qq.com> Date: Sat, 15 Oct 2022 17:12:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAatp=5Fselect=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E9=BB=98=E8=AE=A4=E9=80=89=E4=B8=AD=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=85=88build=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=E8=AF=95=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/arm11/acf.h | 9 ++++++ include/arm11/atp.h | 4 +++ source/arm11/acf.c | 59 ++++++++++++++++++++++++++++++++------ source/arm11/atp.c | 27 ++++++++++------- source/arm11/filebrowser.c | 33 +++++++++++++++++---- 5 files changed, 108 insertions(+), 24 deletions(-) diff --git a/include/arm11/acf.h b/include/arm11/acf.h index 3826641..8f613f4 100644 --- a/include/arm11/acf.h +++ b/include/arm11/acf.h @@ -41,6 +41,15 @@ extern acf_error_t acf_initialize( INPUT(acf_text_t) filename_of_acf_font ); +extern acf_error_t acf_calculate( + INPUT(acf_rectedge_t) width_in_pixel_of_canvas, + INPUT(acf_text_t) text_painting_in_utf8, + + OUTPUT(acf_rectedge_t) using_width_in_pixel_of_canvas, + OUTPUT(acf_counter_t) rendered_char_counting, + OUTPUT(acf_text_t) text_not_rendered_in_utf8 +); + extern acf_canvas_t acf_get_canvas( INPUT(acf_rectedge_t) width_in_pixel_of_canvas, INPUT(acf_text_t) text_painting_in_utf8, diff --git a/include/arm11/atp.h b/include/arm11/atp.h index 3929378..93a78bb 100644 --- a/include/arm11/atp.h +++ b/include/arm11/atp.h @@ -60,12 +60,14 @@ typedef struct { typedef atp_error_t (*atp_lineprovider_t)( INPUT(atp_callerdata_t) some_data_provided_by_caller, INPUT(atp_counter_t) line_index_of_this_page, + OUTPUT(atp_linecfg_t) configuration_of_this_line ); typedef atp_error_t (*atp_itemprovider_t)( INPUT(atp_callerdata_t) some_data_provided_by_caller, INPUT(atp_counter_t) index_of_current_option_item, + OUTPUT(atp_itemcfg_t) configuration_of_current_option_item ); @@ -91,6 +93,8 @@ extern atp_error_t atp_select( INPUT(atp_itemprovider_t) item_information_provider, INPUT(atp_keyhandler_t) extra_key_handler, INPUT(atp_callerdata_t) some_data_from_caller, + INPUT(atp_counter_t) index_of_default_selected_item, + OUTPUT(atp_itemval_t) value_of_select_item ); diff --git a/source/arm11/acf.c b/source/arm11/acf.c index abd26c5..e81b78a 100644 --- a/source/arm11/acf.c +++ b/source/arm11/acf.c @@ -279,7 +279,7 @@ static int render_unicode(FHandle fd, int *x, unsigned width, unsigned height, u // render // 从上往下(y从大到小,x从小到大)进行绘制 - int px = *x, py = -1-gblfont.offsety; // px/py不参与计算位置 + int px = *x, py = -1-gblfont.offsety; // px/py不参与计算位置 int cx = px + bbx[2], cy = py + bbx[1] + bbx[3]; // cx/cy计算位置进行绘制 // 先检查宽度 @@ -287,17 +287,20 @@ static int render_unicode(FHandle fd, int *x, unsigned width, unsigned height, u return 1; // 绘制 - for (int i = 0; i < bbx[1]; ++i) + if ( ram != NULL ) { - for (int j = 0; j < bbx[0]; ++j) + for (int i = 0; i < bbx[1]; ++i) { - int tx = cx+j, ty = cy-i; - // see: https://www.zhihu.com/question/264505093/answer/281849883 - if( ( tx | ((int)width-tx) | ty | ((int)height-ty) ) > 0 ) // 0 <= tx && tx < width && 0 <= ty && ty <= height + for (int j = 0; j < bbx[0]; ++j) { - if( BIT_AT_POS(glyph, bbx[0] * i + j) ) + int tx = cx+j, ty = cy-i; + // see: https://www.zhihu.com/question/264505093/answer/281849883 + if( ( tx | ((int)width-tx) | ty | ((int)height-ty) ) > 0 ) // 0 <= tx && tx < width && 0 <= ty && ty <= height { - SET_AT_POS( ram, PIX_IN_LINE(tx, ty, width) ); + if( BIT_AT_POS(glyph, bbx[0] * i + j) ) + { + SET_AT_POS( ram, PIX_IN_LINE(tx, ty, width) ); + } } } } @@ -387,3 +390,43 @@ acf_canvas_t acf_get_canvas(acf_rectedge_t width, acf_text_t text, acf_rectedge_ fClose(font); return canvas; } + +acf_canvas_t acf_calculate(acf_rectedge_t width, acf_text_t text, acf_rectedge_t *realwidth, acf_counter_t *renderedcnt, acf_text_t *rest) +{ + FHandle font; + if( gblfont.filename == NULL || RES_OK != fOpen(&font, gblfont.filename, FA_OPEN_EXISTING | FA_READ) ) + { + // log + return ACFONT_NOT_FOUND; + } + + uint32_t unicode; + int linex = 0; + int rendered_count = 0; + const char *utf8_line = text; + + for (const char *next = next_unicode(utf8_line, &unicode); + next != NULL; + next = next_unicode(utf8_line, &unicode)) + { + int error = render_unicode(font, &linex, width, gblfont.height, unicode, NULL); + if( error > 0 ) break; + else if( error < 0 ) error = render_unicode(font, &linex, width, gblfont.height, '?', NULL); + + if( error ) + { + fClose(font); + return error; + } + + utf8_line = next; + ++rendered_count; + } + + if( realwidth != NULL ) *realwidth = linex; + if( renderedcnt != NULL ) *renderedcnt = rendered_count; + if( rest != NULL ) *rest = utf8_line; + + fClose(font); + return 0; +} diff --git a/source/arm11/atp.c b/source/arm11/atp.c index e1b8d2f..4ac572b 100644 --- a/source/arm11/atp.c +++ b/source/arm11/atp.c @@ -223,11 +223,11 @@ static void draw_options( int start_row, int start_idx, int option_cnt, int sele else draw_options( 0, idx_top - title_len, cnt, item_sel, provider, data ); \ } -atp_error_t atp_select( atp_text_t title, atp_counter_t cnt, atp_itemprovider_t provider, atp_keyhandler_t handler, atp_callerdata_t data, atp_itemval_t *res ) +atp_error_t atp_select( atp_text_t title, atp_counter_t cnt, atp_itemprovider_t provider, atp_keyhandler_t handler, atp_callerdata_t data, atp_counter_t index, atp_itemval_t *res ) { uint8_t title_offset[TITLE_MAX]; - int idx_top = 0, title_len = 1; - int item_sel = 0; + int item_sel = index < cnt ? index : 0; + int title_len = 1; atp_itemcfg_t config; screen_clean(); @@ -236,17 +236,22 @@ atp_error_t atp_select( atp_text_t title, atp_counter_t cnt, atp_itemprovider_t const char *cursor = title; for( int i=0; i < TITLE_MAX; ++i ) { - const char *next = easy_put( cursor, ATP_PLACEMENT_LEFT, ATP_COLOR_LIGHT, i ); - if( *next == '\0' ) break; + const char *next; + if( 0 == acf_calculate( CONTAINER_RECT_WIDTH, cursor, NULL, NULL, &next ) ) + { + if( *next == '\0' ) break; - title_offset[i] = next - cursor; - ++title_len; - cursor = next; + title_offset[i] = next - cursor; + ++title_len; + cursor = next; + } } for( int i=title_len; i < TITLE_MAX; ++i ) title_offset[i] = 0; // draw item - draw_options( title_len, 0, cnt, item_sel, provider, data ); + int idx_top = item_sel + title_len; + idx_top = idx_top - idx_top%CONTAINER_MAX_LINES; + REFRESH_PAGE; while( 1 ) { @@ -338,7 +343,9 @@ atp_error_t atp_select( atp_text_t title, atp_counter_t cnt, atp_itemprovider_t // 更新item_sel item_sel = idx_top + item_sel % CONTAINER_MAX_LINES; - if( item_sel >= (int)cnt ) item_sel = cnt-1; + if( idx_top == 0 && item_sel >= CONTAINER_MAX_LINES-title_len ) + item_sel = 0; + else if( item_sel >= (int)cnt ) item_sel = cnt-1; // 更新view REFRESH_PAGE; diff --git a/source/arm11/filebrowser.c b/source/arm11/filebrowser.c index 819a7e2..882295e 100644 --- a/source/arm11/filebrowser.c +++ b/source/arm11/filebrowser.c @@ -76,7 +76,7 @@ int dlistCompare(const void *a, const void *b) return res; } -static Result scanDir(const char *const path, DirList *const dList, const char *const filter) +static Result scanDir(const char *const path, DirList *const dList, const char *const filter, const char *match, int *index) { FILINFO *const fis = (FILINFO*)malloc(sizeof(FILINFO) * DIR_READ_BLOCKS); if(fis == NULL) return RES_OUT_OF_MEM; @@ -127,6 +127,18 @@ scanEnd: qsort(dList->ptrs, dList->num, sizeof(char*), dlistCompare); + if( match != NULL ) + { + for( int i=0; i < dList->num; ++i ) + { + if( strcmp(match, &dList->ptrs[i][1]) == 0 ) + { + *index = i; + break; + } + } + } + return res; } @@ -156,6 +168,7 @@ atp_error_t display_empty( atp_callerdata_t, atp_counter_t, atp_linecfg_t *confi if(*(tmpPathPtr - 1) == ':') tmpPathPtr++; \ *tmpPathPtr = '\0'; \ scan = 1; \ + upFrom = tmpPathPtr + 1; \ } Result browseFiles(const char *const basePath, char selected[512]) { @@ -170,15 +183,18 @@ Result browseFiles(const char *const basePath, char selected[512]) if(dList == NULL) return RES_OUT_OF_MEM; Result res; - if((res = scanDir(curDir, dList, ".gba")) != RES_OK) goto end; + if((res = scanDir(curDir, dList, ".gba", NULL, NULL)) != RES_OK) goto end; - while( 1 ){ + const char *upFrom = NULL; + int selecting = 0; + while( 1 ) + { atp_itemval_t value; atp_boolean_t scan = 0; atp_error_t error; const u32 count = dList->num; if( count > 0 ) - error = atp_select( curDir, count, display_folder, NULL, (atp_callerdata_t)dList, &value ); + error = atp_select( curDir, count, display_folder, NULL, (atp_callerdata_t)dList, selecting, &value ); else error = atp_show( 1, display_empty, NULL ); u32 pathLen = strlen(curDir); @@ -210,7 +226,12 @@ Result browseFiles(const char *const basePath, char selected[512]) safeStrcpy( selected, curDir, 512 ); break; } - else scan = 1; + else + { + scan = 1; + selecting = 0; + upFrom = NULL; + } } } else if( error == ATP_NO_ACTION ) @@ -220,7 +241,7 @@ Result browseFiles(const char *const basePath, char selected[512]) if( scan ) { - if(RES_OK != (res = scanDir(curDir, dList, ".gba")) ) + if(RES_OK != (res = scanDir(curDir, dList, ".gba", upFrom, &selecting)) ) break; } }