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
,
77 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
80 ftfont_build_basic_charsets ()
84 cs_iso8859_1
= FcCharSetCreate ();
87 for (c
= ' '; c
< 127; c
++)
88 if (! FcCharSetAddChar (cs_iso8859_1
, c
))
91 /* This part is currently disabled. Should be fixed later. */
92 for (c
= 192; c
< 256; c
++)
93 if (! FcCharSetAddChar (cs_iso8859_1
, c
))
100 ftfont_pattern_entity (p
, frame
, registry
)
102 Lisp_Object frame
, registry
;
111 if (FcPatternGetString (p
, FC_FILE
, 0, &file
) != FcResultMatch
)
113 if (FcPatternGetCharSet (p
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
116 entity
= Fmake_vector (make_number (FONT_ENTITY_MAX
), null_string
);
118 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
119 ASET (entity
, FONT_REGISTRY_INDEX
, registry
);
120 ASET (entity
, FONT_FRAME_INDEX
, frame
);
121 ASET (entity
, FONT_OBJLIST_INDEX
, Qnil
);
123 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
124 ASET (entity
, FONT_FOUNDRY_INDEX
, intern_downcase (str
, strlen (str
)));
125 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
126 ASET (entity
, FONT_FAMILY_INDEX
, intern_downcase (str
, strlen (str
)));
127 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
129 if (numeric
== FC_WEIGHT_REGULAR
)
131 ASET (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
133 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
134 ASET (entity
, FONT_SLANT_INDEX
, make_number (numeric
+ 100));
135 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
136 ASET (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
137 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
138 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
140 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
142 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) != FcResultMatch
)
144 file
= FcStrCopy (file
);
148 p
= FcPatternCreate ();
152 if (FcPatternAddString (p
, FC_FILE
, file
) == FcFalse
153 || (charset
&& FcPatternAddCharSet (p
, FC_CHARSET
, charset
) == FcFalse
)
155 && FcPatternAddInteger (p
, FC_SPACING
, numeric
) == FcFalse
))
157 FcPatternDestroy (p
);
160 ASET (entity
, FONT_EXTRA_INDEX
, make_save_value (p
, 0));
164 static Lisp_Object ftfont_generic_family_list
;
167 ftfont_list_generic_family (spec
, frame
, registry
)
168 Lisp_Object spec
, frame
, registry
;
170 Lisp_Object family
= AREF (spec
, FONT_FAMILY_INDEX
);
171 Lisp_Object slot
, list
, val
;
173 if (EQ (family
, Qmono
))
175 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
176 family
= Qsans_serif
;
177 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
183 /* Not yet listed. */
184 FcObjectSet
*objset
= NULL
;
185 FcPattern
*pattern
= NULL
, *pat
= NULL
;
186 FcFontSet
*fontset
= NULL
;
190 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
191 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
,
192 FC_CHARSET
, FC_FILE
, NULL
);
195 pattern
= FcPatternBuild (NULL
, FC_FAMILY
, FcTypeString
,
196 SYMBOL_FcChar8 (family
), (char *) 0);
199 pat
= FcPatternCreate ();
202 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
203 for (i
= 0, val
= Qnil
;
204 FcPatternGetString (pattern
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
207 if (strcmp ((char *) fam
, (char *) SYMBOL_FcChar8 (family
)) == 0)
209 if (! FcPatternAddString (pat
, FC_FAMILY
, fam
))
211 fontset
= FcFontList (NULL
, pat
, objset
);
214 /* Here we build the list in reverse order so that the last
215 loop in this function build a list in the correct
217 for (j
= 0; j
< fontset
->nfont
; j
++)
221 entity
= ftfont_pattern_entity (fontset
->fonts
[j
],
224 val
= Fcons (entity
, val
);
226 FcFontSetDestroy (fontset
);
228 FcPatternDel (pat
, FC_FAMILY
);
231 XSETCDR (slot
, list
);
233 if (pat
) FcPatternDestroy (pat
);
234 if (pattern
) FcPatternDestroy (pattern
);
235 if (fontset
) FcFontSetDestroy (fontset
);
236 if (objset
) FcObjectSetDestroy (objset
);
240 ASET (spec
, FONT_FAMILY_INDEX
, Qnil
);
241 for (val
= Qnil
; CONSP (list
); list
= XCDR (list
))
242 if (font_match_p (spec
, XCAR (list
)))
243 val
= Fcons (XCAR (list
), val
);
244 ASET (spec
, FONT_FAMILY_INDEX
, family
);
245 return Fvconcat (1, &val
);
249 static Lisp_Object ftfont_get_cache
P_ ((Lisp_Object
));
250 static Lisp_Object ftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
251 static Lisp_Object ftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
252 static Lisp_Object ftfont_list_family
P_ ((Lisp_Object
));
253 static void ftfont_free_entity
P_ ((Lisp_Object
));
254 static struct font
*ftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
255 static void ftfont_close
P_ ((FRAME_PTR
, struct font
*));
256 static int ftfont_has_char
P_ ((Lisp_Object
, int));
257 static unsigned ftfont_encode_char
P_ ((struct font
*, int));
258 static int ftfont_text_extents
P_ ((struct font
*, unsigned *, int,
259 struct font_metrics
*));
260 static int ftfont_get_bitmap
P_ ((struct font
*, unsigned,
261 struct font_bitmap
*, int));
262 static int ftfont_anchor_point
P_ ((struct font
*, unsigned, int,
265 struct font_driver ftfont_driver
=
267 (Lisp_Object
) NULL
, /* Qfreetype */
275 /* We can't draw a text without device dependent functions. */
281 /* We can't draw a text without device dependent functions. */
296 #endif /* HAVE_LIBOTF */
299 extern Lisp_Object QCname
;
302 ftfont_get_cache (frame
)
305 return freetype_font_cache
;
309 ftfont_list (frame
, spec
)
310 Lisp_Object frame
, spec
;
312 Lisp_Object val
, tmp
, extra
;
314 FcPattern
*pattern
= NULL
;
315 FcCharSet
*charset
= NULL
;
316 FcLangSet
*langset
= NULL
;
317 FcFontSet
*fontset
= NULL
;
318 FcObjectSet
*objset
= NULL
;
320 Lisp_Object registry
= Qunicode_bmp
;
325 char otf_script
[15]; /* For "otlayout\:XXXX" */
329 if (! fc_initialized
)
335 if (! NILP (AREF (spec
, FONT_ADSTYLE_INDEX
))
336 && ! EQ (AREF (spec
, FONT_ADSTYLE_INDEX
), null_string
))
338 if (! NILP (AREF (spec
, FONT_SLANT_INDEX
))
339 && XINT (AREF (spec
, FONT_SLANT_INDEX
)) < 100)
340 /* Fontconfig doesn't support reverse-italic/obligue. */
343 if (! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
345 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
346 if (EQ (registry
, Qiso8859_1
))
349 && ftfont_build_basic_charsets () < 0)
351 charset
= cs_iso8859_1
;
353 else if (! EQ (registry
, Qiso10646_1
) && ! EQ (registry
, Qunicode_bmp
))
357 otf_script
[0] = '\0';
359 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
360 CONSP (extra
); extra
= XCDR (extra
))
362 Lisp_Object key
, val
;
365 key
= XCAR (tmp
), val
= XCDR (tmp
);
368 script
= assq_no_quit (val
, Votf_script_alist
);
369 if (CONSP (script
) && SYMBOLP (XCDR (script
)))
370 script
= XCDR (script
);
371 tmp
= SYMBOL_NAME (val
);
372 sprintf (otf_script
, "otlayout:%s", (char *) SDATA (tmp
));
374 else if (EQ (key
, QClanguage
))
376 langset
= FcLangSetCreate ();
381 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
385 for (; CONSP (val
); val
= XCDR (val
))
386 if (SYMBOLP (XCAR (val
))
387 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
390 else if (EQ (key
, QCscript
))
392 else if (EQ (key
, QCdpi
))
394 else if (EQ (key
, QCspacing
))
395 spacing
= XINT (val
);
396 else if (EQ (key
, QCscalable
))
397 scalable
= ! NILP (val
);
400 if (! NILP (script
) && ! charset
)
402 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
406 charset
= FcCharSetCreate ();
409 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
410 if (CHARACTERP (XCAR (chars
))
411 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
416 pattern
= FcPatternCreate ();
419 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
420 if (SYMBOLP (tmp
) && ! NILP (tmp
)
421 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
423 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
424 if (SYMBOLP (tmp
) && ! NILP (tmp
)
425 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
427 /* Emacs conventionally doesn't distinguish normal, regular, and
428 medium weight, but fontconfig does. So, we can't restrict font
429 listing by weight. We check it after getting a list. */
430 tmp
= AREF (spec
, FONT_WEIGHT_INDEX
);
433 tmp
= AREF (spec
, FONT_SLANT_INDEX
);
435 && ! FcPatternAddInteger (pattern
, FC_SLANT
, XINT (tmp
) - 100))
437 tmp
= AREF (spec
, FONT_WIDTH_INDEX
);
439 && ! FcPatternAddInteger (pattern
, FC_WIDTH
, XINT (tmp
)))
443 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
446 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
449 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
452 && ! FcPatternAddInteger (pattern
, FC_SPACING
, spacing
))
455 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
458 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
459 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
,
460 FC_CHARSET
, FC_FILE
, NULL
);
465 #ifndef FC_CAPABILITY
467 #else /* not FC_CAPABILITY */
468 if (! FcObjectSetAdd (objset
, FC_CAPABILITY
))
470 #endif /* not FC_CAPABILITY */
473 fontset
= FcFontList (NULL
, pattern
, objset
);
477 if (fontset
->nfont
> 0)
481 if (NILP (AREF (spec
, FONT_SIZE_INDEX
)))
484 pixel_size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
486 for (i
= 0, val
= Qnil
; i
< fontset
->nfont
; i
++)
494 if (FcPatternGetDouble (fontset
->fonts
[i
], FC_PIXEL_SIZE
, 0,
495 &this) == FcResultMatch
496 && ((this < pixel_size
- FONT_PIXEL_SIZE_QUANTUM
)
497 || (this > pixel_size
+ FONT_PIXEL_SIZE_QUANTUM
)))
504 if (FcPatternGetInteger (fontset
->fonts
[i
], FC_WEIGHT
, 0,
505 &this) != FcResultMatch
508 || this < FC_WEIGHT_REGULAR
509 || this > FC_WEIGHT_MEDIUM
)))
517 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0,
518 &this) != FcResultMatch
519 || ! strstr ((char *) this, otf_script
))
522 #endif /* FC_CAPABILITY */
523 entity
= ftfont_pattern_entity (fontset
->fonts
[i
], frame
, registry
);
525 val
= Fcons (entity
, val
);
527 val
= Fvconcat (1, &val
);
529 else if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
530 val
= ftfont_list_generic_family (spec
, frame
, registry
);
534 /* We come here because of unexpected error in fontconfig API call
535 (usually insufficient memory). */
539 if (charset
&& charset
!= cs_iso8859_1
) FcCharSetDestroy (charset
);
540 if (objset
) FcObjectSetDestroy (objset
);
541 if (fontset
) FcFontSetDestroy (fontset
);
542 if (langset
) FcLangSetDestroy (langset
);
543 if (pattern
) FcPatternDestroy (pattern
);
549 ftfont_match (frame
, spec
)
550 Lisp_Object frame
, spec
;
552 Lisp_Object extra
, val
, entity
;
553 FcPattern
*pattern
= NULL
, *match
= NULL
;
556 if (! fc_initialized
)
562 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
563 val
= assq_no_quit (QCname
, extra
);
564 if (! CONSP (val
) || ! STRINGP (XCDR (val
)))
568 pattern
= FcNameParse (SDATA (XCDR (val
)));
571 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
573 FcDefaultSubstitute (pattern
);
574 match
= FcFontMatch (NULL
, pattern
, &result
);
577 entity
= ftfont_pattern_entity (match
, frame
, Qunicode_bmp
);
578 FcPatternDestroy (match
);
581 FcPatternDestroy (pattern
);
588 ftfont_list_family (frame
)
592 FcPattern
*pattern
= NULL
;
593 FcFontSet
*fontset
= NULL
;
594 FcObjectSet
*objset
= NULL
;
597 if (! fc_initialized
)
603 pattern
= FcPatternCreate ();
606 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
609 fontset
= FcFontList (NULL
, pattern
, objset
);
614 for (i
= 0; i
< fontset
->nfont
; i
++)
616 FcPattern
*pat
= fontset
->fonts
[i
];
619 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
620 list
= Fcons (intern_downcase ((char *) str
, strlen ((char *) str
)),
625 if (objset
) FcObjectSetDestroy (objset
);
626 if (fontset
) FcFontSetDestroy (fontset
);
627 if (pattern
) FcPatternDestroy (pattern
);
634 ftfont_free_entity (entity
)
637 Lisp_Object val
= AREF (entity
, FONT_EXTRA_INDEX
);
638 FcPattern
*pattern
= XSAVE_VALUE (val
)->pointer
;
640 FcPatternDestroy (pattern
);
644 ftfont_open (f
, entity
, pixel_size
)
649 struct ftfont_info
*ftfont_info
;
661 val
= AREF (entity
, FONT_EXTRA_INDEX
);
662 if (XTYPE (val
) != Lisp_Misc
663 || XMISCTYPE (val
) != Lisp_Misc_Save_Value
)
665 pattern
= XSAVE_VALUE (val
)->pointer
;
666 if (XSAVE_VALUE (val
)->integer
== 0)
668 /* We have not yet created FT_Face for this font. */
670 && FT_Init_FreeType (&ft_library
) != 0)
672 if (FcPatternGetString (pattern
, FC_FILE
, 0, &file
) != FcResultMatch
)
674 if (FT_New_Face (ft_library
, (char *) file
, 0, &ft_face
) != 0)
676 FcPatternAddFTFace (pattern
, FC_FT_FACE
, ft_face
);
677 ft_size
= ft_face
->size
;
681 if (FcPatternGetFTFace (pattern
, FC_FT_FACE
, 0, &ft_face
)
684 if (FT_New_Size (ft_face
, &ft_size
) != 0)
686 if (FT_Activate_Size (ft_size
) != 0)
688 FT_Done_Size (ft_size
);
693 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
696 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
698 if (XSAVE_VALUE (val
)->integer
== 0)
699 FT_Done_Face (ft_face
);
703 ftfont_info
= malloc (sizeof (struct ftfont_info
));
706 ftfont_info
->ft_size
= ft_size
;
708 font
= (struct font
*) ftfont_info
;
709 font
->entity
= entity
;
710 font
->pixel_size
= size
;
711 font
->driver
= &ftfont_driver
;
714 while (name
&& font_unparse_fcname (entity
, pixel_size
, name
, len
) < 0)
716 char *new = realloc (name
, len
+= 32);
722 font
->font
.full_name
= font
->font
.name
= name
;
723 font
->file_name
= (char *) file
;
724 font
->font
.size
= ft_face
->size
->metrics
.max_advance
>> 6;
725 if (font
->font
.size
<= 0)
726 font
->font
.size
= size
;
727 font
->font
.charset
= font
->encoding_charset
= font
->repertory_charset
= -1;
728 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
729 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
730 font
->font
.height
= font
->ascent
+ font
->descent
;
731 if (FcPatternGetInteger (pattern
, FC_SPACING
, 0, &spacing
) != FcResultMatch
)
732 spacing
= FC_PROPORTIONAL
;
733 if (spacing
!= FC_PROPORTIONAL
)
734 font
->font
.average_width
= font
->font
.space_width
= font
->font
.size
;
739 for (i
= 32; i
< 127; i
++)
741 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) != 0)
744 font
->font
.space_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
745 font
->font
.average_width
+= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
749 /* The font contains all ASCII printable characters. */
750 font
->font
.average_width
/= 95;
755 font
->font
.space_width
= font
->font
.size
;
756 font
->font
.average_width
= font
->font
.size
;
760 /* Unfortunately FreeType doesn't provide a way to get minimum char
761 width. So, we use space_width instead. */
762 font
->min_width
= font
->font
.space_width
;
764 font
->font
.baseline_offset
= 0;
765 font
->font
.relative_compose
= 0;
766 font
->font
.default_ascent
= 0;
767 font
->font
.vertical_centering
= 0;
769 (XSAVE_VALUE (val
)->integer
)++;
775 ftfont_close (f
, font
)
779 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
780 Lisp_Object entity
= font
->entity
;
781 Lisp_Object val
= AREF (entity
, FONT_EXTRA_INDEX
);
783 (XSAVE_VALUE (val
)->integer
)--;
784 if (XSAVE_VALUE (val
)->integer
== 0)
785 FT_Done_Face (ftfont_info
->ft_size
->face
);
787 FT_Done_Size (ftfont_info
->ft_size
);
793 ftfont_has_char (entity
, c
)
801 val
= AREF (entity
, FONT_EXTRA_INDEX
);
802 pattern
= XSAVE_VALUE (val
)->pointer
;
803 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
805 return (FcCharSetHasChar (charset
, (FcChar32
) c
) == FcTrue
);
809 ftfont_encode_char (font
, c
)
813 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
814 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
815 FT_ULong charcode
= c
;
816 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
818 return (code
> 0 ? code
: 0xFFFFFFFF);
822 ftfont_text_extents (font
, code
, nglyphs
, metrics
)
826 struct font_metrics
*metrics
;
828 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
829 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
833 if (ftfont_info
->ft_size
!= ft_face
->size
)
834 FT_Activate_Size (ftfont_info
->ft_size
);
836 bzero (metrics
, sizeof (struct font_metrics
));
837 for (i
= 0; i
< nglyphs
; i
++)
839 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
841 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
845 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
846 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
847 if (metrics
->rbearing
848 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
850 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
851 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
852 metrics
->ascent
= m
->horiBearingY
>> 6;
853 if (metrics
->descent
> ((m
->horiBearingY
+ m
->height
) >> 6))
854 metrics
->descent
= (m
->horiBearingY
+ m
->height
) >> 6;
856 width
+= m
->horiAdvance
>> 6;
860 width
+= font
->font
.space_width
;
864 metrics
->width
= width
;
870 ftfont_get_bitmap (font
, code
, bitmap
, bits_per_pixel
)
873 struct font_bitmap
*bitmap
;
876 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
877 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
878 FT_Int32 load_flags
= FT_LOAD_RENDER
;
880 if (ftfont_info
->ft_size
!= ft_face
->size
)
881 FT_Activate_Size (ftfont_info
->ft_size
);
882 if (bits_per_pixel
== 1)
884 #ifdef FT_LOAD_TARGET_MONO
885 load_flags
|= FT_LOAD_TARGET_MONO
;
887 load_flags
|= FT_LOAD_MONOCHROME
;
890 else if (bits_per_pixel
!= 8)
891 /* We don't support such a rendering. */
894 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
896 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
897 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
898 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
899 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
900 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
901 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
902 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
903 bitmap
->extra
= NULL
;
909 ftfont_anchor_point (font
, code
, index
, x
, y
)
915 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
916 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
918 if (ftfont_info
->ft_size
!= ft_face
->size
)
919 FT_Activate_Size (ftfont_info
->ft_size
);
920 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
922 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
924 if (index
>= ft_face
->glyph
->outline
.n_points
)
926 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
927 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
935 DEFSYM (Qfreetype
, "freetype");
936 DEFSYM (Qmonospace
, "monospace");
937 DEFSYM (Qsans_serif
, "sans-serif");
938 DEFSYM (Qserif
, "serif");
939 DEFSYM (Qmono
, "mono");
940 DEFSYM (Qsans
, "sans");
941 DEFSYM (Qsans__serif
, "sans serif");
943 staticpro (&freetype_font_cache
);
944 freetype_font_cache
= Fcons (Qt
, Qnil
);
946 staticpro (&ftfont_generic_family_list
);
947 ftfont_generic_family_list
948 = Fcons (Fcons (Qmonospace
, Qt
),
949 Fcons (Fcons (Qsans_serif
, Qt
),
950 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
952 ftfont_driver
.type
= Qfreetype
;
953 register_font_driver (&ftfont_driver
, NULL
);
956 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
957 (do not change this comment) */