1 #include <rfb/rfb.h>
2 
rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,rfbPixel col)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 
rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char * string,rfbPixel colour)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 */
rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,rfbPixel col,rfbPixel bcol)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 
rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char * string,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour)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 
rfbWidthOfString(rfbFontDataPtr font,const char * string)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 
rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)126 int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c)
127 {
128   return(font->metaData[c*5+1]+font->metaData[c*5+3]);
129 }
130 
rfbFontBBox(rfbFontDataPtr font,unsigned char c,int * x1,int * y1,int * x2,int * y2)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 
rfbWholeFontBBox(rfbFontDataPtr font,int * x1,int * y1,int * x2,int * y2)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 
rfbLoadConsoleFont(char * filename)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 
rfbFreeFont(rfbFontDataPtr f)191 void rfbFreeFont(rfbFontDataPtr f)
192 {
193   free(f->data);
194   free(f->metaData);
195   free(f);
196 }
197