Mercurial > foo_out_sdl
diff foosdk/sdk/foobar2000/shared/text_drawing.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/shared/text_drawing.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,230 @@ +#include "shared.h" + + +static bool is_rect_null(const RECT * r) +{ + return r->right <= r->left || r->bottom <= r->top; +} + +UINT SHARED_EXPORT uGetTextHeight(HDC dc) +{ + TEXTMETRIC tm; + POINT pt[2]; + GetTextMetrics(dc,&tm); + pt[0].x = 0; + pt[0].y = tm.tmHeight; + pt[1].x = 0; + pt[1].y = 0; + LPtoDP(dc,pt,2); + + int ret = pt[0].y - pt[1].y; + return ret > 1 ? (unsigned)ret : 1; +} + +static int get_text_width(HDC dc,const TCHAR * src,int len) +{ + if (len<=0) return 0; + else + { + SIZE goatse; + GetTextExtentPoint32(dc,src,len,&goatse); + return goatse.cx; + } +} + +//GetTextExtentPoint32 wrapper, removes color marks +static int get_text_width_color(HDC dc,const TCHAR * src,int len) +{ + int ptr = 0; + int start = 0; + int rv = 0; + if (len<0) len = (int) _tcslen(src); + while(ptr<len) + { + if (src[ptr]==3) + { + rv += get_text_width(dc,src+start,ptr-start); + ptr++; + while(ptr<len && src[ptr]!=3) ptr++; + if (ptr<len) ptr++; + start = ptr; + } + else ptr++; + } + rv += get_text_width(dc,src+start,ptr-start); + return rv; +} + + +static BOOL text_out_colors(HDC dc,const TCHAR * src,int len,int pos_x,int pos_y,const RECT * clip,bool selected,DWORD default_color) +{ + if (clip) + { + if (is_rect_null(clip) || clip->right<=pos_x || clip->bottom<=pos_y) return TRUE; + } + SetTextAlign(dc,TA_LEFT); + SetBkMode(dc,TRANSPARENT); + SetTextColor(dc,selected ? 0xFFFFFF - default_color : default_color); + + int title_ptr = 0; + int textout_start = 0; + int position = pos_x;//item.left+BORDER; + + for(;;) + { + if (title_ptr>=len || src[title_ptr]==3) + { + if (title_ptr>textout_start) + { + int width = get_text_width(dc,src+textout_start,title_ptr-textout_start); + ExtTextOut(dc,position,pos_y,clip ? ETO_CLIPPED : 0,clip,src+textout_start,title_ptr-textout_start,0); + position += width; + textout_start = title_ptr; + } + if (title_ptr>=len) break; + } + if (src[title_ptr]==3) + { + DWORD new_color; + DWORD new_inverted; + bool have_inverted = false; + + if (src[title_ptr+1]==3) {new_color=default_color;title_ptr+=2;} + else + { + title_ptr++; + new_color = _tcstoul(src+title_ptr,0,16); + while(title_ptr<len && src[title_ptr]!=3) + { + if (!have_inverted && src[title_ptr-1]=='|') + { + new_inverted = _tcstoul(src+title_ptr,0,16); + have_inverted = true; + } + title_ptr++; + } + if (title_ptr<len) title_ptr++; + } + if (selected) new_color = have_inverted ? new_inverted : 0xFFFFFF - new_color; + SetTextColor(dc,new_color); + textout_start = title_ptr; + } + else + { + title_ptr = (int)( CharNext(src+title_ptr)-src ); + } + } + return TRUE; +} + +static BOOL text_out_colors_tab(HDC dc,const TCHAR * display,int display_len,const RECT * item,int border,const RECT * base_clip,bool selected,DWORD default_color,bool columns) +{ + RECT clip; + if (base_clip) + IntersectRect(&clip,base_clip,item); + else clip = *item; + + if (is_rect_null(&clip)) return TRUE; + + int pos_y = item->top + (item->bottom-item->top - (int)uGetTextHeight(dc)) / 2; + + int n_tabs = 0; + int total_width = 0; + { + int start = 0; + int n; + for(n=0;n<display_len;n++) + { + if (display[n]=='\t') + { + if (start<n) total_width += get_text_width_color(dc,display+start,n-start) + 2*border; + start = n+1; + n_tabs++; + } + } + if (start<display_len) + { + total_width += get_text_width_color(dc,display+start,display_len-start) + 2*border; + } + } + + int tab_total = item->right - item->left; + if (!columns) tab_total -= total_width; + int ptr = display_len; + int tab_ptr = 0; + int written = 0; + int clip_x = item->right; + do + { + int ptr_end = ptr; + while(ptr>0 && display[ptr-1]!='\t') ptr--; + const TCHAR * t_string = display + ptr; + int t_length = ptr_end - ptr; + if (t_length>0) + { + int t_width = get_text_width_color(dc,t_string,t_length) + border*2; + + int pos_x; + int pos_x_right; + + if (!columns) + { + pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) - written; + } + else + { + if (tab_ptr==0) pos_x_right = item->right; + else pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) + t_width; + } + + if (ptr==0) + { + pos_x = item->left; + } + else + { + pos_x = pos_x_right - t_width ; + if (pos_x<item->left) pos_x = item->left; + } + + RECT t_clip = clip; + + if (t_clip.right > clip_x) t_clip.right = clip_x; + + text_out_colors(dc,t_string,t_length,pos_x+border,pos_y,&t_clip,selected,default_color); + + if (clip_x>pos_x) clip_x = pos_x; + + written += t_width; + } + + if (ptr>0) + { + ptr--;//tab char + tab_ptr++; + } + } + while(ptr>0); + + return TRUE; +} + +extern "C" { + +BOOL SHARED_EXPORT uTextOutColors(HDC dc,const char * p_text,UINT len,int x,int y,const RECT * clip,BOOL is_selected,DWORD default_color) +{ + try { + pfc::stringcvt::string_os_from_utf8 temp(p_text); + return text_out_colors(dc,temp,pfc::downcast_guarded<int>(temp.length()),x,y,clip,!!is_selected,default_color); + } catch(...) {return FALSE;} +} + +BOOL SHARED_EXPORT uTextOutColorsTabbed(HDC dc,const char * p_text,UINT len,const RECT * item,int border,const RECT * clip,BOOL selected,DWORD default_color,BOOL use_columns) +{ + try { + pfc::stringcvt::string_os_from_utf8 temp(p_text); + return text_out_colors_tab(dc,temp,pfc::downcast_guarded<int>(temp.length()),item,border,clip,!!selected,default_color,!!use_columns); + } catch(...) {return FALSE;} +} + +} \ No newline at end of file
