4 * Copyright (c) the Notion team 2013.
5 * Copyright (c) Tuomo Valkonen 1999-2009.
7 * See the included file LICENSE for details.
12 #include <libtu/objp.h>
13 #include <ioncore/common.h>
14 #include <ioncore/log.h>
18 #include "precompose.h"
21 /*{{{ UTF-8 processing */
25 #define UTF_2_DATA 0x1F
26 #define UTF_3_DATA 0x0F
34 static void toucs(const char *str_
, int len
, XChar2b
**str16
, int *len16
)
37 const uchar
*str
=(const uchar
*)str_
;
40 *str16
=ALLOC_N(XChar2b
, len
);
46 if((str
[i
] & UTF_3
) == UTF_3
){
49 ch
=((str
[i
] & UTF_3_DATA
) << 12)
50 | ((str
[i
+1] & UTF_DATA
) << 6)
51 | (str
[i
+2] & UTF_DATA
);
53 }else if((str
[i
] & UTF_2
) == UTF_2
){
56 ch
= ((str
[i
] & UTF_2_DATA
) << 6) | (str
[i
+1] & UTF_DATA
);
58 }else if(str
[i
] < UTF_1
){
67 wchar_t precomp
=do_precomposition(prev
, ch
);
74 (*str16
)[*len16
].byte2
=ch
&0xff;
75 (*str16
)[*len16
].byte1
=(ch
>>8)&0xff;
88 static DEFont
*fonts
=NULL
;
91 static bool iso10646_font(const char *fontname
)
95 if(strchr(fontname
, ',')!=NULL
)
96 return FALSE
; /* fontset */
98 iso
=strstr(fontname
, "iso10646-1");
99 return (iso
!=NULL
&& iso
[10]=='\0');
102 const char *de_default_fontname()
105 return "-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*";
110 DEFont
*de_load_font(const char *fontname
)
113 XFontSet fontset
=NULL
;
114 XFontStruct
*fontstruct
=NULL
;
115 const char *default_fontname
=de_default_fontname();
117 assert(fontname
!=NULL
);
119 /* There shouldn't be that many fonts... */
120 for(fnt
=fonts
; fnt
!=NULL
; fnt
=fnt
->next
){
121 if(strcmp(fnt
->pattern
, fontname
)==0){
127 if(ioncore_g
.use_mb
&& !(ioncore_g
.enc_utf8
&& iso10646_font(fontname
))){
128 LOG(DEBUG
, FONT
, "Loading fontset %s", fontname
);
129 fontset
=de_create_font_set(fontname
);
131 if(XContextDependentDrawing(fontset
)){
132 warn(TR("Fontset for font pattern '%s' implements context "
133 "dependent drawing, which is unsupported. Expect "
134 "clutter."), fontname
);
138 LOG(DEBUG
, FONT
, "Loading fontstruct %s", fontname
);
139 fontstruct
=XLoadQueryFont(ioncore_g
.dpy
, fontname
);
142 if(fontstruct
==NULL
&& fontset
==NULL
){
143 if(strcmp(fontname
, default_fontname
)!=0){
145 LOG(WARN
, FONT
, TR("Could not load font \"%s\", trying \"%s\""),
146 fontname
, default_fontname
);
147 fnt
=de_load_font(default_fontname
);
149 LOG(WARN
, FONT
, TR("Failed to load fallback font."));
160 fnt
->fontset
=fontset
;
161 fnt
->fontstruct
=fontstruct
;
162 fnt
->pattern
=scopy(fontname
);
167 LINK_ITEM(fonts
, fnt
, next
, prev
);
173 bool de_set_font_for_style(DEStyle
*style
, DEFont
*font
)
175 if(style
->font
!=NULL
)
176 de_free_font(style
->font
);
181 if(style
->font
->fontstruct
!=NULL
){
182 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
183 style
->font
->fontstruct
->fid
);
190 bool de_load_font_for_style(DEStyle
*style
, const char *fontname
)
192 if(style
->font
!=NULL
)
193 de_free_font(style
->font
);
195 style
->font
=de_load_font(fontname
);
197 if(style
->font
==NULL
)
200 if(style
->font
->fontstruct
!=NULL
){
201 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
202 style
->font
->fontstruct
->fid
);
209 void de_free_font(DEFont
*font
)
211 if(--font
->refcount
!=0)
214 if(font
->fontset
!=NULL
)
215 XFreeFontSet(ioncore_g
.dpy
, font
->fontset
);
216 if(font
->fontstruct
!=NULL
)
217 XFreeFont(ioncore_g
.dpy
, font
->fontstruct
);
218 if(font
->pattern
!=NULL
)
221 UNLINK_ITEM(fonts
, font
, next
, prev
);
232 void debrush_get_font_extents(DEBrush
*brush
, GrFontExtents
*fnte
)
234 if(brush
->d
->font
==NULL
){
235 DE_RESET_FONT_EXTENTS(fnte
);
239 defont_get_font_extents(brush
->d
->font
, fnte
);
243 void defont_get_font_extents(DEFont
*font
, GrFontExtents
*fnte
)
245 if(font
->fontset
!=NULL
){
246 XFontSetExtents
*ext
=XExtentsOfFontSet(font
->fontset
);
249 fnte
->max_height
=ext
->max_logical_extent
.height
;
250 fnte
->max_width
=ext
->max_logical_extent
.width
;
251 fnte
->baseline
=-ext
->max_logical_extent
.y
;
253 }else if(font
->fontstruct
!=NULL
){
254 XFontStruct
*fnt
=font
->fontstruct
;
255 fnte
->max_height
=fnt
->ascent
+fnt
->descent
;
256 fnte
->max_width
=fnt
->max_bounds
.width
;
257 fnte
->baseline
=fnt
->ascent
;
262 DE_RESET_FONT_EXTENTS(fnte
);
266 uint
debrush_get_text_width(DEBrush
*brush
, const char *text
, uint len
)
268 if(brush
->d
->font
==NULL
|| text
==NULL
|| len
==0)
271 return defont_get_text_width(brush
->d
->font
, text
, len
);
275 uint
defont_get_text_width(DEFont
*font
, const char *text
, uint len
)
277 if(font
->fontset
!=NULL
){
279 #ifdef CF_DE_USE_XUTF8
280 if(ioncore_g
.enc_utf8
)
281 Xutf8TextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
284 XmbTextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
286 }else if(font
->fontstruct
!=NULL
){
287 if(ioncore_g
.enc_utf8
){
288 XChar2b
*str16
; int len16
=0;
291 toucs(text
, len
, &str16
, &len16
);
293 res
=XTextWidth16(font
->fontstruct
, str16
, len16
);
299 return XTextWidth(font
->fontstruct
, text
, len
);
310 /*{{{ String drawing */
313 void debrush_do_draw_string_default(DEBrush
*brush
, int x
, int y
,
314 const char *str
, int len
, bool needfill
,
315 DEColourGroup
*colours
)
317 GC gc
=brush
->d
->normal_gc
;
319 if(brush
->d
->font
==NULL
)
322 XSetForeground(ioncore_g
.dpy
, gc
, colours
->fg
);
325 if(brush
->d
->font
->fontset
!=NULL
){
326 #ifdef CF_DE_USE_XUTF8
327 if(ioncore_g
.enc_utf8
)
328 Xutf8DrawString(ioncore_g
.dpy
, brush
->win
,
329 brush
->d
->font
->fontset
,
333 XmbDrawString(ioncore_g
.dpy
, brush
->win
,
334 brush
->d
->font
->fontset
,
336 }else if(brush
->d
->font
->fontstruct
!=NULL
){
337 if(ioncore_g
.enc_utf8
){
338 XChar2b
*str16
; int len16
=0;
339 toucs(str
, len
, &str16
, &len16
);
340 XDrawString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
343 XDrawString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
347 XSetBackground(ioncore_g
.dpy
, gc
, colours
->bg
);
348 if(brush
->d
->font
->fontset
!=NULL
){
349 #ifdef CF_DE_USE_XUTF8
350 if(ioncore_g
.enc_utf8
)
351 Xutf8DrawImageString(ioncore_g
.dpy
, brush
->win
,
352 brush
->d
->font
->fontset
,
356 XmbDrawImageString(ioncore_g
.dpy
, brush
->win
,
357 brush
->d
->font
->fontset
,
359 }else if(brush
->d
->font
->fontstruct
!=NULL
){
360 if(ioncore_g
.enc_utf8
){
361 XChar2b
*str16
; int len16
=0;
362 toucs(str
, len
, &str16
, &len16
);
363 XDrawImageString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
366 XDrawImageString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
373 void debrush_do_draw_string(DEBrush
*brush
, int x
, int y
,
374 const char *str
, int len
, bool needfill
,
375 DEColourGroup
*colours
)
377 CALL_DYN(debrush_do_draw_string
, brush
, (brush
, x
, y
, str
, len
,
382 void debrush_draw_string(DEBrush
*brush
, int x
, int y
,
383 const char *str
, int len
, bool needfill
)
385 DEColourGroup
*cg
=debrush_get_current_colour_group(brush
);
387 debrush_do_draw_string(brush
, x
, y
, str
, len
, needfill
, cg
);