diff options
Diffstat (limited to 'krfb/libvncserver/font.c')
-rw-r--r-- | krfb/libvncserver/font.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/krfb/libvncserver/font.c b/krfb/libvncserver/font.c new file mode 100644 index 00000000..b9d68d0f --- /dev/null +++ b/krfb/libvncserver/font.c @@ -0,0 +1,192 @@ +#include "rfb.h" + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,unsigned char c,Pixel col) +{ + int i,j,width,height; + unsigned char* data=font->data+font->metaData[c*5]; + unsigned char d=*data; + int rowstride=rfbScreen->paddedWidthInBytes; + int bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8; + char *colour=(char*)&col; + + if(!rfbEndianTest) + colour += 4-bpp; + + width=font->metaData[c*5+1]; + height=font->metaData[c*5+2]; + x+=font->metaData[c*5+3]; + y+=-font->metaData[c*5+4]-height+1; + + for(j=0;j<height;j++) { + for(i=0;i<width;i++) { + if((i&7)==0) { + d=*data; + data++; + } + if(d&0x80) + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp); + d<<=1; + } + /* if((i&7)!=0) data++; */ + } + return(width); +} + +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,const char* string,Pixel colour) +{ + while(*string) { + x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour); + string++; + } +} + +/* TODO: these two functions need to be more efficient */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,unsigned char c, + int x1,int y1,int x2,int y2, + Pixel col,Pixel bcol) +{ + int i,j,width,height; + unsigned char* data=font->data+font->metaData[c*5]; + unsigned char d; + int rowstride=rfbScreen->paddedWidthInBytes; + int bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8,extra_bytes=0; + char* colour=(char*)&col; + char* bcolour=(char*)&bcol; + + if(!rfbEndianTest) { + colour+=4-bpp; + bcolour+=4-bpp; + } + + width=font->metaData[c*5+1]; + height=font->metaData[c*5+2]; + x+=font->metaData[c*5+3]; + y+=-font->metaData[c*5+4]-height+1; + + /* after clipping, x2 will be count of bytes between rows, + * x1 start of i, y1 start of j, width and height will be adjusted. */ + if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0; + if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0; + if(y2<y+height) height-=y+height-y2; + if(x2<x+width) { extra_bytes+=(x1+width)/8-(x+width-x2+7)/8; width-=x+width-x2; } + + d=*data; + for(j=y1;j<height;j++) { + if((x1&7)!=0) + d=data[-1]; /* TODO: check if in this case extra_bytes is correct! */ + for(i=x1;i<width;i++) { + if((i&7)==0) { + d=*data; + data++; + } + /* if(x+i>=x1 && x+i<x2 && y+j>=y1 && y+j<y2) */ { + if(d&0x80) { + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp, + colour,bpp); + } else if(bcol!=col) { + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp, + bcolour,bpp); + } + } + d<<=1; + } + /* if((i&7)==0) data++; */ + data += extra_bytes; + } + return(width); +} + +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,const char* string, + int x1,int y1,int x2,int y2, + Pixel colour,Pixel backColour) +{ + while(*string) { + x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2, + colour,backColour); + string++; + } +} + +int rfbWidthOfString(rfbFontDataPtr font,const char* string) +{ + int i=0; + while(*string) { + i+=font->metaData[*string*5+1]; + string++; + } + return(i); +} + +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c) +{ + return(font->metaData[c*5+1]+font->metaData[c*5+3]); +} + +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2) +{ + *x1+=font->metaData[c*5+3]; + *y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1; + *x2=*x1+font->metaData[c*5+1]; + *y2=*y1+font->metaData[c*5+2]; +} + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + +void rfbWholeFontBBox(rfbFontDataPtr font, + int *x1, int *y1, int *x2, int *y2) +{ + int i; + int* m=font->metaData; + + (*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=-INT_MAX+1; + for(i=0;i<256;i++) { + if(m[i*5+1]-m[i*5+3]>(*x2)) + (*x2)=m[i*5+1]-m[i*5+3]; + if(-m[i*5+2]+m[i*5+4]<(*y1)) + (*y1)=-m[i*5+2]+m[i*5+4]; + if(m[i*5+3]<(*x1)) + (*x1)=m[i*5+3]; + if(-m[i*5+4]>(*y2)) + (*y2)=-m[i*5+4]; + } +} + +rfbFontDataPtr rfbLoadConsoleFont(char *filename) +{ + FILE *f=fopen(filename,"rb"); + rfbFontDataPtr p; + int i; + + if(!f) return(0); + + p=(rfbFontDataPtr)malloc(sizeof(rfbFontData)); + p->data=(unsigned char*)malloc(4096); + if(1!=fread(p->data,4096,1,f)) { + free(p->data); + free(p); + return(0); + } + fclose(f); + p->metaData=(int*)malloc(256*5*sizeof(int)); + for(i=0;i<256;i++) { + p->metaData[i*5+0]=i*16; /* offset */ + p->metaData[i*5+1]=8; /* width */ + p->metaData[i*5+2]=16; /* height */ + p->metaData[i*5+3]=0; /* xhot */ + p->metaData[i*5+4]=0; /* yhot */ + } + return(p); +} + +void rfbFreeFont(rfbFontDataPtr f) +{ + free(f->data); + free(f->metaData); + free(f); +} |