1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
28 #include FT_FREETYPE_H
30 #include <fontconfig/fontconfig.h>
31 #include <fontconfig/fcfreetype.h>
34 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "character.h"
43 /* Symbolic type of this font-driver. */
44 Lisp_Object Qfreetype
;
46 /* Fontconfig's generic families and their aliases. */
47 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
49 /* Flag to tell if FcInit is areadly called or not. */
50 static int fc_initialized
;
52 /* Handle to a FreeType library instance. */
53 static FT_Library ft_library
;
55 /* Cache for FreeType fonts. */
56 static Lisp_Object freetype_font_cache
;
58 /* Fontconfig's charset used for finding fonts of registry
60 static FcCharSet
*cs_iso8859_1
;
62 /* The actual structure for FreeType font that can be casted to struct
71 static int ftfont_build_basic_charsets
P_ ((void));
72 static Lisp_Object ftfont_pattern_entity
P_ ((FcPattern
*,
73 Lisp_Object
, Lisp_Object
));
74 static Lisp_Object ftfont_list_generic_family
P_ ((Lisp_Object
, Lisp_Object
,
76 Lisp_Object ftfont_font_format
P_ ((FcPattern
*));
78 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
81 ftfont_build_basic_charsets ()
85 cs_iso8859_1
= FcCharSetCreate ();
88 for (c
= ' '; c
< 127; c
++)
89 if (! FcCharSetAddChar (cs_iso8859_1
, c
))
92 /* This part is currently disabled. Should be fixed later. */
93 for (c
= 192; c
< 256; c
++)
94 if (! FcCharSetAddChar (cs_iso8859_1
, c
))
101 ftfont_pattern_entity (p
, frame
, registry
)
103 Lisp_Object frame
, registry
;
106 FcChar8
*file
, *fontformat
;
112 if (FcPatternGetString (p
, FC_FILE
, 0, &file
) != FcResultMatch
)
114 if (FcPatternGetCharSet (p
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
117 if (FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fontformat
) != FcResultMatch
)
118 #endif /* FC_FONTFORMAT */
121 entity
= Fmake_vector (make_number (FONT_ENTITY_MAX
), null_string
);
123 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
124 ASET (entity
, FONT_REGISTRY_INDEX
, registry
);
125 ASET (entity
, FONT_FRAME_INDEX
, frame
);
126 ASET (entity
, FONT_OBJLIST_INDEX
, Qnil
);
128 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
129 ASET (entity
, FONT_FOUNDRY_INDEX
, intern_downcase (str
, strlen (str
)));
130 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
131 ASET (entity
, FONT_FAMILY_INDEX
, intern_downcase (str
, strlen (str
)));
132 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
134 if (numeric
== FC_WEIGHT_REGULAR
)
136 ASET (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
138 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
139 ASET (entity
, FONT_SLANT_INDEX
, make_number (numeric
+ 100));
140 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
141 ASET (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
142 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
143 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
145 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
147 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) != FcResultMatch
)
149 file
= FcStrCopy (file
);
153 p
= FcPatternCreate ();
157 if (FcPatternAddString (p
, FC_FILE
, file
) == FcFalse
159 && FcPatternAddCharSet (p
, FC_CHARSET
, charset
) == FcFalse
)
162 && FcPatternAddString (p
, FC_FONTFORMAT
, fontformat
) == FcFalse
)
163 #endif /* FC_FONTFORMAT */
165 && FcPatternAddInteger (p
, FC_SPACING
, numeric
) == FcFalse
))
167 FcPatternDestroy (p
);
170 ASET (entity
, FONT_EXTRA_INDEX
, make_save_value (p
, 0));
174 static Lisp_Object ftfont_generic_family_list
;
177 ftfont_list_generic_family (spec
, frame
, registry
)
178 Lisp_Object spec
, frame
, registry
;
180 Lisp_Object family
= AREF (spec
, FONT_FAMILY_INDEX
);
181 Lisp_Object slot
, list
, val
;
183 if (EQ (family
, Qmono
))
185 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
186 family
= Qsans_serif
;
187 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
193 /* Not yet listed. */
194 FcObjectSet
*objset
= NULL
;
195 FcPattern
*pattern
= NULL
, *pat
= NULL
;
196 FcFontSet
*fontset
= NULL
;
200 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
201 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
,
205 #endif /* FC_FONTFORMAT */
209 pattern
= FcPatternBuild (NULL
, FC_FAMILY
, FcTypeString
,
210 SYMBOL_FcChar8 (family
), (char *) 0);
213 pat
= FcPatternCreate ();
216 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
217 for (i
= 0, val
= Qnil
;
218 FcPatternGetString (pattern
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
221 if (strcmp ((char *) fam
, (char *) SYMBOL_FcChar8 (family
)) == 0)
223 if (! FcPatternAddString (pat
, FC_FAMILY
, fam
))
225 fontset
= FcFontList (NULL
, pat
, objset
);
228 /* Here we build the list in reverse order so that the last
229 loop in this function build a list in the correct
231 for (j
= 0; j
< fontset
->nfont
; j
++)
235 entity
= ftfont_pattern_entity (fontset
->fonts
[j
],
238 val
= Fcons (entity
, val
);
240 FcFontSetDestroy (fontset
);
242 FcPatternDel (pat
, FC_FAMILY
);
245 XSETCDR (slot
, list
);
247 if (pat
) FcPatternDestroy (pat
);
248 if (pattern
) FcPatternDestroy (pattern
);
249 if (fontset
) FcFontSetDestroy (fontset
);
250 if (objset
) FcObjectSetDestroy (objset
);
254 ASET (spec
, FONT_FAMILY_INDEX
, Qnil
);
255 for (val
= Qnil
; CONSP (list
); list
= XCDR (list
))
256 if (font_match_p (spec
, XCAR (list
)))
257 val
= Fcons (XCAR (list
), val
);
258 ASET (spec
, FONT_FAMILY_INDEX
, family
);
259 return Fvconcat (1, &val
);
263 static Lisp_Object ftfont_get_cache
P_ ((Lisp_Object
));
264 static Lisp_Object ftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
265 static Lisp_Object ftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
266 static Lisp_Object ftfont_list_family
P_ ((Lisp_Object
));
267 static void ftfont_free_entity
P_ ((Lisp_Object
));
268 static struct font
*ftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
269 static void ftfont_close
P_ ((FRAME_PTR
, struct font
*));
270 static int ftfont_has_char
P_ ((Lisp_Object
, int));
271 static unsigned ftfont_encode_char
P_ ((struct font
*, int));
272 static int ftfont_text_extents
P_ ((struct font
*, unsigned *, int,
273 struct font_metrics
*));
274 static int ftfont_get_bitmap
P_ ((struct font
*, unsigned,
275 struct font_bitmap
*, int));
276 static int ftfont_anchor_point
P_ ((struct font
*, unsigned, int,
279 struct font_driver ftfont_driver
=
289 /* We can't draw a text without device dependent functions. */
295 /* We can't draw a text without device dependent functions. */
309 #endif /* HAVE_LIBOTF */
312 extern Lisp_Object QCname
;
315 ftfont_get_cache (frame
)
318 return freetype_font_cache
;
322 ftfont_list (frame
, spec
)
323 Lisp_Object frame
, spec
;
325 Lisp_Object val
, tmp
, extra
;
327 FcPattern
*pattern
= NULL
;
328 FcCharSet
*charset
= NULL
;
329 FcLangSet
*langset
= NULL
;
330 FcFontSet
*fontset
= NULL
;
331 FcObjectSet
*objset
= NULL
;
333 Lisp_Object registry
= Qunicode_bmp
;
338 char otf_script
[15]; /* For "otlayout\:XXXX" */
342 if (! fc_initialized
)
348 if (! NILP (AREF (spec
, FONT_ADSTYLE_INDEX
))
349 && ! EQ (AREF (spec
, FONT_ADSTYLE_INDEX
), null_string
))
351 if (! NILP (AREF (spec
, FONT_SLANT_INDEX
))
352 && XINT (AREF (spec
, FONT_SLANT_INDEX
)) < 100)
353 /* Fontconfig doesn't support reverse-italic/obligue. */
356 if (! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
358 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
359 if (EQ (registry
, Qiso8859_1
))
362 && ftfont_build_basic_charsets () < 0)
364 charset
= cs_iso8859_1
;
366 else if (! EQ (registry
, Qiso10646_1
)
367 && ! EQ (registry
, Qunicode_bmp
)
368 && ! EQ (registry
, Qunicode_sip
))
372 otf_script
[0] = '\0';
374 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
375 CONSP (extra
); extra
= XCDR (extra
))
377 Lisp_Object key
, val
;
380 key
= XCAR (tmp
), val
= XCDR (tmp
);
383 script
= assq_no_quit (val
, Votf_script_alist
);
384 if (CONSP (script
) && SYMBOLP (XCDR (script
)))
385 script
= XCDR (script
);
386 tmp
= SYMBOL_NAME (val
);
387 sprintf (otf_script
, "otlayout:%s", (char *) SDATA (tmp
));
389 else if (EQ (key
, QClanguage
))
391 langset
= FcLangSetCreate ();
396 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
400 for (; CONSP (val
); val
= XCDR (val
))
401 if (SYMBOLP (XCAR (val
))
402 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
405 else if (EQ (key
, QCscript
))
407 else if (EQ (key
, QCdpi
))
409 else if (EQ (key
, QCspacing
))
410 spacing
= XINT (val
);
411 else if (EQ (key
, QCscalable
))
412 scalable
= ! NILP (val
);
415 if (! NILP (script
) && ! charset
)
417 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
421 charset
= FcCharSetCreate ();
424 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
425 if (CHARACTERP (XCAR (chars
))
426 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
431 pattern
= FcPatternCreate ();
434 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
435 if (SYMBOLP (tmp
) && ! NILP (tmp
)
436 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
438 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
439 if (SYMBOLP (tmp
) && ! NILP (tmp
)
440 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
442 /* Emacs conventionally doesn't distinguish normal, regular, and
443 medium weight, but fontconfig does. So, we can't restrict font
444 listing by weight. We check it after getting a list. */
445 tmp
= AREF (spec
, FONT_WEIGHT_INDEX
);
448 tmp
= AREF (spec
, FONT_SLANT_INDEX
);
450 && ! FcPatternAddInteger (pattern
, FC_SLANT
, XINT (tmp
) - 100))
452 tmp
= AREF (spec
, FONT_WIDTH_INDEX
);
454 && ! FcPatternAddInteger (pattern
, FC_WIDTH
, XINT (tmp
)))
458 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
461 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
464 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
467 && ! FcPatternAddInteger (pattern
, FC_SPACING
, spacing
))
470 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
473 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
474 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
,
478 #endif /* FC_FONTFORMAT */
484 #ifndef FC_CAPABILITY
486 #else /* not FC_CAPABILITY */
487 if (! FcObjectSetAdd (objset
, FC_CAPABILITY
))
489 #endif /* not FC_CAPABILITY */
492 fontset
= FcFontList (NULL
, pattern
, objset
);
496 if (fontset
->nfont
> 0)
500 if (NILP (AREF (spec
, FONT_SIZE_INDEX
)))
503 pixel_size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
505 for (i
= 0, val
= Qnil
; i
< fontset
->nfont
; i
++)
513 if (FcPatternGetDouble (fontset
->fonts
[i
], FC_PIXEL_SIZE
, 0,
514 &this) == FcResultMatch
515 && ((this < pixel_size
- FONT_PIXEL_SIZE_QUANTUM
)
516 || (this > pixel_size
+ FONT_PIXEL_SIZE_QUANTUM
)))
523 if (FcPatternGetInteger (fontset
->fonts
[i
], FC_WEIGHT
, 0,
524 &this) != FcResultMatch
527 || this < FC_WEIGHT_REGULAR
528 || this > FC_WEIGHT_MEDIUM
)))
536 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0,
537 &this) != FcResultMatch
538 || ! strstr ((char *) this, otf_script
))
541 #endif /* FC_CAPABILITY */
542 entity
= ftfont_pattern_entity (fontset
->fonts
[i
], frame
, registry
);
544 val
= Fcons (entity
, val
);
546 val
= Fvconcat (1, &val
);
548 else if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
549 val
= ftfont_list_generic_family (spec
, frame
, registry
);
553 /* We come here because of unexpected error in fontconfig API call
554 (usually insufficient memory). */
558 if (charset
&& charset
!= cs_iso8859_1
) FcCharSetDestroy (charset
);
559 if (objset
) FcObjectSetDestroy (objset
);
560 if (fontset
) FcFontSetDestroy (fontset
);
561 if (langset
) FcLangSetDestroy (langset
);
562 if (pattern
) FcPatternDestroy (pattern
);
568 ftfont_match (frame
, spec
)
569 Lisp_Object frame
, spec
;
571 Lisp_Object extra
, val
, entity
;
572 FcPattern
*pattern
= NULL
, *match
= NULL
;
575 if (! fc_initialized
)
581 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
582 val
= assq_no_quit (QCname
, extra
);
583 if (! CONSP (val
) || ! STRINGP (XCDR (val
)))
587 pattern
= FcNameParse (SDATA (XCDR (val
)));
590 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
592 FcDefaultSubstitute (pattern
);
593 match
= FcFontMatch (NULL
, pattern
, &result
);
596 entity
= ftfont_pattern_entity (match
, frame
, Qunicode_bmp
);
597 FcPatternDestroy (match
);
600 FcPatternDestroy (pattern
);
607 ftfont_list_family (frame
)
611 FcPattern
*pattern
= NULL
;
612 FcFontSet
*fontset
= NULL
;
613 FcObjectSet
*objset
= NULL
;
616 if (! fc_initialized
)
622 pattern
= FcPatternCreate ();
625 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
628 fontset
= FcFontList (NULL
, pattern
, objset
);
633 for (i
= 0; i
< fontset
->nfont
; i
++)
635 FcPattern
*pat
= fontset
->fonts
[i
];
638 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
639 list
= Fcons (intern_downcase ((char *) str
, strlen ((char *) str
)),
644 if (objset
) FcObjectSetDestroy (objset
);
645 if (fontset
) FcFontSetDestroy (fontset
);
646 if (pattern
) FcPatternDestroy (pattern
);
653 ftfont_free_entity (entity
)
656 Lisp_Object val
= AREF (entity
, FONT_EXTRA_INDEX
);
657 FcPattern
*pattern
= XSAVE_VALUE (val
)->pointer
;
659 FcPatternDestroy (pattern
);
663 ftfont_open (f
, entity
, pixel_size
)
668 struct ftfont_info
*ftfont_info
;
680 val
= AREF (entity
, FONT_EXTRA_INDEX
);
681 if (XTYPE (val
) != Lisp_Misc
682 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
684 pattern
= XSAVE_VALUE (val
)->pointer
;
685 if (XSAVE_VALUE (val
)->integer
== 0)
687 /* We have not yet created FT_Face for this font. */
689 && FT_Init_FreeType (&ft_library
) != 0)
691 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
693 if (FT_New_Face (ft_library
, (char *) file
, 0, &ft_face
) != 0)
695 FcPatternAddFTFace (pattern
, FC_FT_FACE
, ft_face
);
696 ft_size
= ft_face
->size
;
700 if (FcPatternGetFTFace (pattern
, FC_FT_FACE
, 0, &ft_face
)
703 if (FT_New_Size (ft_face
, &ft_size
) != 0)
705 if (FT_Activate_Size (ft_size
) != 0)
707 FT_Done_Size (ft_size
);
712 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
715 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
717 if (XSAVE_VALUE (val
)->integer
== 0)
718 FT_Done_Face (ft_face
);
722 ftfont_info
= malloc (sizeof (struct ftfont_info
));
725 ftfont_info
->ft_size
= ft_size
;
727 font
= (struct font
*) ftfont_info
;
728 font
->format
= ftfont_font_format (pattern
);
729 font
->entity
= entity
;
730 font
->pixel_size
= size
;
731 font
->driver
= &ftfont_driver
;
734 while (name
&& font_unparse_fcname (entity
, pixel_size
, name
, len
) < 0)
736 char *new = realloc (name
, len
+= 32);
742 font
->font
.full_name
= font
->font
.name
= name
;
743 font
->file_name
= (char *) file
;
744 font
->font
.size
= ft_face
->size
->metrics
.max_advance
>> 6;
745 if (font
->font
.size
<= 0)
746 font
->font
.size
= size
;
747 font
->font
.charset
= font
->encoding_charset
= font
->repertory_charset
= -1;
748 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
749 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
750 font
->font
.height
= font
->ascent
+ font
->descent
;
751 if (FcPatternGetInteger (pattern
, FC_SPACING
, 0, &spacing
) != FcResultMatch
)
752 spacing
= FC_PROPORTIONAL
;
753 if (spacing
!= FC_PROPORTIONAL
)
754 font
->font
.average_width
= font
->font
.space_width
= font
->font
.size
;
759 for (i
= 32; i
< 127; i
++)
761 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) != 0)
764 font
->font
.space_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
765 font
->font
.average_width
+= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
769 /* The font contains all ASCII printable characters. */
770 font
->font
.average_width
/= 95;
775 font
->font
.space_width
= font
->font
.size
;
776 font
->font
.average_width
= font
->font
.size
;
780 /* Unfortunately FreeType doesn't provide a way to get minimum char
781 width. So, we use space_width instead. */
782 font
->min_width
= font
->font
.space_width
;
784 font
->font
.baseline_offset
= 0;
785 font
->font
.relative_compose
= 0;
786 font
->font
.default_ascent
= 0;
787 font
->font
.vertical_centering
= 0;
789 (XSAVE_VALUE (val
)->integer
)++;
795 ftfont_close (f
, font
)
799 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
800 Lisp_Object entity
= font
->entity
;
801 Lisp_Object val
= AREF (entity
, FONT_EXTRA_INDEX
);
803 (XSAVE_VALUE (val
)->integer
)--;
804 if (XSAVE_VALUE (val
)->integer
== 0)
805 FT_Done_Face (ftfont_info
->ft_size
->face
);
807 FT_Done_Size (ftfont_info
->ft_size
);
813 ftfont_has_char (entity
, c
)
821 val
= AREF (entity
, FONT_EXTRA_INDEX
);
822 pattern
= XSAVE_VALUE (val
)->pointer
;
823 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
825 return (FcCharSetHasChar (charset
, (FcChar32
) c
) == FcTrue
);
829 ftfont_encode_char (font
, c
)
833 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
834 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
835 FT_ULong charcode
= c
;
836 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
838 return (code
> 0 ? code
: 0xFFFFFFFF);
842 ftfont_text_extents (font
, code
, nglyphs
, metrics
)
846 struct font_metrics
*metrics
;
848 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
849 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
853 if (ftfont_info
->ft_size
!= ft_face
->size
)
854 FT_Activate_Size (ftfont_info
->ft_size
);
856 bzero (metrics
, sizeof (struct font_metrics
));
857 for (i
= 0; i
< nglyphs
; i
++)
859 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
861 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
865 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
866 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
867 if (metrics
->rbearing
868 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
870 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
871 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
872 metrics
->ascent
= m
->horiBearingY
>> 6;
873 if (metrics
->descent
> ((m
->horiBearingY
+ m
->height
) >> 6))
874 metrics
->descent
= (m
->horiBearingY
+ m
->height
) >> 6;
876 width
+= m
->horiAdvance
>> 6;
880 width
+= font
->font
.space_width
;
884 metrics
->width
= width
;
890 ftfont_get_bitmap (font
, code
, bitmap
, bits_per_pixel
)
893 struct font_bitmap
*bitmap
;
896 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
897 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
898 FT_Int32 load_flags
= FT_LOAD_RENDER
;
900 if (ftfont_info
->ft_size
!= ft_face
->size
)
901 FT_Activate_Size (ftfont_info
->ft_size
);
902 if (bits_per_pixel
== 1)
904 #ifdef FT_LOAD_TARGET_MONO
905 load_flags
|= FT_LOAD_TARGET_MONO
;
907 load_flags
|= FT_LOAD_MONOCHROME
;
910 else if (bits_per_pixel
!= 8)
911 /* We don't support such a rendering. */
914 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
916 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
917 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
918 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
919 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
920 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
921 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
922 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
923 bitmap
->extra
= NULL
;
929 ftfont_anchor_point (font
, code
, index
, x
, y
)
935 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
936 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
938 if (ftfont_info
->ft_size
!= ft_face
->size
)
939 FT_Activate_Size (ftfont_info
->ft_size
);
940 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
942 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
944 if (index
>= ft_face
->glyph
->outline
.n_points
)
946 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
947 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
952 ftfont_font_format (FcPattern
*pattern
)
957 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
959 if (strcmp ((char *) str
, "TrueType") == 0)
960 return intern ("truetype");
961 if (strcmp ((char *) str
, "Type 1") == 0)
962 return intern ("type1");
963 if (strcmp ((char *) str
, "PCF") == 0)
964 return intern ("pcf");
965 if (strcmp ((char *) str
, "BDF") == 0)
966 return intern ("bdf");
967 #else /* not FC_FONTFORMAT */
968 if (FcPatternGetString (pattern
, FC_FILE
, 0, &str
) != FcResultMatch
)
970 if (strcasestr ((char *) str
, ".ttf") == 0)
971 return intern ("truetype");
972 if (strcasestr ((char *) str
, "pfb") == 0)
973 return intern ("type1");
974 if (strcasestr ((char *) str
, "pcf") == 0)
975 return intern ("pcf");
976 if (strcasestr ((char *) str
, "bdf") == 0)
977 return intern ("bdf");
978 #endif /* not FC_FONTFORMAT */
979 return intern ("unknown");
986 DEFSYM (Qfreetype
, "freetype");
987 DEFSYM (Qmonospace
, "monospace");
988 DEFSYM (Qsans_serif
, "sans-serif");
989 DEFSYM (Qserif
, "serif");
990 DEFSYM (Qmono
, "mono");
991 DEFSYM (Qsans
, "sans");
992 DEFSYM (Qsans__serif
, "sans serif");
994 staticpro (&freetype_font_cache
);
995 freetype_font_cache
= Fcons (Qt
, Qnil
);
997 staticpro (&ftfont_generic_family_list
);
998 ftfont_generic_family_list
999 = Fcons (Fcons (Qmonospace
, Qt
),
1000 Fcons (Fcons (Qsans_serif
, Qt
),
1001 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
1003 ftfont_driver
.type
= Qfreetype
;
1004 register_font_driver (&ftfont_driver
, NULL
);
1007 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
1008 (do not change this comment) */