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