1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "font.H"
6
Character(class ScalableFont * sf,char c_in)7 Character::Character(class ScalableFont *sf,char c_in)
8 : dpy(sf->dpy), c(c_in)
9 {
10 XCharStruct *cs;
11 cs = &sf->fs->per_char[((unsigned char)c)-sf->fs->min_char_or_byte2];
12
13 w = cs->rbearing - cs->lbearing;
14 h = cs->ascent + cs->descent;
15 offx = cs->lbearing;
16 offy = cs->ascent;
17 addx = cs->width;
18 addy = 0;
19
20 pix = 0;
21 img = 0;
22
23 Init(sf);
24 switch(sf->mode) {
25 case 0: break;
26 case 90: TurnLeft(); break;
27 case 180: Mirror(); break;
28 case 270: TurnRight(); break;
29 case 360: break;
30 case -90: FlipY(); TurnRight(); break;
31 case -180: FlipX(); break;
32 case -270: FlipY(); TurnLeft(); break;
33 case -360: FlipY(); break;
34 default: break;
35 }
36 }
37
~Character()38 Character::~Character() {
39 DropData();
40 }
41
Init(class ScalableFont * sf)42 void Character::Init(class ScalableFont *sf) {
43 DropPix();
44
45 pix = XCreatePixmap(dpy,DefaultRootWindow(dpy),w,h,1);
46 XGCValues values;
47 values.foreground = 0;
48 values.background = 0;
49 if (sf) values.font = sf->fs->fid;
50 GC gc=XCreateGC(dpy,pix,
51 ((sf)?GCFont:0)|GCForeground|GCBackground,&values);
52 XFillRectangle(dpy,pix,gc,0,0,w,h); /* clear background */
53 XSetForeground(dpy,gc,1);
54 XDrawString(dpy,pix,gc,-offx,offy,&c,1);
55 XFreeGC(dpy,gc);
56
57 Pix2Img();
58 }
59
PrintImg()60 void Character::PrintImg() {
61 if (!img) return;
62 //
63 // print the data to stdout for debugging
64 //
65 #if (0)
66 XCharStruct *cs;
67 cs = &sf->fs->per_char[((unsigned char)c)-sf->fs->min_char_or_byte2];
68 #endif
69
70 for (int y=0;y<img->height;y++) {
71 for (int x=0;x<img->width;x++) {
72 // if (img->data[y*img->bytes_per_line+x/8] & (1<<(7-(x%8))))
73 if (XGetPixel(img,x,y))
74 putchar('*');
75 else putchar('.');
76 }
77 switch(y) {
78 case 0: printf( " character: %c\n", c ); break;
79 case 1: printf( " width: %3d, height: %3d\n", w, h ); break;
80 case 2: printf( " offx: %3d, offy: %3d\n", offx, offy ); break;
81 case 3: printf( " addx: %3d, addy: %3d\n", addx, addy ); break;
82 #if (0)
83 case 4: printf( " lbearing:%3d, rbearing:%3d\n",
84 cs->lbearing, cs->rbearing ); break;
85 case 5: printf( " ascent: %3d, descent: %3d\n",
86 cs->ascent, cs->descent ); break;
87 case 6: printf( " width: %3d\n", cs->width ); break;
88 #endif
89 default: putchar('\n'); break;
90 }
91 }
92 }
93
Pix2Img()94 void Character::Pix2Img() {
95 DropImg();
96
97 img=XGetImage(dpy,pix,0,0,w,h,1,XYPixmap);
98 // PrintImg();
99 }
100
TurnRight()101 void Character::TurnRight() {
102 PrepareImg();
103
104 XImage *new_img;
105 int bytes_per_line = (img->bitmap_pad/8)
106 * ((img->height+img->bitmap_pad-1)/img->bitmap_pad);
107 char *data = (char*)malloc(bytes_per_line*img->width);
108
109 new_img = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),
110 1,XYBitmap,0,data,img->height,img->width,img->bitmap_pad,bytes_per_line);
111
112 for (int x=0;x<new_img->width;x++) {
113 for (int y=0;y<new_img->height;y++) {
114 XPutPixel(new_img,x,y,XGetPixel(img,y,img->height-1-x));
115 }
116 }
117
118 DropImg();
119 img = new_img;
120
121 int help;
122 help = offx; offx = offy-h; offy = -help;
123 help = addx; addx = -addy; addy = help;
124 help = w; w = h; h = help;
125
126 DropPix();
127 }
128
TurnLeft()129 void Character::TurnLeft() {
130 PrepareImg();
131
132 XImage *new_img;
133 int bytes_per_line = (img->bitmap_pad/8)
134 * ((img->height+img->bitmap_pad-1)/img->bitmap_pad);
135 char *data = (char*)malloc(bytes_per_line*img->width);
136
137 new_img = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),
138 1,XYBitmap,0,data,img->height,img->width,img->bitmap_pad,bytes_per_line);
139
140 for (int x=0;x<new_img->width;x++) {
141 for (int y=0;y<new_img->height;y++) {
142 XPutPixel(new_img,x,y,XGetPixel(img,img->width-1-y,x));
143 }
144 }
145
146 DropImg();
147 img = new_img;
148
149 int help;
150 help = offx; offx = -offy; offy = help+w;
151 help = addx; addx = addy; addy = -help;
152 help = w; w = h; h = help;
153
154 DropPix();
155 }
156
ImgFlipX()157 void Character::ImgFlipX() {
158 PrepareImg();
159 for (int y=0;y<h;y++) {
160 for (int x=0;x<w/2;x++) {
161 unsigned long h1=XGetPixel(img,x,y);
162 unsigned long h2=XGetPixel(img,w-1-x,y);
163 XPutPixel(img,x,y,h2);
164 XPutPixel(img,w-1-x,y,h1);
165 }
166 }
167 DropPix();
168 }
169
FlipX()170 void Character::FlipX() {
171 ImgFlipX();
172 offx = -offx-w;
173 addx = -addx;
174 }
175
ImgFlipY()176 void Character::ImgFlipY() {
177 char buffer[1000];
178 char *b_p=buffer;
179
180 if ((unsigned)img->bytes_per_line>sizeof(buffer)) b_p=new char[img->bytes_per_line];
181 PrepareImg();
182 for (int y=0;y<h/2;y++) {
183 char *p1 = img->data + y * img->bytes_per_line;
184 char *p2 = img->data + (h-1-y) * img->bytes_per_line;
185 memcpy(buffer,p1,img->bytes_per_line);
186 memcpy(p1,p2,img->bytes_per_line);
187 memcpy(p2,buffer,img->bytes_per_line);
188 }
189 DropPix();
190 if (b_p!=buffer) delete b_p;
191 }
192
FlipY()193 void Character::FlipY() {
194 ImgFlipY();
195 offy = h-offy;
196 }
197
Img2Pix()198 void Character::Img2Pix() {
199 DropPix();
200
201 pix = XCreatePixmap(dpy,DefaultRootWindow(dpy),w,h,1);
202 XGCValues values;
203 values.foreground = 1;
204 values.background = 0;
205 GC gc=XCreateGC(dpy,pix,GCForeground|GCBackground,&values);
206 XFillRectangle(dpy,pix,gc,0,0,w,h); /*** TEST ***/
207 XPutImage(dpy,pix,gc,img,0,0,0,0,w,h);
208 XFreeGC(dpy,gc);
209 }
210
Draw(Drawable d,GC gc,int * x,int * y)211 void Character::Draw( Drawable d, GC gc, int *x, int *y ) {
212 if (!pix) Img2Pix();
213 #if (0)
214 XCopyPlane(dpy,pix,d,gc,0,0,w,h, (*x)+offx, (*y)-offy,1);
215 #endif
216 #if (1)
217 XGCValues save_val;
218 XGCValues stipple_val;
219 unsigned long valuemask = GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin;
220 XGetGCValues(dpy,gc,valuemask,&save_val);
221 stipple_val.fill_style = FillStippled;
222 stipple_val.stipple = pix;
223 stipple_val.ts_x_origin = (*x)+offx;
224 stipple_val.ts_y_origin = (*y)-offy;
225 XChangeGC(dpy,gc,valuemask,&stipple_val);
226 XFillRectangle(dpy,d,gc,(*x)+offx,(*y)-offy,w,h);
227 if ( save_val.fill_style!=FillStippled
228 && save_val.fill_style!=FillOpaqueStippled ) valuemask&= ~GCStipple;
229 XChangeGC(dpy,gc,valuemask,&save_val);
230 #endif
231 #if (0)
232 XSetClipMask(dpy,gc,pix);
233 XSetClipOrigin(dpy,gc,(*x)+offx,(*y)-offy);
234 XFillRectangle(dpy,d,gc,(*x)+offx,(*y)-offy,w,h);
235 XSetClipMask(dpy,gc,None);
236 #endif
237 #if (0)
238 XSetStipple(dpy,gc,pix);
239 XSetFillStyle(dpy,gc,FillStippled);
240 XSetTSOrigin(dpy,gc,(*x)+offx,(*y)-offy);
241 XFillRectangle(dpy,d,gc,(*x)+offx,(*y)-offy,w,h);
242 XSetFillStyle(dpy,gc,FillSolid);
243 #endif
244 *x += addx;
245 *y += addy;
246 }
247
BBox(int * tlx,int * tly,int * brx,int * bry)248 void Character::BBox( int *tlx, int *tly, int *brx, int *bry ) {
249 *tlx = offx;
250 *tly = -offy;
251 *brx = *tlx + w;
252 *bry = *tly + h;
253 }
254
255 // ===========================================================================
256
ScalableFont(Display * dpy_in,const char * fontname,int mode_in)257 ScalableFont::ScalableFont( Display *dpy_in, const char *fontname, int mode_in )
258 : dpy(dpy_in), mode(mode_in)
259 {
260 name=strdup(fontname);
261 fs=XLoadQueryFont(dpy,name);
262 if (!fs) {
263 fprintf(stderr,"ERROR: can't load font\n '%s'\n",name);
264 fprintf(stderr,"you should try to use the font-option on your system\n" );
265 exit(-1);
266 }
267 nchr = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
268 chr = new Character*[nchr];
269 memset(chr,0,sizeof(Character*)*(nchr));
270 }
271
~ScalableFont()272 ScalableFont::~ScalableFont() {
273 for (int i=nchr-1;i>=0;i--) {
274 if (chr[i]) delete chr[i];
275 }
276 delete chr;
277 if (fs) {
278 XFreeFont(dpy,fs);
279 }
280 if (name) free(name);
281 }
282
GetChar(char c)283 Character *ScalableFont::GetChar(char c) {
284 int id = ((unsigned char)c)-fs->min_char_or_byte2;
285 if (id<0 && id>=nchr) id=0;
286 if (!chr[id]) chr[id] = new Character(this,c);
287 return chr[id];
288 }
289
GetString(const char * str)290 const char *ScalableFont::GetString(const char *str) {
291 return str;
292 }
293
TurnRight()294 void ScalableFont::TurnRight() {
295 mode-=90;
296 if (mode<-360||(mode>=-90&&mode<0)) mode+=360;
297 for (int i=0;i<nchr;i++) {
298 if (chr[i]) chr[i]->TurnRight();
299 }
300 }
301
TurnLeft()302 void ScalableFont::TurnLeft() {
303 mode+=90;
304 if (mode>360||(mode>=0&&mode<90)) mode-=360;
305 for (int i=0;i<nchr;i++) {
306 if (chr[i]) chr[i]->TurnLeft();
307 }
308 }
309
Flip()310 void ScalableFont::Flip() {
311 mode = (mode>=0)?mode-360:mode+360;
312 if (mode%180==0) {
313 for (int i=0;i<nchr;i++) {
314 if (chr[i]) chr[i]->FlipY();
315 }
316 }
317 else {
318 for (int i=0;i<nchr;i++) {
319 if (chr[i]) chr[i]->FlipX();
320 }
321 }
322 }
323
Draw(Drawable d,GC gc,int x,int y,const char * str)324 void ScalableFont::Draw( Drawable d, GC gc, int x, int y, const char *str ) {
325 const char *str_p = GetString(str);
326
327 while( *str_p ) {
328 GetChar(*str_p++)->Draw(d,gc,&x,&y);
329 }
330 }
331
DrawCentered(Drawable d,GC gc,int x,int y,const char * str)332 void ScalableFont::DrawCentered( Drawable d, GC gc, int x, int y, const char *str ) {
333 const char *str_p = GetString(str);
334 int tlx, tly, brx, bry;
335
336 BBox(str_p,&tlx,&tly,&brx,&bry);
337 x -= (tlx+brx)/2;
338 y -= (tly+bry)/2;
339 while( *str_p ) {
340 GetChar(*str_p++)->Draw(d,gc,&x,&y);
341 }
342 }
343
Width(const char * str,int * ox,int * oy)344 void ScalableFont::Width( const char *str, int *ox, int *oy ) {
345 const char *str_p = GetString(str);
346 *ox = *oy = 0;
347 while( *str_p ) {
348 GetChar(*str_p++)->AddWidth(ox,oy);
349 }
350 }
351
BBox(const char * str,int * tlx,int * tly,int * brx,int * bry)352 void ScalableFont::BBox( const char *str, int *tlx, int *tly, int *brx, int *bry ) {
353 const char *str_p = GetString(str);
354 const int MAX=32767;
355 int ox, oy;
356 int tlx2, tly2, brx2, bry2;
357
358 ox = oy = 0;
359 *tlx = MAX; *tly = MAX;
360 *brx = -MAX; *bry = -MAX;
361
362 while( *str_p ) {
363 Character *chr_p=GetChar(*str_p++);
364
365 chr_p->BBox(&tlx2,&tly2,&brx2,&bry2);
366 tlx2+=ox; tly2+=oy;
367 brx2+=ox; bry2+=oy;
368 if (tlx2<*tlx) *tlx=tlx2;
369 if (tly2<*tly) *tly=tly2;
370 if (brx2>*brx) *brx=brx2;
371 if (bry2>*bry) *bry=bry2;
372 chr_p->AddWidth(&ox,&oy);
373 }
374 }
375
376 // ===========================================================================
377
FlipFont(Display * dpy,const char * fontname,int mode)378 FlipFont::FlipFont(Display *dpy, const char *fontname, int mode )
379 : ScalableFont(dpy,fontname,mode) {
380 }
381
~FlipFont()382 FlipFont::~FlipFont() {
383 }
384
GetChar(char c)385 Character *FlipFont::GetChar(char c) {
386 int id = ((unsigned char)c)-fs->min_char_or_byte2;
387 if (id<0 && id>=nchr) id=0;
388 if (!chr[id]) {
389 if (c<0) {
390 int flip_mode = (mode>=0)?mode-360:mode+360;
391 chr[id] = new Character(this,c+128);
392 if (flip_mode%180==0) chr[id]->FlipY();
393 else chr[id]->FlipX();
394 }
395 else {
396 chr[id] = new Character(this,c);
397 }
398 }
399 return chr[id];
400 }
401
GetString(const char * str)402 const char *FlipFont::GetString(const char *str) {
403 static char mystr[1024];
404 char *dest;
405 int reverse;
406
407 if (str==mystr) return str;
408
409 dest=mystr;
410 reverse=0;
411 while(*str&&dest<(mystr+sizeof(mystr)-1)) {
412 if (*str=='\r') reverse^=1;
413 else {
414 *dest++ = (reverse)?(*str^0x80):*str;
415 }
416 str++;
417 }
418 *dest='\0';
419 return mystr;
420 }
421