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
31 static void toucs(const char *str_
, int len
, XChar2b
**str16
, int *len16
)
34 const uchar
*str
=(const uchar
*)str_
;
37 *str16
=ALLOC_N(XChar2b
, len
);
43 if((str
[i
] & UTF_3
) == UTF_3
){
46 ch
=((str
[i
] & UTF_3_DATA
) << 12)
47 | ((str
[i
+1] & UTF_DATA
) << 6)
48 | (str
[i
+2] & UTF_DATA
);
50 }else if((str
[i
] & UTF_2
) == UTF_2
){
53 ch
= ((str
[i
] & UTF_2_DATA
) << 6) | (str
[i
+1] & UTF_DATA
);
55 }else if(str
[i
] < UTF_1
){
64 wchar_t precomp
=do_precomposition(prev
, ch
);
71 (*str16
)[*len16
].byte2
=ch
&0xff;
72 (*str16
)[*len16
].byte1
=(ch
>>8)&0xff;
85 static DEFont
*fonts
=NULL
;
88 static bool iso10646_font(const char *fontname
)
92 if(strchr(fontname
, ',')!=NULL
)
93 return FALSE
; /* fontset */
95 iso
=strstr(fontname
, "iso10646-1");
96 return (iso
!=NULL
&& iso
[10]=='\0');
99 const char *de_default_fontname()
102 return "-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*";
107 DEFont
*de_load_font(const char *fontname
)
110 XFontSet fontset
=NULL
;
111 XFontStruct
*fontstruct
=NULL
;
112 const char *default_fontname
=de_default_fontname();
114 assert(fontname
!=NULL
);
116 /* There shouldn't be that many fonts... */
117 for(fnt
=fonts
; fnt
!=NULL
; fnt
=fnt
->next
){
118 if(strcmp(fnt
->pattern
, fontname
)==0){
124 if(ioncore_g
.use_mb
&& !(ioncore_g
.enc_utf8
&& iso10646_font(fontname
))){
125 LOG(DEBUG
, FONT
, "Loading fontset %s", fontname
);
126 fontset
=de_create_font_set(fontname
);
128 if(XContextDependentDrawing(fontset
)){
129 warn(TR("Fontset for font pattern '%s' implements context "
130 "dependent drawing, which is unsupported. Expect "
131 "clutter."), fontname
);
135 LOG(DEBUG
, FONT
, "Loading fontstruct %s", fontname
);
136 fontstruct
=XLoadQueryFont(ioncore_g
.dpy
, fontname
);
139 if(fontstruct
==NULL
&& fontset
==NULL
){
140 if(strcmp(fontname
, default_fontname
)!=0){
142 LOG(WARN
, FONT
, TR("Could not load font \"%s\", trying \"%s\""),
143 fontname
, default_fontname
);
144 fnt
=de_load_font(default_fontname
);
146 LOG(WARN
, FONT
, TR("Failed to load fallback font."));
157 fnt
->fontset
=fontset
;
158 fnt
->fontstruct
=fontstruct
;
159 fnt
->pattern
=scopy(fontname
);
164 LINK_ITEM(fonts
, fnt
, next
, prev
);
170 bool de_set_font_for_style(DEStyle
*style
, DEFont
*font
)
172 if(style
->font
!=NULL
)
173 de_free_font(style
->font
);
178 if(style
->font
->fontstruct
!=NULL
){
179 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
180 style
->font
->fontstruct
->fid
);
187 bool de_load_font_for_style(DEStyle
*style
, const char *fontname
)
189 if(style
->font
!=NULL
)
190 de_free_font(style
->font
);
192 style
->font
=de_load_font(fontname
);
194 if(style
->font
==NULL
)
197 if(style
->font
->fontstruct
!=NULL
){
198 XSetFont(ioncore_g
.dpy
, style
->normal_gc
,
199 style
->font
->fontstruct
->fid
);
206 void de_free_font(DEFont
*font
)
208 if(--font
->refcount
!=0)
211 if(font
->fontset
!=NULL
)
212 XFreeFontSet(ioncore_g
.dpy
, font
->fontset
);
213 if(font
->fontstruct
!=NULL
)
214 XFreeFont(ioncore_g
.dpy
, font
->fontstruct
);
215 if(font
->pattern
!=NULL
)
218 UNLINK_ITEM(fonts
, font
, next
, prev
);
229 void debrush_get_font_extents(DEBrush
*brush
, GrFontExtents
*fnte
)
231 if(brush
->d
->font
==NULL
){
232 DE_RESET_FONT_EXTENTS(fnte
);
236 defont_get_font_extents(brush
->d
->font
, fnte
);
240 void defont_get_font_extents(DEFont
*font
, GrFontExtents
*fnte
)
242 if(font
->fontset
!=NULL
){
243 XFontSetExtents
*ext
=XExtentsOfFontSet(font
->fontset
);
246 fnte
->max_height
=ext
->max_logical_extent
.height
;
247 fnte
->max_width
=ext
->max_logical_extent
.width
;
248 fnte
->baseline
=-ext
->max_logical_extent
.y
;
250 }else if(font
->fontstruct
!=NULL
){
251 XFontStruct
*fnt
=font
->fontstruct
;
252 fnte
->max_height
=fnt
->ascent
+fnt
->descent
;
253 fnte
->max_width
=fnt
->max_bounds
.width
;
254 fnte
->baseline
=fnt
->ascent
;
259 DE_RESET_FONT_EXTENTS(fnte
);
263 uint
debrush_get_text_width(DEBrush
*brush
, const char *text
, uint len
)
265 if(brush
->d
->font
==NULL
|| text
==NULL
|| len
==0)
268 return defont_get_text_width(brush
->d
->font
, text
, len
);
272 uint
defont_get_text_width(DEFont
*font
, const char *text
, uint len
)
274 if(font
->fontset
!=NULL
){
276 #ifdef CF_DE_USE_XUTF8
277 if(ioncore_g
.enc_utf8
)
278 Xutf8TextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
281 XmbTextExtents(font
->fontset
, text
, len
, NULL
, &lext
);
283 }else if(font
->fontstruct
!=NULL
){
284 if(ioncore_g
.enc_utf8
){
285 XChar2b
*str16
; int len16
=0;
288 toucs(text
, len
, &str16
, &len16
);
290 res
=XTextWidth16(font
->fontstruct
, str16
, len16
);
296 return XTextWidth(font
->fontstruct
, text
, len
);
307 /*{{{ String drawing */
310 void debrush_do_draw_string_default(DEBrush
*brush
, int x
, int y
,
311 const char *str
, int len
, bool needfill
,
312 DEColourGroup
*colours
)
314 GC gc
=brush
->d
->normal_gc
;
316 if(brush
->d
->font
==NULL
)
319 XSetForeground(ioncore_g
.dpy
, gc
, colours
->fg
);
322 if(brush
->d
->font
->fontset
!=NULL
){
323 #ifdef CF_DE_USE_XUTF8
324 if(ioncore_g
.enc_utf8
)
325 Xutf8DrawString(ioncore_g
.dpy
, brush
->win
,
326 brush
->d
->font
->fontset
,
330 XmbDrawString(ioncore_g
.dpy
, brush
->win
,
331 brush
->d
->font
->fontset
,
333 }else if(brush
->d
->font
->fontstruct
!=NULL
){
334 if(ioncore_g
.enc_utf8
){
335 XChar2b
*str16
; int len16
=0;
336 toucs(str
, len
, &str16
, &len16
);
337 XDrawString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
340 XDrawString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
344 XSetBackground(ioncore_g
.dpy
, gc
, colours
->bg
);
345 if(brush
->d
->font
->fontset
!=NULL
){
346 #ifdef CF_DE_USE_XUTF8
347 if(ioncore_g
.enc_utf8
)
348 Xutf8DrawImageString(ioncore_g
.dpy
, brush
->win
,
349 brush
->d
->font
->fontset
,
353 XmbDrawImageString(ioncore_g
.dpy
, brush
->win
,
354 brush
->d
->font
->fontset
,
356 }else if(brush
->d
->font
->fontstruct
!=NULL
){
357 if(ioncore_g
.enc_utf8
){
358 XChar2b
*str16
; int len16
=0;
359 toucs(str
, len
, &str16
, &len16
);
360 XDrawImageString16(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str16
, len16
);
363 XDrawImageString(ioncore_g
.dpy
, brush
->win
, gc
, x
, y
, str
, len
);
370 void debrush_do_draw_string(DEBrush
*brush
, int x
, int y
,
371 const char *str
, int len
, bool needfill
,
372 DEColourGroup
*colours
)
374 CALL_DYN(debrush_do_draw_string
, brush
, (brush
, x
, y
, str
, len
,
379 void debrush_draw_string(DEBrush
*brush
, int x
, int y
,
380 const char *str
, int len
, bool needfill
)
382 DEColourGroup
*cg
=debrush_get_current_colour_group(brush
);
384 debrush_do_draw_string(brush
, x
, y
, str
, len
, needfill
, cg
);