1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
3 * Font code completely reworked for the Pango conversion
4 * Copyright (C) 2002 Cyrille Chepelov
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include <string.h> /* strlen */
30 #include <pango/pango.h>
32 #include <pango/pangoft2.h>
35 #include <gtk/gtk.h> /* just for gtk_get_default_language() */
41 /** Define this if you want to use the layout cache to speed up output.
42 * Appears to be buggy, see bug #307320. */
45 static PangoContext
* pango_context
= NULL
;
49 GObject parent_instance
;
51 PangoFontDescription
* pfd
;
52 /* mutable */ char* legacy_name
;
56 /* This is the global factor that says what zoom factor is 100%. It's
57 * normally 20.0 (and likely to stay that way). It is defined by how many
58 * pixels one cm is represented as.
60 static real global_zoom_factor
= 20.0;
63 /* For debugging: Sort families */
65 cmp_families (const void *a
, const void *b
)
67 const char *a_name
= pango_font_family_get_name (*(PangoFontFamily
**)a
);
68 const char *b_name
= pango_font_family_get_name (*(PangoFontFamily
**)b
);
70 return g_utf8_collate (a_name
, b_name
);
73 /* For debugging: List all font families */
77 PangoFontFamily
**families
;
81 pango_context_list_families(dia_font_get_context(), &families
, &nfamilies
);
82 qsort (families
, nfamilies
, sizeof (PangoFontFamily
*), cmp_families
);
83 for (i
= 0; i
< nfamilies
; i
++) {
84 puts(pango_font_family_get_name(families
[i
]));
91 dia_font_check_for_font(int font
) {
95 check
= dia_font_new_from_style(font
, 1.0);
96 loaded
= pango_context_load_font(dia_font_get_context(),
99 message_error(_("Can't load font %s.\n"), dia_font_get_family(check
));
104 dia_font_init(PangoContext
* pcontext
)
106 pango_context
= pcontext
;
107 /* We must have these three fonts! */
108 dia_font_check_for_font(DIA_FONT_SANS
);
109 dia_font_check_for_font(DIA_FONT_SERIF
);
110 dia_font_check_for_font(DIA_FONT_MONOSPACE
);
113 /* We might not need these anymore, when using FT2/Win32 fonts only */
114 static GList
*pango_contexts
;
117 dia_font_push_context(PangoContext
*pcontext
) {
118 pango_contexts
= g_list_prepend(pango_contexts
, pango_context
);
119 pango_context
= pcontext
;
120 pango_context_set_language (pango_context
, gtk_get_default_language ());
121 g_object_ref(pcontext
);
125 dia_font_pop_context() {
126 g_object_unref(pango_context
);
127 pango_context
= (PangoContext
*)pango_contexts
->data
;
128 pango_context_set_language (pango_context
, gtk_get_default_language ());
129 pango_contexts
= g_list_next(pango_contexts
);
133 dia_font_get_context() {
134 if (pango_context
== NULL
) {
136 /* This is suggested by new Pango (1.2.4+), but doesn't get us the
138 dia_font_push_context(pango_ft2_font_map_create_context(pango_ft2_font_map_new()));
140 dia_font_push_context(pango_ft2_get_context(75,75));
142 dia_font_push_context(gdk_pango_context_get());
146 return pango_context
;
149 /* dia centimetres to pango device units */
151 dcm_to_pdu(real dcm
) { return dcm
* global_zoom_factor
* PANGO_SCALE
; }
152 /* pango device units to dia centimetres */
154 pdu_to_dcm(gint pdu
) { return (real
)pdu
/ (global_zoom_factor
* PANGO_SCALE
); }
156 static void dia_font_class_init(DiaFontClass
* class);
157 static void dia_font_finalize(GObject
* object
);
158 static void dia_font_init_instance(DiaFont
*);
161 dia_font_get_type (void)
163 static GType object_type
= 0;
166 static const GTypeInfo object_info
=
168 sizeof (DiaFontClass
),
169 (GBaseInitFunc
) NULL
,
170 (GBaseFinalizeFunc
) NULL
,
171 (GClassInitFunc
) dia_font_class_init
, /* class_init */
172 NULL
, /* class_finalize */
173 NULL
, /* class_data */
176 (GInstanceInitFunc
)dia_font_init_instance
178 object_type
= g_type_register_static (G_TYPE_OBJECT
,
184 static gpointer parent_class
;
187 dia_font_class_init(DiaFontClass
* klass
)
189 GObjectClass
* object_class
= G_OBJECT_CLASS(klass
);
190 parent_class
= g_type_class_peek_parent(klass
);
191 object_class
->finalize
= dia_font_finalize
;
195 dia_font_init_instance(DiaFont
* font
)
197 /*GObject *gobject = G_OBJECT(font); */
201 dia_font_new(const char *family
, DiaFontStyle style
, real height
)
203 DiaFont
* retval
= dia_font_new_from_style(style
, height
);
205 pango_font_description_set_family(retval
->pfd
,family
);
207 pango_context_load_font(dia_font_get_context(), retval
->pfd
);
213 dia_pfd_set_family(PangoFontDescription
* pfd
, DiaFontFamily fam
) {
216 pango_font_description_set_family(pfd
, "sans");
218 case DIA_FONT_SERIF
:
219 pango_font_description_set_family(pfd
, "serif");
221 case DIA_FONT_MONOSPACE
:
222 pango_font_description_set_family(pfd
, "monospace");
225 /* Pango does allow fonts without a name */
231 dia_pfd_set_weight(PangoFontDescription
* pfd
, DiaFontWeight fw
) {
233 case DIA_FONT_ULTRALIGHT
:
234 pango_font_description_set_weight(pfd
, PANGO_WEIGHT_ULTRALIGHT
);
236 case DIA_FONT_LIGHT
:
237 pango_font_description_set_weight(pfd
, PANGO_WEIGHT_LIGHT
);
239 case DIA_FONT_WEIGHT_NORMAL
:
240 pango_font_description_set_weight(pfd
, PANGO_WEIGHT_NORMAL
);
242 case DIA_FONT_MEDIUM
: /* Pango doesn't have this, but
243 'intermediate values are possible' */
244 pango_font_description_set_weight(pfd
, 500);
246 case DIA_FONT_DEMIBOLD
: /* Pango doesn't have this, ... */
247 pango_font_description_set_weight(pfd
, 600);
250 pango_font_description_set_weight(pfd
, PANGO_WEIGHT_BOLD
);
252 case DIA_FONT_ULTRABOLD
:
253 pango_font_description_set_weight(pfd
, PANGO_WEIGHT_ULTRABOLD
);
255 case DIA_FONT_HEAVY
:
256 pango_font_description_set_weight(pfd
, PANGO_WEIGHT_HEAVY
);
259 g_assert_not_reached();
264 dia_pfd_set_slant(PangoFontDescription
* pfd
, DiaFontSlant fo
) {
266 case DIA_FONT_NORMAL
:
267 pango_font_description_set_style(pfd
,PANGO_STYLE_NORMAL
);
269 case DIA_FONT_OBLIQUE
:
270 pango_font_description_set_style(pfd
,PANGO_STYLE_OBLIQUE
);
272 case DIA_FONT_ITALIC
:
273 pango_font_description_set_style(pfd
,PANGO_STYLE_ITALIC
);
276 g_assert_not_reached();
280 static void dia_pfd_set_size(PangoFontDescription
* pfd
, real height
)
281 { /* inline candidate... */
282 pango_font_description_set_size(pfd
, dcm_to_pdu(height
) );
287 dia_font_new_from_style(DiaFontStyle style
, real height
)
290 /* in the future we could establish Dia's own default font
291 * matching to be as (font-)system independent as possible.
292 * For now fall back to Pangos configuration --hb
294 PangoFontDescription
* pfd
= pango_font_description_new();
295 dia_pfd_set_family(pfd
,DIA_FONT_STYLE_GET_FAMILY(style
));
296 dia_pfd_set_weight(pfd
,DIA_FONT_STYLE_GET_WEIGHT(style
));
297 dia_pfd_set_slant(pfd
,DIA_FONT_STYLE_GET_SLANT(style
));
298 dia_pfd_set_size(pfd
,height
);
300 retval
= DIA_FONT(g_object_new(DIA_TYPE_FONT
, NULL
));
303 retval
->legacy_name
= NULL
;
307 DiaFont
* dia_font_copy(const DiaFont
* font
)
309 if (!font
) return NULL
;
310 return dia_font_new(dia_font_get_family(font
),
311 dia_font_get_style(font
),
312 dia_font_get_height(font
));
316 dia_font_finalize(GObject
* object
)
319 font
= DIA_FONT(object
);
320 if (font
->pfd
) pango_font_description_free(font
->pfd
);
321 G_OBJECT_CLASS(parent_class
)->finalize(object
);
324 DiaFont
* dia_font_ref(DiaFont
* font
)
326 g_object_ref(G_OBJECT(font
));
330 void dia_font_unref(DiaFont
* font
)
332 g_object_unref(G_OBJECT(font
));
336 dia_font_get_style(const DiaFont
* font
)
340 static int weight_map
[] = {
341 DIA_FONT_ULTRALIGHT
, DIA_FONT_LIGHT
,
342 DIA_FONT_WEIGHT_NORMAL
, /* intentionaly ==0 */
343 DIA_FONT_MEDIUM
, DIA_FONT_DEMIBOLD
, /* not yet in Pango */
344 DIA_FONT_BOLD
, DIA_FONT_ULTRABOLD
, DIA_FONT_HEAVY
347 PangoStyle pango_style
= pango_font_description_get_style(font
->pfd
);
348 PangoWeight pango_weight
= pango_font_description_get_weight(font
->pfd
);
350 g_assert(PANGO_WEIGHT_ULTRALIGHT
<= pango_weight
&& pango_weight
<= PANGO_WEIGHT_HEAVY
);
351 g_assert(PANGO_WEIGHT_ULTRALIGHT
== 200);
352 g_assert(PANGO_WEIGHT_NORMAL
== 400);
353 g_assert(PANGO_WEIGHT_BOLD
== 700);
355 style
= weight_map
[(pango_weight
- PANGO_WEIGHT_ULTRALIGHT
) / 100];
356 style
|= (pango_style
<< 2);
362 dia_font_get_family(const DiaFont
* font
)
364 return pango_font_description_get_family(font
->pfd
);
367 G_CONST_RETURN PangoFontDescription
*
368 dia_font_get_description(const DiaFont
* font
)
374 dia_font_get_height(const DiaFont
* font
)
376 return pdu_to_dcm(pango_font_description_get_size(font
->pfd
));
380 dia_font_set_height(DiaFont
* font
, real height
)
382 pango_font_description_set_size(font
->pfd
, dcm_to_pdu(height
));
387 dia_font_get_psfontname(const DiaFont
*font
)
389 /* FIXME: this will very likely not work ! */
390 return dia_font_get_legacy_name(font
);
393 void dia_font_set_any_family(DiaFont
* font
, const char* family
)
395 g_assert(font
!= NULL
);
396 pango_font_description_set_family(font
->pfd
, family
);
397 if (font
->legacy_name
) {
398 g_free(font
->legacy_name
);
399 font
->legacy_name
= NULL
;
403 void dia_font_set_family(DiaFont
* font
, DiaFontFamily family
)
405 g_assert(font
!= NULL
);
406 dia_pfd_set_family(font
->pfd
,family
);
407 if (font
->legacy_name
) {
408 g_free(font
->legacy_name
);
409 font
->legacy_name
= NULL
;
413 void dia_font_set_weight(DiaFont
* font
, DiaFontWeight weight
)
415 g_assert(font
!= NULL
);
416 dia_pfd_set_weight(font
->pfd
,weight
);
419 void dia_font_set_slant(DiaFont
* font
, DiaFontSlant slant
)
421 g_assert(font
!= NULL
);
422 dia_pfd_set_slant(font
->pfd
,slant
);
426 struct weight_name
{ DiaFontWeight fw
; const char *name
; };
427 static const struct weight_name weight_names
[] = {
428 {DIA_FONT_ULTRALIGHT
, "200"},
429 {DIA_FONT_LIGHT
,"300"},
430 {DIA_FONT_WEIGHT_NORMAL
,"normal"},
431 {DIA_FONT_WEIGHT_NORMAL
,"400"},
432 {DIA_FONT_MEDIUM
, "500"},
433 {DIA_FONT_DEMIBOLD
, "600"},
434 {DIA_FONT_BOLD
, "700"},
435 {DIA_FONT_ULTRABOLD
, "800"},
436 {DIA_FONT_HEAVY
, "900"},
439 G_CONST_RETURN
char *dia_font_get_weight_string(const DiaFont
* font
)
441 const struct weight_name
* p
;
442 DiaFontWeight fw
= DIA_FONT_STYLE_GET_WEIGHT(dia_font_get_style(font
));
444 for (p
= weight_names
; p
->name
!= NULL
; ++p
) {
445 if (p
->fw
== fw
) return p
->name
;
450 void dia_font_set_weight_from_string(DiaFont
* font
, const char* weight
) {
451 DiaFontWeight fw
= DIA_FONT_WEIGHT_NORMAL
;
452 const struct weight_name
* p
;
454 for (p
= weight_names
; p
->name
!= NULL
; ++p
) {
455 if (0 == strncmp(weight
,p
->name
,8)) {
461 dia_font_set_weight(font
,fw
);
465 struct slant_name
{ DiaFontSlant fo
; const char *name
; };
466 static const struct slant_name slant_names
[] = {
467 { DIA_FONT_NORMAL
, "normal"},
468 { DIA_FONT_OBLIQUE
, "oblique"},
469 { DIA_FONT_ITALIC
, "italic"},
472 G_CONST_RETURN
char *
473 dia_font_get_slant_string(const DiaFont
* font
)
475 const struct slant_name
* p
;
477 DIA_FONT_STYLE_GET_SLANT(dia_font_get_style(font
));
479 for (p
= slant_names
; p
->name
!= NULL
; ++p
) {
480 if (p
->fo
== fo
) return p
->name
;
485 void dia_font_set_slant_from_string(DiaFont
* font
, const char* obli
) {
486 DiaFontSlant fo
= DIA_FONT_NORMAL
;
487 const struct slant_name
* p
;
489 DiaFontStyle old_style
;
491 old_style
= dia_font_get_style(font
);
492 old_fo
= DIA_FONT_STYLE_GET_SLANT(old_style
);
494 for (p
= slant_names
; p
->name
!= NULL
; ++p
) {
495 if (0 == strncmp(obli
,p
->name
,8)) {
500 dia_font_set_slant(font
,fo
);
504 /* ************************************************************************ */
505 /* Non-scaled versions of the utility routines */
506 /* ************************************************************************ */
509 dia_font_string_width(const char* string
, DiaFont
*font
, real height
)
511 return dia_font_scaled_string_width(string
,font
,height
,global_zoom_factor
);
515 dia_font_ascent(const char* string
, DiaFont
* font
, real height
)
517 return dia_font_scaled_ascent(string
,font
,height
,global_zoom_factor
);
520 real
dia_font_descent(const char* string
, DiaFont
* font
, real height
)
522 return dia_font_scaled_descent(string
,font
,height
,global_zoom_factor
);
532 static GHashTable
*layoutcache
;
535 layout_cache_equals(gconstpointer e1
, gconstpointer e2
)
537 LayoutCacheItem
*i1
= (LayoutCacheItem
*)e1
,
538 *i2
= (LayoutCacheItem
*)e2
;
540 /* don't try strcmp() with null pointers ... */
541 if (!i1
->string
|| i2
->string
)
544 return strcmp(i1
->string
, i2
->string
) == 0 &&
545 pango_font_description_equal(i1
->font
->pfd
, i2
->font
->pfd
);
549 layout_cache_hash(gconstpointer el
)
551 LayoutCacheItem
*item
= (LayoutCacheItem
*)el
;
553 return g_str_hash(item
->string
) ^
554 pango_font_description_hash(item
->font
->pfd
);
557 static long layout_cache_last_use
;
560 layout_cache_cleanup_entry(gpointer key
, gpointer value
, gpointer data
)
562 LayoutCacheItem
*item
= (LayoutCacheItem
*)value
;
563 /** Remove unused items */
564 if (item
->usecount
== 0) return TRUE
;
569 /** The actual hash cleanup, called when idle. */
571 layout_cache_cleanup_idle(gpointer data
)
573 GHashTable
*table
= (GHashTable
*)(data
);
575 g_hash_table_foreach_remove(table
, layout_cache_cleanup_entry
, NULL
);
579 /** Every ten minutes, clean up those strings that haven't seen use since
583 layout_cache_cleanup(gpointer data
)
585 /* Only cleanup if there has been font activity since last cleanup */
586 if (time(0) - layout_cache_last_use
< 10) {
587 /* Don't go directly to cleanup, wait till there's a pause. */
588 g_idle_add(layout_cache_cleanup_idle
, data
);
590 /* Keep doing this */
595 layout_cache_free_key(gpointer data
)
597 LayoutCacheItem
*item
= (LayoutCacheItem
*)data
;
599 if (item
->string
!= NULL
) {
600 g_free(item
->string
);
604 if (item
->font
!= NULL
) {
605 dia_font_unref(item
->font
);
609 if (item
->layout
!= NULL
) {
610 g_object_unref(item
->layout
);
618 dia_font_build_layout(const char* string
, DiaFont
* font
, real height
)
622 PangoAttribute
* attr
;
627 LayoutCacheItem
*cached
, *item
;
629 layout_cache_last_use
= time(0);
630 if (layoutcache
== NULL
) {
631 /** Note that key and value are the same -- it's a HashSet */
632 layoutcache
= g_hash_table_new_full(layout_cache_hash
,
634 layout_cache_free_key
,
636 /** Check for cache cleanup every 10 seconds. */
637 /** This frequent a check is really a hack while we figure out the
638 * exact problems with reffing the fonts.
639 * Note to self: The equals function should compare pfd's, but
640 * then DiaFonts are freed too early.
642 g_timeout_add(10*1000, layout_cache_cleanup
, (gpointer
)layoutcache
);
647 dia_font_set_height(font
, height
);
650 item
= g_new0(LayoutCacheItem
,1);
651 item
->string
= g_strdup(string
);
654 /* If it's in the cache, use that instead. */
655 cached
= g_hash_table_lookup(layoutcache
, item
);
656 if (cached
!= NULL
) {
657 g_object_ref(cached
->layout
);
658 g_free(item
->string
);
661 return cached
->layout
;
664 item
->font
= dia_font_copy(font
);
665 dia_font_ref(item
->font
);
668 /* This could should account for DPI, but it doesn't do right. Grrr...
670 GdkScreen *screen = gdk_screen_get_default();
671 real dpi = gdk_screen_get_width(screen)/
672 (gdk_screen_get_width_mm(screen)/25.4);
673 printf("height = %f, dpi = %f, new height = %f\n",
674 height, dpi, height * (dpi/100));
679 layout
= pango_layout_new(dia_font_get_context());
681 length
= string
? strlen(string
) : 0;
682 pango_layout_set_text(layout
, string
, length
);
684 list
= pango_attr_list_new();
685 desc
= g_utf8_strdown(pango_font_description_get_family(font
->pfd
), -1);
686 pango_font_description_set_family(font
->pfd
, desc
);
688 attr
= pango_attr_font_desc_new(font
->pfd
);
689 attr
->start_index
= 0;
690 attr
->end_index
= length
;
691 pango_attr_list_insert(list
,attr
); /* eats attr */
693 pango_layout_set_attributes(layout
,list
);
694 pango_attr_list_unref(list
);
696 pango_layout_set_indent(layout
,0);
697 pango_layout_set_justify(layout
,FALSE
);
698 pango_layout_set_alignment(layout
,PANGO_ALIGN_LEFT
);
701 item
->layout
= layout
;
702 g_object_ref(layout
);
704 g_hash_table_replace(layoutcache
, item
, item
);
710 /* ************************************************************************ */
711 /* scaled versions of the utility routines */
712 /* ************************************************************************ */
715 dia_font_set_nominal_zoom_factor(real size_one
)
716 { global_zoom_factor
= size_one
; }
721 dia_font_scaled_string_width(const char* string
, DiaFont
*font
, real height
,
728 if (string
== NULL
|| string
[0] == '\0') {
732 layout
= dia_font_scaled_build_layout(string
, font
, height
, zoom_factor
);
733 pango_layout_get_size(layout
,&lw
,&lh
);
734 g_object_unref(G_OBJECT(layout
));
736 result
= pdu_to_dcm(lw
);
737 /* Scale the result back for the zoom factor */
738 result
/= (zoom_factor
/global_zoom_factor
);
743 dia_font_vertical_extents(const char* string
, DiaFont
* font
,
744 real height
, real zoom_factor
,
746 real
* top
, real
* baseline
, real
* bottom
)
748 PangoRectangle ink_rect
,logical_rect
;
750 PangoLayoutIter
* iter
;
753 if (string
== NULL
|| string
[0] == '\0') {
757 layout
= dia_font_scaled_build_layout(string
, font
,
758 height
, zoom_factor
);
759 iter
= pango_layout_get_iter(layout
);
760 for (i
= 0; i
< line_no
; ++i
) {
761 if (!pango_layout_iter_next_line(iter
)) {
762 pango_layout_iter_free(iter
);
763 g_object_unref(G_OBJECT(layout
));
768 pango_layout_iter_get_line_extents(iter
,&ink_rect
,&logical_rect
);
770 *top
= pdu_to_dcm(logical_rect
.y
);
771 *bottom
= pdu_to_dcm(logical_rect
.y
+ logical_rect
.height
);
772 *baseline
= pdu_to_dcm(pango_layout_iter_get_baseline(iter
));
774 pango_layout_iter_free(iter
);
775 g_object_unref(G_OBJECT(layout
));
782 dia_font_scaled_ascent(const char* string
, DiaFont
* font
, real height
,
785 real top
,bline
,bottom
;
786 if (!string
|| string
[0] == '\0') {
787 /* This hack won't work for fonts that don't cover ASCII */
788 dia_font_vertical_extents("XjgM149",font
,height
,zoom_factor
,
789 0,&top
,&bline
,&bottom
);
791 dia_font_vertical_extents(string
,font
,height
,zoom_factor
,
792 0,&top
,&bline
,&bottom
);
794 return (bline
-top
)/(zoom_factor
/global_zoom_factor
);
797 real
dia_font_scaled_descent(const char* string
, DiaFont
* font
,
798 real height
, real zoom_factor
)
800 real top
,bline
,bottom
;
802 if (!string
|| string
[0] == '\0') {
803 /* This hack won't work for fonts that don't cover ASCII */
804 dia_font_vertical_extents("XjgM149",font
,height
,zoom_factor
,
805 0,&top
,&bline
,&bottom
);
807 dia_font_vertical_extents(string
,font
,height
,zoom_factor
,
808 0,&top
,&bline
,&bottom
);
810 return (bottom
-bline
)/(zoom_factor
/global_zoom_factor
);
814 dia_font_scaled_build_layout(const char* string
, DiaFont
* font
,
815 real height
, real zoom_factor
)
817 DiaFont
* altered_font
;
820 real target_zoomed_width
;
822 real altered_scaling
;
825 scaling
= zoom_factor
/ global_zoom_factor
;
826 if (fabs(1.0 - scaling
) < 1E-7) {
827 return dia_font_build_layout(string
,font
,height
);
830 nozoom_width
= dia_font_string_width(string
,font
,height
);
831 target_zoomed_width
= nozoom_width
* scaling
;
833 /* First try: no tweaks. */
834 real_width
= dia_font_string_width(string
,font
, height
* scaling
);
835 if (real_width
<= target_zoomed_width
) {
836 return dia_font_build_layout(string
,font
,height
*scaling
);
839 altered_font
= dia_font_copy(font
);
841 /* Last try. Using the "reduce overall size" strategy. */
842 for (altered_scaling
= scaling
;
843 altered_scaling
> (scaling
/ 2);
844 altered_scaling
*= (target_zoomed_width
/real_width
>0.98?0.98:
845 target_zoomed_width
/real_width
) ) {
846 real_width
= dia_font_string_width(string
,font
,
847 height
* altered_scaling
);
849 if (real_width
<= target_zoomed_width
) {
850 layout
= dia_font_build_layout(string
,altered_font
,
851 height
*altered_scaling
);
852 dia_font_unref(altered_font
);
857 /* Everything has failed. Returning non-tweaked variant. */
858 g_warning("Failed to appropriately tweak zoomed font for zoom factor %f.", zoom_factor
);
859 dia_font_unref(altered_font
);
860 return dia_font_build_layout(string
,font
,height
*scaling
);
864 * Compatibility with older files out of pre Pango Time.
865 * Make old files look as similar as possible
866 * List should be kept alphabetically sorted by oldname, in case of
867 * duplicates the one with the preferred newname comes first.
869 * FIXME: DIA_FONT_FAMILY_ANY in the list below does mean noone knows better
871 static struct _legacy_font
{
874 DiaFontStyle style
; /* the DIA_FONT_FAMILY() is used as falback only */
876 { "AvantGarde-Book", "AvantGarde", DIA_FONT_SERIF
},
877 { "AvantGarde-BookOblique", "AvantGarde", DIA_FONT_SERIF
| DIA_FONT_OBLIQUE
},
878 { "AvantGarde-Demi", "AvantGarde", DIA_FONT_SERIF
| DIA_FONT_DEMIBOLD
},
879 { "AvantGarde-DemiOblique", "AvantGarde", DIA_FONT_SERIF
| DIA_FONT_OBLIQUE
| DIA_FONT_DEMIBOLD
},
880 { "Batang", "Batang", DIA_FONT_FAMILY_ANY
},
881 { "Bookman-Demi", "Bookman Old Style", DIA_FONT_SERIF
| DIA_FONT_DEMIBOLD
},
882 { "Bookman-DemiItalic", "Bookman Old Style", DIA_FONT_SERIF
| DIA_FONT_DEMIBOLD
| DIA_FONT_ITALIC
},
883 { "Bookman-Light", "Bookman Old Style", DIA_FONT_SERIF
| DIA_FONT_LIGHT
},
884 { "Bookman-LightItalic", "Bookman Old Style", DIA_FONT_SERIF
| DIA_FONT_LIGHT
| DIA_FONT_ITALIC
},
885 { "BousungEG-Light-GB", "BousungEG-Light-GB", DIA_FONT_FAMILY_ANY
},
886 { "Courier", "monospace", DIA_FONT_MONOSPACE
},
887 { "Courier", "Courier New", DIA_FONT_MONOSPACE
},
888 { "Courier-Bold", "monospace", DIA_FONT_MONOSPACE
| DIA_FONT_BOLD
},
889 { "Courier-Bold", "Courier New", DIA_FONT_MONOSPACE
| DIA_FONT_BOLD
},
890 { "Courier-BoldOblique", "monospace", DIA_FONT_MONOSPACE
| DIA_FONT_ITALIC
| DIA_FONT_BOLD
},
891 { "Courier-BoldOblique", "Courier New", DIA_FONT_MONOSPACE
| DIA_FONT_ITALIC
| DIA_FONT_BOLD
},
892 { "Courier-Oblique", "monospace", DIA_FONT_MONOSPACE
| DIA_FONT_ITALIC
},
893 { "Courier-Oblique", "Courier New", DIA_FONT_MONOSPACE
| DIA_FONT_ITALIC
},
894 { "Dotum", "Dotum", DIA_FONT_FAMILY_ANY
},
895 { "GBZenKai-Medium", "GBZenKai-Medium", DIA_FONT_FAMILY_ANY
},
896 { "GothicBBB-Medium", "GothicBBB-Medium", DIA_FONT_FAMILY_ANY
},
897 { "Gulim", "Gulim", DIA_FONT_FAMILY_ANY
},
898 { "Headline", "Headline", DIA_FONT_FAMILY_ANY
},
899 { "Helvetica", "sans", DIA_FONT_SANS
},
900 { "Helvetica", "Arial", DIA_FONT_SANS
},
901 { "Helvetica-Bold", "sans", DIA_FONT_SANS
| DIA_FONT_BOLD
},
902 { "Helvetica-Bold", "Arial", DIA_FONT_SANS
| DIA_FONT_BOLD
},
903 { "Helvetica-BoldOblique", "sans", DIA_FONT_SANS
| DIA_FONT_BOLD
| DIA_FONT_ITALIC
},
904 { "Helvetica-BoldOblique", "Arial", DIA_FONT_SANS
| DIA_FONT_BOLD
| DIA_FONT_ITALIC
},
905 { "Helvetica-Narrow", "Arial Narrow", DIA_FONT_SANS
| DIA_FONT_MEDIUM
},
906 { "Helvetica-Narrow-Bold", "Arial Narrow", DIA_FONT_SANS
| DIA_FONT_DEMIBOLD
},
907 { "Helvetica-Narrow-BoldOblique", "Arial Narrow", DIA_FONT_SANS
| DIA_FONT_MEDIUM
| DIA_FONT_OBLIQUE
},
908 { "Helvetica-Narrow-Oblique", "Arial Narrow", DIA_FONT_SANS
| DIA_FONT_MEDIUM
| DIA_FONT_OBLIQUE
},
909 { "Helvetica-Oblique", "sans", DIA_FONT_SANS
| DIA_FONT_ITALIC
},
910 { "Helvetica-Oblique", "Arial", DIA_FONT_SANS
| DIA_FONT_ITALIC
},
911 { "MOESung-Medium", "MOESung-Medium", DIA_FONT_FAMILY_ANY
},
912 { "NewCenturySchoolbook-Bold", "Century Schoolbook SWA", DIA_FONT_SERIF
| DIA_FONT_BOLD
},
913 { "NewCenturySchoolbook-BoldItalic", "Century Schoolbook SWA", DIA_FONT_SERIF
| DIA_FONT_BOLD
| DIA_FONT_ITALIC
},
914 { "NewCenturySchoolbook-Italic", "Century Schoolbook SWA", DIA_FONT_SERIF
| DIA_FONT_ITALIC
},
915 { "NewCenturySchoolbook-Roman", "Century Schoolbook SWA", DIA_FONT_SERIF
},
916 { "Palatino-Bold", "Palatino", DIA_FONT_FAMILY_ANY
| DIA_FONT_BOLD
},
917 { "Palatino-BoldItalic", "Palatino", DIA_FONT_FAMILY_ANY
| DIA_FONT_BOLD
| DIA_FONT_ITALIC
},
918 { "Palatino-Italic", "Palatino", DIA_FONT_FAMILY_ANY
| DIA_FONT_ITALIC
},
919 { "Palatino-Roman", "Palatino", DIA_FONT_FAMILY_ANY
},
920 { "Ryumin-Light", "Ryumin", DIA_FONT_FAMILY_ANY
| DIA_FONT_LIGHT
},
921 { "ShanHeiSun-Light", "ShanHeiSun", DIA_FONT_FAMILY_ANY
| DIA_FONT_LIGHT
},
922 { "Song-Medium", "Song-Medium", DIA_FONT_FAMILY_ANY
| DIA_FONT_MEDIUM
},
923 { "Symbol", "Symbol", DIA_FONT_SANS
| DIA_FONT_MEDIUM
},
924 { "Times-Bold", "serif", DIA_FONT_SERIF
| DIA_FONT_BOLD
},
925 { "Times-Bold", "Times New Roman", DIA_FONT_SERIF
| DIA_FONT_BOLD
},
926 { "Times-BoldItalic", "serif", DIA_FONT_SERIF
| DIA_FONT_ITALIC
| DIA_FONT_BOLD
},
927 { "Times-BoldItalic", "Times New Roman", DIA_FONT_SERIF
| DIA_FONT_ITALIC
| DIA_FONT_BOLD
},
928 { "Times-Italic", "serif", DIA_FONT_SERIF
| DIA_FONT_ITALIC
},
929 { "Times-Italic", "Times New Roman", DIA_FONT_SERIF
| DIA_FONT_ITALIC
},
930 { "Times-Roman", "serif", DIA_FONT_SERIF
},
931 { "Times-Roman", "Times New Roman", DIA_FONT_SERIF
},
932 { "ZapfChancery-MediumItalic", "Zapf Calligraphic 801 SWA", DIA_FONT_SERIF
| DIA_FONT_MEDIUM
},
933 { "ZapfDingbats", "Zapf Calligraphic 801 SWA", DIA_FONT_SERIF
},
934 { "ZenKai-Medium", "ZenKai", DIA_FONT_FAMILY_ANY
| DIA_FONT_MEDIUM
},
939 * Given a legacy name as stored until Dia-0.90 construct
940 * a new DiaFont which is as similar as possible
943 dia_font_new_from_legacy_name(const char* name
)
945 /* do NOT translate anything here !!! */
947 struct _legacy_font
* found
= NULL
;
951 for (i
= 0; i
< G_N_ELEMENTS(legacy_fonts
); i
++) {
952 if (!strcmp(name
, legacy_fonts
[i
].oldname
)) {
953 found
= &legacy_fonts
[i
];
958 retval
= dia_font_new (found
->newname
, found
->style
, height
);
959 retval
->legacy_name
= found
->oldname
;
961 /* We tried our best, let Pango complain */
962 retval
= dia_font_new (name
, DIA_FONT_WEIGHT_NORMAL
, height
);
963 retval
->legacy_name
= NULL
;
970 dia_font_get_legacy_name(const DiaFont
*font
)
972 const char* matched_name
= NULL
;
977 /* if we have loaded it from an old file, use the old name */
978 if (font
->legacy_name
)
979 return font
->legacy_name
;
981 family
= dia_font_get_family (font
);
982 style
= dia_font_get_style (font
);
983 for (i
= 0; i
< G_N_ELEMENTS(legacy_fonts
); i
++) {
984 if (0 == g_strcasecmp (legacy_fonts
[i
].newname
, family
)) {
985 /* match weight and slant */
986 DiaFontStyle st
= legacy_fonts
[i
].style
;
987 if ((DIA_FONT_STYLE_GET_SLANT(style
) | DIA_FONT_STYLE_GET_WEIGHT(style
))
988 == (DIA_FONT_STYLE_GET_SLANT(st
) | DIA_FONT_STYLE_GET_WEIGHT(st
))) {
989 return legacy_fonts
[i
].oldname
; /* exact match */
990 } else if (0 == (DIA_FONT_STYLE_GET_SLANT(st
) | DIA_FONT_STYLE_GET_WEIGHT(st
))) {
991 matched_name
= legacy_fonts
[i
].oldname
;
992 /* 'unmodified' font, continue matching */
996 return matched_name
? matched_name
: "Courier";