From 506a1a2ce7d96efad938c2f004c535b65898cc3c Mon Sep 17 00:00:00 2001 From: GetAway Date: Sat, 26 Nov 2016 12:33:49 +0100 Subject: [PATCH] port code from martii for a smoother rendering & better RC handling --- gfx.c | 54 ++++--- gfx.h | 1 - io.c | 77 +++++++-- io.h | 4 +- msgbox.c | 153 +++++++++--------- msgbox.h | 44 ++--- text.c | 472 +++++++++++++++++++++++++++++++++--------------------- text.h | 4 +- txtform.c | 13 +- 9 files changed, 493 insertions(+), 329 deletions(-) diff --git a/gfx.c b/gfx.c index d49bb90..fadbb28 100644 --- a/gfx.c +++ b/gfx.c @@ -4,13 +4,13 @@ void RenderBox(int _sx, int _sy, int _ex, int _ey, int rad, int col) { int F,R=rad,ssx=startx+_sx,ssy=starty+_sy,dxx=_ex-_sx,dyy=_ey-_sy,rx,ry,wx,wy,count; - unsigned char *pos=(lbb+(ssx<<2)+fix_screeninfo.line_length*ssy); - unsigned char *pos0, *pos1, *pos2, *pos3, *i; - unsigned char pix[4]={bl[col],gn[col],rd[col],tr[col]}; + uint32_t *pos = lbb + ssx + stride * ssy; + uint32_t *pos0, *pos1, *pos2, *pos3, *i; + uint32_t pix = bgra[col]; if (dxx<0) { - printf("[msgbox] RenderBox called with dx < 0 (%d)\n", dxx); + printf("msgbox RenderBox called with dx < 0 (%d)\n", dxx); dxx=0; } @@ -48,10 +48,11 @@ void RenderBox(int _sx, int _sy, int _ex, int _ey, int rad, int col) rx=R-ssx; ry=R-ssy; - pos0=pos+((dyy-ry)*fix_screeninfo.line_length); - pos1=pos+(ry*fix_screeninfo.line_length); - pos2=pos+(rx*fix_screeninfo.line_length); - pos3=pos+((dyy-rx)*fix_screeninfo.line_length); + pos0=pos+(dyy-ry)*stride; + pos1=pos+ry*stride; + pos2=pos+rx*stride; + pos3=pos+(dyy-rx)*stride; + while (ssx <= ssy) { rx=R-ssx; @@ -59,18 +60,20 @@ void RenderBox(int _sx, int _sy, int _ex, int _ey, int rad, int col) wx=rx<<1; wy=ry<<1; - for(i=pos0+(rx<<2); i #include #include -#include #include #include #include @@ -15,20 +14,20 @@ #include #include #include -#include "msgbox.h" - +#include +#include #include "io.h" +#include "msgbox.h" -#define RC_DEVICE "/dev/input/nevis_ir" extern int instance; struct input_event ev; static unsigned short rccode=-1; -static int rc = 0; +static int rc; int InitRC(void) { - rc = open(RC_DEVICE, O_RDONLY); + rc = open(RC_DEVICE, O_RDONLY | O_CLOEXEC); if(rc == -1) { perror("msgbox "); @@ -60,19 +59,65 @@ int RCKeyPressed(void) return 0; } +void ClearRC(void) +{ + struct pollfd pfd; + pfd.fd = rc; + pfd.events = POLLIN; + pfd.revents = 0; -int GetRCCode(void) + do + poll(&pfd, 1, 300); + while(read(rc, &ev, sizeof(ev)) == sizeof(ev)); +} + +int GetRCCode(int timeout_in_ms) { - int rv; - - if(!RCKeyPressed() || (get_instance()>instance)) + int rv = -1; + + if (get_instance()>instance) { - return -1; + return rv; } - rv=rccode; - while(RCKeyPressed()); - - return rv; -} + if (timeout_in_ms) { + struct pollfd pfd; + struct timeval tv; + uint64_t ms_now, ms_final; + + pfd.fd = rc; + pfd.events = POLLIN; + pfd.revents = 0; + + gettimeofday( &tv, NULL ); + ms_now = tv.tv_usec/1000 + tv.tv_sec * 1000; + if (timeout_in_ms > 0) + ms_final = ms_now + timeout_in_ms; + else + ms_final = UINT64_MAX; + while (ms_final > ms_now) { + switch(poll(&pfd, 1, timeout_in_ms)) { + case -1: + perror("GetRCCode: poll() failed"); + case 0: + return -1; + default: + ; + } + if(RCKeyPressed()) { + rv = rccode; + while(RCKeyPressed()); + return rv; + } + gettimeofday( &tv, NULL ); + ms_now = tv.tv_usec/1000 + tv.tv_sec * 1000; + if (timeout_in_ms > 0) + timeout_in_ms = (int)(ms_final - ms_now); + } + } else if(RCKeyPressed()) { + rv = rccode; + while(RCKeyPressed()); + } + return rv; +} diff --git a/io.h b/io.h index 1619ae7..2cb93f8 100644 --- a/io.h +++ b/io.h @@ -1,5 +1,4 @@ #ifndef __IO_H__ - #define __IO_H__ #define RC_DEVICE "/dev/input/nevis_ir" @@ -7,6 +6,7 @@ int InitRC(void); int CloseRC(void); int RCKeyPressed(void); -int GetRCCode(void); +int GetRCCode(int); +void ClearRC(void); #endif diff --git a/msgbox.c b/msgbox.c index 81dbc87..c1cf5f4 100644 --- a/msgbox.c +++ b/msgbox.c @@ -8,7 +8,7 @@ #include "gfx.h" #include "txtform.h" -#define M_VERSION 1.18 +#define M_VERSION 1.20 #define NCF_FILE "/var/tuxbox/config/neutrino.conf" #define HDF_FILE "/tmp/.msgbox_hidden" @@ -18,27 +18,6 @@ // if font is not in usual place, we look here: #define FONT "/share/fonts/neutrino.ttf" -FT_Error error; -FT_Library library; -FTC_Manager manager; -FTC_SBitCache cache; -FTC_SBit sbit; -#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0 -FTC_Image_Desc desc; -#else -FTC_ImageTypeRec desc; -#endif - -FT_Face face; -FT_Bool use_kerning; -FT_UInt prev_glyphindex; - -char *butmsg[MAX_BUTTONS]; -struct fb_fix_screeninfo fix_screeninfo; -struct fb_var_screeninfo var_screeninfo; -int startx, starty, sx, ex, sy, ey, debounce, rblock; -int fb; - // CMCST, CMCS, CMCT, CMC, CMCIT, CMCI, CMHT, CMH // WHITE, BLUE0, TRANSP, CMS, ORANGE, GREEN, YELLOW, RED @@ -51,6 +30,8 @@ unsigned char rd[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, unsigned char tr[] = { 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +uint32_t bgra[20]; + void TrimString(char *strg); // OSD stuff @@ -59,18 +40,18 @@ static char spres[][5]={"","_crt","_lcd"}; char *line_buffer=NULL, *title=NULL; int size=24, type=0, timeout=0, refresh=3, flash=0, selection=0, tbuttons=0, buttons=0, bpline=3, echo=0, absolute=0, mute=1, header=1, cyclic=1; -int rbutt[16],hide=0,radius=10; +char *butmsg[16]; +int rbutt[16],hide=0,radius=11; // Misc const char NOMEM[]="msgbox \n"; char TMP_FILE[64]="/tmp/msgbox.tmp"; -unsigned char *lfb = 0, *lbb = 0, *obb = 0, *hbb = 0, *ibb = 0; -unsigned char nstr[BUFSIZE]=""; -unsigned char *trstr; -unsigned char sc[8]={'a','o','u','A','O','U','z','d'}, tc[8]={0xE4,0xF6,0xFC,0xC4,0xD6,0xDC,0xDF,0xB0}; -unsigned char rc = ' '; +uint32_t *lfb = NULL, *lbb = NULL, *obb = NULL, *hbb = NULL, *ibb = NULL; +char nstr[BUFSIZE]={0}; +char *trstr; const char INST_FILE[]="/tmp/rc.locked"; int instance=0; +int stride; int get_instance(void) { @@ -87,9 +68,10 @@ int rval=0; void put_instance(int pval) { +FILE *fh; + if(pval) { - FILE *fh; if((fh=fopen(INST_FILE,"w"))!=NULL) { fputc(pval,fh); @@ -102,21 +84,23 @@ void put_instance(int pval) } } -static void quit_signal() +static void quit_signal(int sig) { put_instance(get_instance()-1); - printf("msgbox Version %.2f killed\n",M_VERSION); + printf("%s Version %.2f killed, signal %d\n", "msgbox", M_VERSION, sig); exit(1); } int Read_Neutrino_Cfg(char *entry) { FILE *nfh; +char tstr [512], *cfptr=NULL; int rv=-1; if((nfh=fopen(NCF_FILE,"r"))!=NULL) { - char tstr [512]={0}, *cfptr=NULL; + tstr[0]=0; + while((!feof(nfh)) && ((strstr(tstr,entry)==NULL) || ((cfptr=strchr(tstr,'='))==NULL))) { fgets(tstr,500,nfh); @@ -195,7 +179,11 @@ char *pt1=strdup(sptr),*pt2,*pt3; if(strlen(pt2)) { rbutt[btn]=tbuttons; - butmsg[btn]=strdup(pt2); + size_t l = strlen(pt2); + char *t = (char *)alloca(l * 4 + 1); + memcpy(t, pt2, l + 1); + TranslateString(t, l * 4); + butmsg[btn]=strdup(t); CatchTabs(butmsg[btn++]); } if(run) @@ -221,17 +209,17 @@ static int psx, psy, pxw, pyw, myo=0, buttx=80, butty=30, buttdx=20, buttdy=10, int show_txt(int buttonly) { FILE *tfh; -int x1,y1,cut,rv=-1,btns=buttons,lbtns=(buttons>bpline)?bpline:buttons,blines=1+((btns-1)/lbtns); +int i,bx,by,x1,y1,rv=-1,run=1,line=0,action=1,cut,itmp,btns=buttons,lbtns=(buttons>bpline)?bpline:buttons,blines=1+((btns-1)/lbtns); if(hide) { - memcpy(lfb, hbb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(lfb, hbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); return 0; } - yo=40+((header)?FSIZE_MED*5/4:0); + yo=20+((header)?FSIZE_MED*5/4:0); if(!buttonly) { - memcpy(lbb, ibb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(lbb, ibb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } if((tfh=fopen(TMP_FILE,"r"))!=NULL) { @@ -248,7 +236,6 @@ int x1,y1,cut,rv=-1,btns=buttons,lbtns=(buttons>bpline)?bpline:buttons,blines=1+ if(type==1) { myo=blines*(butty+buttdy); - int itmp = 0,i; for(i=0; ibpline)?bpline:buttons,blines=1+ if(btns) { buttxstart=psx+pxw/2-(((double)lbtns*(double)buttsize+(((lbtns>2)&&(lbtns&1))?((double)buttdx):0.0))/2.0); - buttystart=psy+y1*dy; + buttystart=psy+y1*dy+15; } } - int bx,by,run=1,line=0,action=1; + while(run) { //frame layout @@ -301,19 +288,18 @@ int x1,y1,cut,rv=-1,btns=buttons,lbtns=(buttons>bpline)?bpline:buttons,blines=1+ { if(!buttonly) { - RenderBox(psx-20, psy-yo, psx+pxw+20, psy+pyw+myo, radius, CMH); - RenderBox(psx-20+2, psy-yo+2, psx+pxw+20-2, psy+pyw+myo-2, radius, CMC); + RenderBox(psx-20, psy-yo, psx+pxw+20, psy+pyw+myo+15, radius, CMH); + RenderBox(psx-20+2, psy-yo+2, psx+pxw+20-2, psy+pyw+myo+15-2, radius, CMC); if(header) { RenderBox(psx-20, psy-yo+2-FSIZE_BIG/2, psx+pxw+20, psy-yo+FSIZE_BIG*3/4, radius, CMH); RenderString(title, psx, psy-yo+FSIZE_BIG/2, pxw, CENTER, FSIZE_BIG, CMHT); } } - if(buttonly || !(rv=fh_txt_load(TMP_FILE, psx, pxw, psy, dy, size, line, &cut))) + if(buttonly || !(rv=fh_txt_load(TMP_FILE, psx, pxw, psy+15, dy, size, line, &cut))) { if(type==1) { - int i; for(i=0; ibpline)?bpline:buttons,blines=1+ RenderString(butmsg[i], buttxstart+bx*(buttsize+buttdx/2), buttystart+by*(butty+buttdy/2)+butty-7, buttsize, CENTER, 26, (i==(selection-1))?CMCST:CMCIT); } } - memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(lfb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } } run=0; @@ -342,7 +328,7 @@ FILE *xfh; if((xfh=fopen(msg,"r"))!=NULL) { fclose(xfh); - snprintf(TMP_FILE,sizeof(TMP_FILE),"%s",msg); + strcpy(TMP_FILE,msg); } else { @@ -351,6 +337,12 @@ FILE *xfh; } else { + size_t l = strlen(msg); + char *t = (char *)alloca(l * 4 + 1); + memcpy(t, msg, l + 1); + TranslateString(t, l * 4); + msg = t; + if((xfh=fopen(TMP_FILE,"w"))!=NULL) { while(*msg) @@ -408,11 +400,10 @@ void ShowUsage(void) int main (int argc, char **argv) { -int index=0,tv=0,found=0, spr=0; -int dloop=1, rcc=-1, cupd=0; -char rstr[BUFSIZE]={0}, *rptr=NULL, *aptr=NULL; -time_t tm1=0,tm2=0; -//clock_t tk1=0; +int ix,tv,found=0, spr; +int dloop=1, rcc=-1; +char rstr[BUFSIZE]={0}, *rptr, *aptr; +time_t tm1,tm2; FILE *fh; if(argc<2) @@ -443,8 +434,13 @@ FILE *fh; { if(strstr(aptr,"title=")!=NULL) { - title=strdup(rptr); + size_t l = strlen(rptr); + char *t = (char *)alloca(l * 4 + 1); + memcpy(t, rptr, l + 1); + TranslateString(t, l * 4); + title = strdup(t); CatchTabs(title); + if(strcmp(title,"none")==0) { header=0; @@ -661,27 +657,30 @@ FILE *fh; ey=620; - for(index=CMCST; index<=CMH; index++) + for(ix=CMCST; ix<=CMH; ix++) { - sprintf(rstr,"menu_%s_alpha",menucoltxt[index]); + sprintf(rstr,"menu_%s_alpha",menucoltxt[ix]); if((tv=Read_Neutrino_Cfg(rstr))>=0) - tr[index]=255-(float)tv*2.55; + tr[ix]=255-(float)tv*2.55; - sprintf(rstr,"menu_%s_blue",menucoltxt[index]); + sprintf(rstr,"menu_%s_blue",menucoltxt[ix]); if((tv=Read_Neutrino_Cfg(rstr))>=0) - bl[index]=(float)tv*2.55; + bl[ix]=(float)tv*2.55; - sprintf(rstr,"menu_%s_green",menucoltxt[index]); + sprintf(rstr,"menu_%s_green",menucoltxt[ix]); if((tv=Read_Neutrino_Cfg(rstr))>=0) - gn[index]=(float)tv*2.55; + gn[ix]=(float)tv*2.55; - sprintf(rstr,"menu_%s_red",menucoltxt[index]); + sprintf(rstr,"menu_%s_red",menucoltxt[ix]); if((tv=Read_Neutrino_Cfg(rstr))>=0) - rd[index]=(float)tv*2.55; + rd[ix]=(float)tv*2.55; } + for (ix = 0; ix <= RED; ix++) + bgra[ix] = (tr[ix] << 24) | (rd[ix] << 16) | (gn[ix] << 8) | bl[ix]; + if(Read_Neutrino_Cfg("rounded_corners")>0) - radius=10; + radius=11; else radius=0; @@ -712,7 +711,8 @@ FILE *fh; perror("msgbox \n"); return -1; } - if(!(lfb = (unsigned char*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0))) + + if(!(lfb = (uint32_t*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0))) { perror("msgbox \n"); return -1; @@ -762,7 +762,7 @@ FILE *fh; use_kerning = FT_HAS_KERNING(face); - desc.flags = FT_LOAD_MONOCHROME; + desc.flags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT; //init backbuffer @@ -774,6 +774,7 @@ FILE *fh; munmap(lfb, fix_screeninfo.smem_len); return -1; } + stride = fix_screeninfo.line_length/sizeof(uint32_t); if(!(obb = malloc(fix_screeninfo.line_length*var_screeninfo.yres))) { @@ -810,27 +811,27 @@ FILE *fh; if(refresh & 1) { - memcpy(ibb, lfb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(ibb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } else { - memset(ibb, TRANSP, fix_screeninfo.line_length*var_screeninfo.yres); + memset(ibb, TRANSP, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } if(mute==2) { - memcpy(hbb, lfb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(hbb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } else { - memset(hbb, TRANSP, fix_screeninfo.line_length*var_screeninfo.yres); + memset(hbb, TRANSP, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } if(refresh & 2) { - memcpy(obb, lfb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(obb, lbb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } else { - memset(obb, TRANSP, fix_screeninfo.line_length*var_screeninfo.yres); + memset(obb, TRANSP, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); } startx = sx; @@ -852,13 +853,16 @@ FILE *fh; //main loop while((rcc!=KEY_EXIT) && (rcc!=KEY_OK) && ((timeout==-1)||((tm2-tm1)100) { if(cyclic) @@ -868,13 +872,14 @@ FILE *fh; } } usleep(10000L); +#endif } if(mute && rcc==KEY_MUTE) { hide^=1; show_txt(0); - usleep(500000L); - while(GetRCCode()!=-1); + + while(GetRCCode(300)!=-1); if(hide) { if((fh=fopen(HDF_FILE,"w"))!=NULL) @@ -939,7 +944,7 @@ FILE *fh; //cleanup - memcpy(lfb, obb, fix_screeninfo.line_length*var_screeninfo.yres); + memcpy(lfb, obb, var_screeninfo.xres*var_screeninfo.yres*sizeof(uint32_t)); munmap(lfb, fix_screeninfo.smem_len); close(fb); free(lbb); diff --git a/msgbox.h b/msgbox.h index 6198b00..981df54 100644 --- a/msgbox.h +++ b/msgbox.h @@ -1,7 +1,8 @@ #ifndef __MSGBOX_H__ - #define __MSGBOX_H__ +#include +#define _FILE_OFFSET_BITS 64 #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include FT_FREETYPE_H @@ -26,23 +28,21 @@ #define MAX_BUTTONS 16 #define BUFSIZE 4095 -extern unsigned char FONT[64]; - enum {LEFT, CENTER, RIGHT}; -extern FT_Error error; -extern FT_Library library; -extern FTC_Manager manager; -extern FTC_SBitCache cache; -extern FTC_SBit sbit; +FT_Error error; +FT_Library library; +FTC_Manager manager; +FTC_SBitCache cache; +FTC_SBit sbit; #if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0 -extern FTC_Image_Desc desc; +FTC_Image_Desc desc; #else -extern FTC_ImageTypeRec desc; +FTC_ImageTypeRec desc; #endif -extern FT_Face face; -extern FT_UInt prev_glyphindex; -extern FT_Bool use_kerning; +FT_Face face; +FT_UInt prev_glyphindex; +FT_Bool use_kerning; // rc codes @@ -102,7 +102,7 @@ extern FT_Bool use_kerning; //devs -extern int fb; +int fb; //framebuffer stuff @@ -116,21 +116,25 @@ extern int FSIZE_MED; extern int FSIZE_SMALL; extern int TABULATOR; -extern unsigned char *lfb, *lbb, *obb, *hbb; +extern uint32_t *lfb, *lbb, *obb, *hbb; -extern struct fb_fix_screeninfo fix_screeninfo; -extern struct fb_var_screeninfo var_screeninfo; -extern unsigned char rd[],gn[],bl[],tr[]; +struct fb_fix_screeninfo fix_screeninfo; +struct fb_var_screeninfo var_screeninfo; +extern uint32_t bgra[]; +extern int stride; + +int startx, starty, sx, ex, sy, ey; +//int debounce, rblock; -extern int startx, starty, sx, ex, sy, ey, debounce, rblock; -extern unsigned char sc[8], tc[8]; extern char *butmsg[MAX_BUTTONS]; extern int buttons,selection; extern int instance; int get_instance(void); void put_instance(int pval); +#ifndef FB_DEVICE #define FB_DEVICE "/dev/fb/0" +#endif #endif diff --git a/text.c b/text.c index d78c2c1..c223f51 100644 --- a/text.c +++ b/text.c @@ -1,21 +1,147 @@ #include "text.h" #include "gfx.h" #include "io.h" +#include "msgbox.h" int FSIZE_BIG=28; int FSIZE_MED=24; int FSIZE_SMALL=20; int TABULATOR=72; +static char *sc = "aouAOUzd", + *su= "\xA4\xB6\xBC\x84\x96\x9C\x9F", + *tc="\xE4\xF6\xFC\xC4\xD6\xDC\xDF\xB0"; + +// from neutrino/src/driver/fontrenderer.cpp +int UTF8ToUnicode(char **textp, const int utf8_encoded) // returns -1 on error +{ + int unicode_value, i; + char *text = *textp; + if (utf8_encoded && ((((unsigned char)(*text)) & 0x80) != 0)) + { + int remaining_unicode_length; + if ((((unsigned char)(*text)) & 0xf8) == 0xf0) { + unicode_value = ((unsigned char)(*text)) & 0x07; + remaining_unicode_length = 3; + } else if ((((unsigned char)(*text)) & 0xf0) == 0xe0) { + unicode_value = ((unsigned char)(*text)) & 0x0f; + remaining_unicode_length = 2; + } else if ((((unsigned char)(*text)) & 0xe0) == 0xc0) { + unicode_value = ((unsigned char)(*text)) & 0x1f; + remaining_unicode_length = 1; + } else { + (*textp)++; + return -1; + } + + *textp += remaining_unicode_length; + + for (i = 0; *text && i < remaining_unicode_length; i++) { + text++; + if (((*text) & 0xc0) != 0x80) { + remaining_unicode_length = -1; + return -1; // incomplete or corrupted character + } + unicode_value <<= 6; + unicode_value |= ((unsigned char)(*text)) & 0x3f; + } + } else + unicode_value = (unsigned char)(*text); + + (*textp)++; + return unicode_value; +} + +void CopyUTF8Char(char **to, char **from) +{ + int remaining_unicode_length; + if (!((unsigned char)(**from) & 0x80)) + remaining_unicode_length = 1; + else if ((((unsigned char)(**from)) & 0xf8) == 0xf0) + remaining_unicode_length = 4; + else if ((((unsigned char)(**from)) & 0xf0) == 0xe0) + remaining_unicode_length = 3; + else if ((((unsigned char)(**from)) & 0xe0) == 0xc0) + remaining_unicode_length = 2; + else { + (*from)++; + return; + } + while (**from && remaining_unicode_length) { + **to = **from; + (*from)++, (*to)++, remaining_unicode_length--; + } +} + +int isValidUTF8(char *text) { + while (*text) + if (-1 == UTF8ToUnicode(&text, 1)) + return 0; + return 1; +} + +void TranslateString(char *src, size_t size) +{ + char *fptr = src; + size_t src_len = strlen(src); + char *tptr_start = alloca(src_len * 4 + 1); + char *tptr = tptr_start; + + if (isValidUTF8(src)) { + strncpy(tptr_start, fptr, src_len + 1); + } + else { + while (*fptr) { + int i; + for (i = 0; tc[i] && (tc[i] != *fptr); i++); + if (tc[i]) { + *tptr++ = 0xC3; + *tptr++ = su[i]; + fptr++; + } else if (*fptr & 0x80) + fptr++; + else + *tptr++ = *fptr++; + } + *tptr = 0; + } + + fptr = tptr_start; + tptr = src; + char *tptr_end = src + size - 4; + + while (*fptr && tptr <= tptr_end) { + if (*fptr == '~') { + fptr++; + int i; + for (i = 0; sc[i] && (sc[i] != *fptr); i++); + if (*fptr == 'd') { + *tptr++ = 0xC2; + *tptr++ = 0xb0; + fptr++; + } else if (sc[i]) { + *tptr++ = 0xC3; + *tptr++ = su[i]; + fptr++; + } else { + *tptr++ = '~'; + } + } else { + CopyUTF8Char(&tptr, &fptr); + } + } + *tptr = 0; +} + /****************************************************************************** * MyFaceRequester ******************************************************************************/ -FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library _library, FT_Pointer request_data, FT_Face *aface) +FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library lib, FT_Pointer request_data __attribute__((unused)), FT_Face *aface) { FT_Error result; - request_data=request_data;//for unused request_data - result = FT_New_Face(_library, face_id, 0, aface); + + result = FT_New_Face(lib, face_id, 0, aface); if(result) printf("msgbox \n", (char*)face_id); @@ -26,72 +152,138 @@ FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library _library, FT_Pointer req * RenderChar ******************************************************************************/ +struct colors_struct +{ + uint32_t fgcolor, bgcolor; + uint32_t colors[256]; +}; + +#define COLORS_LRU_SIZE 16 +static struct colors_struct *colors_lru_array[COLORS_LRU_SIZE] = { NULL }; + +static uint32_t *lookup_colors(uint32_t fgcolor, uint32_t bgcolor) +{ + struct colors_struct *cs; + int i = 0, j; + for (i = 0; i < COLORS_LRU_SIZE; i++) + if (colors_lru_array[i] && colors_lru_array[i]->fgcolor == fgcolor && colors_lru_array[i]->bgcolor == bgcolor) { + cs = colors_lru_array[i]; + for (j = i; j > 0; j--) + colors_lru_array[j] = colors_lru_array[j - 1]; + colors_lru_array[0] = cs; + return cs->colors; + } + i--; + cs = colors_lru_array[i]; + if (!cs) + cs = (struct colors_struct *) calloc(1, sizeof(struct colors_struct)); + for (j = i; j > 0; j--) + colors_lru_array[j] = colors_lru_array[j - 1]; + cs->fgcolor = fgcolor; + cs->bgcolor = bgcolor; + + int ro = var_screeninfo.red.offset; + int go = var_screeninfo.green.offset; + int bo = var_screeninfo.blue.offset; + int to = var_screeninfo.transp.offset; + int rm = (1 << var_screeninfo.red.length) - 1; + int gm = (1 << var_screeninfo.green.length) - 1; + int bm = (1 << var_screeninfo.blue.length) - 1; + int tm = (1 << var_screeninfo.transp.length) - 1; + int fgr = ((int)fgcolor >> ro) & rm; + int fgg = ((int)fgcolor >> go) & gm; + int fgb = ((int)fgcolor >> bo) & bm; + int fgt = ((int)fgcolor >> to) & tm; + int deltar = (((int)bgcolor >> ro) & rm) - fgr; + int deltag = (((int)bgcolor >> go) & gm) - fgg; + int deltab = (((int)bgcolor >> bo) & bm) - fgb; + int deltat = (((int)bgcolor >> to) & tm) - fgt; + for (i = 0; i < 256; i++) + cs->colors[255 - i] = + (((fgr + deltar * i / 255) & rm) << ro) | + (((fgg + deltag * i / 255) & gm) << go) | + (((fgb + deltab * i / 255) & bm) << bo) | + (((fgt + deltat * i / 255) & tm) << to); + + colors_lru_array[0] = cs; + return cs->colors; +} + int RenderChar(FT_ULong currentchar, int _sx, int _sy, int _ex, int color) { -// unsigned char pix[4]={oldcmap.red[col],oldcmap.green[col],oldcmap.blue[col],oldcmap.transp[col]}; -// unsigned char pix[4]={0x80,0x80,0x80,0x80}; + int row, pitch; FT_UInt glyphindex; FT_Vector kerning; -// FT_Error _error; + FT_Error err; + + if (currentchar == '\r') // display \r in windows edited files + { + if(color != -1) + { + if (_sx + 10 < _ex) + RenderBox(_sx, _sy - 10, _sx + 10, _sy, GRID, color); + else + return -1; + } + return 10; + } - currentchar=currentchar & 0xFF; + if (currentchar == '\t') + { + /* simulate horizontal TAB */ + return 15; + } //load char - if(!(glyphindex = FT_Get_Char_Index(face, (int)currentchar))) + if(!(glyphindex = FT_Get_Char_Index(face, currentchar))) { -// printf("msgbox \n", (int)currentchar, _error); + printf("msgbox \n", (int)currentchar, error); return 0; } -// no kerning used -/* if(use_kerning) { FT_Get_Kerning(face, prev_glyphindex, glyphindex, ft_kerning_default, &kerning); prev_glyphindex = glyphindex; kerning.x >>= 6; - } - else -*/ + } else kerning.x = 0; - //render char + //render char if(color != -1) /* don't render char, return charwidth only */ { - if(_sx + sbit->xadvance >= _ex){ + if (_sx + sbit->xadvance >= _ex) return -1; /* limit to maxwidth */ - } - unsigned char pix[4]={bl[color],gn[color],rd[color],tr[color]}; - int row, pitch, bit, x = 0, y = 0; + uint32_t bgcolor = *(lbb + (sy + _sy) * stride + (sx + _sx)); + uint32_t fgcolor = bgra[color]; + uint32_t *colors = lookup_colors(fgcolor, bgcolor); + uint32_t *p = lbb + (sx + _sx + sbit->left + kerning.x) + stride * (sy + _sy - sbit->top); + uint32_t *r = p + (_ex - _sx); /* end of usable box */ for(row = 0; row < sbit->height; row++) { - for(pitch = 0; pitch < sbit->pitch; pitch++) + uint32_t *q = p; + uint8_t *s = sbit->buffer + row * sbit->pitch; + for(pitch = 0; pitch < sbit->width; pitch++) { - for(bit = 7; bit >= 0; bit--) - { - if(pitch*8 + 7-bit >= sbit->width) break; /* render needed bits only */ - - if((sbit->buffer[row * sbit->pitch + pitch]) & 1<left + kerning.x + x)*4 + fix_screeninfo.line_length*(starty + _sy - sbit->top + y),pix,4); - - x++; - } + if (*s) + *q = colors[*s]; + q++, s++; + if (q > r) /* we are past _ex */ + break; } - - x = 0; - y++; + p += stride; + r += stride; } - } //return charwidth @@ -103,66 +295,39 @@ int RenderChar(FT_ULong currentchar, int _sx, int _sy, int _ex, int color) * GetStringLen ******************************************************************************/ -int GetStringLen(int _sx, char *string, int size) +int GetStringLen(int _sx, char *string, size_t size) { -unsigned int i = 0; -int stringlen = 0; + int i, stringlen = 0; //reset kerning - prev_glyphindex = 0; + prev_glyphindex = 0; //calc len - if(size) - { - desc.width = desc.height = size; - } - - while(*string != '\0') - { - if(*string != '~') - { - stringlen += RenderChar(*string, -1, -1, -1, -1); - } - else - { - string++; - if(*string=='t') - { - stringlen=desc.width+TABULATOR*((int)(stringlen/TABULATOR)+1); - } - else - { - if(*string=='T') - { - if(sscanf(string+1,"%4d",&i)==1) - { - string+=4; - stringlen=i-_sx; - } - } - else - { - int found=0; - for(i=0; i maxwidth */ - _sx += charwidth; - } - else - { - switch(*rptr) - { - case 'R': varcolor=RED; break; - case 'G': varcolor=GREEN; break; - case 'Y': varcolor=YELLOW; break; - case 'B': varcolor=BLUE1; break; - case 'S': varcolor=color; break; - case 't': - _sx=TABULATOR*((int)(_sx/TABULATOR)+1); - break; - case 'T': - if(sscanf(rptr+1,"%4d",&i)==1) - { - rptr+=4; - _sx=i; - } - break; - } - } - } - else + ++rptr; + switch(*rptr) { - int uml = 0; - switch(*rptr) /* skip Umlauts */ - { - case '\xc4': - case '\xd6': - case '\xdc': - case '\xe4': - case '\xf6': - case '\xfc': - case '\xdf': uml=1; break; - } - if (uml == 0) - { - // UTF8_to_Latin1 encoding - if (((*rptr) & 0xf0) == 0xf0) /* skip (can't be encoded in Latin1) */ - { - rptr++; - if ((*rptr) == 0) - *rptr='\x3f'; // ? question mark - rptr++; - if ((*rptr) == 0) - *rptr='\x3f'; - rptr++; - if ((*rptr) == 0) - *rptr='\x3f'; - } - else if (((*rptr) & 0xe0) == 0xe0) /* skip (can't be encoded in Latin1) */ + case 'R': varcolor=RED; break; + case 'G': varcolor=GREEN; break; + case 'Y': varcolor=YELLOW; break; + case 'B': varcolor=BLUE1; break; + case 'S': varcolor=color; break; + case 't': + _sx=TABULATOR*((int)(_sx/TABULATOR)+1); + break; + case 'T': + if(sscanf(rptr+1,"%4d",&i)==1) { - rptr++; - if ((*rptr) == 0) - *rptr='\x3f'; - rptr++; - if ((*rptr) == 0) - *rptr='\x3f'; + rptr+=4; + _sx=i; } - else if (((*rptr) & 0xc0) == 0xc0) - { - char c = (((*rptr) & 3) << 6); - rptr++; - if ((*rptr) == 0) - *rptr='\x3f'; - *rptr = (c | ((*rptr) & 0x3f)); - } - } - if((charwidth = RenderChar(*rptr, _sx, _sy, _ex, varcolor)) == -1) return _sx; /* string > maxwidth */ - _sx += charwidth; + break; } rptr++; } + else + { + if((charwidth = RenderChar(UTF8ToUnicode(&rptr, 1), _sx, _sy, _ex, varcolor)) == -1) return _sx; /* string > maxwidth */ + _sx += charwidth; + } + } return stringlen; } diff --git a/text.h b/text.h index a76a0ca..3cfe53c 100644 --- a/text.h +++ b/text.h @@ -1,12 +1,12 @@ #ifndef __TEXT_H__ - #define __TEXT_H__ #include "msgbox.h" FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *aface); int RenderString(char *string, int sx, int sy, int maxwidth, int layout, int size, int color); -int GetStringLen(int sx, char *string, int size); +void TranslateString(char *src, size_t size); +int GetStringLen(int sx, char *string, size_t size); void CatchTabs(char *text); #endif diff --git a/txtform.c b/txtform.c index 9b183a4..b53b3d6 100644 --- a/txtform.c +++ b/txtform.c @@ -59,19 +59,23 @@ int just, color=CMCT; if((loop>0) && (ys<(ey-dy))) { rstr[j]=0; + char *t = (char *)alloca(j * 4 + 1); + memcpy(t, rstr, j + 1); + TranslateString(t, j * 4); + if(plot) { if(loop>=line) { - RenderString(rstr, xs, ys, xw, just, size, color); + RenderString(t, xs, ys, xw, just, size, color); ys+=dy; } } else { - if(strlen(rstr)) + if(strlen(t)) { - slen=GetStringLen(xs, rstr, size); + slen=GetStringLen(xs, t, size); if(slen>*x) { *x=slen; @@ -91,7 +95,8 @@ int just, color=CMCT; int fh_txt_load(const char *name, int _sx, int wx, int _sy, int dy, int size, int line, int *cut) { - int dummy; +int dummy; + return fh_txt_trans(name, _sx, wx, _sy, dy, size, line, cut, &dummy, &dummy, 1); } -- 2.39.5