summaryrefslogtreecommitdiffstats
path: root/libvncserver/font.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvncserver/font.c')
-rwxr-xr-xlibvncserver/font.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/libvncserver/font.c b/libvncserver/font.c
new file mode 100755
index 0000000..423d415
--- /dev/null
+++ b/libvncserver/font.c
@@ -0,0 +1,192 @@
+#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->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,rfbPixel 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,
+ 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->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,
+ 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];
+ *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);
+}