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>
16 #include "precompose.h"
19 /*{{{ UTF-8 processing */
23 #define UTF_2_DATA 0x1F
24 #define UTF_3_DATA 0x0F
32 static void toucs(const char *str_
, int len
, XChar2b
**str16
, int *len16
)
35 const uchar
*str
=(const uchar
*)str_
;
38 *str16
=ALLOC_N(XChar2b
, len
);
44 if((str
[i
] & UTF_3
) == UTF_3
){
47 ch
=((str
[i
] & UTF_3_DATA
) << 12)
48 | ((str
[i
+1] & UTF_DATA
) << 6)
49 | (str
[i
+2] & UTF_DATA
);
51 }else if((str
[i
] & UTF_2
) == UTF_2
){
54 ch
= ((str
[i
] & UTF_2_DATA
) << 6) | (str
[i
+1] & UTF_DATA
);
56 }else if(str
[i
] < UTF_1
){
65 wchar_t precomp
=do_precomposition(prev
, ch
);
72 (*str16
)[*len16
].byte2
=ch
&0xff;
73 (*str16
)[*len16
].byte1
=(ch
>>8)&0xff;
86 static DEFont
*fonts
=NULL
;
89 static bool iso10646_font(const char *fontname
)
93 if(strchr(fontname
, ',')!=NULL
)
94 return FALSE
; /* fontset */
96 iso
=strstr(fontname
, "iso10646-1");
97 return (iso
!=NULL
&& iso
[10]=='\0');
101 DEFont
*de_load_font(const char *fontname
)
104 XFontSet fontset
=NULL
;
105 XFontStruct
*fontstruct
=NULL
;
107 assert(fontname
!=NULL
);
109 /* There shouldn't be that many fonts... */
110 for(fnt
=fonts
; fnt
!=NULL
; fnt
=fnt
->next
){
111 if(strcmp(fnt
->pattern
, fontname
)==0){
117 if(ioncore_g
.use_mb
&& !(ioncore_g
.enc_utf8
&& iso10646_font(fontname
))){
118 fontset
=de_create_font_set(fontname
);
120 if(XContextDependentDrawing(fontset
)){
121 warn(TR("Fontset for font pattern '%s' implements context "
122 "dependent drawing, which is unsupported. Expect "
123 "clutter."), fontname
);
127 fontstruct
=XLoadQueryFont(ioncore_g
.dpy
, fontname
);
130 if(fontstruct
==NULL
&& fontset
==NULL
){
131 if(strcmp(fontname
, CF_FALLBACK_FONT_NAME
)!=0){
133 warn(TR("Could not load font \"%s\", trying \"%s\""),
134 fontname
, CF_FALLBACK_FONT_NAME
);
135 fnt
=de_load_font(CF_FALLBACK_FONT_NAME
);
137 warn(TR("Failed to load fallback font."));
148 fnt
->fontset
=fontset
;
149 fnt
->fontstruct
=fontstruct
;
150 fnt
->pattern
=scopy(fontname
);
155 LINK_ITEM(fonts
, fnt
, next
, prev
);
161 bool de_set_font_for_style(DEStyle
*style
, DEFont
*font
)
163 if(style
->font
!=NULL
)
164 de_free_font(style
->font
);
169 if(style
->font
->fontstruct
!=NULL
){
170 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
171 style
->font
->fontstruct
->fid
);
178 bool de_load_font_for_style(DEStyle
*style
, const char *fontname
)
180 if(style
->font
!=NULL
)
181 de_free_font(style
->font
);
183 style
->font
=de_load_font(fontname
);
185 if(style
->font
==NULL
)
188 if(style
->font
->fontstruct
!=NULL
){
189 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
190 style
->font
->fontstruct
->fid
);
197 void de_free_font(DEFont
*font
)
199 if(--font
->refcount
!=0)
202 if(font
->fontset
!=NULL
)
203 XFreeFontSet(ioncore_g
.dpy
, font
->fontset
);
204 if(font
->fontstruct
!=NULL
)
205 XFreeFont(ioncore_g
.dpy
, font
->fontstruct
);
206 if(font
->pattern
!=NULL
)
209 UNLINK_ITEM(fonts
, font
, next
, prev
);
220 void debrush_get_font_extents(DEBrush
*brush
, GrFontExtents
*fnte
)
222 if(brush
->d
->font
==NULL
){
223 DE_RESET_FONT_EXTENTS(fnte
);
227 defont_get_font_extents(brush
->d
->font
, fnte
);
231 void defont_get_font_extents(DEFont
*font
, GrFontExtents
*fnte
)
233 if(font
->fontset
!=NULL
){
234 XFontSetExtents
*ext
=XExtentsOfFontSet(font
->fontset
);
237 fnte
->max_height
=ext
->max_logical_extent
.height
;
238 fnte
->max_width
=ext
->max_logical_extent
.width
;
239 fnte
->baseline
=-ext
->max_logical_extent
.y
;
241 }else if(font
->fontstruct
!=NULL
){
242 XFontStruct
*fnt
=font
->fontstruct
;
243 fnte
->max_height
=fnt
->ascent
+fnt
->descent
;
244 fnte
->max_width
=fnt
->max_bounds
.width
;
245 fnte
->baseline
=fnt
->ascent
;
250 DE_RESET_FONT_EXTENTS(fnte
);
254 uint
debrush_get_text_width(DEBrush
*brush
, const char *text
, uint len
)
256 if(brush
->d
->font
==NULL
|| text
==NULL
|| len
==0)
259 return defont_get_text_width(brush
->d
->font
, text
, len
);
263 uint
defont_get_text_width(DEFont
*font
, const char *text
, uint len
)
265 if(font
->fontset
!=NULL
){
267 #ifdef CF_DE_USE_XUTF8
268 if(ioncore_g
.enc_utf8
)
269 Xutf8TextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
272 XmbTextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
274 }else if(font
->fontstruct
!=NULL
){
275 if(ioncore_g
.enc_utf8
){
276 XChar2b
*str16
; int len16
=0;
279 toucs(text
, len
, &str16
, &len16
);
281 res
=XTextWidth16(font
->fontstruct
, str16
, len16
);
287 return XTextWidth(font
->fontstruct
, text
, len
);
298 /*{{{ String drawing */
301 void debrush_do_draw_string_default(DEBrush
*brush
, int x
, int y
,
302 const char *str
, int len
, bool needfill
,
303 DEColourGroup
*colours
)
305 GC gc
=brush
->d
->normal_gc
;
307 if(brush
->d
->font
==NULL
)
310 XSetForeground(ioncore_g
.dpy
, gc
, colours
->fg
);
313 if(brush
->d
->font
->fontset
!=NULL
){
314 #ifdef CF_DE_USE_XUTF8
315 if(ioncore_g
.enc_utf8
)
316 Xutf8DrawString(ioncore_g
.dpy
, brush
->win
,
317 brush
->d
->font
->fontset
,
321 XmbDrawString(ioncore_g
.dpy
, brush
->win
,
322 brush
->d
->font
->fontset
,
324 }else if(brush
->d
->font
->fontstruct
!=NULL
){
325 if(ioncore_g
.enc_utf8
){
326 XChar2b
*str16
; int len16
=0;
327 toucs(str
, len
, &str16
, &len16
);
328 XDrawString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
331 XDrawString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
335 XSetBackground(ioncore_g
.dpy
, gc
, colours
->bg
);
336 if(brush
->d
->font
->fontset
!=NULL
){
337 #ifdef CF_DE_USE_XUTF8
338 if(ioncore_g
.enc_utf8
)
339 Xutf8DrawImageString(ioncore_g
.dpy
, brush
->win
,
340 brush
->d
->font
->fontset
,
344 XmbDrawImageString(ioncore_g
.dpy
, brush
->win
,
345 brush
->d
->font
->fontset
,
347 }else if(brush
->d
->font
->fontstruct
!=NULL
){
348 if(ioncore_g
.enc_utf8
){
349 XChar2b
*str16
; int len16
=0;
350 toucs(str
, len
, &str16
, &len16
);
351 XDrawImageString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
354 XDrawImageString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
361 void debrush_do_draw_string(DEBrush
*brush
, int x
, int y
,
362 const char *str
, int len
, bool needfill
,
363 DEColourGroup
*colours
)
365 CALL_DYN(debrush_do_draw_string
, brush
, (brush
, x
, y
, str
, len
,
370 void debrush_draw_string(DEBrush
*brush
, int x
, int y
,
371 const char *str
, int len
, bool needfill
)
373 DEColourGroup
*cg
=debrush_get_current_colour_group(brush
);
375 debrush_do_draw_string(brush
, x
, y
, str
, len
, needfill
, cg
);