Home | History | Annotate | Download | only in libvncserver
      1 #include <rfb/rfb.h>
      2 
      3 int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
      4 		 int x,int y,unsigned char c,rfbPixel col)
      5 {
      6   int i,j,width,height;
      7   unsigned char* data=font->data+font->metaData[c*5];
      8   unsigned char d=*data;
      9   int rowstride=rfbScreen->paddedWidthInBytes;
     10   int bpp=rfbScreen->serverFormat.bitsPerPixel/8;
     11   char *colour=(char*)&col;
     12 
     13   if(!rfbEndianTest)
     14     colour += 4-bpp;
     15 
     16   width=font->metaData[c*5+1];
     17   height=font->metaData[c*5+2];
     18   x+=font->metaData[c*5+3];
     19   y+=-font->metaData[c*5+4]-height+1;
     20 
     21   for(j=0;j<height;j++) {
     22     for(i=0;i<width;i++) {
     23       if((i&7)==0) {
     24 	d=*data;
     25 	data++;
     26       }
     27       if(d&0x80 && y+j >= 0 && y+j < rfbScreen->height &&
     28           x+i >= 0 && x+i < rfbScreen->width)
     29 	memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp);
     30       d<<=1;
     31     }
     32     /* if((i&7)!=0) data++; */
     33   }
     34   return(width);
     35 }
     36 
     37 void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
     38 		   int x,int y,const char* string,rfbPixel colour)
     39 {
     40   while(*string) {
     41     x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour);
     42     string++;
     43   }
     44 }
     45 
     46 /* TODO: these two functions need to be more efficient */
     47 /* if col==bcol, assume transparent background */
     48 int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
     49 			int x,int y,unsigned char c,
     50 			int x1,int y1,int x2,int y2,
     51 			rfbPixel col,rfbPixel bcol)
     52 {
     53   int i,j,width,height;
     54   unsigned char* data=font->data+font->metaData[c*5];
     55   unsigned char d;
     56   int rowstride=rfbScreen->paddedWidthInBytes;
     57   int bpp=rfbScreen->serverFormat.bitsPerPixel/8,extra_bytes=0;
     58   char* colour=(char*)&col;
     59   char* bcolour=(char*)&bcol;
     60 
     61   if(!rfbEndianTest) {
     62     colour+=4-bpp;
     63     bcolour+=4-bpp;
     64   }
     65 
     66   width=font->metaData[c*5+1];
     67   height=font->metaData[c*5+2];
     68   x+=font->metaData[c*5+3];
     69   y+=-font->metaData[c*5+4]-height+1;
     70 
     71   /* after clipping, x2 will be count of bytes between rows,
     72    * x1 start of i, y1 start of j, width and height will be adjusted. */
     73   if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0;
     74   if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0;
     75   if(y2<y+height) height-=y+height-y2;
     76   if(x2<x+width) { extra_bytes+=(x1+width)/8-(x+width-x2+7)/8; width-=x+width-x2; }
     77 
     78   d=*data;
     79   for(j=y1;j<height;j++) {
     80     if((x1&7)!=0)
     81       d=data[-1]; /* TODO: check if in this case extra_bytes is correct! */
     82     for(i=x1;i<width;i++) {
     83       if((i&7)==0) {
     84 	d=*data;
     85 	data++;
     86       }
     87       /* if(x+i>=x1 && x+i<x2 && y+j>=y1 && y+j<y2) */ {
     88 	 if(d&0x80) {
     89 	   memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
     90 		  colour,bpp);
     91 	 } else if(bcol!=col) {
     92 	   memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,
     93 		  bcolour,bpp);
     94 	 }
     95       }
     96       d<<=1;
     97     }
     98     /* if((i&7)==0) data++; */
     99     data += extra_bytes;
    100   }
    101   return(width);
    102 }
    103 
    104 void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
    105 			   int x,int y,const char* string,
    106 			   int x1,int y1,int x2,int y2,
    107 			   rfbPixel colour,rfbPixel backColour)
    108 {
    109   while(*string) {
    110     x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2,
    111 			   colour,backColour);
    112     string++;
    113   }
    114 }
    115 
    116 int rfbWidthOfString(rfbFontDataPtr font,const char* string)
    117 {
    118   int i=0;
    119   while(*string) {
    120     i+=font->metaData[*string*5+1];
    121     string++;
    122   }
    123   return(i);
    124 }
    125 
    126 int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)
    127 {
    128   return(font->metaData[c*5+1]+font->metaData[c*5+3]);
    129 }
    130 
    131 void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2)
    132 {
    133   *x1+=font->metaData[c*5+3];
    134   *y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1;
    135   *x2=*x1+font->metaData[c*5+1]+1;
    136   *y2=*y1+font->metaData[c*5+2]+1;
    137 }
    138 
    139 #ifndef INT_MAX
    140 #define INT_MAX 0x7fffffff
    141 #endif
    142 
    143 void rfbWholeFontBBox(rfbFontDataPtr font,
    144 		      int *x1, int *y1, int *x2, int *y2)
    145 {
    146    int i;
    147    int* m=font->metaData;
    148 
    149    (*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=1-(INT_MAX);
    150    for(i=0;i<256;i++) {
    151       if(m[i*5+1]-m[i*5+3]>(*x2))
    152 	(*x2)=m[i*5+1]-m[i*5+3];
    153       if(-m[i*5+2]+m[i*5+4]<(*y1))
    154 	(*y1)=-m[i*5+2]+m[i*5+4];
    155       if(m[i*5+3]<(*x1))
    156 	(*x1)=m[i*5+3];
    157       if(-m[i*5+4]>(*y2))
    158 	(*y2)=-m[i*5+4];
    159    }
    160    (*x2)++;
    161    (*y2)++;
    162 }
    163 
    164 rfbFontDataPtr rfbLoadConsoleFont(char *filename)
    165 {
    166   FILE *f=fopen(filename,"rb");
    167   rfbFontDataPtr p;
    168   int i;
    169 
    170   if(!f) return NULL;
    171 
    172   p=(rfbFontDataPtr)malloc(sizeof(rfbFontData));
    173   p->data=(unsigned char*)malloc(4096);
    174   if(1!=fread(p->data,4096,1,f)) {
    175     free(p->data);
    176     free(p);
    177     return NULL;
    178   }
    179   fclose(f);
    180   p->metaData=(int*)malloc(256*5*sizeof(int));
    181   for(i=0;i<256;i++) {
    182     p->metaData[i*5+0]=i*16; /* offset */
    183     p->metaData[i*5+1]=8; /* width */
    184     p->metaData[i*5+2]=16; /* height */
    185     p->metaData[i*5+3]=0; /* xhot */
    186     p->metaData[i*5+4]=0; /* yhot */
    187   }
    188   return(p);
    189 }
    190 
    191 void rfbFreeFont(rfbFontDataPtr f)
    192 {
    193   free(f->data);
    194   free(f->metaData);
    195   free(f);
    196 }
    197