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