4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
11 #include <libtu/objp.h>
12 #include <ioncore/common.h>
13 #include <ioncore/log.h>
17 #include "precompose.h"
20 /*{{{ UTF-8 processing */
24 #define UTF_2_DATA 0x1F
25 #define UTF_3_DATA 0x0F
33 static void toucs(const char *str_
, int len
, XChar2b
**str16
, int *len16
)
36 const uchar
*str
=(const uchar
*)str_
;
39 *str16
=ALLOC_N(XChar2b
, len
);
45 if((str
[i
] & UTF_3
) == UTF_3
){
48 ch
=((str
[i
] & UTF_3_DATA
) << 12)
49 | ((str
[i
+1] & UTF_DATA
) << 6)
50 | (str
[i
+2] & UTF_DATA
);
52 }else if((str
[i
] & UTF_2
) == UTF_2
){
55 ch
= ((str
[i
] & UTF_2_DATA
) << 6) | (str
[i
+1] & UTF_DATA
);
57 }else if(str
[i
] < UTF_1
){
66 wchar_t precomp
=do_precomposition(prev
, ch
);
73 (*str16
)[*len16
].byte2
=ch
&0xff;
74 (*str16
)[*len16
].byte1
=(ch
>>8)&0xff;
87 static DEFont
*fonts
=NULL
;
90 static bool iso10646_font(const char *fontname
)
94 if(strchr(fontname
, ',')!=NULL
)
95 return FALSE
; /* fontset */
97 iso
=strstr(fontname
, "iso10646-1");
98 return (iso
!=NULL
&& iso
[10]=='\0');
102 DEFont
*de_load_font(const char *fontname
)
105 XFontSet fontset
=NULL
;
106 XFontStruct
*fontstruct
=NULL
;
108 assert(fontname
!=NULL
);
110 /* There shouldn't be that many fonts... */
111 for(fnt
=fonts
; fnt
!=NULL
; fnt
=fnt
->next
){
112 if(strcmp(fnt
->pattern
, fontname
)==0){
118 if(ioncore_g
.use_mb
&& !(ioncore_g
.enc_utf8
&& iso10646_font(fontname
))){
119 LOG(DEBUG
, FONT
, "Loading fontset %s", fontname
);
120 fontset
=de_create_font_set(fontname
);
122 if(XContextDependentDrawing(fontset
)){
123 warn(TR("Fontset for font pattern '%s' implements context "
124 "dependent drawing, which is unsupported. Expect "
125 "clutter."), fontname
);
129 LOG(DEBUG
, FONT
, "Loading fontstruct %s", fontname
);
130 fontstruct
=XLoadQueryFont(ioncore_g
.dpy
, fontname
);
133 if(fontstruct
==NULL
&& fontset
==NULL
){
134 if(strcmp(fontname
, CF_FALLBACK_FONT_NAME
)!=0){
136 LOG(WARN
, FONT
, TR("Could not load font \"%s\", trying \"%s\""),
137 fontname
, CF_FALLBACK_FONT_NAME
);
138 fnt
=de_load_font(CF_FALLBACK_FONT_NAME
);
140 LOG(WARN
, FONT
, TR("Failed to load fallback font."));
151 fnt
->fontset
=fontset
;
152 fnt
->fontstruct
=fontstruct
;
153 fnt
->pattern
=scopy(fontname
);
158 LINK_ITEM(fonts
, fnt
, next
, prev
);
164 bool de_set_font_for_style(DEStyle
*style
, DEFont
*font
)
166 if(style
->font
!=NULL
)
167 de_free_font(style
->font
);
172 if(style
->font
->fontstruct
!=NULL
){
173 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
174 style
->font
->fontstruct
->fid
);
181 bool de_load_font_for_style(DEStyle
*style
, const char *fontname
)
183 if(style
->font
!=NULL
)
184 de_free_font(style
->font
);
186 style
->font
=de_load_font(fontname
);
188 if(style
->font
==NULL
)
191 if(style
->font
->fontstruct
!=NULL
){
192 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
193 style
->font
->fontstruct
->fid
);
200 void de_free_font(DEFont
*font
)
202 if(--font
->refcount
!=0)
205 if(font
->fontset
!=NULL
)
206 XFreeFontSet(ioncore_g
.dpy
, font
->fontset
);
207 if(font
->fontstruct
!=NULL
)
208 XFreeFont(ioncore_g
.dpy
, font
->fontstruct
);
209 if(font
->pattern
!=NULL
)
212 UNLINK_ITEM(fonts
, font
, next
, prev
);
223 void debrush_get_font_extents(DEBrush
*brush
, GrFontExtents
*fnte
)
225 if(brush
->d
->font
==NULL
){
226 DE_RESET_FONT_EXTENTS(fnte
);
230 defont_get_font_extents(brush
->d
->font
, fnte
);
234 void defont_get_font_extents(DEFont
*font
, GrFontExtents
*fnte
)
236 if(font
->fontset
!=NULL
){
237 XFontSetExtents
*ext
=XExtentsOfFontSet(font
->fontset
);
240 fnte
->max_height
=ext
->max_logical_extent
.height
;
241 fnte
->max_width
=ext
->max_logical_extent
.width
;
242 fnte
->baseline
=-ext
->max_logical_extent
.y
;
244 }else if(font
->fontstruct
!=NULL
){
245 XFontStruct
*fnt
=font
->fontstruct
;
246 fnte
->max_height
=fnt
->ascent
+fnt
->descent
;
247 fnte
->max_width
=fnt
->max_bounds
.width
;
248 fnte
->baseline
=fnt
->ascent
;
253 DE_RESET_FONT_EXTENTS(fnte
);
257 uint
debrush_get_text_width(DEBrush
*brush
, const char *text
, uint len
)
259 if(brush
->d
->font
==NULL
|| text
==NULL
|| len
==0)
262 return defont_get_text_width(brush
->d
->font
, text
, len
);
266 uint
defont_get_text_width(DEFont
*font
, const char *text
, uint len
)
268 if(font
->fontset
!=NULL
){
270 #ifdef CF_DE_USE_XUTF8
271 if(ioncore_g
.enc_utf8
)
272 Xutf8TextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
275 XmbTextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
277 }else if(font
->fontstruct
!=NULL
){
278 if(ioncore_g
.enc_utf8
){
279 XChar2b
*str16
; int len16
=0;
282 toucs(text
, len
, &str16
, &len16
);
284 res
=XTextWidth16(font
->fontstruct
, str16
, len16
);
290 return XTextWidth(font
->fontstruct
, text
, len
);
301 /*{{{ String drawing */
304 void debrush_do_draw_string_default(DEBrush
*brush
, int x
, int y
,
305 const char *str
, int len
, bool needfill
,
306 DEColourGroup
*colours
)
308 GC gc
=brush
->d
->normal_gc
;
310 if(brush
->d
->font
==NULL
)
313 XSetForeground(ioncore_g
.dpy
, gc
, colours
->fg
);
316 if(brush
->d
->font
->fontset
!=NULL
){
317 #ifdef CF_DE_USE_XUTF8
318 if(ioncore_g
.enc_utf8
)
319 Xutf8DrawString(ioncore_g
.dpy
, brush
->win
,
320 brush
->d
->font
->fontset
,
324 XmbDrawString(ioncore_g
.dpy
, brush
->win
,
325 brush
->d
->font
->fontset
,
327 }else if(brush
->d
->font
->fontstruct
!=NULL
){
328 if(ioncore_g
.enc_utf8
){
329 XChar2b
*str16
; int len16
=0;
330 toucs(str
, len
, &str16
, &len16
);
331 XDrawString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
334 XDrawString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
338 XSetBackground(ioncore_g
.dpy
, gc
, colours
->bg
);
339 if(brush
->d
->font
->fontset
!=NULL
){
340 #ifdef CF_DE_USE_XUTF8
341 if(ioncore_g
.enc_utf8
)
342 Xutf8DrawImageString(ioncore_g
.dpy
, brush
->win
,
343 brush
->d
->font
->fontset
,
347 XmbDrawImageString(ioncore_g
.dpy
, brush
->win
,
348 brush
->d
->font
->fontset
,
350 }else if(brush
->d
->font
->fontstruct
!=NULL
){
351 if(ioncore_g
.enc_utf8
){
352 XChar2b
*str16
; int len16
=0;
353 toucs(str
, len
, &str16
, &len16
);
354 XDrawImageString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
357 XDrawImageString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
364 void debrush_do_draw_string(DEBrush
*brush
, int x
, int y
,
365 const char *str
, int len
, bool needfill
,
366 DEColourGroup
*colours
)
368 CALL_DYN(debrush_do_draw_string
, brush
, (brush
, x
, y
, str
, len
,
373 void debrush_draw_string(DEBrush
*brush
, int x
, int y
,
374 const char *str
, int len
, bool needfill
)
376 DEColourGroup
*cg
=debrush_get_current_colour_group(brush
);
378 debrush_do_draw_string(brush
, x
, y
, str
, len
, needfill
, cg
);