summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2020-12-13 17:23:26 +0300
committerDr.Smile <vabnick@gmail.com>2021-02-22 18:44:54 +0300
commit82b225b3d6653091d028b39d561d185ed76a7be5 (patch)
tree7a41f473b4b5242919e3a3d8414fa17373132f8a
parent05cde3b5b686e41f96e6b5b1a731617f220aedda (diff)
downloadlibass-82b225b3d6653091d028b39d561d185ed76a7be5.tar.bz2
libass-82b225b3d6653091d028b39d561d185ed76a7be5.tar.xz
parsing: use string references for font family and drawing text
That eliminates most uses of strdup() in the rendering process.
-rw-r--r--libass/ass_cache.c19
-rw-r--r--libass/ass_cache_template.h6
-rw-r--r--libass/ass_font.c2
-rw-r--r--libass/ass_fontselect.c2
-rw-r--r--libass/ass_parse.c31
-rw-r--r--libass/ass_render.c50
-rw-r--r--libass/ass_render.h6
-rw-r--r--libass/ass_shaper.c4
-rw-r--r--libass/ass_utils.h33
9 files changed, 77 insertions, 76 deletions
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index d0dd6fb..70c0113 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -40,12 +40,13 @@
// font cache
static bool font_key_move(void *dst, void *src)
{
- ASS_FontDesc *k = src;
- if (dst)
- memcpy(dst, src, sizeof(ASS_FontDesc));
- else
- free(k->family);
- return true;
+ if (!dst)
+ return true;
+
+ ASS_FontDesc *d = dst, *s = dst;
+ memcpy(dst, src, sizeof(ASS_FontDesc));
+ d->family.str = ass_copy_string(s->family);
+ return d->family.str;
}
static void font_destruct(void *key, void *value)
@@ -207,8 +208,8 @@ static bool outline_key_move(void *dst, void *src)
}
memcpy(dst, src, sizeof(OutlineHashKey));
if (s->type == OUTLINE_DRAWING) {
- d->u.drawing.text = strdup(s->u.drawing.text);
- return d->u.drawing.text;
+ d->u.drawing.text.str = ass_copy_string(s->u.drawing.text);
+ return d->u.drawing.text.str;
}
if (s->type == OUTLINE_BORDER)
ass_cache_inc_ref(s->u.border.outline);
@@ -226,7 +227,7 @@ static void outline_destruct(void *key, void *value)
ass_cache_dec_ref(k->u.glyph.font);
break;
case OUTLINE_DRAWING:
- free(k->u.drawing.text);
+ free((char *) k->u.drawing.text.str);
break;
case OUTLINE_BORDER:
ass_cache_dec_ref(k->u.border.outline);
diff --git a/libass/ass_cache_template.h b/libass/ass_cache_template.h
index 80515c2..3328d44 100644
--- a/libass/ass_cache_template.h
+++ b/libass/ass_cache_template.h
@@ -5,7 +5,7 @@
#define GENERIC(type, member) \
type member;
#define STRING(member) \
- char *member;
+ ASS_StringView member;
#define VECTOR(member) \
ASS_Vector member;
#define END(typedefnamename) \
@@ -22,7 +22,7 @@
#define GENERIC(type, member) \
a->member == b->member &&
#define STRING(member) \
- strcmp(a->member, b->member) == 0 &&
+ ass_string_equal(a->member, b->member) &&
#define VECTOR(member) \
a->member.x == b->member.x && a->member.y == b->member.y &&
#define END(typedefname) \
@@ -38,7 +38,7 @@
#define GENERIC(type, member) \
hval = fnv_32a_buf(&p->member, sizeof(p->member), hval);
#define STRING(member) \
- hval = fnv_32a_str(p->member, hval);
+ hval = fnv_32a_buf(p->member.str, p->member.len, hval);
#define VECTOR(member) GENERIC(, member.x); GENERIC(, member.y);
#define END(typedefname) \
return hval; \
diff --git a/libass/ass_font.c b/libass/ass_font.c
index 29ee877..7d79d2e 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -588,5 +588,5 @@ void ass_font_clear(ASS_Font *font)
if (font->faces[i])
FT_Done_Face(font->faces[i]);
}
- free(font->desc.family);
+ free((char *) font->desc.family.str);
}
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c
index d360e1c..3bf034b 100644
--- a/libass/ass_fontselect.c
+++ b/libass/ass_fontselect.c
@@ -692,7 +692,7 @@ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library,
int *uid, ASS_FontStream *data, uint32_t code)
{
char *res = 0;
- const char *family = font->desc.family;
+ const char *family = font->desc.family.str; // always zero-terminated
unsigned bold = font->desc.bold;
unsigned italic = font->desc.italic;
ASS_FontProvider *default_provider = priv->default_provider;
diff --git a/libass/ass_parse.c b/libass/ass_parse.c
index 2e35e2b..8ba39c8 100644
--- a/libass/ass_parse.c
+++ b/libass/ass_parse.c
@@ -102,17 +102,16 @@ void update_font(ASS_Renderer *render_priv)
unsigned val;
ASS_FontDesc desc;
- if (!render_priv->state.family)
+ desc.family = render_priv->state.family;
+ if (!desc.family.str)
return;
- if (render_priv->state.family[0] == '@') {
+ if (desc.family.len && desc.family.str[0] == '@') {
desc.vertical = 1;
- desc.family = strdup(render_priv->state.family + 1);
+ desc.family.str++;
+ desc.family.len--;
} else {
desc.vertical = 0;
- desc.family = strdup(render_priv->state.family);
}
- if (!desc.family)
- return;
val = render_priv->state.bold;
// 0 = normal, 1 = bold, >1 = exact weight
@@ -234,7 +233,8 @@ static bool parse_vector_clip(ASS_Renderer *render_priv,
scale = argtoi(args[0]);
struct arg text = args[nargs - 1];
- render_priv->state.clip_drawing_text = strndup(text.start, text.end - text.start);
+ render_priv->state.clip_drawing_text.str = text.start;
+ render_priv->state.clip_drawing_text.len = text.end - text.start;
render_priv->state.clip_drawing_scale = scale;
return true;
}
@@ -381,7 +381,7 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
render_priv->state.clip_y1 =
render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr;
render_priv->state.clip_mode = 1;
- } else if (!render_priv->state.clip_drawing_text) {
+ } else if (!render_priv->state.clip_drawing_text.str) {
if (parse_vector_clip(render_priv, args, nargs))
render_priv->state.clip_drawing_mode = 1;
}
@@ -517,19 +517,16 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
render_priv->state.frz =
render_priv->state.style->Angle;
} else if (tag("fn")) {
- char *family;
char *start = args->start;
if (nargs && strncmp(start, "0", args->end - start)) {
skip_spaces(&start);
- family = strndup(start, args->end - start);
+ render_priv->state.family.str = start;
+ render_priv->state.family.len = args->end - start;
} else {
- family = strdup(render_priv->state.style->FontName);
- }
- if (family) {
- free(render_priv->state.family);
- render_priv->state.family = family;
- update_font(render_priv);
+ render_priv->state.family.str = render_priv->state.style->FontName;
+ render_priv->state.family.len = strlen(render_priv->state.style->FontName);
}
+ update_font(render_priv);
} else if (tag("alpha")) {
int i;
if (nargs) {
@@ -708,7 +705,7 @@ char *parse_tags(ASS_Renderer *render_priv, char *p, char *end, double pwr,
render_priv->state.clip_y1 =
render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr;
render_priv->state.clip_mode = 0;
- } else if (!render_priv->state.clip_drawing_text) {
+ } else if (!render_priv->state.clip_drawing_text.str) {
if (parse_vector_clip(render_priv, args, nargs))
render_priv->state.clip_drawing_mode = 0;
}
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 56ed2f3..1962702 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -644,7 +644,7 @@ static inline size_t bitmap_size(const Bitmap *bm)
*/
static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head)
{
- if (!render_priv->state.clip_drawing_text)
+ if (!render_priv->state.clip_drawing_text.str)
return;
OutlineHashKey ol_key;
@@ -998,13 +998,9 @@ void reset_render_context(ASS_Renderer *render_priv, ASS_Style *style)
(style->StrikeOut ? DECO_STRIKETHROUGH : 0);
render_priv->state.font_size = style->FontSize;
- char* new_family = strdup(style->FontName);
- if (new_family) {
- free(render_priv->state.family);
- render_priv->state.family = new_family;
- render_priv->state.treat_family_as_pattern =
- style->treat_fontname_as_pattern;
- }
+ render_priv->state.family.str = style->FontName;
+ render_priv->state.family.len = strlen(style->FontName);
+ render_priv->state.treat_family_as_pattern = style->treat_fontname_as_pattern;
render_priv->state.bold = style->Bold;
render_priv->state.italic = style->Italic;
update_font(render_priv);
@@ -1067,17 +1063,14 @@ init_render_context(ASS_Renderer *render_priv, ASS_Event *event)
static void free_render_context(ASS_Renderer *render_priv)
{
ass_cache_dec_ref(render_priv->state.font);
- free(render_priv->state.family);
- free(render_priv->state.clip_drawing_text);
render_priv->state.font = NULL;
- render_priv->state.family = NULL;
- render_priv->state.clip_drawing_text = NULL;
+ render_priv->state.family.str = NULL;
+ render_priv->state.family.len = 0;
+ render_priv->state.clip_drawing_text.str = NULL;
+ render_priv->state.clip_drawing_text.len = 0;
- TextInfo *text_info = &render_priv->text_info;
- for (int n = 0; n < text_info->length; n++)
- free(text_info->glyphs[n].drawing_text);
- text_info->length = 0;
+ render_priv->text_info.length = 0;
}
/**
@@ -1095,7 +1088,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
int32_t asc, desc;
OutlineHashKey key;
- if (info->drawing_text) {
+ if (info->drawing_text.str) {
key.type = OUTLINE_DRAWING;
key.u.drawing.text = info->drawing_text;
val = ass_cache_get(priv->cache.outline_cache, &key, priv);
@@ -1143,7 +1136,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
info->bbox.x_max = lrint(val->cbox.x_max * scale.x + offset.x);
info->bbox.y_max = lrint(val->cbox.y_max * scale.y + offset.y);
- if (info->drawing_text || priv->settings.shaper == ASS_SHAPING_SIMPLE) {
+ if (info->drawing_text.str || priv->settings.shaper == ASS_SHAPING_SIMPLE) {
info->cluster_advance.x = info->advance.x = lrint(val->advance * scale.x);
info->cluster_advance.y = info->advance.y = 0;
}
@@ -1180,7 +1173,7 @@ size_t ass_outline_construct(void *key, void *value, void *priv)
case OUTLINE_DRAWING:
{
ASS_Rect bbox;
- const char *text = outline_key->u.drawing.text;
+ const char *text = outline_key->u.drawing.text.str; // always zero-terminated
if (!ass_drawing_parse(&v->outline[0], &bbox, text, render_priv->library))
return 1;
@@ -1874,9 +1867,9 @@ static void split_style_runs(ASS_Renderer *render_priv)
info->starts_new_run =
info->effect_timing || // but ignore effect_skip_timing
(effect_type != EF_NONE && effect_type != last_effect_type) ||
- info->drawing_text ||
- last->drawing_text ||
- strcmp(last->font->desc.family, info->font->desc.family) ||
+ info->drawing_text.str ||
+ last->drawing_text.str ||
+ !ass_string_equal(last->font->desc.family, info->font->desc.family) ||
last->font->desc.vertical != info->font->desc.vertical ||
last->font_size != info->font_size ||
last->c[0] != info->c[0] ||
@@ -1913,11 +1906,10 @@ static bool parse_events(ASS_Renderer *render_priv, ASS_Event *event)
TextInfo *text_info = &render_priv->text_info;
char *p = event->Text, *q;
- char *drawing_text;
// Event parsing.
while (true) {
- drawing_text = NULL;
+ ASS_StringView drawing_text = {NULL, 0};
// get next char, executing style override
// this affects render_context
@@ -1933,7 +1925,8 @@ static bool parse_events(ASS_Renderer *render_priv, ASS_Event *event)
q++;
while ((*q != '{') && (*q != 0))
q++;
- drawing_text = strndup(p, q - p);
+ drawing_text.str = p;
+ drawing_text.len = q - p;
code = 0xfffc; // object replacement character
p = q;
break;
@@ -1966,7 +1959,7 @@ static bool parse_events(ASS_Renderer *render_priv, ASS_Event *event)
memset(info, 0, sizeof(GlyphInfo));
// Parse drawing
- if (drawing_text) {
+ if (drawing_text.str) {
info->drawing_text = drawing_text;
info->drawing_scale = render_priv->state.drawing_scale;
info->drawing_pbo = render_priv->state.pbo;
@@ -1975,7 +1968,7 @@ static bool parse_events(ASS_Renderer *render_priv, ASS_Event *event)
// Fill glyph information
info->symbol = code;
info->font = render_priv->state.font;
- if (!drawing_text)
+ if (!drawing_text.str)
ass_cache_inc_ref(info->font);
for (int i = 0; i < 4; i++) {
uint32_t clr = render_priv->state.c[i];
@@ -2018,7 +2011,7 @@ static bool parse_events(ASS_Renderer *render_priv, ASS_Event *event)
render_priv->font_scale * info->scale_x);
info->scale_fix = 1;
- if (!drawing_text)
+ if (!drawing_text.str)
fix_glyph_scaling(render_priv, info);
text_info->length++;
@@ -2032,7 +2025,6 @@ static bool parse_events(ASS_Renderer *render_priv, ASS_Event *event)
fail:
free_render_context(render_priv);
- free(drawing_text);
return false;
}
diff --git a/libass/ass_render.h b/libass/ass_render.h
index 43a7185..18d87ba 100644
--- a/libass/ass_render.h
+++ b/libass/ass_render.h
@@ -131,7 +131,7 @@ typedef struct glyph_info {
int glyph_index;
hb_script_t script;
double font_size;
- char *drawing_text;
+ ASS_StringView drawing_text;
int drawing_scale;
int drawing_pbo;
OutlineHashValue *outline;
@@ -239,7 +239,7 @@ typedef struct {
double shadow_x;
double shadow_y;
double pbo; // drawing baseline offset
- char *clip_drawing_text;
+ ASS_StringView clip_drawing_text;
// used to store RenderContext.style when doing selective style overrides
ASS_Style override_style_temp_storage;
@@ -262,7 +262,7 @@ typedef struct {
int scroll_y0, scroll_y1;
// face properties
- char *family;
+ ASS_StringView family;
unsigned bold;
unsigned italic;
int treat_family_as_pattern;
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
index 41392c6..4665e7a 100644
--- a/libass/ass_shaper.c
+++ b/libass/ass_shaper.c
@@ -665,7 +665,7 @@ static bool shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
glyphs[i].skip = true;
for (i = 0; i < len; i++) {
- if (glyphs[i].drawing_text) {
+ if (glyphs[i].drawing_text.str) {
glyphs[i].skip = false;
continue;
}
@@ -805,7 +805,7 @@ void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
// find appropriate fonts for the shape runs
for (i = 0; i < len; i++) {
GlyphInfo *info = glyphs + i;
- if (!info->drawing_text) {
+ if (!info->drawing_text.str) {
// set size and get glyph index
ass_font_get_index(render_priv->fontselect, info->font,
info->symbol, &info->face_index, &info->glyph_index);
diff --git a/libass/ass_utils.h b/libass/ass_utils.h
index 1108c90..3f65b87 100644
--- a/libass/ass_utils.h
+++ b/libass/ass_utils.h
@@ -52,6 +52,26 @@ int has_avx(void);
int has_avx2(void);
#endif
+typedef struct {
+ const char *str;
+ size_t len;
+} ASS_StringView;
+
+static inline char *ass_copy_string(ASS_StringView src)
+{
+ char *buf = malloc(src.len + 1);
+ if (buf) {
+ memcpy(buf, src.str, src.len);
+ buf[src.len] = '\0';
+ }
+ return buf;
+}
+
+static inline bool ass_string_equal(ASS_StringView str1, ASS_StringView str2)
+{
+ return str1.len == str2.len && !memcmp(str1.str, str2.str, str1.len);
+}
+
#ifndef HAVE_STRNDUP
char *ass_strndup(const char *s, size_t n);
#define strndup ass_strndup
@@ -163,9 +183,9 @@ static inline int double_to_d22(double x)
#define FNV1_32A_INIT 0x811c9dc5U
#define FNV1_32A_PRIME 16777619U
-static inline uint32_t fnv_32a_buf(void *buf, size_t len, uint32_t hval)
+static inline uint32_t fnv_32a_buf(const void *buf, size_t len, uint32_t hval)
{
- unsigned char *bp = (unsigned char *) buf;
+ const uint8_t *bp = buf;
size_t n = (len + 3) / 4;
switch (len % 4) {
@@ -178,15 +198,6 @@ static inline uint32_t fnv_32a_buf(void *buf, size_t len, uint32_t hval)
return hval;
}
-static inline uint32_t fnv_32a_str(const char *str, uint32_t hval)
-{
- unsigned char *s = (unsigned char *) str;
- while (*s) {
- hval ^= *s++;
- hval *= FNV1_32A_PRIME;
- }
- return hval;
-}
static inline int mystrtoi(char **p, int *res)
{