comparison libass/ass_render.c @ 19965:70352570e9ae

Shadow support in libass.
author eugeni
date Sun, 24 Sep 2006 16:04:37 +0000
parents fb2063eaa445
children fa122b7c71c6
comparison
equal deleted inserted replaced
19964:edee81101156 19965:70352570e9ae
51 // glyph_info_t and text_info_t are used for text centering and word-wrapping operations 51 // glyph_info_t and text_info_t are used for text centering and word-wrapping operations
52 typedef struct glyph_info_s { 52 typedef struct glyph_info_s {
53 unsigned symbol; 53 unsigned symbol;
54 FT_Glyph glyph; 54 FT_Glyph glyph;
55 FT_Glyph outline_glyph; 55 FT_Glyph outline_glyph;
56 bitmap_t* bm; 56 bitmap_t* bm; // glyph bitmap
57 bitmap_t* bm_o; 57 bitmap_t* bm_o; // outline bitmap
58 bitmap_t* bm_s; // shadow bitmap
58 FT_BBox bbox; 59 FT_BBox bbox;
59 FT_Vector pos; 60 FT_Vector pos;
60 char linebreak; // the first (leading) glyph of some line ? 61 char linebreak; // the first (leading) glyph of some line ?
61 uint32_t c[4]; // colors 62 uint32_t c[4]; // colors
62 FT_Vector advance; // 26.6 63 FT_Vector advance; // 26.6
66 // part of the glyph to the left of it is displayed in a different color. 67 // part of the glyph to the left of it is displayed in a different color.
67 int effect_skip_timing; // delay after the end of last karaoke word 68 int effect_skip_timing; // delay after the end of last karaoke word
68 int asc, desc; // font max ascender and descender 69 int asc, desc; // font max ascender and descender
69 // int height; 70 // int height;
70 int be; // blur edges 71 int be; // blur edges
72 int shadow;
71 73
72 glyph_hash_key_t hash_key; 74 glyph_hash_key_t hash_key;
73 } glyph_info_t; 75 } glyph_info_t;
74 76
75 typedef struct line_info_s { 77 typedef struct line_info_s {
111 uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA 113 uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA
112 int clip_x0, clip_y0, clip_x1, clip_y1; 114 int clip_x0, clip_y0, clip_x1, clip_y1;
113 char detect_collisions; 115 char detect_collisions;
114 uint32_t fade; // alpha from \fad 116 uint32_t fade; // alpha from \fad
115 char be; // blur edges 117 char be; // blur edges
118 int shadow;
116 119
117 effect_t effect_type; 120 effect_t effect_type;
118 int effect_timing; 121 int effect_timing;
119 int effect_skip_timing; 122 int effect_skip_timing;
120 123
374 if (text_info->glyphs[i].glyph) { 377 if (text_info->glyphs[i].glyph) {
375 if ((text_info->glyphs[i].symbol == '\n') || (text_info->glyphs[i].symbol == 0)) 378 if ((text_info->glyphs[i].symbol == '\n') || (text_info->glyphs[i].symbol == 0))
376 continue; 379 continue;
377 error = glyph_to_bitmap(ass_instance->synth_priv, 380 error = glyph_to_bitmap(ass_instance->synth_priv,
378 text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph, 381 text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph,
379 &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o, text_info->glyphs[i].be); 382 &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o,
383 &text_info->glyphs[i].bm_s, text_info->glyphs[i].be);
380 if (error) 384 if (error)
381 text_info->glyphs[i].symbol = 0; 385 text_info->glyphs[i].symbol = 0;
382 FT_Done_Glyph(text_info->glyphs[i].glyph); 386 FT_Done_Glyph(text_info->glyphs[i].glyph);
383 if (text_info->glyphs[i].outline_glyph) 387 if (text_info->glyphs[i].outline_glyph)
384 FT_Done_Glyph(text_info->glyphs[i].outline_glyph); 388 FT_Done_Glyph(text_info->glyphs[i].outline_glyph);
385 389
386 // cache 390 // cache
387 hash_val.bbox_scaled = text_info->glyphs[i].bbox; 391 hash_val.bbox_scaled = text_info->glyphs[i].bbox;
388 hash_val.bm_o = text_info->glyphs[i].bm_o; 392 hash_val.bm_o = text_info->glyphs[i].bm_o;
389 hash_val.bm = text_info->glyphs[i].bm; 393 hash_val.bm = text_info->glyphs[i].bm;
394 hash_val.bm_s = text_info->glyphs[i].bm_s;
390 hash_val.advance.x = text_info->glyphs[i].advance.x; 395 hash_val.advance.x = text_info->glyphs[i].advance.x;
391 hash_val.advance.y = text_info->glyphs[i].advance.y; 396 hash_val.advance.y = text_info->glyphs[i].advance.y;
392 cache_add_glyph(&(text_info->glyphs[i].hash_key), &hash_val); 397 cache_add_glyph(&(text_info->glyphs[i].hash_key), &hash_val);
393 398
394 } 399 }
400 }
401
402 for (i = 0; i < text_info->length; ++i) {
403 glyph_info_t* info = text_info->glyphs + i;
404 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0))
405 continue;
406
407 pen_x = dst_x + info->pos.x + info->shadow;
408 pen_y = dst_y + info->pos.y + info->shadow;
409 bm = info->bm_s;
410
411 tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail);
395 } 412 }
396 413
397 for (i = 0; i < text_info->length; ++i) { 414 for (i = 0; i < text_info->length; ++i) {
398 glyph_info_t* info = text_info->glyphs + i; 415 glyph_info_t* info = text_info->glyphs + i;
399 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o) 416 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o)
990 int val = strtol(p, &p, 10); 1007 int val = strtol(p, &p, 10);
991 render_context.effect_type = EF_KARAOKE; 1008 render_context.effect_type = EF_KARAOKE;
992 if (render_context.effect_timing) 1009 if (render_context.effect_timing)
993 render_context.effect_skip_timing += render_context.effect_timing; 1010 render_context.effect_skip_timing += render_context.effect_timing;
994 render_context.effect_timing = val * 10; 1011 render_context.effect_timing = val * 10;
1012 } else if (mystrcmp(&p, "shad")) {
1013 int val;
1014 if (mystrtoi(&p, 10, &val))
1015 render_context.shadow = val;
1016 else
1017 render_context.shadow = render_context.style->Shadow;
995 } 1018 }
996 1019
997 return p; 1020 return p;
998 1021
999 #undef skip 1022 #undef skip
1135 change_border(-1.); 1158 change_border(-1.);
1136 render_context.scale_x = render_context.style->ScaleX; 1159 render_context.scale_x = render_context.style->ScaleX;
1137 render_context.scale_y = render_context.style->ScaleY; 1160 render_context.scale_y = render_context.style->ScaleY;
1138 render_context.hspacing = 0; // FIXME 1161 render_context.hspacing = 0; // FIXME
1139 render_context.be = 0; 1162 render_context.be = 0;
1163 render_context.shadow = render_context.style->Shadow;
1140 1164
1141 // FIXME: does not reset unsupported attributes. 1165 // FIXME: does not reset unsupported attributes.
1142 } 1166 }
1143 1167
1144 /** 1168 /**
1206 1230
1207 if (val) { 1231 if (val) {
1208 info->glyph = info->outline_glyph = 0; 1232 info->glyph = info->outline_glyph = 0;
1209 info->bm = val->bm; 1233 info->bm = val->bm;
1210 info->bm_o = val->bm_o; 1234 info->bm_o = val->bm_o;
1235 info->bm_s = val->bm_s;
1211 info->bbox = val->bbox_scaled; 1236 info->bbox = val->bbox_scaled;
1212 info->advance.x = val->advance.x; 1237 info->advance.x = val->advance.x;
1213 info->advance.y = val->advance.y; 1238 info->advance.y = val->advance.y;
1214 1239
1215 return 0; 1240 return 0;
1250 } 1275 }
1251 } else { 1276 } else {
1252 info->outline_glyph = 0; 1277 info->outline_glyph = 0;
1253 } 1278 }
1254 1279
1255 info->bm = info->bm_o = 0; 1280 info->bm = info->bm_o = info->bm_s = 0;
1256 1281
1257 return 0; 1282 return 0;
1258 } 1283 }
1259 1284
1260 /** 1285 /**
1623 text_info.glyphs[text_info.length].effect_timing = render_context.effect_timing; 1648 text_info.glyphs[text_info.length].effect_timing = render_context.effect_timing;
1624 text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing; 1649 text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing;
1625 text_info.glyphs[text_info.length].asc = get_face_ascender(render_context.face); 1650 text_info.glyphs[text_info.length].asc = get_face_ascender(render_context.face);
1626 text_info.glyphs[text_info.length].desc = get_face_descender(render_context.face); 1651 text_info.glyphs[text_info.length].desc = get_face_descender(render_context.face);
1627 text_info.glyphs[text_info.length].be = render_context.be; 1652 text_info.glyphs[text_info.length].be = render_context.be;
1653 text_info.glyphs[text_info.length].shadow = render_context.shadow;
1628 1654
1629 text_info.length++; 1655 text_info.length++;
1630 1656
1631 render_context.effect_type = EF_NONE; 1657 render_context.effect_type = EF_NONE;
1632 render_context.effect_timing = 0; 1658 render_context.effect_timing = 0;