1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*-
2 // vim:ts=8:sw=8:noet:ai:
4 Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include FT_FREETYPE_H
26 #include FT_SYNTHESIS_H
30 #include "ass_library.h"
32 #include "ass_bitmap.h"
33 #include "ass_cache.h"
34 #include "ass_fontconfig.h"
38 * Select Microfost Unicode CharMap, if the font has one.
39 * Otherwise, let FreeType decide.
41 static void charmap_magic(FT_Face face
)
44 for (i
= 0; i
< face
->num_charmaps
; ++i
) {
45 FT_CharMap cmap
= face
->charmaps
[i
];
46 unsigned pid
= cmap
->platform_id
;
47 unsigned eid
= cmap
->encoding_id
;
48 if (pid
== 3 /*microsoft*/ && (eid
== 1 /*unicode bmp*/ || eid
== 10 /*full unicode*/)) {
49 FT_Set_Charmap(face
, cmap
);
55 static int find_font(ass_library_t
* library
, char* name
)
58 for (i
= 0; i
< library
->num_fontdata
; ++i
)
59 if (strcasecmp(name
, library
->fontdata
[i
].name
) == 0)
64 ass_font_t
* ass_font_new(ass_library_t
* library
, FT_Library ftlibrary
, void* fc_priv
, ass_font_desc_t
* desc
)
73 font
= ass_font_cache_find(desc
);
77 path
= fontconfig_select(fc_priv
, desc
->family
, desc
->bold
, desc
->italic
, &index
);
79 mem_idx
= find_font(library
, path
);
81 error
= FT_New_Memory_Face(ftlibrary
, library
->fontdata
[mem_idx
].data
,
82 library
->fontdata
[mem_idx
].size
, 0, &face
);
84 mp_msg(MSGT_ASS
, MSGL_WARN
, MSGTR_LIBASS_ErrorOpeningMemoryFont
, path
);
88 error
= FT_New_Face(ftlibrary
, path
, index
, &face
);
90 mp_msg(MSGT_ASS
, MSGL_WARN
, MSGTR_LIBASS_ErrorOpeningFont
, path
, index
);
97 font
= calloc(1, sizeof(ass_font_t
));
98 font
->ftlibrary
= ftlibrary
;
99 font
->path
= strdup(path
);
102 font
->desc
.family
= strdup(desc
->family
);
103 font
->desc
.bold
= desc
->bold
;
104 font
->desc
.italic
= desc
->italic
;
106 font
->m
.xx
= font
->m
.yy
= (FT_Fixed
)0x10000L
;
107 font
->m
.xy
= font
->m
.yy
= 0;
108 font
->v
.x
= font
->v
.y
= 0;
111 #ifdef HAVE_FONTCONFIG
112 font
->charset
= FcCharSetCreate();
115 ass_font_cache_add(font
);
120 void ass_font_set_transform(ass_font_t
* font
, FT_Matrix
* m
, FT_Vector
* v
)
122 if (font
->m
.xx
!= m
->xx
||
123 font
->m
.xy
!= m
->xy
||
124 font
->m
.yx
!= m
->yx
||
125 font
->m
.yy
!= m
->yy
||
135 FT_Set_Transform(font
->face
, &font
->m
, &font
->v
);
139 void ass_font_set_size(ass_font_t
* font
, int size
)
141 if (font
->size
!= size
) {
143 FT_Set_Pixel_Sizes(font
->face
, 0, size
);
147 #ifdef HAVE_FONTCONFIG
148 static void ass_font_reselect(void* fontconfig_priv
, ass_font_t
* font
)
155 path
= fontconfig_select_with_charset(fontconfig_priv
, font
->desc
.family
, font
->desc
.bold
,
156 font
->desc
.italic
, &index
, font
->charset
);
157 if (strcasecmp(path
, font
->path
) == 0 && index
== font
->index
) {
162 error
= FT_New_Face(font
->ftlibrary
, path
, index
, &face
);
164 mp_msg(MSGT_ASS
, MSGL_WARN
, MSGTR_LIBASS_ErrorOpeningFont
, path
, index
);
169 if (font
->face
) FT_Done_Face(font
->face
);
173 font
->path
= strdup(path
);
176 FT_Set_Transform(font
->face
, &font
->m
, &font
->v
);
177 FT_Set_Pixel_Sizes(font
->face
, 0, font
->size
);
181 FT_Glyph
ass_font_get_glyph(void* fontconfig_priv
, ass_font_t
* font
, uint32_t ch
)
190 index
= FT_Get_Char_Index(font
->face
, ch
);
191 #ifdef HAVE_FONTCONFIG
192 FcCharSetAddChar(font
->charset
, ch
);
194 mp_msg(MSGT_ASS
, MSGL_INFO
, MSGTR_LIBASS_GlyphNotFoundReselectingFont
,
195 ch
, font
->desc
.family
, font
->desc
.bold
, font
->desc
.italic
);
196 ass_font_reselect(fontconfig_priv
, font
);
197 index
= FT_Get_Char_Index(font
->face
, ch
);
199 mp_msg(MSGT_ASS
, MSGL_ERR
, MSGTR_LIBASS_GlyphNotFound
,
200 ch
, font
->desc
.family
, font
->desc
.bold
, font
->desc
.italic
);
205 error
= FT_Load_Glyph(font
->face
, index
, FT_LOAD_NO_BITMAP
);
207 mp_msg(MSGT_ASS
, MSGL_WARN
, MSGTR_LIBASS_ErrorLoadingGlyph
);
211 #if (FREETYPE_MAJOR > 2) || \
212 ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR >= 2)) || \
213 ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 10))
214 // FreeType >= 2.1.10 required
215 if (!(font
->face
->style_flags
& FT_STYLE_FLAG_ITALIC
) &&
216 (font
->desc
.italic
> 55)) {
217 FT_GlyphSlot_Oblique(font
->face
->glyph
);
220 error
= FT_Get_Glyph(font
->face
->glyph
, &glyph
);
222 mp_msg(MSGT_ASS
, MSGL_WARN
, MSGTR_LIBASS_ErrorLoadingGlyph
);
229 void ass_font_free(ass_font_t
* font
)
231 if (font
->face
) FT_Done_Face(font
->face
);
232 if (font
->path
) free(font
->path
);
233 if (font
->desc
.family
) free(font
->desc
.family
);
234 #ifdef HAVE_FONTCONFIG
235 if (font
->charset
) FcCharSetDestroy(font
->charset
);