| #include <rfb/rfb.h> |
| |
| int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, |
| int x,int y,unsigned char c,rfbPixel 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->serverFormat.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 && y+j >= 0 && y+j < rfbScreen->height && |
| x+i >= 0 && x+i < rfbScreen->width) |
| 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,rfbPixel colour) |
| { |
| while(*string) { |
| x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour); |
| string++; |
| } |
| } |
| |
| /* TODO: these two functions need to be more efficient */ |
| /* if col==bcol, assume transparent background */ |
| int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, |
| int x,int y,unsigned char c, |
| int x1,int y1,int x2,int y2, |
| rfbPixel col,rfbPixel 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->serverFormat.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, |
| rfbPixel colour,rfbPixel 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]+1; |
| *y2=*y1+font->metaData[c*5+2]+1; |
| } |
| |
| #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)=1-(INT_MAX); |
| 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]; |
| } |
| (*x2)++; |
| (*y2)++; |
| } |
| |
| rfbFontDataPtr rfbLoadConsoleFont(char *filename) |
| { |
| FILE *f=fopen(filename,"rb"); |
| rfbFontDataPtr p; |
| int i; |
| |
| if(!f) return NULL; |
| |
| 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 NULL; |
| } |
| 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); |
| } |