Mercurial > mplayer.hg
annotate libass/ass_font.c @ 31001:6215761e4d02
sync with en/mplayer.1 rev. 31028
author | jrash |
---|---|
date | Sat, 17 Apr 2010 02:14:55 +0000 |
parents | 48d020c5ceca |
children | e64df5862cea |
rev | line source |
---|---|
21277 | 1 /* |
26723 | 2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
3 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
4 * This file is part of libass. |
26723 | 5 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
6 * libass is free software; you can redistribute it and/or modify |
26723 | 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. | |
10 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
11 * libass is distributed in the hope that it will be useful, |
26723 | 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. | |
15 * | |
16 * 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
|
17 * with libass; if not, write to the Free Software Foundation, Inc., |
26723 | 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ | |
21277 | 20 |
21 #include "config.h" | |
22 | |
23 #include <inttypes.h> | |
24 #include <ft2build.h> | |
25 #include FT_FREETYPE_H | |
26 #include FT_SYNTHESIS_H | |
27 #include FT_GLYPH_H | |
23328 | 28 #include FT_TRUETYPE_TABLES_H |
30200 | 29 #include FT_OUTLINE_H |
21277 | 30 |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
31 #include "ass.h" |
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
32 #include "ass_library.h" |
21277 | 33 #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
|
34 #include "ass_bitmap.h" |
7b7627ff1937
Move ass_font_desc_t and ass_font_t declarations to ass_font.h.
eugeni
parents:
21320
diff
changeset
|
35 #include "ass_cache.h" |
21277 | 36 #include "ass_fontconfig.h" |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
37 #include "ass_utils.h" |
21277 | 38 |
39 /** | |
40 * Select Microfost Unicode CharMap, if the font has one. | |
41 * Otherwise, let FreeType decide. | |
42 */ | |
30200 | 43 static void charmap_magic(ASS_Library *library, FT_Face face) |
21277 | 44 { |
30200 | 45 int i; |
46 for (i = 0; i < face->num_charmaps; ++i) { | |
47 FT_CharMap cmap = face->charmaps[i]; | |
48 unsigned pid = cmap->platform_id; | |
49 unsigned eid = cmap->encoding_id; | |
50 if (pid == 3 /*microsoft */ | |
51 && (eid == 1 /*unicode bmp */ | |
52 || eid == 10 /*full unicode */ )) { | |
53 FT_Set_Charmap(face, cmap); | |
54 return; | |
55 } | |
56 } | |
22210
4a958bd08920
Select the first charmap in the font, if FreeType did not autoselect any.
eugeni
parents:
21630
diff
changeset
|
57 |
30200 | 58 if (!face->charmap) { |
59 if (face->num_charmaps == 0) { | |
60 ass_msg(library, MSGL_WARN, "Font face with no charmaps"); | |
61 return; | |
62 } | |
63 ass_msg(library, MSGL_WARN, | |
64 "No charmap autodetected, trying the first one"); | |
65 FT_Set_Charmap(face, face->charmaps[0]); | |
66 return; | |
67 } | |
21277 | 68 } |
69 | |
30200 | 70 static void update_transform(ASS_Font *font) |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
71 { |
30200 | 72 int i; |
73 FT_Matrix m; | |
74 m.xx = double_to_d16(font->scale_x); | |
75 m.yy = double_to_d16(font->scale_y); | |
76 m.xy = m.yx = 0; | |
77 for (i = 0; i < font->n_faces; ++i) | |
78 FT_Set_Transform(font->faces[i], &m, &font->v); | |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
79 } |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23212
diff
changeset
|
80 |
21630 | 81 /** |
82 * \brief find a memory font by name | |
83 */ | |
30200 | 84 static int find_font(ASS_Library *library, char *name) |
21460 | 85 { |
30200 | 86 int i; |
87 for (i = 0; i < library->num_fontdata; ++i) | |
88 if (strcasecmp(name, library->fontdata[i].name) == 0) | |
89 return i; | |
90 return -1; | |
21460 | 91 } |
92 | |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
93 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
|
94 |
23982
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
95 static void buggy_font_workaround(FT_Face face) |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
96 { |
30200 | 97 // Some fonts have zero Ascender/Descender fields in 'hhea' table. |
98 // In this case, get the information from 'os2' table or, as | |
99 // a last resort, from face.bbox. | |
100 if (face->ascender + face->descender == 0 || face->height == 0) { | |
101 TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); | |
102 if (os2) { | |
103 face->ascender = os2->sTypoAscender; | |
104 face->descender = os2->sTypoDescender; | |
105 face->height = face->ascender - face->descender; | |
106 } else { | |
107 face->ascender = face->bbox.yMax; | |
108 face->descender = face->bbox.yMin; | |
109 face->height = face->ascender - face->descender; | |
110 } | |
111 } | |
23982
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
112 } |
17b5fa69243c
Workaround for fonts with zero ascender/descender in horizontal header.
eugeni
parents:
23981
diff
changeset
|
113 |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
114 /** |
30200 | 115 * \brief Select a face with the given charcode and add it to ASS_Font |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
116 * \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
|
117 */ |
30200 | 118 static int add_face(void *fc_priv, ASS_Font *font, uint32_t ch) |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
119 { |
30200 | 120 char *path; |
121 int index; | |
122 FT_Face face; | |
123 int error; | |
124 int mem_idx; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
125 |
30200 | 126 if (font->n_faces == ASS_FONT_MAX_FACES) |
127 return -1; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
128 |
30200 | 129 path = |
130 fontconfig_select(font->library, fc_priv, font->desc.family, | |
131 font->desc.treat_family_as_pattern, | |
132 font->desc.bold, font->desc.italic, &index, ch); | |
133 if (!path) | |
134 return -1; | |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
135 |
30200 | 136 mem_idx = find_font(font->library, path); |
137 if (mem_idx >= 0) { | |
138 error = | |
139 FT_New_Memory_Face(font->ftlibrary, | |
140 (unsigned char *) font->library-> | |
141 fontdata[mem_idx].data, | |
142 font->library->fontdata[mem_idx].size, 0, | |
143 &face); | |
144 if (error) { | |
145 ass_msg(font->library, MSGL_WARN, | |
146 "Error opening memory font: '%s'", path); | |
147 free(path); | |
148 return -1; | |
149 } | |
150 } else { | |
151 error = FT_New_Face(font->ftlibrary, path, index, &face); | |
152 if (error) { | |
153 ass_msg(font->library, MSGL_WARN, | |
154 "Error opening font: '%s', %d", path, index); | |
155 free(path); | |
156 return -1; | |
157 } | |
158 } | |
159 charmap_magic(font->library, face); | |
160 buggy_font_workaround(face); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
161 |
30200 | 162 font->faces[font->n_faces++] = face; |
163 update_transform(font); | |
164 face_set_size(face, font->size); | |
165 free(path); | |
166 return font->n_faces - 1; | |
23981
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
167 } |
705628816d98
Factor out common code from ass_font_new and ass_font_reselect.
eugeni
parents:
23980
diff
changeset
|
168 |
21630 | 169 /** |
30200 | 170 * \brief Create a new ASS_Font according to "desc" argument |
21630 | 171 */ |
30200 | 172 ASS_Font *ass_font_new(void *font_cache, ASS_Library *library, |
173 FT_Library ftlibrary, void *fc_priv, | |
174 ASS_FontDesc *desc) | |
21277 | 175 { |
30200 | 176 int error; |
177 ASS_Font *fontp; | |
178 ASS_Font font; | |
21317 | 179 |
30200 | 180 fontp = ass_font_cache_find((Hashmap *) font_cache, desc); |
181 if (fontp) | |
182 return fontp; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
183 |
30200 | 184 font.library = library; |
185 font.ftlibrary = ftlibrary; | |
186 font.n_faces = 0; | |
187 font.desc.family = strdup(desc->family); | |
188 font.desc.treat_family_as_pattern = desc->treat_family_as_pattern; | |
189 font.desc.bold = desc->bold; | |
190 font.desc.italic = desc->italic; | |
21277 | 191 |
30200 | 192 font.scale_x = font.scale_y = 1.; |
193 font.v.x = font.v.y = 0; | |
194 font.size = 0.; | |
21277 | 195 |
30200 | 196 error = add_face(fc_priv, &font, 0); |
197 if (error == -1) { | |
198 free(font.desc.family); | |
199 return 0; | |
200 } else | |
201 return ass_font_cache_add((Hashmap *) font_cache, &font); | |
21277 | 202 } |
203 | |
21630 | 204 /** |
205 * \brief Set font transformation matrix and shift vector | |
206 **/ | |
30200 | 207 void ass_font_set_transform(ASS_Font *font, double scale_x, |
208 double scale_y, FT_Vector *v) | |
21277 | 209 { |
30200 | 210 font->scale_x = scale_x; |
211 font->scale_y = scale_y; | |
212 if (v) { | |
213 font->v.x = v->x; | |
214 font->v.y = v->y; | |
215 } | |
216 update_transform(font); | |
21277 | 217 } |
218 | |
23328 | 219 static void face_set_size(FT_Face face, double size) |
220 { | |
30200 | 221 TT_HoriHeader *hori = FT_Get_Sfnt_Table(face, ft_sfnt_hhea); |
222 TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); | |
223 double mscale = 1.; | |
224 FT_Size_RequestRec rq; | |
225 FT_Size_Metrics *m = &face->size->metrics; | |
226 // VSFilter uses metrics from TrueType OS/2 table | |
227 // The idea was borrowed from asa (http://asa.diac24.net) | |
228 if (hori && os2) { | |
229 int hori_height = hori->Ascender - hori->Descender; | |
230 int os2_height = os2->usWinAscent + os2->usWinDescent; | |
231 if (hori_height && os2_height) | |
232 mscale = (double) hori_height / os2_height; | |
233 } | |
234 memset(&rq, 0, sizeof(rq)); | |
235 rq.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; | |
236 rq.width = 0; | |
237 rq.height = double_to_d6(size * mscale); | |
238 rq.horiResolution = rq.vertResolution = 0; | |
239 FT_Request_Size(face, &rq); | |
240 m->ascender /= mscale; | |
241 m->descender /= mscale; | |
242 m->height /= mscale; | |
23328 | 243 } |
244 | |
21630 | 245 /** |
246 * \brief Set font size | |
247 **/ | |
30200 | 248 void ass_font_set_size(ASS_Font *font, double size) |
21277 | 249 { |
30200 | 250 int i; |
251 if (font->size != size) { | |
252 font->size = size; | |
253 for (i = 0; i < font->n_faces; ++i) | |
254 face_set_size(font->faces[i], size); | |
255 } | |
21277 | 256 } |
257 | |
21630 | 258 /** |
259 * \brief Get maximal font ascender and descender. | |
260 * \param ch character code | |
261 * The values are extracted from the font face that provides glyphs for the given character | |
262 **/ | |
30200 | 263 void ass_font_get_asc_desc(ASS_Font *font, uint32_t ch, int *asc, |
264 int *desc) | |
265 { | |
266 int i; | |
267 for (i = 0; i < font->n_faces; ++i) { | |
268 FT_Face face = font->faces[i]; | |
269 TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); | |
270 if (FT_Get_Char_Index(face, ch)) { | |
271 int y_scale = face->size->metrics.y_scale; | |
272 if (os2) { | |
273 *asc = FT_MulFix(os2->usWinAscent, y_scale); | |
274 *desc = FT_MulFix(os2->usWinDescent, y_scale); | |
275 } else { | |
276 *asc = FT_MulFix(face->ascender, y_scale); | |
277 *desc = FT_MulFix(-face->descender, y_scale); | |
278 } | |
279 return; | |
280 } | |
281 } | |
282 | |
283 *asc = *desc = 0; | |
284 } | |
285 | |
286 /* | |
287 * Strike a glyph with a horizontal line; it's possible to underline it | |
288 * and/or strike through it. For the line's position and size, truetype | |
289 * tables are consulted. Obviously this relies on the data in the tables | |
290 * being accurate. | |
291 * | |
292 */ | |
293 static int ass_strike_outline_glyph(FT_Face face, ASS_Font *font, | |
294 FT_Glyph glyph, int under, int through) | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
295 { |
30200 | 296 TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
297 TT_Postscript *ps = FT_Get_Sfnt_Table(face, ft_sfnt_post); | |
298 FT_Outline *ol = &((FT_OutlineGlyph) glyph)->outline; | |
299 int bear, advance, y_scale, i, dir; | |
300 | |
301 if (!under && !through) | |
302 return 0; | |
303 | |
304 // Grow outline | |
305 i = (under ? 4 : 0) + (through ? 4 : 0); | |
306 ol->points = realloc(ol->points, sizeof(FT_Vector) * | |
307 (ol->n_points + i)); | |
308 ol->tags = realloc(ol->tags, ol->n_points + i); | |
309 i = !!under + !!through; | |
310 ol->contours = realloc(ol->contours, sizeof(short) * | |
311 (ol->n_contours + i)); | |
312 | |
313 // If the bearing is negative, the glyph starts left of the current | |
314 // pen position | |
315 bear = FFMIN(face->glyph->metrics.horiBearingX, 0); | |
316 // We're adding half a pixel to avoid small gaps | |
317 advance = d16_to_d6(glyph->advance.x) + 32; | |
318 y_scale = face->size->metrics.y_scale; | |
319 | |
320 // Reverse drawing direction for non-truetype fonts | |
321 dir = FT_Outline_Get_Orientation(ol); | |
322 | |
323 // Add points to the outline | |
324 if (under && ps) { | |
325 int pos, size; | |
326 pos = FT_MulFix(ps->underlinePosition, y_scale * font->scale_y); | |
327 size = FT_MulFix(ps->underlineThickness, | |
328 y_scale * font->scale_y / 2); | |
329 | |
330 if (pos > 0 || size <= 0) | |
331 return 1; | |
332 | |
333 FT_Vector points[4] = { | |
334 {.x = bear, .y = pos + size}, | |
335 {.x = advance, .y = pos + size}, | |
336 {.x = advance, .y = pos - size}, | |
337 {.x = bear, .y = pos - size}, | |
338 }; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
339 |
30200 | 340 if (dir == FT_ORIENTATION_TRUETYPE) { |
341 for (i = 0; i < 4; i++) { | |
342 ol->points[ol->n_points] = points[i]; | |
343 ol->tags[ol->n_points++] = 1; | |
344 } | |
345 } else { | |
346 for (i = 3; i >= 0; i--) { | |
347 ol->points[ol->n_points] = points[i]; | |
348 ol->tags[ol->n_points++] = 1; | |
349 } | |
350 } | |
351 | |
352 ol->contours[ol->n_contours++] = ol->n_points - 1; | |
353 } | |
354 | |
355 if (through && os2) { | |
356 int pos, size; | |
357 pos = FT_MulFix(os2->yStrikeoutPosition, y_scale * font->scale_y); | |
358 size = FT_MulFix(os2->yStrikeoutSize, y_scale * font->scale_y / 2); | |
359 | |
360 if (pos < 0 || size <= 0) | |
361 return 1; | |
362 | |
363 FT_Vector points[4] = { | |
364 {.x = bear, .y = pos + size}, | |
365 {.x = advance, .y = pos + size}, | |
366 {.x = advance, .y = pos - size}, | |
367 {.x = bear, .y = pos - size}, | |
368 }; | |
369 | |
370 if (dir == FT_ORIENTATION_TRUETYPE) { | |
371 for (i = 0; i < 4; i++) { | |
372 ol->points[ol->n_points] = points[i]; | |
373 ol->tags[ol->n_points++] = 1; | |
374 } | |
375 } else { | |
376 for (i = 3; i >= 0; i--) { | |
377 ol->points[ol->n_points] = points[i]; | |
378 ol->tags[ol->n_points++] = 1; | |
379 } | |
380 } | |
381 | |
382 ol->contours[ol->n_contours++] = ol->n_points - 1; | |
383 } | |
384 | |
385 return 0; | |
386 } | |
387 | |
388 /** | |
389 * Slightly embold a glyph without touching its metrics | |
390 */ | |
391 static void ass_glyph_embolden(FT_GlyphSlot slot) | |
392 { | |
393 int str; | |
394 | |
395 if (slot->format != FT_GLYPH_FORMAT_OUTLINE) | |
396 return; | |
397 | |
398 str = FT_MulFix(slot->face->units_per_EM, | |
399 slot->face->size->metrics.y_scale) / 64; | |
400 | |
401 FT_Outline_Embolden(&slot->outline, str); | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
402 } |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
403 |
21630 | 404 /** |
405 * \brief Get a glyph | |
406 * \param ch character code | |
407 **/ | |
30200 | 408 FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ASS_Font *font, |
409 uint32_t ch, ASS_Hinting hinting, int deco) | |
21277 | 410 { |
30200 | 411 int error; |
412 int index = 0; | |
413 int i; | |
414 FT_Glyph glyph; | |
415 FT_Face face = 0; | |
416 int flags = 0; | |
21350 | 417 |
30200 | 418 if (ch < 0x20) |
419 return 0; | |
420 // Handle NBSP like a regular space when rendering the glyph | |
421 if (ch == 0xa0) | |
422 ch = ' '; | |
423 if (font->n_faces == 0) | |
424 return 0; | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
425 |
30200 | 426 for (i = 0; i < font->n_faces; ++i) { |
427 face = font->faces[i]; | |
428 index = FT_Get_Char_Index(face, ch); | |
429 if (index) | |
430 break; | |
431 } | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
432 |
27393 | 433 #ifdef CONFIG_FONTCONFIG |
30200 | 434 if (index == 0) { |
435 int face_idx; | |
436 ass_msg(font->library, MSGL_INFO, | |
437 "Glyph 0x%X not found, selecting one more " | |
438 "font for (%s, %d, %d)", ch, font->desc.family, | |
439 font->desc.bold, font->desc.italic); | |
440 face_idx = add_face(fontconfig_priv, font, ch); | |
441 if (face_idx >= 0) { | |
442 face = font->faces[face_idx]; | |
443 index = FT_Get_Char_Index(face, ch); | |
444 if (index == 0) { | |
445 ass_msg(font->library, MSGL_ERR, | |
446 "Glyph 0x%X not found in font for (%s, %d, %d)", | |
447 ch, font->desc.family, font->desc.bold, | |
448 font->desc.italic); | |
449 } | |
450 } | |
451 } | |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
452 #endif |
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21350
diff
changeset
|
453 |
30200 | 454 switch (hinting) { |
455 case ASS_HINTING_NONE: | |
456 flags = FT_LOAD_NO_HINTING; | |
457 break; | |
458 case ASS_HINTING_LIGHT: | |
459 flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT; | |
460 break; | |
461 case ASS_HINTING_NORMAL: | |
462 flags = FT_LOAD_FORCE_AUTOHINT; | |
463 break; | |
464 case ASS_HINTING_NATIVE: | |
465 flags = 0; | |
466 break; | |
467 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
468 |
30200 | 469 error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP | flags); |
470 if (error) { | |
471 ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d", | |
472 index); | |
473 return 0; | |
474 } | |
475 if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) && | |
476 (font->desc.italic > 55)) { | |
477 FT_GlyphSlot_Oblique(face->glyph); | |
478 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
479 |
30200 | 480 if (!(face->style_flags & FT_STYLE_FLAG_BOLD) && |
481 (font->desc.bold > 80)) { | |
482 ass_glyph_embolden(face->glyph); | |
483 } | |
484 error = FT_Get_Glyph(face->glyph, &glyph); | |
485 if (error) { | |
486 ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d", | |
487 index); | |
488 return 0; | |
489 } | |
490 | |
491 ass_strike_outline_glyph(face, font, glyph, deco & DECO_UNDERLINE, | |
492 deco & DECO_STRIKETHROUGH); | |
493 | |
494 return glyph; | |
21277 | 495 } |
496 | |
21630 | 497 /** |
498 * \brief Get kerning for the pair of glyphs. | |
499 **/ | |
30200 | 500 FT_Vector ass_font_get_kerning(ASS_Font *font, uint32_t c1, uint32_t c2) |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
501 { |
30200 | 502 FT_Vector v = { 0, 0 }; |
503 int i; | |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21618
diff
changeset
|
504 |
30200 | 505 for (i = 0; i < font->n_faces; ++i) { |
506 FT_Face face = font->faces[i]; | |
507 int i1 = FT_Get_Char_Index(face, c1); | |
508 int i2 = FT_Get_Char_Index(face, c2); | |
509 if (i1 && i2) { | |
510 if (FT_HAS_KERNING(face)) | |
511 FT_Get_Kerning(face, i1, i2, FT_KERNING_DEFAULT, &v); | |
512 return v; | |
513 } | |
514 if (i1 || i2) // these glyphs are from different font faces, no kerning information | |
515 return v; | |
516 } | |
517 return v; | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
518 } |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21460
diff
changeset
|
519 |
21630 | 520 /** |
30200 | 521 * \brief Deallocate ASS_Font |
21630 | 522 **/ |
30200 | 523 void ass_font_free(ASS_Font *font) |
21277 | 524 { |
30200 | 525 int i; |
526 for (i = 0; i < font->n_faces; ++i) | |
527 if (font->faces[i]) | |
528 FT_Done_Face(font->faces[i]); | |
529 if (font->desc.family) | |
530 free(font->desc.family); | |
531 free(font); | |
21277 | 532 } |