// Additional support for UTF-8 by
// Paolo Rampino aka Akirad <info at tuttoainternet.it>
-
#include "asset.h"
#include "bccmodels.h"
#include "bcsignals.h"
#include "language.h"
#include "mwindow.inc"
#include "overlayframe.h"
+#include "plugin.h"
#include "renderengine.h"
#include "titler.h"
#include "titlerwindow.h"
#include <endian.h>
#include <byteswap.h>
#include <iconv.h>
-#include <wctype.h>
#include <sys/stat.h>
#include <fontconfig/fontconfig.h>
+#define FIXED_FONT "bitstream vera sans mono (bitstream)"
#define SMALL (1.0 / 64.0)
#define MAX_FLT 3.40282347e+38
TitleConfig::TitleConfig()
{
+ strcpy(font, "fixed");
+ strcpy(encoding, DEFAULT_ENCODING);
style = 0;
+ size = 24;
color = BLACK;
alpha = 0xff;
+ outline_size = 0.;
+ outline_color = WHITE;
outline_alpha = 0xff;
- size = 24;
+ color_stroke = 0xff0000;
+ stroke_width = 0.0;
motion_strategy = NO_MOTION;
- loop = 0;
line_pitch = 0;
+ loop = 0;
hjustification = JUSTIFY_CENTER;
vjustification = JUSTIFY_MID;
- fade_in = 0.0;
- fade_out = 0.0;
+ fade_in = 0.0; fade_out = 0.0;
+ pixels_per_second = 100.0;
+ wtext[0] = 0; wlen = 0;
title_x = title_y = 0.0;
title_w = title_h = 0;
- dropshadow = 2;
- strcpy(font, "fixed");
- strcpy(encoding, DEFAULT_ENCODING);
- timecode_format = DEFAULT_TIMECODEFORMAT;
- pixels_per_second = 1.0;
- timecode = 0;
- stroke_width = 1.0;
- wtext[0] = 0; wlen = 0;
- color_stroke = 0xff0000;
- outline_color = WHITE;
- background = 0;
- strcpy(background_path, "");
-
- outline_size = 0;
- window_w = 800;
+ window_w = 860;
window_h = 460;
next_keyframe_position = 0;
prev_keyframe_position = 0;
+ timecode = 0;
+ dropshadow = 2;
+ background = 0;
+ strcpy(background_path, "");
+ timecode_format = DEFAULT_TIMECODEFORMAT;
drag = 0;
loop_playback = 0;
}
int TitleConfig::equivalent(TitleConfig &that)
{
return !strcasecmp(font, that.font) &&
+ !strcasecmp(encoding, that.encoding) &&
style == that.style &&
size == that.size &&
color == that.color &&
- color_stroke == that.color_stroke &&
- stroke_width == that.stroke_width &&
- outline_color == that.outline_color &&
alpha == that.alpha &&
+ outline_size == that.outline_size &&
+ outline_color == that.outline_color &&
outline_alpha == that.outline_alpha &&
- EQUIV(pixels_per_second, that.pixels_per_second) &&
- motion_strategy == that.motion_strategy &&
- loop == that.loop &&
+ color_stroke == that.color_stroke &&
+ stroke_width == that.stroke_width &&
+// dont require redraw for these
+// motion_strategy == that.motion_strategy &&
line_pitch == that.line_pitch &&
+// loop == that.loop &&
hjustification == that.hjustification &&
vjustification == that.vjustification &&
- fade_in == that.fade_in && fade_out == that.fade_out &&
- title_x == that.title_x && title_y == that.title_y &&
+// fade_in == that.fade_in && fade_out == that.fade_out &&
+// EQUIV(pixels_per_second, that.pixels_per_second) &&
+ wlen == that.wlen &&
+ !memcmp(wtext, that.wtext, wlen * sizeof(wchar_t)) &&
+// title_x == that.title_x && title_y == that.title_y &&
title_w == that.title_w && title_h == that.title_h &&
- dropshadow == that.dropshadow &&
+// window_w == that.window_w && window_h == that.window_h &&
timecode == that.timecode &&
+ dropshadow == that.dropshadow &&
+ background == that.background &&
+ !strcmp(background_path, that.background_path) &&
timecode_format == that.timecode_format &&
- outline_size == that.outline_size &&
- !strcasecmp(encoding, that.encoding) &&
- wlen == that.wlen &&
- !memcmp(wtext, that.wtext, wlen * sizeof(wchar_t));
+// drag == that.drag &&
+ loop_playback == that.loop_playback;
}
void TitleConfig::copy_from(TitleConfig &that)
{
strcpy(font, that.font);
+ strcpy(encoding, that.encoding);
style = that.style;
size = that.size;
color = that.color;
- color_stroke = that.color_stroke;
- stroke_width = that.stroke_width;
- outline_color = that.outline_color;
alpha = that.alpha;
+ outline_size = that.outline_size;
+ outline_color = that.outline_color;
outline_alpha = that.outline_alpha;
- pixels_per_second = that.pixels_per_second;
+ color_stroke = that.color_stroke;
+ stroke_width = that.stroke_width;
motion_strategy = that.motion_strategy;
- loop = that.loop;
line_pitch = that.line_pitch;
+ loop = that.loop;
hjustification = that.hjustification;
vjustification = that.vjustification;
fade_in = that.fade_in;
fade_out = that.fade_out;
- title_x = that.title_x;
- title_y = that.title_y;
- title_w = that.title_w;
- title_h = that.title_h;
- dropshadow = that.dropshadow;
+ pixels_per_second = that.pixels_per_second;
+ wlen = that.wlen;
+ memcpy(wtext, that.wtext, that.wlen * sizeof(wchar_t));
+ title_x = that.title_x; title_y = that.title_y;
+ title_w = that.title_w; title_h = that.title_h;
+ window_w = that.window_w; window_h = that.window_h;
timecode = that.timecode;
+ dropshadow = that.dropshadow;
+ background = that.background;
+ strcpy(background_path, that.background_path);
timecode_format = that.timecode_format;
- outline_size = that.outline_size;
- strcpy(encoding, that.encoding);
- memcpy(wtext, that.wtext, that.wlen * sizeof(wchar_t));
- wlen = that.wlen;
- window_w = that.window_w;
- window_h = that.window_h;
+ drag = that.drag;
+ loop_playback = that.loop_playback;
}
void TitleConfig::interpolate(TitleConfig &prev, TitleConfig &next,
int64_t prev_frame, int64_t next_frame, int64_t current_frame)
{
+ double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
+ double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
strcpy(font, prev.font);
strcpy(encoding, prev.encoding);
style = prev.style;
size = prev.size;
color = prev.color;
- color_stroke = prev.color_stroke;
- stroke_width = prev.stroke_width;
- outline_color = prev.outline_color;
alpha = prev.alpha;
+ outline_size = prev.outline_size;
+ outline_color = prev.outline_color;
outline_alpha = prev.outline_alpha;
+ color_stroke = prev.color_stroke;
+ stroke_width = prev.stroke_width;
motion_strategy = prev.motion_strategy;
- loop = prev.loop;
line_pitch = prev.line_pitch;
+ loop = prev.loop;
hjustification = prev.hjustification;
vjustification = prev.vjustification;
fade_in = prev.fade_in;
fade_out = prev.fade_out;
- outline_size = prev.outline_size;
pixels_per_second = prev.pixels_per_second;
- memcpy(wtext, prev.wtext, prev.wlen * sizeof(wchar_t));
wlen = prev.wlen;
+ memcpy(wtext, prev.wtext, prev.wlen * sizeof(wchar_t));
wtext[wlen] = 0;
-
- double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
- double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
- this->title_x = prev.title_x * prev_scale + next.title_x * next_scale;
- this->title_y = prev.title_y * prev_scale + next.title_y * next_scale;
-// this->title_x = prev.title_x;
-// this->title_y = prev.title_y;
+ this->title_x = prev.title_x == next.title_x ? prev.title_x :
+ prev.title_x * prev_scale + next.title_x * next_scale;
+ this->title_y = prev.title_y == next.title_y ? prev.title_y :
+ prev.title_y * prev_scale + next.title_y * next_scale;
+ this->title_w = prev.title_w == next.title_w ? prev.title_w :
+ prev.title_w * prev_scale + next.title_w * next_scale;
+ this->title_h = prev.title_h == next.title_h ? prev.title_h :
+ prev.title_h * prev_scale + next.title_h * next_scale;
+ window_w = prev.window_w;
+ window_h = prev.window_h;
timecode = prev.timecode;
+ this->dropshadow = prev.dropshadow == next.dropshadow ? prev.dropshadow :
+ prev.dropshadow * prev_scale + next.dropshadow * next_scale;
+ background = prev.background;
+ strcpy(background_path, prev.background_path);
timecode_format = prev.timecode_format;
- this->dropshadow = prev.dropshadow * prev_scale + next.dropshadow * next_scale;
-// this->dropshadow = prev.dropshadow;
+ drag = prev.drag;
+ loop_playback = prev.loop_playback;
}
void TitleConfig::to_wtext(const char *from_enc, const char *text, int tlen)
{
GlyphPackage *pkg = (GlyphPackage*)package;
TitleGlyph *glyph = pkg->glyph;
+ BC_Resources *resources = BC_WindowBase::get_resources();
+ if( resources->font_debug )
+ printf("GlyphUnit load glyph (%s) %04x, '%c'\n", glyph->font->displayname,
+ (unsigned)glyph->char_code, (unsigned)glyph->char_code);
int result = 0;
char new_path[BCTEXTLEN];
if( plugin->load_freetype_face(freetype_library, freetype_face, glyph->font->path) ) {
glyph->font->path);
result = 1;
}
-
if( !result ) {
int gindex = FT_Get_Char_Index(freetype_face, glyph->char_code);
-
-//printf("GlyphUnit::process_package 1 %c\n", glyph->char_code);
-// Char not found
+ if( !gindex && !freetype_face->charmap && // if no default charmap
+ freetype_face->charmaps && freetype_face->charmaps[0] &&
+ !FT_Select_Charmap(freetype_face, freetype_face->charmaps[0]->encoding) ) {
+ gindex = FT_Get_Char_Index(freetype_face, glyph->char_code);
+ }
if( gindex == 0 ) {
- BC_Resources *resources = BC_WindowBase::get_resources();
+printf("GlyphUnit::process_package 1 glyph not found (%s) %04x, '%c'\n",
+ glyph->font->displayname, (unsigned)glyph->char_code, (unsigned)glyph->char_code);
// Search replacement font
if( resources->find_font_by_char(glyph->char_code, new_path, freetype_face) ) {
plugin->load_freetype_face(freetype_library,
delete outline_engine;
}
-const char* TitleMain::plugin_title() { return _("Title"); }
+const char* TitleMain::plugin_title() { return C_("Title"); }
int TitleMain::is_realtime() { return 1; }
int TitleMain::is_synthesis() { return 1; }
void TitleMain::build_previews(TitleWindow *gui)
{
- ArrayList<BC_FontEntry*>&fonts = *gui->get_resources()->fontlist;
+ BC_Resources *resources = BC_WindowBase::get_resources();
+ ArrayList<BC_FontEntry*>&fonts = *resources->fontlist;
for( int font_number=0; font_number<fonts.size(); ++font_number ) {
BC_FontEntry *font = fonts.get(font_number);
const char *test_string = "Aa";
char new_path[BCTEXTLEN];
int text_height = gui->get_text_height(LARGEFONT);
- int text_color = BC_WindowBase::get_resources()->default_text_color;
+ int max_height = 3*text_height/2, max_width = 2 * max_height;
+ int text_color = resources->default_text_color;
int r = (text_color >> 16) & 0xff;
int g = (text_color >> 8) & 0xff;
int b = text_color & 0xff;
int total_w = 0;
int total_h = 0;
for( int pass=0; pass<2; ++pass ) {
+ if( resources->font_debug )
+ printf("Titler: build previews pass %d\n",pass);
//printf("TitleMain::build_previews %d %d %d\n",
//__LINE__, text_height, total_h);
for( int font_number=0; font_number<fonts.size(); ++font_number ) {
for( int i=0; i<font_number; ++i ) {
if( !strcasecmp(fonts[i]->displayname, font->displayname) ) {
if( pass == 1 ) {
- font->image = fonts[i]->image;
+ font->image = new VFrame(*fonts[i]->image);
}
skip = 1;
break;
}
if( skip ) continue;
-
- int current_x = 0, current_w = 0, current_h = 0, current_ascent = 0;
- if( pass == 1 ) {
+ if( resources->font_debug )
+ printf("Titler: preview %s = %s\n",font->displayname, font->path);
+ if( pass > 0 ) {
font->image = new VFrame;
font->image->set_use_shm(0);
font->image->reallocate(0, -1, 0, 0, 0,
font->image->clear_frame();
}
+ int current_w = 1, current_h = 1;
+ int current_x = 0, current_ascent = 0;
int len = strlen(test_string);
+
for( int j=0; j<len; ++j ) {
FT_ULong c = test_string[j];
// memory leaks here are fatal
if( load_freetype_face(freetype_library, freetype_face, new_path)) continue;
FT_Set_Pixel_Sizes(freetype_face, text_height, 0);
if( FT_Load_Char(freetype_face, c, FT_LOAD_RENDER) ) continue;
+ int glyph_w = freetype_face->glyph->bitmap.width;
+ int glyph_h = freetype_face->glyph->bitmap.rows;
+ if( glyph_h > max_height ) glyph_h = max_height;
+ int glyph_a = freetype_face->glyph->advance.x >> 6;
+ int glyph_t = freetype_face->glyph->bitmap_top;
if( pass == 0 ) {
- current_w = current_x + freetype_face->glyph->bitmap.width;
- if( (int)freetype_face->glyph->bitmap_top > current_ascent )
- current_ascent = freetype_face->glyph->bitmap_top;
- if( (int)freetype_face->glyph->bitmap.rows > total_h )
- total_h = freetype_face->glyph->bitmap.rows;
- if( (int)freetype_face->glyph->bitmap.rows > current_h )
- current_h = freetype_face->glyph->bitmap.rows;
+ current_w = current_x + glyph_w;
+ if( current_w > max_width ) current_w = max_width;
+ if( total_w < current_w ) total_w = current_w;
+ if( current_ascent < glyph_t ) current_ascent = glyph_t;
+ if( current_h < glyph_h ) current_h = glyph_h;
+ if( total_h < glyph_h ) total_h = glyph_h;
}
else {
// copy 1 row at a time, center vertically
- int out_y = (total_h - height[font_number]) / 2 +
- ascent[font_number] - freetype_face->glyph->bitmap_top;
- for( int in_y = 0;
- in_y < (int)freetype_face->glyph->bitmap.rows && out_y < total_h;
- ++in_y, ++out_y ) {
- unsigned char *out_row = font->image->get_rows()[out_y] +
- current_x * 4;
+ int out_y = (total_h-height[font_number])/2 + ascent[font_number]-glyph_t;
+ if( out_y < 0 ) out_y = 0;
+ for( int in_y = 0; in_y < glyph_h && out_y < total_h; ++in_y, ++out_y ) {
unsigned char *in_row = freetype_face->glyph->bitmap.buffer +
freetype_face->glyph->bitmap.pitch * in_y;
+ int out_x = current_x;
+ unsigned char *out_row = font->image->get_rows()[out_y] +
+ out_x * 4;
- for( int out_x = 0;
- out_x < (int)freetype_face->glyph->bitmap.width && out_x < total_w;
- ++out_x ) {
+ for( int in_x = 0; in_x < glyph_w && out_x < total_w; ++in_x, ++out_x ) {
*out_row = (*in_row * r +
(0xff - *in_row) * *out_row) / 0xff; ++out_row;
*out_row = (*in_row * g +
in_row++;
}
}
- current_x += freetype_face->glyph->advance.x >> 6;
}
+ current_x += glyph_a;
}
-
height[font_number] = current_h;
ascent[font_number] = current_ascent;
- if( pass == 0 && current_w > total_w ) total_w = current_w;
}
}
int TitleMain::load_font(BC_FontEntry *font)
{
- if( load_freetype_face(freetype_library,freetype_face, font->path) ) return 1;
+ if( !font || load_freetype_face(freetype_library,freetype_face, font->path) ) return 1;
strcpy(text_font, font->displayname);
return 0;
}
delete bg_frame; bg_frame = 0;
}
if( !bg_frame )
- bg_frame = new VFrame(0, -1, bw, bh, output_model, -1);
+ bg_frame = new VFrame(bw, bh, output_model);
int64_t position = get_source_position() - get_source_start();
if( !read_background(bg_frame, position, output_model) ) {
if( !overlay_frame )
BC_FontEntry* TitleMain::get_font(const char *font_name, int style)
{
- int flavor =
+ if( !strcmp("fixed", font_name) )
+ font_name = FIXED_FONT;
+ int flavor = FL_WIDTH_MASK |
((style & BC_FONT_ITALIC) != 0 ? FL_SLANT_ITALIC | FL_SLANT_OBLIQUE : FL_SLANT_ROMAN) |
((style & BC_FONT_BOLD) != 0 ? FL_WEIGHT_BOLD | FL_WEIGHT_DEMIBOLD |
FL_WEIGHT_EXTRABOLD| FL_WEIGHT_BLACK | FL_WEIGHT_EXTRABLACK :
FL_WEIGHT_BOOK | FL_WEIGHT_NORMAL | FL_WEIGHT_MEDIUM |
FL_WEIGHT_LIGHT | FL_WEIGHT_EXTRALIGHT | FL_WEIGHT_THIN);
- int mask = FL_WEIGHT_MASK | FL_SLANT_MASK;
+ int mask = FL_WEIGHT_MASK | FL_SLANT_MASK | FL_WIDTH_MASK;
BC_Resources *resources = BC_WindowBase::get_resources();
- return resources->find_fontentry(font_name, flavor, mask, style);
+ BC_FontEntry *font = resources->find_fontentry(font_name, flavor, mask, style);
+ if( font && strcmp(font_name, font->displayname) ) font = 0;
+ return font;
}
BC_FontEntry* TitleMain::config_font()
{
BC_FontEntry *font = get_font(config.font, config.style);
- if( font && load_font(font) ) font = 0;
+ if( !font || load_font(font) )
+ load_font(font = get_font(FIXED_FONT,0));
return font;
}
-static inline bool is_ltr(wchar_t wch) { return (wch>='a' && wch<='z') || (wch>='A' && wch<='Z'); }
-static inline bool is_nbr(wchar_t wch) { return (wch>='0' && wch<='9'); }
+static inline bool is_ltr(wchar_t wch) { return iswalpha(wch); }
+static inline bool is_nbr(wchar_t wch) { return iswdigit(wch); }
static inline bool is_ws(wchar_t wch) { return wch==' ' || wch=='\t'; }
static inline bool is_idch(wchar_t wch) { return is_ltr(wch) || is_nbr(wch) || wch=='_'; }
// return eof=-1, chr=0, opener=1, closer=2
int TitleParser::wget(wchar_t &wch)
{
- char *ip = id, *tp = text; *ip = 0; *tp = 0;
- int ilen = sizeof(id), tlen = sizeof(text), ich;
+ wchar_t *wip = wid, *wtp = wtxt; *wip = 0; *wtp = 0;
+ int ilen = sizeof(wid)/sizeof(wid[0]);
+ int tlen = sizeof(wtxt)/sizeof(wtxt[0]);
+ int ich;
while( (ich=wnext()) >= 0 ) {
if( ich == '\\' ) {
if( (ich=wnext()) == '\n' ) continue;
int ret = 1; long pos = tell();
if( (ich=wnext()) == '/' ) { ret = 2; ich = wnext(); }
if( is_ltr(ich) ) {
- *ip++ = ich;
+ *wip++ = ich;
while( is_idch(ich=wnext()) )
- if( --ilen > 0 ) *ip++ = ich;
+ if( --ilen > 0 ) *wip++ = ich;
}
- *ip = 0;
+ *wip = 0;
while( is_ws(ich) ) ich = wnext();
while( ich >= 0 && ich != '>' ) {
if( ich == '\n' || ich == '<' ) { ich = -1; break; }
if( ich == '\\' && (ich=wnext()) < 0 ) break;
- if( --tlen > 0 ) *tp++ = ich;
+ if( --tlen > 0 ) *wtp++ = ich;
ich = wnext();
}
- *tp = 0;
+ *wtp = 0;
if( ich < 0 ) { ich = '<'; seek(pos); ret = 0; }
wch = ich;
return ret;
}
+int TitleParser::tget(wchar_t &wch)
+{
+ int ret = wget(wch);
+ if( ret > 0 ) {
+ int wid_len = wcslen(wid)+1;
+ BC_Resources::encode(
+ BC_Resources::wide_encoding, plugin->config.encoding,
+ (char*)wid,wid_len*sizeof(wid[0]), (char *)id,sizeof(id));
+ int wtxt_len = wcslen(wtxt)+1;
+ BC_Resources::encode(
+ BC_Resources::wide_encoding, plugin->config.encoding,
+ (char*)wtxt,wtxt_len*sizeof(wtxt[0]), (char *)text,sizeof(text));
+ }
+ return ret;
+}
TitleGlyph *TitleMain::get_glyph(FT_ULong char_code, BC_FontEntry *font, int size, int style)
{
int result = cur->advance_x;
if( !nxt ) return result;
FT_Vector kerning;
- FT_Get_Kerning(freetype_face,
- cur->freetype_index, nxt->freetype_index,
- ft_kerning_default, &kerning);
- return result + (kerning.x >> 6);
+ if( !FT_Get_Kerning(freetype_face,
+ cur->freetype_index, nxt->freetype_index,
+ ft_kerning_default, &kerning) )
+ result += (kerning.x >> 6);
+ return result;
}
VFrame *vframe = get_image(path);
if( !vframe && (vframe=VFramePng::vframe_png(path)) != 0 ) {
if( vframe->get_color_model() != text_model ) {
- VFrame *frame = new VFrame(vframe->get_w(), vframe->get_h(), text_model);
+ VFrame *frame = new VFrame(vframe->get_w(), vframe->get_h(),
+ text_model, 0);
frame->transfer_from(vframe); delete vframe;
vframe = frame;
}
int TitleParser::set_attributes(int ret)
{
- if( !strcmp(id,_("nudge")) ) return ret>1 ? cur_nudge.unset(text) : cur_nudge.set(text);
- if( !strcmp(id,_("color")) ) return ret>1 ? cur_color.unset(text) : cur_color.set(text);
- if( !strcmp(id,_("alpha")) ) return ret>1 ? cur_alpha.unset(text) : cur_alpha.set(text);
- if( !strcmp(id,_("font")) ) return ret>1 ? cur_font.unset(text) : cur_font.set(text);
- if( !strcmp(id,_("size")) ) return ret>1 ? cur_size.unset(text) : cur_size.set(text);
- if( !strcmp(id,_("bold")) ) return ret>1 ? cur_bold.unset(text) : cur_bold.set(text);
- if( !strcmp(id,_("italic")) ) return ret>1 ? cur_italic.unset(text) : cur_italic.set(text);
- if( !strcmp(id,_("caps")) ) return ret>1 ? cur_caps.unset(text) : cur_caps.set(text);
- if( !strcmp(id,_("ul")) ) return ret>1 ? cur_under.unset(text) : cur_under.set(text);
- if( !strcmp(id,_("blink")) ) return ret>1 ? cur_blink.unset(text) : cur_blink.set(text);
- if( !strcmp(id,_("fixed")) ) return ret>1 ? cur_fixed.unset(text) : cur_fixed.set(text);
- if( !strcmp(id,_("sup")) ) return ret>1 ? cur_super.unset(text) : cur_super.set(text);
+ if( !strcmp(id,KW_NUDGE) ) return ret>1 ? cur_nudge.unset(text) : cur_nudge.set(text);
+ if( !strcmp(id,KW_COLOR) ) return ret>1 ? cur_color.unset(text) : cur_color.set(text);
+ if( !strcmp(id,KW_ALPHA) ) return ret>1 ? cur_alpha.unset(text) : cur_alpha.set(text);
+ if( !strcmp(id,KW_FONT) ) return ret>1 ? cur_font.unset(text) : cur_font.set(text);
+ if( !strcmp(id,KW_SIZE) ) return ret>1 ? cur_size.unset(text) : cur_size.set(text);
+ if( !strcmp(id,KW_BOLD) ) return ret>1 ? cur_bold.unset(text) : cur_bold.set(text);
+ if( !strcmp(id,KW_ITALIC) ) return ret>1 ? cur_italic.unset(text) : cur_italic.set(text);
+ if( !strcmp(id,KW_CAPS) ) return ret>1 ? cur_caps.unset(text) : cur_caps.set(text);
+ if( !strcmp(id,KW_UL) ) return ret>1 ? cur_under.unset(text) : cur_under.set(text);
+ if( !strcmp(id,KW_BLINK) ) return ret>1 ? cur_blink.unset(text) : cur_blink.set(text);
+ if( !strcmp(id,KW_FIXED) ) return ret>1 ? cur_fixed.unset(text) : cur_fixed.set(text);
+ if( !strcmp(id,KW_SUP) ) return ret>1 ? cur_super.unset(text) : cur_super.set(text);
return 1;
}
while( !wchrs.eof() ) {
wchar_t wch1 = wchrs.wcur(), wch;
long ipos = wchrs.tell();
- int ret = wchrs.wget(wch);
+ int ret = wchrs.tget(wch);
if( ret > 0 ) {
if( !wchrs.set_attributes(ret) ) continue;
- if( !strcmp(wchrs.id,"png") && add_image(wchrs.text) ) continue;
+ if( !strcmp(wchrs.id,KW_PNG) && add_image(wchrs.text) ) continue;
wch = wch1; wchrs.seek(ipos+1);
ret = 0;
}
- if( !ret ) {
- int cur_caps = wchrs.cur_caps;
- if( cur_caps > 0 ) wch = towupper(wch);
- else if( cur_caps < 0 ) wch = towlower(wch);
- BC_FontEntry *cur_font = wchrs.cur_font;
- int cur_size = wchrs.cur_size;
- int cur_style = 0;
- int cur_bold = wchrs.cur_bold;
- if( cur_bold ) cur_style |= BC_FONT_BOLD;
- int cur_italic = wchrs.cur_italic;
- if( cur_italic ) cur_style |= BC_FONT_ITALIC;
- int cur_super = wchrs.cur_super;
- if( cur_super ) cur_size /= 2;
- int exists = 0;
- for( int j=0; j<title_glyphs.count(); ++j ) {
- TitleGlyph *glyph = title_glyphs[j];
- if( glyph->char_code == (FT_ULong)wch && glyph->font == cur_font &&
- glyph->size == cur_size && glyph->style == cur_style ) {
- exists = 1; break;
- }
- }
+ if( ret || wch == '\n' ) continue;
- if( !exists ) {
- total_packages++;
- TitleGlyph *glyph = new TitleGlyph;
- glyph->char_code = (FT_ULong)wch;
- glyph->font = cur_font;
- glyph->size = cur_size;
- glyph->style = cur_style;
- title_glyphs.append(glyph);
+ int cur_caps = wchrs.cur_caps;
+ if( cur_caps > 0 ) wch = towupper(wch);
+ else if( cur_caps < 0 ) wch = towlower(wch);
+ BC_FontEntry *cur_font = wchrs.cur_font;
+ int cur_size = wchrs.cur_size;
+ int cur_style = 0;
+ int cur_bold = wchrs.cur_bold;
+ if( cur_bold ) cur_style |= BC_FONT_BOLD;
+ int cur_italic = wchrs.cur_italic;
+ if( cur_italic ) cur_style |= BC_FONT_ITALIC;
+ int cur_super = wchrs.cur_super;
+ if( cur_super ) cur_size /= 2;
+ int exists = 0;
+ for( int j=0; j<title_glyphs.count(); ++j ) {
+ TitleGlyph *glyph = title_glyphs[j];
+ if( glyph->char_code == (FT_ULong)wch && glyph->font == cur_font &&
+ glyph->size == cur_size && glyph->style == cur_style ) {
+ exists = 1; break;
}
}
+
+ if( !exists && cur_font ) {
+ total_packages++;
+ TitleGlyph *glyph = new TitleGlyph;
+ glyph->char_code = (FT_ULong)wch;
+ glyph->font = cur_font;
+ glyph->size = cur_size;
+ glyph->style = cur_style;
+ title_glyphs.append(glyph);
+ }
}
if( !glyph_engine )
TitleChar *chr = 0;
long ipos = wchrs.tell();
wchar_t wch1 = wchrs.wcur(), wch;
- int ret = wchrs.wget(wch);
+ int ret = wchrs.tget(wch);
if( ret < 0 || wch == '\n' ) {
if( row->x1 > row->x2 ) row->x1 = row->x2 = 0;
if( row->y2 > row->y1 ) row->y1 = row->y2 = 0;
if( ret > 0 ) {
if( !wchrs.set_attributes(ret) ) continue;
ret = -1;
- if( !strcmp(wchrs.id,"png") ) {
+ if( !strcmp(wchrs.id,KW_PNG) ) {
VFrame *png_image = get_image(wchrs.text);
if( png_image ) {
chr = title_chars.add(CHAR_IMAGE, png_image);
case RIGHT_TO_LEFT:
case LEFT_TO_RIGHT: {
float magnitude = config.pixels_per_second *
- (get_source_position() - config.prev_keyframe_position) /
+ (get_source_position() - get_source_start()) /
PluginVClient::project_frame_rate;
if( config.loop ) {
int loop_size = text_w + title_w;
void TitleMain::draw_overlay()
{
-
//printf("TitleMain::draw_overlay 1\n");
fade = 1;
if( !EQUIV(config.fade_in, 0) ) {
- int fade_len = lroundf(config.fade_in * PluginVClient::project_frame_rate);
- int fade_position = get_source_position() - config.prev_keyframe_position;
+ int64_t plugin_start = server->plugin->startproject;
+ int64_t fade_len = lroundf(config.fade_in * PluginVClient::project_frame_rate);
+ int64_t fade_position = get_source_position() - plugin_start;
if( fade_position >= 0 && fade_position < fade_len ) {
fade = (float)fade_position / fade_len;
}
}
if( !EQUIV(config.fade_out, 0) ) {
- int fade_len = lroundf(config.fade_out * PluginVClient::project_frame_rate);
- int fade_position = config.next_keyframe_position - get_source_position();
-
+ int64_t plugin_end = server->plugin->startproject + server->plugin->length;
+ int64_t fade_len = lroundf(config.fade_out * PluginVClient::project_frame_rate);
+ int64_t fade_position = plugin_end - get_source_position();
if( fade_position >= 0 && fade_position < fade_len ) {
fade = (float)fade_position / fade_len;
if( !translate )
translate = new TitleTranslate(this, cpus);
- if( text_x+mask_w > 0 && text_x < title_w ) {
+ int tx = text_x - text_x1 + mask_x1;
+ if( tx < title_w && tx+mask_w > 0 ) {
translate->xlat_mask = text_mask;
translate->run_packages();
if( config.stroke_width >= SMALL && (config.style & BC_FONT_OUTLINE) ) {
output.tag.set_property("LOOP_PLAYBACK", config.loop_playback);
output.append_tag();
output.append_newline();
- char text[BCTEXTLEN];
+ char text[2*sizeof(config.wtext)];
int text_len = BC_Resources::encode(
BC_Resources::wide_encoding, DEFAULT_ENCODING,
(char*)config.wtext, config.wlen*sizeof(wchar_t),
text, sizeof(text));
+ int len = output.length(), avail = MESSAGESIZE-16 - len;
+ if( text_len >= avail ) { // back off last utf8 char
+ text_len = avail;
+ while( text_len > 0 && (text[text_len-1] & 0xc0) == 0x80 )
+ text[--text_len] = 0;
+ if( text_len > 0 )
+ text[--text_len] = 0;
+ }
output.append_text(text, text_len);
output.tag.set_title("/TITLE");
output.append_tag();
}
}
-void TitleMain::insert_text(const char *txt, int pos)
+void TitleMain::insert_text(const wchar_t *wtxt, int pos)
{
- int ilen = strlen(txt);
+ int len = wcslen(wtxt);
wchar_t *wtext = config.wtext;
int wsize = sizeof(config.wtext)-1;
int wlen = config.wlen;
if( pos < 0 ) pos = 0;
if( pos > wlen ) pos = wlen;
- for( int i=wlen-1, j=wlen+ilen-1; i>=pos; --i,--j ) {
+ for( int i=wlen-1, j=wlen+len-1; i>=pos; --i,--j ) {
if( j >= wsize ) continue;
wtext[j] = wtext[i];
}
- for( int i=pos, j=0; j<ilen; ++i,++j ) {
+ for( int i=pos, j=0; j<len; ++i,++j ) {
if( i >= wsize ) break;
- wtext[i] = txt[j];
+ wtext[i] = wtxt[j];
}
- if( (wlen+=ilen) > wsize ) wlen = wsize;
+ if( (wlen+=len) > wsize ) wlen = wsize;
wtext[wlen] = 0;
config.wlen = wlen;
}