1 /****************************************************************************
2 Copyright (C) 1987-2015 by Jeffery P. Hansen
3 Copyright (C) 2015-2018 by Andrey V. Skvortsov
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 ****************************************************************************/
19
20 #include "gate_painter.h"
21 #include "tkgate.h"
22
23 #include <pango/pangoxft.h>
24 #include <assert.h>
25
26 GateColor notAColor = {
27 .xColor = {
28 .pixel = -1
29 },
30 .xftColor = {
31 .pixel = -1
32 }
33 };
34
GateColor_equals(GateColor * lhs,GateColor * rhs)35 Boolean GateColor_equals(GateColor *lhs, GateColor *rhs)
36 {
37 if (memcmp(lhs, rhs, sizeof (GateColor)) == 0)
38 return (GATE_TRUE);
39 else
40 return (GATE_FALSE);
41 }
42
43 /**
44 * @brief virtual methods table for GatePainter class
45 */
46 struct _GatePainter_vtable {
47 void (*init)(GatePainter*, Display*, Drawable);
48 void (*destroy)(GatePainter*);
49 void (*drawString)(GatePainter*, GC, int, int, const char*, int);
50 void (*drawString_new)(GatePainter*, GatePainterContext*, int, int, const char*, int);
51 GatePainterContext *(*createContext)(GatePainter *self);
52 GateColor (*getColor)(GatePainter*, const char*);
53 };
54
55 static void
56 GatePainterXlib_init(GatePainter*, Display*, Drawable);
57
58 static void
59 GatePainterXlib_destroy(GatePainter*);
60
61 static void
62 GatePainterXlib_drawString(GatePainter*, GC, int, int, const char*, int);
63
64 static void
65 GatePainterXlib_drawString_new(GatePainter*, GatePainterContext*, int, int, const char*, int);
66
67 static GatePainterContext*
68 GatePainterXlib_createContext(GatePainter*);
69
70 static GateColor
71 GatePainterXlib_createColor(GatePainter*, const char*);
72
73
74 static void
75 GatePainterPangoXft_init(GatePainter*, Display*, Drawable);
76
77 static void
78 GatePainterPangoXft_destroy(GatePainter *);
79
80 static void
81 GatePainterPangoXft_drawString(GatePainter *, GC, int, int, const char*, int);
82
83 static void
84 GatePainterPangoXft_drawString_new(GatePainter *, GatePainterContext*, int, int, const char*, int);
85
86 static GatePainterContext*
87 GatePainterPangoXft_createContext(GatePainter*);
88
89 static GateColor
90 GatePainterPangoXft_createColor(GatePainter*, const char*);
91
92 /**
93 * @brief virtual methods table for GatePainterContext class
94 */
95 struct _GatePainterContext_vtable {
96 void (*setFont)(GatePainterContext*, GateFont);
97 int (*textWidth)(GatePainterContext*, GateFont, const char*, int len);
98 GateFontMetrics (*fontMetrics)(GatePainterContext*, GateFont*);
99 void (*print)(GatePainterContext*, FILE*);
100 };
101
102 #define GATE_PAINTER \
103 struct _GatePainter_vtable *vtable; \
104 Display *display; \
105 Drawable drawable; \
106
107 struct _GatePainter {
108
109 GATE_PAINTER
110
111 };
112
113 struct _GatePainterXlib {
114
115 GATE_PAINTER
116
117 };
118
119 struct _GatePainterPangoXft {
120
121 GATE_PAINTER
122
123 XftDraw *draw;
124 PangoFontMap *fontMap;
125 Pixmap pixmap;
126 };
127
128 static void GatePainterXlibContext_setFont(GatePainterContext*, GateFont);
129 static void GatePainterPangoXftContext_setFont(GatePainterContext*, GateFont);
130
131 static void GatePainterXlibContext_print(GatePainterContext*, FILE*);
132 static void GatePainterPangoXftContext_print(GatePainterContext*, FILE*);
133
134 static int GatePainterXlibContext_textWidth(GatePainterContext*, GateFont, const char*, int);
135 static int GatePainterPangoXftContext_textWidth(GatePainterContext*, GateFont, const char*, int);
136
137 static GateFontMetrics GatePainterXlibContext_fontMetrics(GatePainterContext *_self, GateFont *font);
138 static GateFontMetrics GatePainterPangoXftContext_fontMetrics(GatePainterContext *_self, GateFont *font);
139
140 static struct _GatePainterContext_vtable _gatePainterXlibContext_vtable = {
141 .setFont = GatePainterXlibContext_setFont,
142 .textWidth = GatePainterXlibContext_textWidth,
143 .fontMetrics = GatePainterXlibContext_fontMetrics,
144 .print = GatePainterXlibContext_print
145 };
146
147 static struct _GatePainterContext_vtable _gatePainterPangoXftContext_vtable = {
148 .setFont = GatePainterPangoXftContext_setFont,
149 .textWidth = GatePainterPangoXftContext_textWidth,
150 .fontMetrics = GatePainterPangoXftContext_fontMetrics,
151 .print = GatePainterPangoXftContext_print
152 };
153
154 #define GATE_PAINTER_CONTEXT \
155 struct _GatePainterContext_vtable *vtable; \
156 GatePainter *painter; \
157 GateColor color; \
158 GC gc;
159
160 struct _GatePainterContext {
161
162 GATE_PAINTER_CONTEXT
163
164 };
165
166 GC
GatePainterContext_gc(GatePainterContext * self)167 GatePainterContext_gc(GatePainterContext *self)
168 {
169 return (self->gc);
170 }
171
172 GC*
GatePainterContext_gcRef(GatePainterContext * self)173 GatePainterContext_gcRef(GatePainterContext *self)
174 {
175 return (&self->gc);
176 }
177
178 void
GatePainterContext_setFont(GatePainterContext * self,GateFont font)179 GatePainterContext_setFont(GatePainterContext *self, GateFont font)
180 {
181 self->vtable->setFont(self, font);
182 }
183
184 void
GatePainterContext_setColor(GatePainterContext * self,GateColor color)185 GatePainterContext_setColor(GatePainterContext *self, GateColor color)
186 {
187 self->color = color;
188 }
189
190 void
GatePainterContext_print(GatePainterContext * self,FILE * stream)191 GatePainterContext_print(GatePainterContext *self, FILE *stream)
192 {
193 self->vtable->print(self, stream);
194 }
195
196 int
GatePainterContext_textWidth(GatePainterContext * self,GateFont font,const char * str,int len)197 GatePainterContext_textWidth(GatePainterContext *self, GateFont font, const char *str, int len)
198 {
199 return (self->vtable->textWidth(self, font, str, len));
200 }
201
202 GateFontMetrics
GatePainterContext_fontMetrics(GatePainterContext * self,GateFont * font)203 GatePainterContext_fontMetrics(GatePainterContext *self, GateFont *font)
204 {
205 return (self->vtable->fontMetrics(self, font));
206 }
207
208 struct _GatePainterXlibContext {
209
210 GATE_PAINTER_CONTEXT
211
212 };
213
214 struct _GatePainterPangoXftContext {
215
216 GATE_PAINTER_CONTEXT
217
218 PangoContext *pangoContext;
219 GHashTable *fontHash;
220 PangoFont *activeFont;
221 PangoLayout *layout;
222 };
223
224 static struct _GatePainter_vtable _gatePainterPangoXft_vtable = {
225 .init = GatePainterPangoXft_init,
226 .destroy = GatePainterPangoXft_destroy,
227 .drawString = GatePainterPangoXft_drawString,
228 .drawString_new = GatePainterPangoXft_drawString_new,
229 .createContext = GatePainterPangoXft_createContext,
230 .getColor = GatePainterPangoXft_createColor
231 };
232
233 static struct _GatePainter_vtable _gatePainterXlib_vtable = {
234 .init = GatePainterXlib_init,
235 .destroy = GatePainterXlib_destroy,
236 .drawString = GatePainterXlib_drawString,
237 .drawString_new = GatePainterXlib_drawString_new,
238 .createContext = GatePainterXlib_createContext,
239 .getColor = GatePainterXlib_createColor
240 };
241
242 void
GatePainter_init(GatePainter * self,Display * display,Drawable draw)243 GatePainter_init(GatePainter *self, Display *display, Drawable draw)
244 {
245 self->display = display;
246 self->drawable = draw;
247 self->vtable->init(self, display, draw);
248 }
249
250 void
GatePainter_destroy(GatePainter * self)251 GatePainter_destroy(GatePainter *self)
252 {
253 self->vtable->destroy(self);
254 }
255
256 void
GatePainter_drawString(GatePainter * self,GC gc,int x,int y,const char * str,int len)257 GatePainter_drawString(GatePainter *self, GC gc, int x, int y, const char *str, int len)
258 {
259 self->vtable->drawString(self, gc, x, y, str, len);
260 }
261
262 void
GatePainter_drawString_new(GatePainter * self,GatePainterContext * gc,int x,int y,const char * str,int len)263 GatePainter_drawString_new(GatePainter *self, GatePainterContext *gc, int x, int y, const char *str, int len)
264 {
265 self->vtable->drawString_new(self, gc, x, y, str, len);
266 }
267
268 GatePainterContext*
GatePainter_createContext(GatePainter * self)269 GatePainter_createContext(GatePainter *self)
270 {
271 GatePainterContext *result;
272
273 result = self->vtable->createContext(self);
274 result->painter = self;
275
276 return result;
277 }
278
279 GateColor
GatePainter_getColor(GatePainter * self,const char * name)280 GatePainter_getColor(GatePainter *self, const char *name)
281 {
282 return (self->vtable->getColor(self, name));
283 }
284
285 Drawable
GatePainter_drawable(GatePainter * self)286 GatePainter_drawable(GatePainter *self)
287 {
288 return (self->drawable);
289 }
290
291 void
GatePainter_setDrawable(GatePainter * self,Drawable newVal)292 GatePainter_setDrawable(GatePainter *self, Drawable newVal)
293 {
294 self->drawable = newVal;
295 }
296
297 GatePainterXlib*
new_GatePainterXlib()298 new_GatePainterXlib()
299 {
300 GatePainterXlib *result;
301
302 result = (GatePainterXlib*)malloc(sizeof (GatePainterXlib));
303 assert(result != NULL);
304
305 result->vtable = &_gatePainterXlib_vtable;
306
307 return (result);
308 }
309
310 static void
GatePainterXlib_init(GatePainter * _self,Display * display,Drawable draw)311 GatePainterXlib_init(GatePainter *_self, Display *display, Drawable draw)
312 {
313 #define self ((GatePainterXlib*)_self)
314
315 #undef self
316 }
317
318 static void
GatePainterXlib_destroy(GatePainter * _self)319 GatePainterXlib_destroy(GatePainter *_self)
320 {
321 #define self ((GatePainterXlib*)_self)
322
323 #undef self
324 }
325
326 static void
GatePainterXlib_drawString(GatePainter * self,GC gc,int x,int y,const char * str,int len)327 GatePainterXlib_drawString(GatePainter *self, GC gc, int x, int y, const char *str, int len)
328 {
329 int res;
330
331 res = XDrawString(self->display, self->drawable, gc, x, y, str, len);
332
333 assert(res == Success);
334 }
335
336 static void
GatePainterXlib_drawString_new(GatePainter * self,GatePainterContext * gc,int x,int y,const char * str,int len)337 GatePainterXlib_drawString_new(GatePainter *self, GatePainterContext *gc, int x, int y, const char *str, int len)
338 {
339 int res;
340
341 res = XDrawString(self->display, self->drawable,
342 GatePainterContext_gc(gc), x, y, str, len);
343
344 assert(res == Success);
345 }
346
347 static GatePainterContext*
GatePainterXlib_createContext(GatePainter * _self)348 GatePainterXlib_createContext(GatePainter *_self)
349 {
350 #define self ((GatePainterXlib*)_self)
351 GatePainterXlibContext *result;
352
353 result = (GatePainterXlibContext*)malloc(sizeof (GatePainterXlibContext));
354 assert(result != NULL);
355
356 result->vtable = &_gatePainterXlibContext_vtable;
357
358 return ((GatePainterContext*)result);
359 #undef self
360 }
361
362 static GateColor
GatePainterXlib_createColor(GatePainter * self,const char * name)363 GatePainterXlib_createColor(GatePainter *self, const char *name)
364 {
365 GateColor result;
366 XColor eXC;
367 //int res;
368
369 /*res =*/ XAllocNamedColor(self->display, TkGate.CM, name, &result.xColor,
370 &eXC);
371 //if (res != Success)
372 // fprintf(stderr, "XAllocNamedColor: %d\n", res);
373
374 return (result);
375 }
376
377 GatePainterPangoXft*
new_GatePainterPangoXft()378 new_GatePainterPangoXft()
379 {
380 GatePainterPangoXft *result;
381
382 result = (GatePainterPangoXft*)malloc(sizeof (GatePainterPangoXft));
383 assert(result != NULL);
384
385 result->vtable = &_gatePainterPangoXft_vtable;
386
387 return (result);
388 }
389
390 static void
GatePainterPangoXft_init(GatePainter * _self,Display * display,Drawable draw)391 GatePainterPangoXft_init(GatePainter *_self, Display *display, Drawable draw)
392 {
393 #define self ((GatePainterPangoXft*)_self)
394
395 self->pixmap = XCreatePixmap(display, draw, 800, 600, 24);
396 self->draw = XftDrawCreate(
397 self->display,
398 self->pixmap,
399 XDefaultVisual(self->display,0),
400 XDefaultColormap(self->display, 0));
401 assert(self->draw);
402
403 self->fontMap = pango_xft_get_font_map(self->display, 0);
404 assert(self->fontMap);
405 #undef self
406 }
407
408 static void
GatePainterPangoXft_destroy(GatePainter * _self)409 GatePainterPangoXft_destroy(GatePainter *_self)
410 {
411 #define self ((GatePainterPangoXft*)_self)
412 XftDrawDestroy(self->draw);
413 #undef self
414 }
415
416 static void
GatePainterPangoXft_drawString(GatePainter * self,GC gc,int x,int y,const char * str,int len)417 GatePainterPangoXft_drawString(GatePainter *self, GC gc, int x, int y, const char *str, int len)
418 {
419 int res;
420
421 res = XDrawString(self->display, self->drawable, gc, x, y, str, len);
422
423 assert(res == Success);
424 }
425
426 static void
GatePainterPangoXft_drawString_new(GatePainter * _self,GatePainterContext * _gc,int x,int y,const char * str,int len)427 GatePainterPangoXft_drawString_new(GatePainter *_self, GatePainterContext *_gc, int x, int y, const char *str, int len)
428 {
429 #define self ((GatePainterPangoXft*)_self)
430 #define gCont ((GatePainterPangoXftContext*)_gc)
431
432 unsigned width, height, function; //, foreground;
433 XGCValues result;
434
435 XGetGCValues(self->display, gCont->gc,
436 GCFunction | GCBackground | GCForeground, &result);
437 function = result.function;
438 //foreground = result.foreground;
439
440 GatePainterContext_print(_gc, stdout);
441 XSetFunction(self->display, gCont->gc, GXcopy);
442 //XSetForeground(self->display, gCont->gc, result.background);
443
444 pango_layout_set_text(gCont->layout, str, len);
445 pango_layout_set_font_description(gCont->layout,
446 pango_font_describe(gCont->activeFont));
447 pango_layout_get_pixel_size(gCont->layout, (int*)&width, (int*)&height);
448
449 XFillRectangle(self->display,self->pixmap, gCont->gc, 0,0, width,height);
450 XSetFunction(self->display, gCont->gc, function);
451 //XSetForeground(self->display, gCont->gc, foreground);
452
453 pango_xft_render_layout(self->draw, &(gCont->color.xftColor), gCont->layout,
454 0, 0);
455 XCopyArea(self->display, self->pixmap, self->drawable, gCont->gc,
456 0,0, width,height, x,y);
457
458 #undef self
459 #undef gCont
460 }
461
462 guint
getFontHash(gconstpointer key)463 getFontHash(gconstpointer key)
464 {
465 GateFont *font = (GateFont*)key;
466 guint res;
467
468 res = ((uint8_t)TkGate.circuit->zoom_factor << 24) |
469 ((uint8_t)font->family << 16) |
470 ((uint8_t)font->prop << 8) |
471 (uint8_t)font->size;
472
473 return (res);
474 }
475
476 gboolean
fontsEqual(gconstpointer a,gconstpointer b)477 fontsEqual(gconstpointer a, gconstpointer b)
478 {
479 int res;
480
481 res = memcmp(a, b, sizeof (GateFont));
482 if (res == 0)
483 return (TRUE);
484 else
485 return (FALSE);
486 }
487
488 static GatePainterContext*
GatePainterPangoXft_createContext(GatePainter * _self)489 GatePainterPangoXft_createContext(GatePainter *_self)
490 {
491 #define self ((GatePainterPangoXft*)_self)
492 GatePainterPangoXftContext *result;
493
494 result = (GatePainterPangoXftContext*)malloc(
495 sizeof (GatePainterPangoXftContext));
496 assert(result != NULL);
497 memset(result, 0, sizeof (GatePainterPangoXftContext));
498
499 result->vtable = &_gatePainterPangoXftContext_vtable;
500 result->pangoContext = pango_font_map_create_context(self->fontMap);
501 assert(result->pangoContext);
502
503 result->fontHash = g_hash_table_new(getFontHash, fontsEqual);
504 assert(result->fontHash);
505
506 XftColorAllocName(self->display, XDefaultVisual(self->display, 0),
507 TkGate.CM, "black", &(result->color.xftColor));
508
509 result->layout = pango_layout_new(result->pangoContext);
510 assert(result->layout);
511
512 return ((GatePainterContext*)result);
513 #undef self
514 }
515
516 static GateColor
GatePainterPangoXft_createColor(GatePainter * self,const char * name)517 GatePainterPangoXft_createColor(GatePainter *self, const char *name)
518 {
519 GateColor result;
520
521 GatePainterXlib_createColor(self, name);
522 XftColorAllocName(self->display, XDefaultVisual(self->display, 0),
523 TkGate.CM, name, &result.xftColor);
524
525 return (result);
526 }
527
528 static void
GatePainterXlibContext_setFont(GatePainterContext * _self,GateFont font)529 GatePainterXlibContext_setFont(GatePainterContext *_self, GateFont font)
530 {
531 #define self ((GatePainterXlibContext*)_self)
532 int res;
533 XFontStruct *fs;
534
535 fs = GetXFont(font, TkGate.circuit->zoom_factor);
536 assert(fs);
537
538 res = XSetFont(self->painter->display, self->gc, fs->fid);
539 if (res != Success);
540 //fprintf(stderr, "XSetFont: error %d\n", res);
541 #undef self
542 }
543
544 void
GatePainterXlibContext_print(GatePainterContext * self,FILE * stream)545 GatePainterXlibContext_print(GatePainterContext *self, FILE *stream)
546 {
547 XGCValues result;
548
549 XGetGCValues(self->painter->display, self->gc,
550 GCFunction | GCForeground | GCBackground | GCFont, &result);
551
552 //fprintf(stream, "GatePainter context:\n"
553 // "\tfunction: %d\n\tforeground: %lx\n\tbackground: %lx\n",
554 // result.function, result.foreground, result.background);
555 }
556
557 void
GatePainterPangoXftContext_print(GatePainterContext * _self,FILE * stream)558 GatePainterPangoXftContext_print(GatePainterContext *_self, FILE *stream)
559 {
560 #define self ((GatePainterPangoXftContext*)_self)
561 XGCValues result;
562
563 XGetGCValues(self->painter->display, self->gc,
564 GCFunction | GCForeground | GCBackground | GCFont, &result);
565
566 //fprintf(stream, "GatePainter context:\n"
567 // "\tfunction: %d\n\tforeground: %lx\n\tbackground: %lx\n",
568 // result.function, result.foreground, result.background);
569 #undef self
570 }
571
572 static PangoFont*
_GatePainterPangoXftContext_addFont(GatePainterPangoXftContext * self,GateFont * font)573 _GatePainterPangoXftContext_addFont(GatePainterPangoXftContext *self, GateFont *font)
574 {
575 #define painter ((GatePainterPangoXft*)self->painter)
576 PangoFontDescription *desc;
577 PangoFont *result;
578 GateFont *key;
579
580 result = (PangoFont*)g_hash_table_lookup(self->fontHash, font);
581 if (result == NULL) {
582 desc = pango_font_description_new();
583 assert(desc);
584 switch (font->family) {
585 case FF_HELVETICA :
586 pango_font_description_set_family(desc, "sans");
587 break;
588 case FF_COURIER :
589 pango_font_description_set_family(desc, "courier");
590 break;
591 case FF_TIMES :
592 pango_font_description_set_family(desc, "serif");
593 break;
594 default:
595 break;
596 }
597 pango_font_description_set_size(desc,
598 getFontSize(font->size)*TkGate.circuit->zoom_factor*PANGO_SCALE*3/4);
599
600 switch (font->prop) {
601 case FP_BOLD :
602 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
603 break;
604 case FP_ITALIC :
605 pango_font_description_set_style(desc, PANGO_STYLE_ITALIC);
606 break;
607 default :
608 break;
609 }
610
611 result = pango_font_map_load_font(painter->fontMap, self->pangoContext,
612 desc);
613 if (!result) {
614 fputs("pango_font_map_load_font: cannot load font", stderr);
615 return (NULL);
616 }
617
618 key = (GateFont*)malloc(sizeof (GateFont));
619 memcpy(key, font, sizeof(GateFont));
620 if (!g_hash_table_insert(self->fontHash, key, result)) {
621 fputs("g_hash_table_insert: cannot insert value", stderr);
622 return (NULL);
623 }
624
625 printf("PainterPangoXft: font desc: family %d, props %d size %d created\n",
626 font->family, font->prop, font->size);
627 }
628 return (result);
629 #undef painter
630 }
631
632 static void
GatePainterPangoXftContext_setFont(GatePainterContext * _self,GateFont font)633 GatePainterPangoXftContext_setFont(GatePainterContext *_self, GateFont font)
634 {
635 #define self ((GatePainterPangoXftContext*)_self)
636 self->activeFont = _GatePainterPangoXftContext_addFont(self, &font);
637 assert(self->activeFont);
638 #undef self
639 }
640
641 static int
GatePainterXlibContext_textWidth(GatePainterContext * self,GateFont font,const char * str,int len)642 GatePainterXlibContext_textWidth(GatePainterContext *self, GateFont font, const char *str, int len)
643 {
644 return (XTextWidth(GetXFont(font, TkGate.circuit->zoom_factor), str, len));
645 }
646
647 static GateFontMetrics
GatePainterXlibContext_fontMetrics(GatePainterContext * _self,GateFont * font)648 GatePainterXlibContext_fontMetrics(GatePainterContext *_self, GateFont *font)
649 {
650 GateFontMetrics result;
651 XFontStruct *fs;
652
653 fs = GetXFont(*font, TkGate.circuit->zoom_factor);
654 result.ascent = fs->ascent;
655 result.descent = fs->descent;
656
657 return (result);
658 }
659
660 static int
GatePainterPangoXftContext_textWidth(GatePainterContext * _self,GateFont font,const char * str,int len)661 GatePainterPangoXftContext_textWidth(GatePainterContext *_self, GateFont font, const char *str, int len)
662 {
663 #define self ((GatePainterPangoXftContext*)_self)
664
665 PangoFont *pangoFont;
666 int width, height;
667
668 pangoFont = _GatePainterPangoXftContext_addFont(self, &font);
669 assert(pangoFont);
670
671 pango_layout_set_text(self->layout, str, len);
672 pango_layout_set_font_description(self->layout,
673 pango_font_describe(pangoFont));
674 pango_layout_get_pixel_size(self->layout, &width, &height);
675
676 return (width);
677 #undef self
678 }
679
680 static GateFontMetrics
GatePainterPangoXftContext_fontMetrics(GatePainterContext * _self,GateFont * font)681 GatePainterPangoXftContext_fontMetrics(GatePainterContext *_self, GateFont *font)
682 {
683 #define self ((GatePainterPangoXftContext*)_self)
684 GateFontMetrics result;
685 PangoFont *pangoFont;
686 PangoFontMetrics *metrics;
687
688 pangoFont = _GatePainterPangoXftContext_addFont(self, font);
689 assert(pangoFont);
690 metrics = pango_font_get_metrics(pangoFont, NULL);
691 assert(metrics);
692
693 result.ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
694 result.descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
695
696 result.descent += result.ascent;
697 result.ascent = 0;
698
699 return (result);
700 #undef self
701 }
702