ass_render.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,195 行 · 第 1/5 页

C
2,195
字号
	*tail = 0;	return head;}/** * \brief Mapping between script and screen coordinates */static int x2scr(int x) {	return x*frame_context.orig_width / frame_context.track->PlayResX + global_settings->left_margin;}/** * \brief Mapping between script and screen coordinates */static int y2scr(int y) {	return y * frame_context.orig_height / frame_context.track->PlayResY + global_settings->top_margin;}// the same for toptitlesstatic int y2scr_top(int y) {	if (global_settings->use_margins)		return y * frame_context.orig_height / frame_context.track->PlayResY;	else		return y * frame_context.orig_height / frame_context.track->PlayResY + global_settings->top_margin;}// the same for subtitlesstatic int y2scr_sub(int y) {	if (global_settings->use_margins)		return y * frame_context.orig_height / frame_context.track->PlayResY +		       global_settings->top_margin + global_settings->bottom_margin;	else		return y * frame_context.orig_height / frame_context.track->PlayResY + global_settings->top_margin;}static void compute_string_bbox( text_info_t* info, FT_BBox *abbox ) {	FT_BBox bbox;	int i;		if (text_info.length > 0) {		bbox.xMin = 32000;		bbox.xMax = -32000;		bbox.yMin = - d6_to_int(text_info.lines[0].asc) + text_info.glyphs[0].pos.y;		bbox.yMax = d6_to_int(text_info.height - text_info.lines[0].asc) + text_info.glyphs[0].pos.y;		for (i = 0; i < text_info.length; ++i) {			int s = text_info.glyphs[i].pos.x;			int e = s + d6_to_int(text_info.glyphs[i].advance.x);			bbox.xMin = FFMIN(bbox.xMin, s);			bbox.xMax = FFMAX(bbox.xMax, e);		}	} else		bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0;	/* return string bbox */	*abbox = bbox;}/** * \brief Check if starting part of (*p) matches sample. If true, shift p to the first symbol after the matching part. */static inline int mystrcmp(char** p, const char* sample) {	int len = strlen(sample);	if (strncmp(*p, sample, len) == 0) {		(*p) += len;		return 1;	} else		return 0;}static void change_font_size(double sz){	double size = sz * frame_context.font_scale;	if (size < 1)		size = 1;	else if (size > frame_context.height * 2)		size = frame_context.height * 2;	ass_font_set_size(render_context.font, size);	render_context.font_size = sz;}/** * \brief Change current font, using setting from render_context. */static void update_font(void){	unsigned val;	ass_renderer_t* priv = frame_context.ass_priv;	ass_font_desc_t desc;	desc.family = strdup(render_context.family);	val = render_context.bold;	// 0 = normal, 1 = bold, >1 = exact weight	if (val == 0) val = 80; // normal	else if (val == 1) val = 200; // bold	desc.bold = val;	val = render_context.italic;	if (val == 0) val = 0; // normal	else if (val == 1) val = 110; //italic	desc.italic = val;	render_context.font = ass_font_new(priv->library, priv->ftlibrary, priv->fontconfig_priv, &desc);	free(desc.family);		if (render_context.font)		change_font_size(render_context.font_size);}/** * \brief Change border width * negative value resets border to style value */static void change_border(double border){	int b;	if (!render_context.font) return;	if (border < 0) {		if (render_context.style->BorderStyle == 1) {			if (render_context.style->Outline == 0 && render_context.style->Shadow > 0)				border = 1.;			else				border = render_context.style->Outline;		} else			border = 1.;	}	render_context.border = border;	b = 64 * border * frame_context.border_scale;	if (b > 0) {		if (!render_context.stroker) {			int error;#if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1))			error = FT_Stroker_New( ass_renderer->ftlibrary, &render_context.stroker );#else // < 2.2			error = FT_Stroker_New( render_context.font->faces[0]->memory, &render_context.stroker );#endif			if (error) {				mp_msg(MSGT_ASS, MSGL_V, "failed to get stroker\n");				render_context.stroker = 0;			}		}		if (render_context.stroker)			FT_Stroker_Set( render_context.stroker, b,					FT_STROKER_LINECAP_ROUND,					FT_STROKER_LINEJOIN_ROUND,					0 );	} else {		FT_Stroker_Done(render_context.stroker);		render_context.stroker = 0;	}}#define _r(c)  ((c)>>24)#define _g(c)  (((c)>>16)&0xFF)#define _b(c)  (((c)>>8)&0xFF)#define _a(c)  ((c)&0xFF)/** * \brief Calculate a weighted average of two colors * calculates c1*(1-a) + c2*a, but separately for each component except alpha */static void change_color(uint32_t* var, uint32_t new, double pwr){	(*var)= ((uint32_t)(_r(*var) * (1 - pwr) + _r(new) * pwr) << 24) +		((uint32_t)(_g(*var) * (1 - pwr) + _g(new) * pwr) << 16) +		((uint32_t)(_b(*var) * (1 - pwr) + _b(new) * pwr) << 8) +		_a(*var);}// like change_color, but for alpha component onlystatic void change_alpha(uint32_t* var, uint32_t new, double pwr){	*var = (_r(*var) << 24) + (_g(*var) << 16) + (_b(*var) << 8) + (_a(*var) * (1 - pwr) + _a(new) * pwr);}/** * \brief Multiply two alpha values * \param a first value * \param b second value * \return result of multiplication * Parameters and result are limited by 0xFF. */static uint32_t mult_alpha(uint32_t a, uint32_t b){	return 0xFF - (0xFF - a) * (0xFF - b) / 0xFF;}/** * \brief Calculate alpha value by piecewise linear function * Used for \fad, \fade implementation. */static unsigned interpolate_alpha(long long now, 		long long t1, long long t2, long long t3, long long t4,		unsigned a1, unsigned a2, unsigned a3){	unsigned a;	double cf;	if (now <= t1) {		a = a1;	} else if (now >= t4) {		a = a3;	} else if (now < t2) { // and > t1		cf = ((double)(now - t1)) / (t2 - t1);		a = a1 * (1 - cf) + a2 * cf;	} else if (now > t3) {		cf = ((double)(now - t3)) / (t4 - t3);		a = a2 * (1 - cf) + a3 * cf;	} else { // t2 <= now <= t3		a = a2;	}	return a;}static void reset_render_context(void);/** * \brief Parse style override tag. * \param p string to parse * \param pwr multiplier for some tag effects (comes from \t tags) */static char* parse_tag(char* p, double pwr) {#define skip_all(x) if (*p == (x)) ++p; else { \	while ((*p != (x)) && (*p != '}') && (*p != 0)) {++p;} }#define skip(x) if (*p == (x)) ++p; else { return p; }		skip_all('\\');	if ((*p == '}') || (*p == 0))		return p;	if (mystrcmp(&p, "fsc")) {		char tp = *p++;		double val;		if (tp == 'x') {			if (mystrtod(&p, &val)) {				val /= 100;				render_context.scale_x = render_context.scale_x * ( 1 - pwr) + val * pwr;			} else				render_context.scale_x = render_context.style->ScaleX;		} else if (tp == 'y') {			if (mystrtod(&p, &val)) {				val /= 100;				render_context.scale_y = render_context.scale_y * ( 1 - pwr) + val * pwr;			} else				render_context.scale_y = render_context.style->ScaleY;		}	} else if (mystrcmp(&p, "fsp")) {		double val;		if (mystrtod(&p, &val))			render_context.hspacing = render_context.hspacing * ( 1 - pwr ) + val * pwr;		else			render_context.hspacing = render_context.style->Spacing;	} else if (mystrcmp(&p, "fs")) {		double val;		if (mystrtod(&p, &val))			val = render_context.font_size * ( 1 - pwr ) + val * pwr;		else			val = render_context.style->FontSize;		if (render_context.font)			change_font_size(val);	} else if (mystrcmp(&p, "bord")) {		double val;		if (mystrtod(&p, &val))			val = render_context.border * ( 1 - pwr ) + val * pwr;		else			val = -1.; // reset to default		change_border(val);	} else if (mystrcmp(&p, "move")) {		int x1, x2, y1, y2;		long long t1, t2, delta_t, t;		int x, y;		double k;		skip('(');		x1 = strtol(p, &p, 10);		skip(',');		y1 = strtol(p, &p, 10);		skip(',');		x2 = strtol(p, &p, 10);		skip(',');		y2 = strtol(p, &p, 10);		if (*p == ',') {			skip(',');			t1 = strtoll(p, &p, 10);			skip(',');			t2 = strtoll(p, &p, 10);			mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%d, %d) -> (%d, %d), (%" PRId64 " .. %" PRId64 ")\n", 				x1, y1, x2, y2, (int64_t)t1, (int64_t)t2);		} else {			t1 = 0;			t2 = render_context.event->Duration;			mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%d, %d) -> (%d, %d)\n", x1, y1, x2, y2);		}		skip(')');		delta_t = t2 - t1;		t = frame_context.time - render_context.event->Start;		if (t < t1)			k = 0.;		else if (t > t2)			k = 1.;		else k = ((double)(t - t1)) / delta_t;		x = k * (x2 - x1) + x1;		y = k * (y2 - y1) + y1;		render_context.pos_x = x;		render_context.pos_y = y;		render_context.detect_collisions = 0;		render_context.evt_type = EVENT_POSITIONED;	} else if (mystrcmp(&p, "frx")) {		double val;		if (mystrtod(&p, &val)) {			val *= M_PI / 180;			render_context.frx = val * pwr + render_context.frx * (1-pwr);		} else			render_context.frx = 0.;	} else if (mystrcmp(&p, "fry")) {		double val;		if (mystrtod(&p, &val)) {			val *= M_PI / 180;			render_context.fry = val * pwr + render_context.fry * (1-pwr);		} else			render_context.fry = 0.;	} else if (mystrcmp(&p, "frz") || mystrcmp(&p, "fr")) {		double val;		if (mystrtod(&p, &val)) {			val *= M_PI / 180;			render_context.frz = val * pwr + render_context.frz * (1-pwr);		} else			render_context.frz = M_PI * render_context.style->Angle / 180.;	} else if (mystrcmp(&p, "fn")) {		char* start = p;		char* family;		skip_all('\\');		if (p > start) {			family = malloc(p - start + 1);			strncpy(family, start, p - start);			family[p - start] = '\0';		} else			family = strdup(render_context.style->FontName);		if (render_context.family)			free(render_context.family);		render_context.family = family;		update_font();	} else if (mystrcmp(&p, "alpha")) {		uint32_t val;		int i;		if (strtocolor(&p, &val)) {			unsigned char a = val >> 24;			for (i = 0; i < 4; ++i)				change_alpha(&render_context.c[i], a, pwr);		} else {			change_alpha(&render_context.c[0], render_context.style->PrimaryColour, pwr);			change_alpha(&render_context.c[1], render_context.style->SecondaryColour, pwr);			change_alpha(&render_context.c[2], render_context.style->OutlineColour, pwr);			change_alpha(&render_context.c[3], render_context.style->BackColour, pwr);		}		// FIXME: simplify	} else if (mystrcmp(&p, "an")) {		int val;		if (mystrtoi(&p, 10, &val) && val) {			int v = (val - 1) / 3; // 0, 1 or 2 for vertical alignment			mp_msg(MSGT_ASS, MSGL_DBG2, "an %d\n", val);			if (v != 0) v = 3 - v;			val = ((val - 1) % 3) + 1; // horizontal alignment			val += v*4;			mp_msg(MSGT_ASS, MSGL_DBG2, "align %d\n", val);			render_context.alignment = val;		} else			render_context.alignment = render_context.style->Alignment;	} else if (mystrcmp(&p, "a")) {		int val;		if (mystrtoi(&p, 10, &val) && val)			render_context.alignment = val;		else			render_context.alignment = render_context.style->Alignment;	} else if (mystrcmp(&p, "pos")) {		int v1, v2;		skip('(');		v1 = strtol(p, &p, 10);		skip(',');		v2 = strtol(p, &p, 10);		skip(')');		mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%d, %d)\n", v1, v2);		render_context.evt_type = EVENT_POSITIONED;		render_context.detect_collisions = 0;		render_context.pos_x = v1;		render_context.pos_y = v2;	} else if (mystrcmp(&p, "fad")) {		int a1, a2, a3;		long long t1, t2, t3, t4;		if (*p == 'e') ++p; // either \fad or \fade		skip('(');		a1 = strtol(p, &p, 10);		skip(',');		a2 = strtol(p, &p, 10);		if (*p == ')') {			// 2-argument version (\fad, according to specs)			// a1 and a2 are fade-in and fade-out durations			t1 = 0;			t4 = render_context.event->Duration;			t2 = a1;			t3 = t4 - a2;			a1 = 0xFF;			a2 = 0;			a3 = 0xFF;		} else {			// 6-argument version (\fade)			// a1 and a2 (and a3) are opacity values			skip(',');			a3 = strtol(p, &p, 10);			skip(',');			t1 = strtoll(p, &p, 10);			skip(',');			t2 = strtoll(p, &p, 10);			skip(',');			t3 = strtoll(p, &p, 10);			skip(',');			t4 = strtoll(p, &p, 10);		}		skip(')');		render_context.fade = interpolate_alpha(frame_context.time - render_context.event->Start, t1, t2, t3, t4, a1, a2, a3);	} else if (mystrcmp(&p, "org")) {		int v1, v2;		skip('(');		v1 = strtol(p, &p, 10);		skip(',');		v2 = strtol(p, &p, 10);		skip(')');		mp_msg(MSGT_ASS, MSGL_DBG2, "org(%d, %d)\n", v1, v2);		//				render_context.evt_type = EVENT_POSITIONED;		render_context.org_x = v1;		render_context.org_y = v2;		render_context.have_origin = 1;	} else if (mystrcmp(&p, "t")) {		double v[3];		int v1, v2;		double v3;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?