changeset 28436:12e936031c36

Allow \be with arguments other than 0 or 1. Implement \blur. Patch by Grigori G, greg at chown ath cx.
author eugeni
date Sat, 07 Feb 2009 01:13:02 +0000
parents a54e0ead7e1e
children 523cf5e9afcb
files libass/ass_bitmap.c libass/ass_bitmap.h libass/ass_cache.h libass/ass_render.c
diffstat 4 files changed, 63 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/libass/ass_bitmap.c	Thu Feb 05 19:45:13 2009 +0000
+++ b/libass/ass_bitmap.c	Sat Feb 07 01:13:02 2009 +0000
@@ -39,11 +39,12 @@
 
 	unsigned *g;
 	unsigned *gt2;
+
+	double radius;
 };
 
 static const unsigned int maxcolor = 255;
 static const unsigned base = 256;
-static const double blur_radius = 1.5;
 
 static int generate_tables(ass_synth_priv_t* priv, double radius)
 {
@@ -52,6 +53,11 @@
 	double volume_diff, volume_factor = 0;
 	unsigned volume;
 
+	if (priv->radius == radius)
+		return 0;
+	else
+		priv->radius = radius;
+
 	priv->g_r = ceil(radius);
 	priv->g_w = 2*priv->g_r+1;
 
@@ -106,10 +112,10 @@
 	priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short));
 }
 
-ass_synth_priv_t* ass_synth_init(void)
+ass_synth_priv_t* ass_synth_init(double radius)
 {
 	ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t));
-	generate_tables(priv, blur_radius);
+	generate_tables(priv, radius);
 	return priv;
 }
 
@@ -248,10 +254,12 @@
 	return bm_s;
 }
 
-int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph,
-		bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be)
+int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur,
+		FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g,
+		bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius)
 {
-	const int bord = be ? ceil(blur_radius) : 0;
+	int bord = be ? (be+1) : 0;
+	bord = (blur_radius > 0.0) ? blur_radius : bord;
 
 	assert(bm_g && bm_o && bm_s);
 
@@ -269,17 +277,29 @@
 			return 1;
 		}
 	}
-	if (*bm_o)
+	if (*bm_o) {
 		resize_tmp(priv, (*bm_o)->w, (*bm_o)->h);
+		resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h);
+	}
 	resize_tmp(priv, (*bm_g)->w, (*bm_g)->h);
+	resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h);
 	
 	if (be) {
-		if (*bm_o)
-			blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
-		else
-			blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+		while (be--) {
+			if (*bm_o)
+				blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+			else
+				blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+		}
+	} else {
+		if (blur_radius > 0.0) {
+			generate_tables(priv_blur, blur_radius);
+			if (*bm_o)
+				blur((*bm_o)->buffer, priv_blur->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv_blur->gt2, priv_blur->g_r, priv_blur->g_w);
+			else
+				blur((*bm_g)->buffer, priv_blur->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv_blur->gt2, priv_blur->g_r, priv_blur->g_w);
+		}
 	}
-
 	if (*bm_o)
 		*bm_s = fix_outline_and_shadow(*bm_g, *bm_o);
 	else
--- a/libass/ass_bitmap.h	Thu Feb 05 19:45:13 2009 +0000
+++ b/libass/ass_bitmap.h	Sat Feb 07 01:13:02 2009 +0000
@@ -28,7 +28,7 @@
 
 typedef struct ass_synth_priv_s ass_synth_priv_t;
 
-ass_synth_priv_t* ass_synth_init(void);
+ass_synth_priv_t* ass_synth_init(double);
 void ass_synth_done(ass_synth_priv_t* priv);
 
 typedef struct bitmap_s {
@@ -46,7 +46,7 @@
  * \param bm_g out: pointer to the bitmap of glyph shadow is returned here
  * \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
  */
-int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be);
+int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius);
 
 void ass_free_bitmap(bitmap_t* bm);
 
--- a/libass/ass_cache.h	Thu Feb 05 19:45:13 2009 +0000
+++ b/libass/ass_cache.h	Sat Feb 07 01:13:02 2009 +0000
@@ -42,6 +42,7 @@
 	unsigned outline; // border width, 16.16 fixed point value
 	int bold, italic;
 	char be; // blur edges
+	double blur; // gaussian blur
 
 	unsigned scale_x, scale_y; // 16.16
 	int frx, fry, frz; // signed 16.16
--- a/libass/ass_render.c	Thu Feb 05 19:45:13 2009 +0000
+++ b/libass/ass_render.c	Sat Feb 07 01:13:02 2009 +0000
@@ -43,6 +43,8 @@
 
 #define MAX_GLYPHS 3000
 #define MAX_LINES 300
+#define BE_RADIUS 1.5
+#define BLUR_MAX_RADIUS 50.0
 
 static int last_render_id = 0;
 
@@ -80,6 +82,7 @@
 	ass_settings_t settings;
 	int render_id;
 	ass_synth_priv_t* synth_priv;
+	ass_synth_priv_t* synth_priv_blur;
 
 	ass_image_t* images_root; // rendering result is stored here
 	ass_image_t* prev_images_root;
@@ -112,6 +115,7 @@
 	int asc, desc; // font max ascender and descender
 //	int height;
 	int be; // blur edges
+	double blur; // gaussian blur
 	int shadow;
 	double frx, fry, frz; // rotation
 	
@@ -160,6 +164,7 @@
 	char detect_collisions;
 	uint32_t fade; // alpha from \fad
 	char be; // blur edges
+	double blur; // gaussian blur
 	int shadow;
 	int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags
 
@@ -258,7 +263,8 @@
 		goto ass_init_exit;
 	}
 
-	priv->synth_priv = ass_synth_init();
+	priv->synth_priv = ass_synth_init(BE_RADIUS);
+	priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS);
 
 	priv->library = library;
 	priv->ftlibrary = ft;
@@ -688,7 +694,16 @@
 	if ((*p == '}') || (*p == 0))
 		return p;
 
-	if (mystrcmp(&p, "fsc")) {
+	if (mystrcmp(&p, "blur")) {
+		double val;
+		if (mystrtod(&p, &val)) {
+			val = (val < 0) ? 0 : val;
+			val = (val > BLUR_MAX_RADIUS) ? BLUR_MAX_RADIUS : val;
+			render_context.blur = val;
+		} else
+			render_context.blur = 0.0;
+	// ASS standard tags
+	} else if (mystrcmp(&p, "fsc")) {
 		char tp = *p++;
 		double val;
 		if (tp == 'x') {
@@ -985,9 +1000,12 @@
 		reset_render_context();
 	} else if (mystrcmp(&p, "be")) {
 		int val;
-		if (mystrtoi(&p, 10, &val))
-			render_context.be = val ? 1 : 0;
-		else
+		if (mystrtoi(&p, 10, &val)) {
+			// Clamp to 10, since high values need excessive CPU
+			val = (val < 0) ? 0 : val;
+			val = (val > 10) ? 10 : val;
+			render_context.be = val;
+		} else
 			render_context.be = 0;
 	} else if (mystrcmp(&p, "b")) {
 		int b;
@@ -1181,6 +1199,7 @@
 	render_context.scale_y = render_context.style->ScaleY;
 	render_context.hspacing = render_context.style->Spacing;
 	render_context.be = 0;
+	render_context.blur = 0.0;
 	render_context.shadow = render_context.style->Shadow;
 	render_context.frx = render_context.fry = 0.;
 	render_context.frz = M_PI * render_context.style->Angle / 180.;
@@ -1321,9 +1340,10 @@
 
 			// render glyph
 			error = glyph_to_bitmap(ass_renderer->synth_priv,
+					ass_renderer->synth_priv_blur,
 					info->glyph, info->outline_glyph,
 					&info->bm, &info->bm_o,
-					&info->bm_s, info->be);
+					&info->bm_s, info->be, info->blur);
 			if (error)
 				info->symbol = 0;
 
@@ -1815,6 +1835,7 @@
 		text_info.glyphs[text_info.length].effect_timing = render_context.effect_timing;
 		text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing;
 		text_info.glyphs[text_info.length].be = render_context.be;
+		text_info.glyphs[text_info.length].blur = render_context.blur;
 		text_info.glyphs[text_info.length].shadow = render_context.shadow;
 		text_info.glyphs[text_info.length].frx = render_context.frx;
 		text_info.glyphs[text_info.length].fry = render_context.fry;
@@ -1839,6 +1860,7 @@
 		text_info.glyphs[text_info.length].hash_key.ch = code;
 		text_info.glyphs[text_info.length].hash_key.advance = shift;
 		text_info.glyphs[text_info.length].hash_key.be = render_context.be;
+		text_info.glyphs[text_info.length].hash_key.blur = render_context.blur;
 
 		text_info.length++;