Updates from greg:
* Scale shadow displacement and blur size like border * Correctly re-initialize glyph_info_t. * When using pan-and-scan, use correct positions. * patch cleanups Originally committed to SVN as r2744.
This commit is contained in:
parent
761f044526
commit
87cee933ed
|
@ -43,11 +43,6 @@ struct ass_synth_priv_s {
|
||||||
double radius;
|
double radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ass_be_priv_s {
|
|
||||||
int size;
|
|
||||||
unsigned char *buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned int maxcolor = 255;
|
static const unsigned int maxcolor = 255;
|
||||||
static const unsigned base = 256;
|
static const unsigned base = 256;
|
||||||
|
|
||||||
|
@ -60,18 +55,15 @@ static int generate_tables(ass_synth_priv_t* priv, double radius)
|
||||||
|
|
||||||
if (priv->radius == radius)
|
if (priv->radius == radius)
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else
|
||||||
priv->radius = radius;
|
priv->radius = radius;
|
||||||
if (priv->g) free(priv->g);
|
|
||||||
if (priv->gt2) free(priv->gt2);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->g_r = ceil(radius);
|
priv->g_r = ceil(radius);
|
||||||
priv->g_w = 2*priv->g_r+1;
|
priv->g_w = 2*priv->g_r+1;
|
||||||
|
|
||||||
if (priv->g_r) {
|
if (priv->g_r) {
|
||||||
priv->g = malloc(priv->g_w * sizeof(unsigned));
|
priv->g = realloc(priv->g, priv->g_w * sizeof(unsigned));
|
||||||
priv->gt2 = malloc(256 * priv->g_w * sizeof(unsigned));
|
priv->gt2 = realloc(priv->gt2, 256 * priv->g_w * sizeof(unsigned));
|
||||||
if (priv->g==NULL || priv->gt2==NULL) {
|
if (priv->g==NULL || priv->gt2==NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +115,6 @@ static void resize_tmp(ass_synth_priv_t* priv, int w, int h)
|
||||||
ass_synth_priv_t* ass_synth_init(double radius)
|
ass_synth_priv_t* ass_synth_init(double radius)
|
||||||
{
|
{
|
||||||
ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t));
|
ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t));
|
||||||
priv->g = priv->gt2 = 0;
|
|
||||||
generate_tables(priv, radius);
|
generate_tables(priv, radius);
|
||||||
return priv;
|
return priv;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +130,7 @@ void ass_synth_done(ass_synth_priv_t* priv)
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap_t* alloc_bitmap(int w, int h)
|
static bitmap_t* alloc_bitmap(int w, int h)
|
||||||
{
|
{
|
||||||
bitmap_t* bm;
|
bitmap_t* bm;
|
||||||
bm = calloc(1, sizeof(bitmap_t));
|
bm = calloc(1, sizeof(bitmap_t));
|
||||||
|
@ -251,7 +242,7 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o)
|
||||||
unsigned char c_g, c_o;
|
unsigned char c_g, c_o;
|
||||||
c_g = g[x];
|
c_g = g[x];
|
||||||
c_o = o[x];
|
c_o = o[x];
|
||||||
o[x] = (c_o > c_g) ? c_o - c_g/2 : 0;
|
o[x] = (c_o > c_g) ? c_o - (c_g/2) : 0;
|
||||||
s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF;
|
s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF;
|
||||||
}
|
}
|
||||||
g += bm_g->w;
|
g += bm_g->w;
|
||||||
|
@ -263,21 +254,24 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o)
|
||||||
return bm_s;
|
return bm_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// \be blur with [1,2,1] matrix
|
/**
|
||||||
|
* \brief Blur with [1,2,1] kernel
|
||||||
|
* This simple blur is exactly the same as the one employed by vsfilter.
|
||||||
|
* In addition, it's slightly faster than gaussian blur.
|
||||||
|
*/
|
||||||
static void be_blur(unsigned char *buf, ass_be_priv_t* priv, int w, int h) {
|
static void be_blur(unsigned char *buf, ass_be_priv_t* priv, int w, int h) {
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
unsigned int p;
|
unsigned int p;
|
||||||
unsigned char *tmp_buf = priv->buf;
|
unsigned char *tmp_buf = priv->buf;
|
||||||
const int wh = w*h;
|
const int wh = w*h;
|
||||||
|
|
||||||
if (priv->size < wh) {
|
if (priv->size < wh) {
|
||||||
priv->buf = realloc(priv->buf, wh);
|
priv->buf = realloc(priv->buf, wh);
|
||||||
priv->size = wh;
|
priv->size = wh;
|
||||||
tmp_buf = priv->buf;
|
tmp_buf = priv->buf;
|
||||||
printf("resized priv to %d bytes\n", wh);
|
|
||||||
}
|
}
|
||||||
memset(tmp_buf, 0, wh);
|
memset(tmp_buf, 0, wh);
|
||||||
|
|
||||||
for (y=0; y<h; y++)
|
for (y=0; y<h; y++)
|
||||||
for (x=1; x<w-1; x++) {
|
for (x=1; x<w-1; x++) {
|
||||||
p = buf[y*w+x-1];
|
p = buf[y*w+x-1];
|
||||||
|
@ -295,54 +289,28 @@ static void be_blur(unsigned char *buf, ass_be_priv_t* priv, int w, int h) {
|
||||||
p = p >> 2;
|
p = p >> 2;
|
||||||
buf[y*w+x] = p;
|
buf[y*w+x] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
//free(tmp_buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static void get_overlap(bitmap_t* a, bitmap_t* b) {
|
|
||||||
int left, top, bottom, right;
|
|
||||||
int old_left, old_top, old_w, old_h;
|
|
||||||
int cur_left, cur_top, cur_w, cur_h;
|
|
||||||
|
|
||||||
// Calculate overlap as coordinates
|
|
||||||
left = (a->left > b->left) ? a->left : b-> left;
|
|
||||||
top = (a->top > b->top) ? a->top : b->top;
|
|
||||||
right = ((a->left+a->w) < (b->left+b->w)) ?
|
|
||||||
(a->left+a->w) : (b->left+b->w);
|
|
||||||
bottom = ((a->top+a->h) < (b->top+b->h)) ?
|
|
||||||
(a->top+a->h) : (b->top+b->h);
|
|
||||||
// Check whether overlap rect is valid
|
|
||||||
// Just return if it isn't...
|
|
||||||
if ((right <= left) || (bottom <= top))
|
|
||||||
return;
|
|
||||||
printf("coord overlap %dx%d+%dx%d\n", left, top, right, bottom);
|
|
||||||
|
|
||||||
// Translate into coordinates+width/height for each bitmap
|
|
||||||
old_left = left-(a->left);
|
|
||||||
old_top = top-(a->top);
|
|
||||||
old_w = right-left;
|
|
||||||
old_h = bottom-top;
|
|
||||||
printf("bitmap overlap %dx%d+%dx%d\n", old_left, old_top, old_w, old_h);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ass_be_priv_t* ass_be_init(void) {
|
ass_be_priv_t* ass_be_init(void) {
|
||||||
ass_be_priv_t* priv;
|
ass_be_priv_t* priv;
|
||||||
priv = malloc(sizeof(ass_be_priv_t));
|
priv = calloc(1, sizeof(ass_be_priv_t));
|
||||||
priv->size = 64*64;
|
|
||||||
priv->buf = malloc(64*64);
|
|
||||||
|
|
||||||
return priv;
|
return priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur,
|
void ass_be_done(ass_be_priv_t* priv) {
|
||||||
|
if (priv->buf)
|
||||||
|
free(priv->buf);
|
||||||
|
free(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
int glyph_to_bitmap(ass_be_priv_t* priv_be, ass_synth_priv_t* priv_blur,
|
||||||
FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g,
|
FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g,
|
||||||
bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius, ass_be_priv_t* be_priv, bitmap_t** bm_oo)
|
bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius)
|
||||||
{
|
{
|
||||||
int bord = be ? (be/4+1) : 0;
|
int bord = be ? (be/4+1) : 0;
|
||||||
blur_radius *= 2;
|
blur_radius *= 2;
|
||||||
bord = (blur_radius > 0.0) ? (int)(blur_radius+3) : (int) bord;
|
bord = (blur_radius > 0.0) ? blur_radius : bord;
|
||||||
|
|
||||||
assert(bm_g && bm_o && bm_s);
|
assert(bm_g && bm_o && bm_s);
|
||||||
|
|
||||||
|
@ -360,35 +328,26 @@ int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur,
|
||||||
return 1;
|
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_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);
|
resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h);
|
||||||
|
|
||||||
if (be) {
|
if (be) {
|
||||||
while (be--) {
|
while (be--) {
|
||||||
if (*bm_o) {
|
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);
|
be_blur((*bm_o)->buffer, priv_be, (*bm_o)->w, (*bm_o)->h);
|
||||||
be_blur((*bm_o)->buffer, be_priv, (*bm_o)->w, (*bm_o)->h);
|
else
|
||||||
//(*bm_o)->top--;
|
be_blur((*bm_g)->buffer, priv_be, (*bm_g)->w, (*bm_g)->h);
|
||||||
//(*bm_o)->left--;
|
|
||||||
} 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);
|
|
||||||
be_blur((*bm_g)->buffer, be_priv, (*bm_g)->w, (*bm_g)->h);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (blur_radius > 0.0) {
|
if (blur_radius > 0.0) {
|
||||||
generate_tables(priv_blur, blur_radius);
|
generate_tables(priv_blur, blur_radius);
|
||||||
if (*bm_o)
|
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);
|
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
|
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);
|
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)
|
if (*bm_o)
|
||||||
*bm_s = fix_outline_and_shadow(*bm_g, *bm_o);
|
*bm_s = fix_outline_and_shadow(*bm_g, *bm_o);
|
||||||
else
|
else
|
||||||
|
|
|
@ -23,15 +23,18 @@
|
||||||
#ifndef LIBASS_BITMAP_H
|
#ifndef LIBASS_BITMAP_H
|
||||||
#define LIBASS_BITMAP_H
|
#define LIBASS_BITMAP_H
|
||||||
|
|
||||||
#define MAX_BOXBLUR 50
|
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_GLYPH_H
|
#include FT_GLYPH_H
|
||||||
|
|
||||||
typedef struct ass_synth_priv_s ass_synth_priv_t;
|
typedef struct ass_synth_priv_s ass_synth_priv_t;
|
||||||
typedef struct ass_be_priv_s ass_be_priv_t;
|
|
||||||
|
typedef struct ass_be_priv_s {
|
||||||
|
int size;
|
||||||
|
unsigned char *buf;
|
||||||
|
} ass_be_priv_t;
|
||||||
|
|
||||||
ass_be_priv_t* ass_be_init(void);
|
ass_be_priv_t* ass_be_init(void);
|
||||||
|
void ass_be_done(ass_be_priv_t* priv);
|
||||||
ass_synth_priv_t* ass_synth_init(double);
|
ass_synth_priv_t* ass_synth_init(double);
|
||||||
void ass_synth_done(ass_synth_priv_t* priv);
|
void ass_synth_done(ass_synth_priv_t* priv);
|
||||||
|
|
||||||
|
@ -50,10 +53,8 @@ typedef struct bitmap_s {
|
||||||
* \param bm_g out: pointer to the bitmap of glyph shadow is returned here
|
* \param bm_g out: pointer to the bitmap of glyph shadow is returned here
|
||||||
* \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
|
* \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
|
||||||
*/
|
*/
|
||||||
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, ass_be_priv_t* be_priv, bitmap_t** bm_oo);
|
int glyph_to_bitmap(ass_be_priv_t* priv_be, 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);
|
void ass_free_bitmap(bitmap_t* bm);
|
||||||
|
|
||||||
bitmap_t* alloc_bitmap(int w, int h);
|
|
||||||
|
|
||||||
#endif /* LIBASS_BITMAP_H */
|
#endif /* LIBASS_BITMAP_H */
|
||||||
|
|
|
@ -43,10 +43,8 @@
|
||||||
|
|
||||||
#define MAX_GLYPHS 3000
|
#define MAX_GLYPHS 3000
|
||||||
#define MAX_LINES 300
|
#define MAX_LINES 300
|
||||||
#define BE_RADIUS 1.5
|
|
||||||
#define BLUR_MAX_RADIUS 50.0
|
#define BLUR_MAX_RADIUS 50.0
|
||||||
|
#define ROUND(x) ((int) ((x) + .5))
|
||||||
#define NEAREST(x) ((int) (x + 0.5))
|
|
||||||
|
|
||||||
static int last_render_id = 0;
|
static int last_render_id = 0;
|
||||||
|
|
||||||
|
@ -83,17 +81,14 @@ struct ass_renderer_s {
|
||||||
fc_instance_t* fontconfig_priv;
|
fc_instance_t* fontconfig_priv;
|
||||||
ass_settings_t settings;
|
ass_settings_t settings;
|
||||||
int render_id;
|
int render_id;
|
||||||
ass_synth_priv_t* synth_priv;
|
|
||||||
ass_synth_priv_t* synth_priv_blur;
|
|
||||||
ass_be_priv_t* be_priv;
|
ass_be_priv_t* be_priv;
|
||||||
|
ass_synth_priv_t* synth_priv_blur;
|
||||||
|
|
||||||
ass_image_t* images_root; // rendering result is stored here
|
ass_image_t* images_root; // rendering result is stored here
|
||||||
ass_image_t* prev_images_root;
|
ass_image_t* prev_images_root;
|
||||||
|
|
||||||
event_images_t* eimg; // temporary buffer for sorting rendered events
|
event_images_t* eimg; // temporary buffer for sorting rendered events
|
||||||
int eimg_size; // allocated buffer size
|
int eimg_size; // allocated buffer size
|
||||||
|
|
||||||
bitmap_t* bm_oo; // pointer to last rendered outline for compositing
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {EF_NONE = 0, EF_KARAOKE, EF_KARAOKE_KF, EF_KARAOKE_KO} effect_t;
|
typedef enum {EF_NONE = 0, EF_KARAOKE, EF_KARAOKE_KF, EF_KARAOKE_KO} effect_t;
|
||||||
|
@ -137,9 +132,6 @@ typedef struct text_info_s {
|
||||||
line_info_t lines[MAX_LINES];
|
line_info_t lines[MAX_LINES];
|
||||||
int n_lines;
|
int n_lines;
|
||||||
int height;
|
int height;
|
||||||
// Free list for composited glyphs
|
|
||||||
void* free_list[MAX_GLYPHS];
|
|
||||||
int free_count;
|
|
||||||
} text_info_t;
|
} text_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,11 +201,19 @@ typedef struct frame_context_s {
|
||||||
double border_scale;
|
double border_scale;
|
||||||
} frame_context_t;
|
} frame_context_t;
|
||||||
|
|
||||||
|
// List of objects to free after each frame
|
||||||
|
typedef struct free_list_s {
|
||||||
|
int count;
|
||||||
|
int size;
|
||||||
|
void** obj;
|
||||||
|
} free_list_t;
|
||||||
|
|
||||||
static ass_renderer_t* ass_renderer;
|
static ass_renderer_t* ass_renderer;
|
||||||
static ass_settings_t* global_settings;
|
static ass_settings_t* global_settings;
|
||||||
static text_info_t text_info;
|
static text_info_t text_info;
|
||||||
static render_context_t render_context;
|
static render_context_t render_context;
|
||||||
static frame_context_t frame_context;
|
static frame_context_t frame_context;
|
||||||
|
static free_list_t free_list;
|
||||||
|
|
||||||
struct render_priv_s {
|
struct render_priv_s {
|
||||||
int top, height;
|
int top, height;
|
||||||
|
@ -232,9 +232,15 @@ static void ass_lazy_track_init(void)
|
||||||
} else {
|
} else {
|
||||||
double orig_aspect = (global_settings->aspect * frame_context.height * frame_context.orig_width) /
|
double orig_aspect = (global_settings->aspect * frame_context.height * frame_context.orig_width) /
|
||||||
frame_context.orig_height / frame_context.width;
|
frame_context.orig_height / frame_context.width;
|
||||||
if (!track->PlayResY) {
|
if (!track->PlayResY && track->PlayResX == 1280) {
|
||||||
|
track->PlayResY = 1024;
|
||||||
|
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY);
|
||||||
|
} else if (!track->PlayResY) {
|
||||||
track->PlayResY = track->PlayResX / orig_aspect + .5;
|
track->PlayResY = track->PlayResX / orig_aspect + .5;
|
||||||
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY);
|
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY);
|
||||||
|
} else if (!track->PlayResX && track->PlayResY == 1024) {
|
||||||
|
track->PlayResX = 1280;
|
||||||
|
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX);
|
||||||
} else if (!track->PlayResX) {
|
} else if (!track->PlayResX) {
|
||||||
track->PlayResX = track->PlayResY * orig_aspect + .5;
|
track->PlayResX = track->PlayResY * orig_aspect + .5;
|
||||||
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX);
|
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX);
|
||||||
|
@ -271,10 +277,8 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library)
|
||||||
goto ass_init_exit;
|
goto ass_init_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->synth_priv = ass_synth_init(BE_RADIUS);
|
|
||||||
priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS);
|
|
||||||
priv->be_priv = ass_be_init();
|
priv->be_priv = ass_be_init();
|
||||||
priv->bm_oo = NULL;
|
priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS);
|
||||||
|
|
||||||
priv->library = library;
|
priv->library = library;
|
||||||
priv->ftlibrary = ft;
|
priv->ftlibrary = ft;
|
||||||
|
@ -293,6 +297,30 @@ ass_init_exit:
|
||||||
return priv;
|
return priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ass_free_objects(void) {
|
||||||
|
int i = 0;
|
||||||
|
while (free_list.count--)
|
||||||
|
free(free_list.obj[i++]);
|
||||||
|
free_list.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ass_free_add(void * obj) {
|
||||||
|
if (free_list.size == 0) {
|
||||||
|
free_list.size = 2;
|
||||||
|
free_list.obj = malloc(free_list.size * sizeof(void *));
|
||||||
|
} else if (free_list.size <= free_list.count+1) {
|
||||||
|
free_list.size *= 2;
|
||||||
|
free_list.obj = realloc(free_list.obj, free_list.size * sizeof(void *));
|
||||||
|
}
|
||||||
|
free_list.obj[free_list.count++] = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ass_free_done(void) {
|
||||||
|
if (free_list.obj)
|
||||||
|
free(free_list.obj);
|
||||||
|
free_list.obj = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ass_renderer_done(ass_renderer_t* priv)
|
void ass_renderer_done(ass_renderer_t* priv)
|
||||||
{
|
{
|
||||||
ass_font_cache_done();
|
ass_font_cache_done();
|
||||||
|
@ -304,10 +332,13 @@ void ass_renderer_done(ass_renderer_t* priv)
|
||||||
}
|
}
|
||||||
if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary);
|
if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary);
|
||||||
if (priv && priv->fontconfig_priv) fontconfig_done(priv->fontconfig_priv);
|
if (priv && priv->fontconfig_priv) fontconfig_done(priv->fontconfig_priv);
|
||||||
if (priv && priv->synth_priv) ass_synth_done(priv->synth_priv);
|
if (priv && priv->synth_priv_blur) ass_synth_done(priv->synth_priv_blur);
|
||||||
|
if (priv && priv->be_priv) ass_be_done(priv->be_priv);
|
||||||
if (priv && priv->eimg) free(priv->eimg);
|
if (priv && priv->eimg) free(priv->eimg);
|
||||||
if (priv) free(priv);
|
if (priv) free(priv);
|
||||||
if (text_info.glyphs) free(text_info.glyphs);
|
if (text_info.glyphs) free(text_info.glyphs);
|
||||||
|
ass_free_objects();
|
||||||
|
ass_free_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -325,8 +356,6 @@ static ass_image_t* my_draw_bitmap(unsigned char* bitmap, int bitmap_w, int bitm
|
||||||
img->color = color;
|
img->color = color;
|
||||||
img->dst_x = dst_x;
|
img->dst_x = dst_x;
|
||||||
img->dst_y = dst_y;
|
img->dst_y = dst_y;
|
||||||
|
|
||||||
//printf("img dest %dx%d\n", dst_x, dst_y);
|
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
@ -410,14 +439,18 @@ static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t c
|
||||||
return tail;
|
return tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Glyph compositing
|
/**
|
||||||
static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, void** free_list, int* free_count) {
|
* \brief Calculate overlapping area of two consecutive bitmaps and in case they
|
||||||
|
* overlap, composite them together
|
||||||
|
* Mainly useful for translucent glyphs and especially borders, to avoid the
|
||||||
|
* luminance adding up where they overlap (which looks ugly)
|
||||||
|
*/
|
||||||
|
static void render_overlap(ass_image_t** last_tail, ass_image_t** tail) {
|
||||||
int left, top, bottom, right;
|
int left, top, bottom, right;
|
||||||
int old_left, old_top, old_w, old_h;
|
int old_left, old_top, w, h, cur_left, cur_top;
|
||||||
int cur_left, cur_top, cur_w, cur_h;
|
|
||||||
int x, y, opos, cpos;
|
int x, y, opos, cpos;
|
||||||
char m;
|
char m;
|
||||||
|
|
||||||
int ax = (*last_tail)->dst_x;
|
int ax = (*last_tail)->dst_x;
|
||||||
int ay = (*last_tail)->dst_y;
|
int ay = (*last_tail)->dst_y;
|
||||||
int aw = (*last_tail)->w;
|
int aw = (*last_tail)->w;
|
||||||
|
@ -428,7 +461,7 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, void** f
|
||||||
int bh = (*tail)->h;
|
int bh = (*tail)->h;
|
||||||
unsigned char* a;
|
unsigned char* a;
|
||||||
unsigned char* b;
|
unsigned char* b;
|
||||||
|
|
||||||
// Calculate overlap as coordinates
|
// Calculate overlap as coordinates
|
||||||
left = (ax > bx) ? ax : bx;
|
left = (ax > bx) ? ax : bx;
|
||||||
top = (ay > by) ? ay : by;
|
top = (ay > by) ? ay : by;
|
||||||
|
@ -439,45 +472,35 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, void** f
|
||||||
// Check whether overlap rect is valid
|
// Check whether overlap rect is valid
|
||||||
if ((right <= left) || (bottom <= top))
|
if ((right <= left) || (bottom <= top))
|
||||||
return;
|
return;
|
||||||
//printf("coord overlap %dx%d+%dx%d\n", left, top, right, bottom);
|
|
||||||
|
|
||||||
// Translate into coordinates+width/height for each bitmap
|
// Translate into coordinates+width/height for each bitmap
|
||||||
old_left = left-(ax);
|
old_left = left-(ax);
|
||||||
old_top = top-(ay);
|
old_top = top-(ay);
|
||||||
old_w = right-left;
|
w = right-left;
|
||||||
old_h = bottom-top;
|
h = bottom-top;
|
||||||
//printf("bitmap overlap %dx%d+%dx%d\n", old_left, old_top, old_w, old_h);
|
|
||||||
|
|
||||||
cur_left = left-(bx);
|
cur_left = left-(bx);
|
||||||
cur_top = top-(by);
|
cur_top = top-(by);
|
||||||
cur_w = right-left;
|
|
||||||
cur_h = bottom-top;
|
|
||||||
//printf("bitmap overlap %dx%d+%dx%d\n\n", cur_left, cur_top, cur_w, cur_h);
|
|
||||||
|
|
||||||
// Allocate new bitmaps and copy over data
|
// Allocate new bitmaps and copy over data
|
||||||
a = (*last_tail)->bitmap;
|
a = (*last_tail)->bitmap;
|
||||||
b = (*tail)->bitmap;
|
b = (*tail)->bitmap;
|
||||||
(*last_tail)->bitmap = malloc(aw*ah);
|
(*last_tail)->bitmap = malloc(aw*ah);
|
||||||
free_list[(*free_count)++] = (*last_tail)->bitmap;
|
ass_free_add((*last_tail)->bitmap);
|
||||||
(*tail)->bitmap = malloc(bw*bh);
|
(*tail)->bitmap = malloc(bw*bh);
|
||||||
free_list[(*free_count)++] = (*tail)->bitmap;
|
ass_free_add((*tail)->bitmap);
|
||||||
memcpy((*last_tail)->bitmap, a, aw*ah);
|
memcpy((*last_tail)->bitmap, a, aw*ah);
|
||||||
memcpy((*tail)->bitmap, b, bw*bh);
|
memcpy((*tail)->bitmap, b, bw*bh);
|
||||||
|
|
||||||
// Composite overlapping area
|
// Composite overlapping area
|
||||||
for (y=0; y<old_h; y++)
|
for (y=0; y<h; y++)
|
||||||
for (x=0; x<old_w; x++) {
|
for (x=0; x<w; x++) {
|
||||||
opos = (old_top+y)*(aw) + (old_left+x);
|
opos = (old_top+y)*(aw) + (old_left+x);
|
||||||
cpos = (cur_top+y)*(bw) + (cur_left+x);
|
cpos = (cur_top+y)*(bw) + (cur_left+x);
|
||||||
//printf("opos %d cpos %d\n", opos, cpos);
|
m = (a[opos] > b[cpos]) ? a[opos] : b[cpos];
|
||||||
m = (a[opos] > b[cpos]) ?
|
|
||||||
a[opos] : b[cpos];
|
|
||||||
(*last_tail)->bitmap[opos] = 0;
|
(*last_tail)->bitmap[opos] = 0;
|
||||||
(*tail)->bitmap[cpos] = m;
|
(*tail)->bitmap[cpos] = m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Convert text_info_t struct to ass_image_t list
|
* \brief Convert text_info_t struct to ass_image_t list
|
||||||
* Splits glyphs in halves when needed (for \kf karaoke).
|
* Splits glyphs in halves when needed (for \kf karaoke).
|
||||||
|
@ -497,8 +520,8 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||||
if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0))
|
if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pen_x = dst_x + info->pos.x + NEAREST(info->shadow);
|
pen_x = dst_x + info->pos.x + ROUND(info->shadow * frame_context.border_scale);
|
||||||
pen_y = dst_y + info->pos.y + NEAREST(info->shadow);
|
pen_y = dst_y + info->pos.y + ROUND(info->shadow * frame_context.border_scale);
|
||||||
bm = info->bm_s;
|
bm = info->bm_s;
|
||||||
|
|
||||||
tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail);
|
tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail);
|
||||||
|
@ -511,7 +534,6 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||||
|
|
||||||
pen_x = dst_x + info->pos.x;
|
pen_x = dst_x + info->pos.x;
|
||||||
pen_y = dst_y + info->pos.y;
|
pen_y = dst_y + info->pos.y;
|
||||||
|
|
||||||
bm = info->bm_o;
|
bm = info->bm_o;
|
||||||
|
|
||||||
if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) {
|
if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) {
|
||||||
|
@ -519,13 +541,8 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||||
} else {
|
} else {
|
||||||
here_tail = tail;
|
here_tail = tail;
|
||||||
tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail);
|
tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail);
|
||||||
// Composite overlapping translucent outlines together
|
if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0))
|
||||||
// Additional bitmaps not stored in cache are allocated for that
|
render_overlap(last_tail, here_tail);
|
||||||
// These are put into a free list which gets freed either
|
|
||||||
// when a new frame starts or when the renderer is dealloc'd
|
|
||||||
if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0)) {
|
|
||||||
render_overlap(last_tail, here_tail, text_info->free_list, &text_info->free_count);
|
|
||||||
}
|
|
||||||
last_tail = here_tail;
|
last_tail = here_tail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,6 +565,7 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||||
} else
|
} else
|
||||||
tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
|
tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
*tail = 0;
|
*tail = 0;
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
@ -559,6 +577,10 @@ static int x2scr(double x) {
|
||||||
return x*frame_context.orig_width_nocrop / frame_context.track->PlayResX +
|
return x*frame_context.orig_width_nocrop / frame_context.track->PlayResX +
|
||||||
FFMAX(global_settings->left_margin, 0);
|
FFMAX(global_settings->left_margin, 0);
|
||||||
}
|
}
|
||||||
|
static int x2scr_pos(double x) {
|
||||||
|
return x*frame_context.orig_width / frame_context.track->PlayResX +
|
||||||
|
global_settings->left_margin;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* \brief Mapping between script and screen coordinates
|
* \brief Mapping between script and screen coordinates
|
||||||
*/
|
*/
|
||||||
|
@ -673,12 +695,9 @@ static void change_border(double border)
|
||||||
if (!render_context.font) return;
|
if (!render_context.font) return;
|
||||||
|
|
||||||
if (border < 0) {
|
if (border < 0) {
|
||||||
if (render_context.style->BorderStyle == 1) {
|
if (render_context.style->BorderStyle == 1)
|
||||||
if (render_context.style->Outline == 0 && render_context.style->Shadow > 0)
|
border = render_context.style->Outline;
|
||||||
border = 0.0; //1.;
|
else
|
||||||
else
|
|
||||||
border = render_context.style->Outline;
|
|
||||||
} else
|
|
||||||
border = 1.;
|
border = 1.;
|
||||||
}
|
}
|
||||||
render_context.border = border;
|
render_context.border = border;
|
||||||
|
@ -876,23 +895,17 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
double x, y;
|
double x, y;
|
||||||
double k;
|
double k;
|
||||||
skip('(');
|
skip('(');
|
||||||
//x1 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &x1);
|
mystrtoi(&p, 10, &x1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//y1 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &y1);
|
mystrtoi(&p, 10, &y1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//x2 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &x2);
|
mystrtoi(&p, 10, &x2);
|
||||||
skip(',');
|
skip(',');
|
||||||
//y2 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &y2);
|
mystrtoi(&p, 10, &y2);
|
||||||
if (*p == ',') {
|
if (*p == ',') {
|
||||||
skip(',');
|
skip(',');
|
||||||
//t1 = strtoll(p, &p, 10);
|
|
||||||
mystrtoll(&p, 10, &t1);
|
mystrtoll(&p, 10, &t1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//t2 = strtoll(p, &p, 10);
|
|
||||||
mystrtoll(&p, 10, &t2);
|
mystrtoll(&p, 10, &t2);
|
||||||
mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%d, %d) -> (%d, %d), (%" PRId64 " .. %" PRId64 ")\n",
|
mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%d, %d) -> (%d, %d), (%" PRId64 " .. %" PRId64 ")\n",
|
||||||
x1, y1, x2, y2, (int64_t)t1, (int64_t)t2);
|
x1, y1, x2, y2, (int64_t)t1, (int64_t)t2);
|
||||||
|
@ -987,10 +1000,8 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
} else if (mystrcmp(&p, "pos")) {
|
} else if (mystrcmp(&p, "pos")) {
|
||||||
int v1, v2;
|
int v1, v2;
|
||||||
skip('(');
|
skip('(');
|
||||||
//v1 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &v1);
|
mystrtoi(&p, 10, &v1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//v2 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &v2);
|
mystrtoi(&p, 10, &v2);
|
||||||
skip(')');
|
skip(')');
|
||||||
mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%d, %d)\n", v1, v2);
|
mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%d, %d)\n", v1, v2);
|
||||||
|
@ -1005,10 +1016,8 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
long long t1, t2, t3, t4;
|
long long t1, t2, t3, t4;
|
||||||
if (*p == 'e') ++p; // either \fad or \fade
|
if (*p == 'e') ++p; // either \fad or \fade
|
||||||
skip('(');
|
skip('(');
|
||||||
//a1 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &a1);
|
mystrtoi(&p, 10, &a1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//a2 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &a2);
|
mystrtoi(&p, 10, &a2);
|
||||||
if (*p == ')') {
|
if (*p == ')') {
|
||||||
// 2-argument version (\fad, according to specs)
|
// 2-argument version (\fad, according to specs)
|
||||||
|
@ -1024,19 +1033,14 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
// 6-argument version (\fade)
|
// 6-argument version (\fade)
|
||||||
// a1 and a2 (and a3) are opacity values
|
// a1 and a2 (and a3) are opacity values
|
||||||
skip(',');
|
skip(',');
|
||||||
//a3 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &a3);
|
mystrtoi(&p, 10, &a3);
|
||||||
skip(',');
|
skip(',');
|
||||||
//t1 = strtoll(p, &p, 10);
|
|
||||||
mystrtoll(&p, 10, &t1);
|
mystrtoll(&p, 10, &t1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//t2 = strtoll(p, &p, 10);
|
|
||||||
mystrtoll(&p, 10, &t2);
|
mystrtoll(&p, 10, &t2);
|
||||||
skip(',');
|
skip(',');
|
||||||
//t3 = strtoll(p, &p, 10);
|
|
||||||
mystrtoll(&p, 10, &t3);
|
mystrtoll(&p, 10, &t3);
|
||||||
skip(',');
|
skip(',');
|
||||||
//t4 = strtoll(p, &p, 10);
|
|
||||||
mystrtoll(&p, 10, &t4);
|
mystrtoll(&p, 10, &t4);
|
||||||
}
|
}
|
||||||
skip(')');
|
skip(')');
|
||||||
|
@ -1044,10 +1048,8 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
} else if (mystrcmp(&p, "org")) {
|
} else if (mystrcmp(&p, "org")) {
|
||||||
int v1, v2;
|
int v1, v2;
|
||||||
skip('(');
|
skip('(');
|
||||||
//v1 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &v1);
|
mystrtoi(&p, 10, &v1);
|
||||||
skip(',');
|
skip(',');
|
||||||
//v2 = strtol(p, &p, 10);
|
|
||||||
mystrtoi(&p, 10, &v2);
|
mystrtoi(&p, 10, &v2);
|
||||||
skip(')');
|
skip(')');
|
||||||
mp_msg(MSGT_ASS, MSGL_DBG2, "org(%d, %d)\n", v1, v2);
|
mp_msg(MSGT_ASS, MSGL_DBG2, "org(%d, %d)\n", v1, v2);
|
||||||
|
@ -1154,7 +1156,7 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
if (mystrtoi(&p, 10, &val)) {
|
if (mystrtoi(&p, 10, &val)) {
|
||||||
// Clamp to 10, since high values need excessive CPU
|
// Clamp to 10, since high values need excessive CPU
|
||||||
val = (val < 0) ? 0 : val;
|
val = (val < 0) ? 0 : val;
|
||||||
val = (val > 50) ? 10 : val;
|
val = (val > 10) ? 10 : val;
|
||||||
render_context.be = val;
|
render_context.be = val;
|
||||||
} else
|
} else
|
||||||
render_context.be = 0;
|
render_context.be = 0;
|
||||||
|
@ -1175,7 +1177,6 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
render_context.italic = render_context.style->Italic;
|
render_context.italic = render_context.style->Italic;
|
||||||
update_font();
|
update_font();
|
||||||
} else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) {
|
} else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) {
|
||||||
//int val = strtol(p, &p, 10);
|
|
||||||
int val = 0;
|
int val = 0;
|
||||||
mystrtoi(&p, 10, &val);
|
mystrtoi(&p, 10, &val);
|
||||||
render_context.effect_type = EF_KARAOKE_KF;
|
render_context.effect_type = EF_KARAOKE_KF;
|
||||||
|
@ -1183,7 +1184,6 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
render_context.effect_skip_timing += render_context.effect_timing;
|
render_context.effect_skip_timing += render_context.effect_timing;
|
||||||
render_context.effect_timing = val * 10;
|
render_context.effect_timing = val * 10;
|
||||||
} else if (mystrcmp(&p, "ko")) {
|
} else if (mystrcmp(&p, "ko")) {
|
||||||
//int val = strtol(p, &p, 10);
|
|
||||||
int val = 0;
|
int val = 0;
|
||||||
mystrtoi(&p, 10, &val);
|
mystrtoi(&p, 10, &val);
|
||||||
render_context.effect_type = EF_KARAOKE_KO;
|
render_context.effect_type = EF_KARAOKE_KO;
|
||||||
|
@ -1191,7 +1191,6 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
render_context.effect_skip_timing += render_context.effect_timing;
|
render_context.effect_skip_timing += render_context.effect_timing;
|
||||||
render_context.effect_timing = val * 10;
|
render_context.effect_timing = val * 10;
|
||||||
} else if (mystrcmp(&p, "k")) {
|
} else if (mystrcmp(&p, "k")) {
|
||||||
//int val = strtol(p, &p, 10);
|
|
||||||
int val = 0;
|
int val = 0;
|
||||||
mystrtoi(&p, 10, &val);
|
mystrtoi(&p, 10, &val);
|
||||||
render_context.effect_type = EF_KARAOKE;
|
render_context.effect_type = EF_KARAOKE;
|
||||||
|
@ -1199,17 +1198,16 @@ static char* parse_tag(char* p, double pwr) {
|
||||||
render_context.effect_skip_timing += render_context.effect_timing;
|
render_context.effect_skip_timing += render_context.effect_timing;
|
||||||
render_context.effect_timing = val * 10;
|
render_context.effect_timing = val * 10;
|
||||||
} else if (mystrcmp(&p, "shad")) {
|
} else if (mystrcmp(&p, "shad")) {
|
||||||
int val = 0;;
|
int val;
|
||||||
if (mystrtoi(&p, 10, &val))
|
if (mystrtoi(&p, 10, &val))
|
||||||
render_context.shadow = val;
|
render_context.shadow = val;
|
||||||
else
|
else
|
||||||
render_context.shadow = render_context.style->Shadow;
|
render_context.shadow = render_context.style->Shadow;
|
||||||
} else if (mystrcmp(&p, "pbo")) {
|
} else if (mystrcmp(&p, "pbo")) {
|
||||||
//(void)strtol(p, &p, 10); // ignored
|
|
||||||
int val = 0;
|
int val = 0;
|
||||||
mystrtoi(&p, 10, &val);
|
mystrtoi(&p, 10, &val); // ignored
|
||||||
} else if (mystrcmp(&p, "p")) {
|
} else if (mystrcmp(&p, "p")) {
|
||||||
int val = 0;
|
int val;
|
||||||
if (!mystrtoi(&p, 10, &val))
|
if (!mystrtoi(&p, 10, &val))
|
||||||
val = 0;
|
val = 0;
|
||||||
render_context.drawing_mode = !!val;
|
render_context.drawing_mode = !!val;
|
||||||
|
@ -1264,7 +1262,7 @@ static unsigned get_next_char(char** str)
|
||||||
return ' ';
|
return ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chr = utf8_get_char((const char **) &p);
|
chr = utf8_get_char((const char **)&p);
|
||||||
*str = p;
|
*str = p;
|
||||||
return chr;
|
return chr;
|
||||||
}
|
}
|
||||||
|
@ -1426,7 +1424,7 @@ static void get_outline_glyph(int symbol, glyph_info_t* info, FT_Vector* advance
|
||||||
key.italic = render_context.italic;
|
key.italic = render_context.italic;
|
||||||
key.outline = render_context.border * 0xFFFF;
|
key.outline = render_context.border * 0xFFFF;
|
||||||
|
|
||||||
info->glyph = info->outline_glyph = 0;
|
memset(info, 0, sizeof(glyph_info_t));
|
||||||
|
|
||||||
val = cache_find_glyph(&key);
|
val = cache_find_glyph(&key);
|
||||||
if (val) {
|
if (val) {
|
||||||
|
@ -1498,11 +1496,11 @@ static void get_bitmap_glyph(glyph_info_t* info)
|
||||||
transform_3d(shift, &info->glyph, &info->outline_glyph, info->frx, info->fry, info->frz);
|
transform_3d(shift, &info->glyph, &info->outline_glyph, info->frx, info->fry, info->frz);
|
||||||
|
|
||||||
// render glyph
|
// render glyph
|
||||||
error = glyph_to_bitmap(ass_renderer->synth_priv,
|
error = glyph_to_bitmap(ass_renderer->be_priv,
|
||||||
ass_renderer->synth_priv_blur,
|
ass_renderer->synth_priv_blur,
|
||||||
info->glyph, info->outline_glyph,
|
info->glyph, info->outline_glyph,
|
||||||
&info->bm, &info->bm_o,
|
&info->bm, &info->bm_o,
|
||||||
&info->bm_s, info->be, info->blur, ass_renderer->be_priv, &ass_renderer->bm_oo);
|
&info->bm_s, info->be, info->blur * frame_context.border_scale);
|
||||||
if (error)
|
if (error)
|
||||||
info->symbol = 0;
|
info->symbol = 0;
|
||||||
|
|
||||||
|
@ -1518,21 +1516,6 @@ static void get_bitmap_glyph(glyph_info_t* info)
|
||||||
FT_Done_Glyph(info->glyph);
|
FT_Done_Glyph(info->glyph);
|
||||||
if (info->outline_glyph)
|
if (info->outline_glyph)
|
||||||
FT_Done_Glyph(info->outline_glyph);
|
FT_Done_Glyph(info->outline_glyph);
|
||||||
|
|
||||||
/*
|
|
||||||
// Find outline overlap rectangle and composite glyphs together
|
|
||||||
if (ass_renderer->bm_oo) {
|
|
||||||
printf("current outline %dx%d+%dx%d\n",
|
|
||||||
info->bm_o->left, info->bm_o->top,
|
|
||||||
info->bm_o->w, info->bm_o->h);
|
|
||||||
printf("old outline %dx%d+%dx%d\n",
|
|
||||||
ass_renderer->bm_oo->left, ass_renderer->bm_oo->top,
|
|
||||||
ass_renderer->bm_oo->w, ass_renderer->bm_oo->h);
|
|
||||||
get_overlap(info->bm_o, ass_renderer->bm_oo);
|
|
||||||
printf("--\n");
|
|
||||||
}
|
|
||||||
ass_renderer->bm_oo = info->bm_o;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2145,7 +2128,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
|
||||||
int base_y = 0;
|
int base_y = 0;
|
||||||
mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y);
|
mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y);
|
||||||
get_base_point(bbox, alignment, &base_x, &base_y);
|
get_base_point(bbox, alignment, &base_x, &base_y);
|
||||||
device_x = x2scr(render_context.pos_x) - base_x;
|
device_x = x2scr_pos(render_context.pos_x) - base_x;
|
||||||
device_y = y2scr(render_context.pos_y) - base_y;
|
device_y = y2scr(render_context.pos_y) - base_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2326,22 +2309,17 @@ int ass_set_fonts_nofc(ass_renderer_t* priv, const char* default_font, const cha
|
||||||
*/
|
*/
|
||||||
static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long now)
|
static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long now)
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
ass_renderer = priv;
|
ass_renderer = priv;
|
||||||
global_settings = &priv->settings;
|
global_settings = &priv->settings;
|
||||||
|
|
||||||
|
|
||||||
if (!priv->settings.frame_width && !priv->settings.frame_height)
|
if (!priv->settings.frame_width && !priv->settings.frame_height)
|
||||||
return 1; // library not initialized
|
return 1; // library not initialized
|
||||||
|
|
||||||
if (track->n_events == 0)
|
if (track->n_events == 0)
|
||||||
return 1; // nothing to do
|
return 1; // nothing to do
|
||||||
|
|
||||||
// Free composited images
|
|
||||||
while (text_info.free_count--)
|
|
||||||
free(text_info.free_list[i++]);
|
|
||||||
text_info.free_count = 0;
|
|
||||||
|
|
||||||
|
ass_free_objects();
|
||||||
|
|
||||||
frame_context.ass_priv = priv;
|
frame_context.ass_priv = priv;
|
||||||
frame_context.width = global_settings->frame_width;
|
frame_context.width = global_settings->frame_width;
|
||||||
frame_context.height = global_settings->frame_height;
|
frame_context.height = global_settings->frame_height;
|
||||||
|
@ -2362,11 +2340,10 @@ static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long n
|
||||||
frame_context.orig_height / frame_context.track->PlayResY;
|
frame_context.orig_height / frame_context.track->PlayResY;
|
||||||
frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY;
|
frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY;
|
||||||
|
|
||||||
frame_context.font_scale_x = ((double)(frame_context.orig_width * track->PlayResY)) / (frame_context.orig_height * track->PlayResX);
|
frame_context.font_scale_x = 1.;
|
||||||
frame_context.font_scale_x = 1.0;
|
|
||||||
priv->prev_images_root = priv->images_root;
|
priv->prev_images_root = priv->images_root;
|
||||||
priv->images_root = 0;
|
priv->images_root = 0;
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,19 +32,17 @@
|
||||||
|
|
||||||
int mystrtoi(char** p, int base, int* res)
|
int mystrtoi(char** p, int base, int* res)
|
||||||
{
|
{
|
||||||
// NOTE: base argument is ignored, but not used anyway
|
// NOTE: base argument is ignored, but not used in libass anyway
|
||||||
double temp_res;
|
double temp_res;
|
||||||
char* start = *p;
|
char* start = *p;
|
||||||
temp_res = strtod(*p, p);
|
temp_res = strtod(*p, p);
|
||||||
*res = (int) (temp_res + 0.5);
|
*res = (int) (temp_res + 0.5);
|
||||||
//printf("read %f, rounded to %d\n", temp_res, *res);
|
|
||||||
if (*p != start) return 1;
|
if (*p != start) return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mystrtoll(char** p, int base, long long* res)
|
int mystrtoll(char** p, int base, long long* res)
|
||||||
{
|
{
|
||||||
// NOTE: base argument is ignored, but not used anyway
|
|
||||||
double temp_res;
|
double temp_res;
|
||||||
char* start = *p;
|
char* start = *p;
|
||||||
temp_res = strtod(*p, p);
|
temp_res = strtod(*p, p);
|
||||||
|
|
Loading…
Reference in a new issue