Mercurial > mplayer.hg
comparison libass/ass_render.c @ 19873:98d32b832c3a
Reduce code duplication in init_render_context().
Don't use glyph stroker for borderless glyphs.
author | eugeni |
---|---|
date | Sun, 17 Sep 2006 15:32:01 +0000 |
parents | 07be98a5dd5f |
children | 55a39486f4a8 |
comparison
equal
deleted
inserted
replaced
19872:8e50cba9fe03 | 19873:98d32b832c3a |
---|---|
377 text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph, | 377 text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph, |
378 &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o, text_info->glyphs[i].be); | 378 &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o, text_info->glyphs[i].be); |
379 if (error) | 379 if (error) |
380 text_info->glyphs[i].symbol = 0; | 380 text_info->glyphs[i].symbol = 0; |
381 FT_Done_Glyph(text_info->glyphs[i].glyph); | 381 FT_Done_Glyph(text_info->glyphs[i].glyph); |
382 FT_Done_Glyph(text_info->glyphs[i].outline_glyph); | 382 if (text_info->glyphs[i].outline_glyph) |
383 FT_Done_Glyph(text_info->glyphs[i].outline_glyph); | |
383 | 384 |
384 // cache | 385 // cache |
385 hash_val.bbox_scaled = text_info->glyphs[i].bbox; | 386 hash_val.bbox_scaled = text_info->glyphs[i].bbox; |
386 hash_val.bm_o = text_info->glyphs[i].bm_o; | 387 hash_val.bm_o = text_info->glyphs[i].bm_o; |
387 hash_val.bm = text_info->glyphs[i].bm; | 388 hash_val.bm = text_info->glyphs[i].bm; |
392 } | 393 } |
393 } | 394 } |
394 | 395 |
395 for (i = 0; i < text_info->length; ++i) { | 396 for (i = 0; i < text_info->length; ++i) { |
396 glyph_info_t* info = text_info->glyphs + i; | 397 glyph_info_t* info = text_info->glyphs + i; |
397 if ((info->symbol == 0) || (info->symbol == '\n')) | 398 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o) |
398 continue; | 399 continue; |
399 | 400 |
400 pen_x = dst_x + info->pos.x; | 401 pen_x = dst_x + info->pos.x; |
401 pen_y = dst_y + info->pos.y; | 402 pen_y = dst_y + info->pos.y; |
402 bm = info->bm_o; | 403 bm = info->bm_o; |
406 } else | 407 } else |
407 tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail); | 408 tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail); |
408 } | 409 } |
409 for (i = 0; i < text_info->length; ++i) { | 410 for (i = 0; i < text_info->length; ++i) { |
410 glyph_info_t* info = text_info->glyphs + i; | 411 glyph_info_t* info = text_info->glyphs + i; |
411 if ((info->symbol == 0) || (info->symbol == '\n')) | 412 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm) |
412 continue; | 413 continue; |
413 | 414 |
414 pen_x = dst_x + info->pos.x; | 415 pen_x = dst_x + info->pos.x; |
415 pen_y = dst_y + info->pos.y; | 416 pen_y = dst_y + info->pos.y; |
416 bm = info->bm; | 417 bm = info->bm; |
557 } | 558 } |
558 | 559 |
559 if (render_context.face) | 560 if (render_context.face) |
560 { | 561 { |
561 change_font_size(render_context.font_size); | 562 change_font_size(render_context.font_size); |
563 | |
564 if (render_context.stroker != 0) { | |
565 FT_Stroker_Done(render_context.stroker); | |
566 render_context.stroker = 0; | |
567 } | |
568 #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1)) | |
569 error = FT_Stroker_New( ass_instance->library, &render_context.stroker ); | |
570 #else // < 2.2 | |
571 error = FT_Stroker_New( render_context.face->memory, &render_context.stroker ); | |
572 #endif | |
573 if ( error ) { | |
574 mp_msg(MSGT_GLOBAL, MSGL_V, "failed to get stroker\n"); | |
575 render_context.stroker = 0; | |
576 } | |
562 } | 577 } |
563 } | 578 } |
564 | 579 |
565 /** | 580 /** |
566 * \brief Change border width | 581 * \brief Change border width |
582 * negative value resets border to style value | |
567 */ | 583 */ |
568 static void change_border(double border) | 584 static void change_border(double border) |
569 { | 585 { |
570 if (!render_context.stroker) { | 586 if (!render_context.stroker) { |
571 if (!no_more_font_messages) | 587 if (!no_more_font_messages) |
572 mp_msg(MSGT_GLOBAL, MSGL_WARN, "No stroker!\n"); | 588 mp_msg(MSGT_GLOBAL, MSGL_WARN, "No stroker!\n"); |
573 } else { | 589 } else { |
590 int b; | |
591 if (border < 0) { | |
592 if (render_context.style->BorderStyle == 1) { | |
593 if (render_context.style->Outline == 0 && render_context.style->Shadow > 0) | |
594 border = 1.; | |
595 else | |
596 border = render_context.style->Outline; | |
597 } else | |
598 border = 1.; | |
599 } | |
574 render_context.border = border; | 600 render_context.border = border; |
575 FT_Stroker_Set( render_context.stroker, | 601 |
576 (int)(64 * border * frame_context.font_scale), | 602 b = 64 * border * frame_context.font_scale; |
603 if (b > 0) | |
604 FT_Stroker_Set( render_context.stroker, b, | |
577 FT_STROKER_LINECAP_ROUND, | 605 FT_STROKER_LINECAP_ROUND, |
578 FT_STROKER_LINEJOIN_ROUND, | 606 FT_STROKER_LINEJOIN_ROUND, |
579 0 ); | 607 0 ); |
608 else { | |
609 FT_Stroker_Done(render_context.stroker); | |
610 render_context.stroker = 0; | |
611 } | |
580 } | 612 } |
581 } | 613 } |
582 | 614 |
583 #define _r(c) ((c)>>24) | 615 #define _r(c) ((c)>>24) |
584 #define _g(c) (((c)>>16)&0xFF) | 616 #define _g(c) (((c)>>16)&0xFF) |
639 a = a2; | 671 a = a2; |
640 } | 672 } |
641 | 673 |
642 return a; | 674 return a; |
643 } | 675 } |
676 | |
677 static void reset_render_context(); | |
644 | 678 |
645 /** | 679 /** |
646 * \brief Parse style override tag. | 680 * \brief Parse style override tag. |
647 * \param p string to parse | 681 * \param p string to parse |
648 * \param pwr multiplier for some tag effects (comes from \t tags) | 682 * \param pwr multiplier for some tag effects (comes from \t tags) |
689 } else if (mystrcmp(&p, "bord")) { | 723 } else if (mystrcmp(&p, "bord")) { |
690 double val; | 724 double val; |
691 if (mystrtod(&p, &val)) | 725 if (mystrtod(&p, &val)) |
692 val = render_context.border * ( 1 - pwr ) + val * pwr; | 726 val = render_context.border * ( 1 - pwr ) + val * pwr; |
693 else | 727 else |
694 val = (render_context.style->BorderStyle == 1) ? render_context.style->Outline : 1.; | 728 val = -1.; // reset to default |
695 change_border(val); | 729 change_border(val); |
696 } else if (mystrcmp(&p, "move")) { | 730 } else if (mystrcmp(&p, "move")) { |
697 int x1, x2, y1, y2; | 731 int x1, x2, y1, y2; |
698 long long t1, t2, delta_t, t; | 732 long long t1, t2, delta_t, t; |
699 int x, y; | 733 int x, y; |
921 case 'a': change_alpha(render_context.c + cidx, val >> 24, pwr); break; | 955 case 'a': change_alpha(render_context.c + cidx, val >> 24, pwr); break; |
922 default: mp_msg(MSGT_GLOBAL, MSGL_WARN, "Bad command: %c%c\n", n, cmd); break; | 956 default: mp_msg(MSGT_GLOBAL, MSGL_WARN, "Bad command: %c%c\n", n, cmd); break; |
923 } | 957 } |
924 mp_msg(MSGT_GLOBAL, MSGL_DBG2, "single c/a at %f: %c%c = %X \n", pwr, n, cmd, render_context.c[cidx]); | 958 mp_msg(MSGT_GLOBAL, MSGL_DBG2, "single c/a at %f: %c%c = %X \n", pwr, n, cmd, render_context.c[cidx]); |
925 } else if (mystrcmp(&p, "r")) { | 959 } else if (mystrcmp(&p, "r")) { |
926 render_context.c[0] = render_context.style->PrimaryColour; | 960 reset_render_context(); |
927 render_context.c[1] = render_context.style->SecondaryColour; | |
928 render_context.c[2] = render_context.style->OutlineColour; | |
929 render_context.c[3] = render_context.style->BackColour; | |
930 render_context.font_size = render_context.style->FontSize; | |
931 | |
932 if (render_context.family) | |
933 free(render_context.family); | |
934 render_context.family = strdup(render_context.style->FontName); | |
935 render_context.bold = - render_context.style->Bold; | |
936 render_context.italic = - render_context.style->Italic; | |
937 update_font(); | |
938 | |
939 if (render_context.stroker) { | |
940 double border = (render_context.style->BorderStyle == 1) ? render_context.style->Outline : 1.; | |
941 change_border(border); | |
942 } | |
943 render_context.scale_x = render_context.style->ScaleX; | |
944 render_context.scale_y = render_context.style->ScaleY; | |
945 render_context.hspacing = 0; // FIXME | |
946 | |
947 // FIXME: does not reset unsupported attributes. | |
948 } else if (mystrcmp(&p, "be")) { | 961 } else if (mystrcmp(&p, "be")) { |
949 int val; | 962 int val; |
950 if (mystrtoi(&p, 10, &val)) | 963 if (mystrtoi(&p, 10, &val)) |
951 render_context.be = val ? 1 : 0; | 964 render_context.be = val ? 1 : 0; |
952 else | 965 else |
1104 } | 1117 } |
1105 | 1118 |
1106 } | 1119 } |
1107 | 1120 |
1108 /** | 1121 /** |
1122 * \brief partially reset render_context to style values | |
1123 * Works like {\r}: resets some style overrides | |
1124 */ | |
1125 static void reset_render_context(void) | |
1126 { | |
1127 render_context.c[0] = render_context.style->PrimaryColour; | |
1128 render_context.c[1] = render_context.style->SecondaryColour; | |
1129 render_context.c[2] = render_context.style->OutlineColour; | |
1130 render_context.c[3] = render_context.style->BackColour; | |
1131 render_context.font_size = render_context.style->FontSize; | |
1132 | |
1133 if (render_context.family) | |
1134 free(render_context.family); | |
1135 render_context.family = strdup(render_context.style->FontName); | |
1136 render_context.bold = - render_context.style->Bold; | |
1137 render_context.italic = - render_context.style->Italic; | |
1138 update_font(); | |
1139 | |
1140 change_border(-1.); | |
1141 render_context.scale_x = render_context.style->ScaleX; | |
1142 render_context.scale_y = render_context.style->ScaleY; | |
1143 render_context.hspacing = 0; // FIXME | |
1144 render_context.be = 0; | |
1145 | |
1146 // FIXME: does not reset unsupported attributes. | |
1147 } | |
1148 | |
1149 /** | |
1109 * \brief Start new event. Reset render_context. | 1150 * \brief Start new event. Reset render_context. |
1110 */ | 1151 */ |
1111 static int init_render_context(ass_event_t* event) | 1152 static void init_render_context(ass_event_t* event) |
1112 { | 1153 { |
1113 int error; | |
1114 | |
1115 // init render_context | |
1116 render_context.event = event; | 1154 render_context.event = event; |
1117 render_context.style = frame_context.track->styles + event->Style; | 1155 render_context.style = frame_context.track->styles + event->Style; |
1118 | 1156 |
1119 render_context.font_size = render_context.style->FontSize; | 1157 reset_render_context(); |
1158 | |
1120 render_context.evt_type = EVENT_NORMAL; | 1159 render_context.evt_type = EVENT_NORMAL; |
1121 render_context.alignment = 0; | 1160 render_context.alignment = 0; |
1122 render_context.rotation = M_PI * render_context.style->Angle / 180.; | 1161 render_context.rotation = M_PI * render_context.style->Angle / 180.; |
1123 render_context.pos_x = 0; | 1162 render_context.pos_x = 0; |
1124 render_context.pos_y = 0; | 1163 render_context.pos_y = 0; |
1125 render_context.org_x = 0; | 1164 render_context.org_x = 0; |
1126 render_context.org_y = 0; | 1165 render_context.org_y = 0; |
1127 render_context.scale_x = render_context.style->ScaleX; | |
1128 render_context.scale_y = render_context.style->ScaleY; | |
1129 render_context.hspacing = 0; | |
1130 render_context.c[0] = render_context.style->PrimaryColour; | |
1131 render_context.c[1] = render_context.style->SecondaryColour; | |
1132 render_context.c[2] = render_context.style->OutlineColour; | |
1133 render_context.c[3] = render_context.style->BackColour; | |
1134 render_context.clip_x0 = 0; | 1166 render_context.clip_x0 = 0; |
1135 render_context.clip_y0 = 0; | 1167 render_context.clip_y0 = 0; |
1136 render_context.clip_x1 = frame_context.track->PlayResX; | 1168 render_context.clip_x1 = frame_context.track->PlayResX; |
1137 render_context.clip_y1 = frame_context.track->PlayResY; | 1169 render_context.clip_y1 = frame_context.track->PlayResY; |
1138 render_context.detect_collisions = 1; | 1170 render_context.detect_collisions = 1; |
1139 render_context.fade = 0; | 1171 render_context.fade = 0; |
1140 render_context.effect_type = EF_NONE; | 1172 render_context.effect_type = EF_NONE; |
1141 render_context.effect_timing = 0; | 1173 render_context.effect_timing = 0; |
1142 render_context.effect_skip_timing = 0; | 1174 render_context.effect_skip_timing = 0; |
1143 render_context.be = 0; | 1175 |
1144 | |
1145 if (render_context.family) | |
1146 free(render_context.family); | |
1147 render_context.family = strdup(render_context.style->FontName); | |
1148 render_context.bold = - render_context.style->Bold; // style value for bold text is -1 | |
1149 render_context.italic = - render_context.style->Italic; | |
1150 | |
1151 update_font(); | |
1152 | |
1153 if (render_context.face) { | |
1154 #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1)) | |
1155 error = FT_Stroker_New( ass_instance->library, &render_context.stroker ); | |
1156 #else // < 2.2 | |
1157 error = FT_Stroker_New( render_context.face->memory, &render_context.stroker ); | |
1158 #endif | |
1159 if ( error ) { | |
1160 mp_msg(MSGT_GLOBAL, MSGL_V, "failed to get stroker\n"); | |
1161 render_context.stroker = 0; | |
1162 } else { | |
1163 // FIXME: probably wrong when render_context.Border == 3 | |
1164 double border = (render_context.style->BorderStyle == 1) ? render_context.style->Outline : 1.; | |
1165 change_border(border); | |
1166 } | |
1167 } | |
1168 | |
1169 apply_transition_effects(event); | 1176 apply_transition_effects(event); |
1170 | 1177 } |
1171 return 0; | 1178 |
1172 } | 1179 static void free_render_context(void) |
1173 | |
1174 static int free_render_context(void) | |
1175 { | 1180 { |
1176 if (render_context.stroker != 0) { | 1181 if (render_context.stroker != 0) { |
1177 FT_Stroker_Done(render_context.stroker); | 1182 FT_Stroker_Done(render_context.stroker); |
1178 render_context.stroker = 0; | 1183 render_context.stroker = 0; |
1179 } | 1184 } |
1180 return 0; | |
1181 } | 1185 } |
1182 | 1186 |
1183 /** | 1187 /** |
1184 * \brief Get normal and outline glyphs from cache (if possible) or font face | 1188 * \brief Get normal and outline glyphs from cache (if possible) or font face |
1185 * \param index face glyph index | 1189 * \param index face glyph index |
1245 } | 1249 } |
1246 | 1250 |
1247 info->advance.x = info->glyph->advance.x >> 10; | 1251 info->advance.x = info->glyph->advance.x >> 10; |
1248 info->advance.y = info->glyph->advance.y >> 10; | 1252 info->advance.y = info->glyph->advance.y >> 10; |
1249 | 1253 |
1250 info->outline_glyph = info->glyph; | 1254 if (render_context.stroker) { |
1251 error = FT_Glyph_Stroke( &(info->outline_glyph), render_context.stroker, 0 ); // don't destroy original | 1255 info->outline_glyph = info->glyph; |
1252 if (error) { | 1256 error = FT_Glyph_Stroke( &(info->outline_glyph), render_context.stroker, 0 ); // don't destroy original |
1253 mp_msg(MSGT_GLOBAL, MSGL_WARN, "FT_Glyph_Stroke error %d \n", error); | 1257 if (error) { |
1254 FT_Glyph_Copy(info->glyph, &info->outline_glyph); | 1258 mp_msg(MSGT_GLOBAL, MSGL_WARN, "FT_Glyph_Stroke error %d \n", error); |
1259 } | |
1260 } else { | |
1261 info->outline_glyph = 0; | |
1255 } | 1262 } |
1256 | 1263 |
1257 info->bm = info->bm_o = 0; | 1264 info->bm = info->bm_o = 0; |
1258 | 1265 |
1259 return 0; | 1266 return 0; |
1817 | 1824 |
1818 info->pos.x += start.x >> 6; | 1825 info->pos.x += start.x >> 6; |
1819 info->pos.y -= start.y >> 6; | 1826 info->pos.y -= start.y >> 6; |
1820 | 1827 |
1821 // mp_msg(MSGT_GLOBAL, MSGL_DBG2, "shift: %d, %d\n", start.x / 64, start.y / 64); | 1828 // mp_msg(MSGT_GLOBAL, MSGL_DBG2, "shift: %d, %d\n", start.x / 64, start.y / 64); |
1822 if (info->glyph) { | 1829 if (info->glyph) |
1823 FT_Glyph_Transform( info->glyph, &matrix_rotate, 0 ); | 1830 FT_Glyph_Transform( info->glyph, &matrix_rotate, 0 ); |
1831 if (info->outline_glyph) | |
1824 FT_Glyph_Transform( info->outline_glyph, &matrix_rotate, 0 ); | 1832 FT_Glyph_Transform( info->outline_glyph, &matrix_rotate, 0 ); |
1825 } | |
1826 } | 1833 } |
1827 } | 1834 } |
1828 | 1835 |
1829 event_images->top = device_y - (text_info.lines[0].asc >> 6); | 1836 event_images->top = device_y - (text_info.lines[0].asc >> 6); |
1830 event_images->height = text_info.height >> 6; | 1837 event_images->height = text_info.height >> 6; |