Mercurial > mplayer.hg
annotate libass/ass_font.c @ 28992:947ef23ba798
Test if create_vdp_decoder() might succeed by calling it from config()
with a small value for max_reference_frames.
This does not make automatic recovery by using software decoder possible,
but lets MPlayer fail more graciously on - actually existing - buggy
hardware that does not support certain H264 widths when using
hardware accelerated decoding (784, 864, 944, 1024, 1808, 1888 pixels on
NVIDIA G98) and if the user tries to hardware-decode more samples at
the same time than supported.
Might break playback of H264 Intra-Only samples on hardware with very
little video memory.
author | cehoyos |
---|---|
date | Sat, 21 Mar 2009 20:11:05 +0000 |
parents | 7fcc0bf5b27a |
children | 0f1b5b68af32 |
rev | line source |
---|---|
21277 | 1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*- |
2 // vim:ts=8:sw=8:noet:ai: | |
3 /* | |
26723 | 4 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
5 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
6 * This file is part of libass. |
26723 | 7 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
8 * libass is free software; you can redistribute it and/or modify |
26723 | 9 * it under the terms of the GNU General Public License as published by |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
13 * libass is distributed in the hope that it will be useful, |
26723 | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License along | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
19 * with libass; if not, write to the Free Software Foundation, Inc., |
26723 | 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
21 */ | |
21277 | 22 |
23 #include "config.h" | |
24 | |
25 #include <inttypes.h> | |
26 #include <ft2build.h> | |
27 #include FT_FREETYPE_H | |
28 #include FT_SYNTHESIS_H | |
29 #include FT_GLYPH_H | |
23328 | 30 #include FT_TRUETYPE_TABLES_H |
21277 | 31 |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
32 #include "ass.h" |
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
33 #include "ass_library.h" |
21277 | 34 #include "ass_font.h" |
21321
7b7627ff1937
Move ass_font_desc_t and ass_font_t declarations to ass_font.h.
eugeni
parents:
21320
diff
changeset
|
35 #include "ass_bitmap.h" |
7b7627ff1937
Move ass_font_desc_t and ass_font_t declarations to ass_font.h.
eugeni
parents:
21320
diff
changeset
|
36 #include "ass_cache.h" |
21277 | 37 #include "ass_fontconfig.h" |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
38 #include "ass_utils.h" |
21277 | 39 #include "mputils.h" |
40 | |
41 /** | |
42 * Select Microfost Unicode CharMap, if the font has one. | |
43 * Otherwise, let FreeType decide. | |
44 */ | |
45 static void charmap_magic(FT_Face face) | |
46 { | |
47 int i; | |
48 for (i = 0; i < face->num_charmaps; ++i) { | |
49 FT_CharMap cmap = face->charmaps[i]; | |
50 unsigned pid = cmap->platform_id; | |
51 unsigned eid = cmap->encoding_id; | |
52 if (pid == 3 /*microsoft*/ && (eid == 1 /*unicode bmp*/ || eid == 10 /*full unicode*/)) { | |
53 FT_Set_Charmap(face, cmap); | |
22210
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
54 return; |
21277 | 55 } |
56 } | |
22210
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
57 |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
58 if (!face->charmap) { |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
59 if (face->num_charmaps == 0) { |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
60 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmaps); |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
61 return; |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
62 } |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
63 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmapAutodetected); |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
64 FT_Set_Charmap(face, face->charmaps[0]); |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
65 return; |
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
66 } |
21277 | 67 } |
68 | |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
69 static void update_transform(ass_font_t* font) |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
70 { |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
71 int i; |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
72 FT_Matrix m; |
23328 | 73 m.xx = double_to_d16(font->scale_x); |
74 m.yy = double_to_d16(font->scale_y); | |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
75 m.xy = m.yx = 0; |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
76 for (i = 0; i < font->n_faces; ++i) |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
77 FT_Set_Transform(font->faces[i], &m, &font->v); |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
78 } |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
79 |
21630 | 80 /** |
81 * \brief find a memory font by name | |
82 */ | |
21460 | 83 static int find_font(ass_library_t* library, char* name) |
84 { | |
85 int i; | |
86 for (i = 0; i < library->num_fontdata; ++i) | |
87 if (strcasecmp(name, library->fontdata[i].name) == 0) | |
88 return i; | |
89 return -1; | |
90 } | |
91 | |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
92 static void face_set_size(FT_Face face, double size); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
93 |
23982
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
94 static void buggy_font_workaround(FT_Face face) |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
95 { |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
96 // Some fonts have zero Ascender/Descender fields in 'hhea' table. |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
97 // In this case, get the information from 'os2' table or, as |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
98 // a last resort, from face.bbox. |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
99 if (face->ascender + face->descender == 0 || face->height == 0) { |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
100 TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
101 if (os2) { |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
102 face->ascender = os2->sTypoAscender; |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
103 face->descender = os2->sTypoDescender; |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
104 face->height = face->ascender - face->descender; |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
105 } else { |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
106 face->ascender = face->bbox.yMax; |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
107 face->descender = face->bbox.yMin; |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
108 face->height = face->ascender - face->descender; |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
109 } |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
110 } |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
111 } |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
112 |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
113 /** |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
114 * \brief Select a face with the given charcode and add it to ass_font_t |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
115 * \return index of the new face in font->faces, -1 if failed |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
116 */ |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
117 static int add_face(void* fc_priv, ass_font_t* font, uint32_t ch) |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
118 { |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
119 char* path; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
120 int index; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
121 FT_Face face; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
122 int error; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
123 int mem_idx; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
124 |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
125 if (font->n_faces == ASS_FONT_MAX_FACES) |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
126 return -1; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
127 |
28860
7fcc0bf5b27a
Treat -font/-subfont as Fontconfig pattern in libass.
eugeni
parents:
27393
diff
changeset
|
128 path = fontconfig_select(fc_priv, font->desc.family, font->desc.treat_family_as_pattern, font->desc.bold, |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
129 font->desc.italic, &index, ch); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
130 |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
131 mem_idx = find_font(font->library, path); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
132 if (mem_idx >= 0) { |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
133 error = FT_New_Memory_Face(font->ftlibrary, (unsigned char*)font->library->fontdata[mem_idx].data, |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
134 font->library->fontdata[mem_idx].size, 0, &face); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
135 if (error) { |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
136 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningMemoryFont, path); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
137 return -1; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
138 } |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
139 } else { |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
140 error = FT_New_Face(font->ftlibrary, path, index, &face); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
141 if (error) { |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
142 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningFont, path, index); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
143 return -1; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
144 } |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
145 } |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
146 charmap_magic(face); |
23982
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
147 buggy_font_workaround(face); |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
148 |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
149 font->faces[font->n_faces++] = face; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
150 update_transform(font); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
151 face_set_size(face, font->size); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
152 return font->n_faces - 1; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
153 } |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
154 |
21630 | 155 /** |
156 * \brief Create a new ass_font_t according to "desc" argument | |
157 */ | |
21460 | 158 ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc) |
21277 | 159 { |
160 int error; | |
23212
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
161 ass_font_t* fontp; |
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
162 ass_font_t font; |
21317 | 163 |
23212
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
164 fontp = ass_font_cache_find(desc); |
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
165 if (fontp) |
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
166 return fontp; |
21277 | 167 |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
168 font.library = library; |
23212
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
169 font.ftlibrary = ftlibrary; |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
170 font.n_faces = 0; |
23212
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
171 font.desc.family = strdup(desc->family); |
28860
7fcc0bf5b27a
Treat -font/-subfont as Fontconfig pattern in libass.
eugeni
parents:
27393
diff
changeset
|
172 font.desc.treat_family_as_pattern = desc->treat_family_as_pattern; |
23212
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
173 font.desc.bold = desc->bold; |
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
174 font.desc.italic = desc->italic; |
21277 | 175 |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
176 font.scale_x = font.scale_y = 1.; |
23212
c932f521344d
In ass_font_new, allocate temporary ass_font_t on stack and return the pointer
eugeni
parents:
23134
diff
changeset
|
177 font.v.x = font.v.y = 0; |
23300 | 178 font.size = 0.; |
21277 | 179 |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
180 error = add_face(fc_priv, &font, 0); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
181 if (error == -1) { |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
182 free(font.desc.family); |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
183 return 0; |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
184 } else |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
185 return ass_font_cache_add(&font); |
21277 | 186 } |
187 | |
21630 | 188 /** |
189 * \brief Set font transformation matrix and shift vector | |
190 **/ | |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
191 void ass_font_set_transform(ass_font_t* font, double scale_x, double scale_y, FT_Vector* v) |
21277 | 192 { |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
193 font->scale_x = scale_x; |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
194 font->scale_y = scale_y; |
21616
2704273f398d
FT_Set_Transform is fast enough to be called once for each glyph.
eugeni
parents:
21615
diff
changeset
|
195 font->v.x = v->x; |
2704273f398d
FT_Set_Transform is fast enough to be called once for each glyph.
eugeni
parents:
21615
diff
changeset
|
196 font->v.y = v->y; |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
197 update_transform(font); |
21277 | 198 } |
199 | |
23328 | 200 static void face_set_size(FT_Face face, double size) |
201 { | |
23340 | 202 #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1)) |
23328 | 203 TT_HoriHeader *hori = FT_Get_Sfnt_Table(face, ft_sfnt_hhea); |
204 TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); | |
205 double mscale = 1.; | |
206 FT_Size_RequestRec rq; | |
207 FT_Size_Metrics *m = &face->size->metrics; | |
208 // VSFilter uses metrics from TrueType OS/2 table | |
209 // The idea was borrowed from asa (http://asa.diac24.net) | |
23983
90038c72d69e
Don't apply windows-like font scaling if hhea or os2 tables contain invalid
eugeni
parents:
23982
diff
changeset
|
210 if (hori && os2) { |
90038c72d69e
Don't apply windows-like font scaling if hhea or os2 tables contain invalid
eugeni
parents:
23982
diff
changeset
|
211 int hori_height = hori->Ascender - hori->Descender; |
90038c72d69e
Don't apply windows-like font scaling if hhea or os2 tables contain invalid
eugeni
parents:
23982
diff
changeset
|
212 int os2_height = os2->usWinAscent + os2->usWinDescent; |
90038c72d69e
Don't apply windows-like font scaling if hhea or os2 tables contain invalid
eugeni
parents:
23982
diff
changeset
|
213 if (hori_height && os2_height) |
90038c72d69e
Don't apply windows-like font scaling if hhea or os2 tables contain invalid
eugeni
parents:
23982
diff
changeset
|
214 mscale = (double)hori_height / os2_height; |
90038c72d69e
Don't apply windows-like font scaling if hhea or os2 tables contain invalid
eugeni
parents:
23982
diff
changeset
|
215 } |
23328 | 216 memset(&rq, 0, sizeof(rq)); |
217 rq.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; | |
218 rq.width = 0; | |
219 rq.height = double_to_d6(size * mscale); | |
220 rq.horiResolution = rq.vertResolution = 0; | |
221 FT_Request_Size(face, &rq); | |
222 m->ascender /= mscale; | |
223 m->descender /= mscale; | |
224 m->height /= mscale; | |
23339
95bc9f4905f8
FT_Request_Size does not exist in FreeType 2.1.*. Fallback to FT_Set_Char_Size.
eugeni
parents:
23328
diff
changeset
|
225 #else |
95bc9f4905f8
FT_Request_Size does not exist in FreeType 2.1.*. Fallback to FT_Set_Char_Size.
eugeni
parents:
23328
diff
changeset
|
226 FT_Set_Char_Size(face, 0, double_to_d6(size), 0, 0); |
95bc9f4905f8
FT_Request_Size does not exist in FreeType 2.1.*. Fallback to FT_Set_Char_Size.
eugeni
parents:
23328
diff
changeset
|
227 #endif |
23328 | 228 } |
229 | |
21630 | 230 /** |
231 * \brief Set font size | |
232 **/ | |
23300 | 233 void ass_font_set_size(ass_font_t* font, double size) |
21277 | 234 { |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
235 int i; |
21319
415e2119e91c
Don't call FT_Set_Transform/FT_Set_Pixel_Sizes if values have not changed.
eugeni
parents:
21317
diff
changeset
|
236 if (font->size != size) { |
21320 | 237 font->size = size; |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
238 for (i = 0; i < font->n_faces; ++i) |
23328 | 239 face_set_size(font->faces[i], size); |
21319
415e2119e91c
Don't call FT_Set_Transform/FT_Set_Pixel_Sizes if values have not changed.
eugeni
parents:
21317
diff
changeset
|
240 } |
21277 | 241 } |
242 | |
21630 | 243 /** |
244 * \brief Get maximal font ascender and descender. | |
245 * \param ch character code | |
246 * The values are extracted from the font face that provides glyphs for the given character | |
247 **/ | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
248 void ass_font_get_asc_desc(ass_font_t* font, uint32_t ch, int* asc, int* desc) |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
249 { |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
250 int i; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
251 for (i = 0; i < font->n_faces; ++i) { |
21620 | 252 FT_Face face = font->faces[i]; |
253 if (FT_Get_Char_Index(face, ch)) { | |
25660
3993c96eaa95
Do not try to guess font metrics based on its bounding box.
eugeni
parents:
24828
diff
changeset
|
254 *asc = face->size->metrics.ascender; |
3993c96eaa95
Do not try to guess font metrics based on its bounding box.
eugeni
parents:
24828
diff
changeset
|
255 *desc = - face->size->metrics.descender; |
21620 | 256 return; |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
257 } |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
258 } |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
259 |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
260 *asc = *desc = 0; |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
261 } |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
262 |
21630 | 263 /** |
264 * \brief Get a glyph | |
265 * \param ch character code | |
266 **/ | |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
267 FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch, ass_hinting_t hinting) |
21277 | 268 { |
269 int error; | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
270 int index = 0; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
271 int i; |
21277 | 272 FT_Glyph glyph; |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
273 FT_Face face = 0; |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
274 int flags = 0; |
21350 | 275 |
276 if (ch < 0x20) | |
277 return 0; | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
278 if (font->n_faces == 0) |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
279 return 0; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
280 |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
281 for (i = 0; i < font->n_faces; ++i) { |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
282 face = font->faces[i]; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
283 index = FT_Get_Char_Index(face, ch); |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
284 if (index) |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
285 break; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
286 } |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
287 |
27393 | 288 #ifdef CONFIG_FONTCONFIG |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
289 if (index == 0) { |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
290 int face_idx; |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
291 mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_GlyphNotFoundReselectingFont, |
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
292 ch, font->desc.family, font->desc.bold, font->desc.italic); |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
293 face_idx = add_face(fontconfig_priv, font, ch); |
24827 | 294 if (face_idx >= 0) { |
24828 | 295 face = font->faces[face_idx]; |
296 index = FT_Get_Char_Index(face, ch); | |
297 if (index == 0) { | |
298 mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_GlyphNotFound, | |
299 ch, font->desc.family, font->desc.bold, font->desc.italic); | |
300 } | |
24827 | 301 } |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
302 } |
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
303 #endif |
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
304 |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
305 switch (hinting) { |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
306 case ASS_HINTING_NONE: flags = FT_LOAD_NO_HINTING; break; |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
307 case ASS_HINTING_LIGHT: flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT; break; |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
308 case ASS_HINTING_NORMAL: flags = FT_LOAD_FORCE_AUTOHINT; break; |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
309 case ASS_HINTING_NATIVE: flags = 0; break; |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
310 } |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
311 |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22210
diff
changeset
|
312 error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP | flags); |
21277 | 313 if (error) { |
314 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); | |
315 return 0; | |
316 } | |
317 | |
318 #if (FREETYPE_MAJOR > 2) || \ | |
319 ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR >= 2)) || \ | |
320 ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 10)) | |
321 // FreeType >= 2.1.10 required | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
322 if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) && |
21277 | 323 (font->desc.italic > 55)) { |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
324 FT_GlyphSlot_Oblique(face->glyph); |
21277 | 325 } |
326 #endif | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
327 error = FT_Get_Glyph(face->glyph, &glyph); |
21277 | 328 if (error) { |
329 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); | |
330 return 0; | |
331 } | |
332 | |
333 return glyph; | |
334 } | |
335 | |
21630 | 336 /** |
337 * \brief Get kerning for the pair of glyphs. | |
338 **/ | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
339 FT_Vector ass_font_get_kerning(ass_font_t* font, uint32_t c1, uint32_t c2) |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
340 { |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
341 FT_Vector v = {0, 0}; |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
342 int i; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
343 |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
344 for (i = 0; i < font->n_faces; ++i) { |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
345 FT_Face face = font->faces[i]; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
346 int i1 = FT_Get_Char_Index(face, c1); |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
347 int i2 = FT_Get_Char_Index(face, c2); |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
348 if (i1 && i2) { |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
349 if (FT_HAS_KERNING(face)) |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
350 FT_Get_Kerning(face, i1, i2, FT_KERNING_DEFAULT, &v); |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
351 return v; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
352 } |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
353 if (i1 || i2) // these glyphs are from different font faces, no kerning information |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
354 return v; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
355 } |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
356 return v; |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
357 } |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
358 |
21630 | 359 /** |
360 * \brief Deallocate ass_font_t | |
361 **/ | |
21277 | 362 void ass_font_free(ass_font_t* font) |
363 { | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
364 int i; |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
365 for (i = 0; i < font->n_faces; ++i) |
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
366 if (font->faces[i]) FT_Done_Face(font->faces[i]); |
21277 | 367 if (font->desc.family) free(font->desc.family); |
21317 | 368 free(font); |
21277 | 369 } |