|
|
|
#include "rfb.h"
|
|
|
|
|
|
|
|
int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
|
|
|
|
int x,int y,unsigned char c,Pixel 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,Pixel 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,
|
|
|
|
Pixel col,Pixel 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,
|
|
|
|
Pixel colour,Pixel 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);
|
|
|
|
}
|