Skip to content

Commit

Permalink
Replace FT_Outline with ASS_Outline
Browse files Browse the repository at this point in the history
  • Loading branch information
MrSmile committed Nov 23, 2014
1 parent f3f8230 commit 507ae26
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 142 deletions.
45 changes: 41 additions & 4 deletions libass/ass_bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ Bitmap *copy_bitmap(const Bitmap *src)
#if CONFIG_RASTERIZER

Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,
FT_Outline *outline, int bord)
ASS_Outline *outline, int bord)
{
ASS_Rasterizer *rst = &render_priv->rasterizer;
if (!rasterizer_set_outline(rst, outline)) {
Expand Down Expand Up @@ -343,8 +343,8 @@ Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,

#else

Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,
FT_Outline *outline, int bord)
static Bitmap *outline_to_bitmap_ft(ASS_Renderer *render_priv,
FT_Outline *outline, int bord)
{
Bitmap *bm;
int w, h;
Expand Down Expand Up @@ -406,6 +406,42 @@ Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,
return bm;
}

Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,
ASS_Outline *outline, int bord)
{
size_t n_points = outline->n_points;
if (n_points > SHRT_MAX) {
ass_msg(render_priv->library, MSGL_WARN, "Too many outline points: %d",
outline->n_points);
n_points = SHRT_MAX;
}

size_t n_contours = FFMIN(outline->n_contours, SHRT_MAX);
short contours_small[EFFICIENT_CONTOUR_COUNT];
short *contours = contours_small;
short *contours_large = NULL;
if (n_contours > EFFICIENT_CONTOUR_COUNT) {
contours_large = malloc(n_contours * sizeof(short));
if (!contours_large)
return NULL;
contours = contours_large;
}
for (size_t i = 0; i < n_contours; ++i)
contours[i] = FFMIN(outline->contours[i], n_points - 1);

FT_Outline ftol;
ftol.n_points = n_points;
ftol.n_contours = n_contours;
ftol.points = outline->points;
ftol.tags = outline->tags;
ftol.contours = contours;
ftol.flags = 0;

Bitmap *bm = outline_to_bitmap_ft(render_priv, &ftol, bord);
free(contours_large);
return bm;
}

#endif

/**
Expand Down Expand Up @@ -671,7 +707,8 @@ void be_blur_c(uint8_t *buf, intptr_t w,
}
}

int outline_to_bitmap3(ASS_Renderer *render_priv, FT_Outline *outline, FT_Outline *border,
int outline_to_bitmap3(ASS_Renderer *render_priv,
ASS_Outline *outline, ASS_Outline *border,
Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s,
int be, double blur_radius, FT_Vector shadow_offset,
int border_style, int border_visible)
Expand Down
14 changes: 12 additions & 2 deletions libass/ass_bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ typedef struct ass_synth_priv ASS_SynthPriv;
ASS_SynthPriv *ass_synth_init(double);
void ass_synth_done(ASS_SynthPriv *priv);

typedef struct {
size_t n_contours, max_contours;
size_t *contours;
size_t n_points, max_points;
FT_Vector *points;
char *tags;
} ASS_Outline;

#define EFFICIENT_CONTOUR_COUNT 8

typedef struct {
int left, top;
int w, h; // width, height
Expand All @@ -37,7 +47,7 @@ typedef struct {
} Bitmap;

Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,
FT_Outline *outline, int bord);
ASS_Outline *outline, int bord);

Bitmap *alloc_bitmap(int w, int h);

Expand All @@ -54,7 +64,7 @@ void ass_synth_blur(ASS_SynthPriv *priv_blur, int opaque_box, int be,
* \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
* \param border_visible whether border is visible if border_style is 3
*/
int outline_to_bitmap3(ASS_Renderer *render_priv, FT_Outline *outline, FT_Outline *border,
int outline_to_bitmap3(ASS_Renderer *render_priv, ASS_Outline *outline, ASS_Outline *border,
Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s,
int be, double blur_radius, FT_Vector shadow_offset,
int border_style, int border_visible);
Expand Down
8 changes: 4 additions & 4 deletions libass/ass_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,10 @@ static void outline_destruct(void *key, void *value)
{
OutlineHashValue *v = value;
OutlineHashKey *k = key;
if (v->outline)
outline_free(v->lib, v->outline);
if (v->border)
outline_free(v->lib, v->border);
outline_free(v->outline);
free(v->outline);
outline_free(v->border);
free(v->border);
if (k->type == OUTLINE_DRAWING)
free(k->u.drawing.text);
free(key);
Expand Down
5 changes: 2 additions & 3 deletions libass/ass_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ typedef struct {
} CompositeHashValue;

typedef struct {
FT_Library lib;
FT_Outline *outline;
FT_Outline *border;
ASS_Outline *outline;
ASS_Outline *border;
FT_BBox bbox_scaled; // bbox after scaling, but before rotation
FT_Vector advance; // 26.6, advance distance to the next outline in line
int asc, desc; // ascender/descender
Expand Down
94 changes: 46 additions & 48 deletions libass/ass_drawing.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
#include FT_OUTLINE_H
#include FT_BBOX_H
#include <math.h>
#include <stdbool.h>
#include <limits.h>

#include "ass_utils.h"
#include "ass_drawing.h"
#include "ass_font.h"

#define CURVE_ACCURACY 64.0
#define GLYPH_INITIAL_POINTS 100
Expand All @@ -32,46 +34,42 @@
/*
* \brief Add a single point to a contour.
*/
static inline void drawing_add_point(ASS_Drawing *drawing,
static inline bool drawing_add_point(ASS_Drawing *drawing,
const FT_Vector *point, char tags)
{
FT_Outline *ol = &drawing->outline;
if (ol->n_points == SHRT_MAX)
return;

if (ol->n_points >= drawing->max_points) {
drawing->max_points *= 2;
ol->points = realloc(ol->points, sizeof(FT_Vector) *
drawing->max_points);
ol->tags = realloc(ol->tags, drawing->max_points);
ASS_Outline *ol = &drawing->outline;
if (ol->n_points >= ol->max_points) {
size_t new_size = 2 * ol->max_points;
if (!ASS_REALLOC_ARRAY(ol->points, new_size))
return false;
if (!ASS_REALLOC_ARRAY(ol->tags, new_size))
return false;
ol->max_points = new_size;
}

ol->points[ol->n_points].x = point->x;
ol->points[ol->n_points].y = point->y;
ol->tags[ol->n_points] = tags;
ol->n_points++;
return true;
}

/*
* \brief Close a contour and check outline size overflow.
*/
static inline void drawing_close_shape(ASS_Drawing *drawing)
static inline bool drawing_close_shape(ASS_Drawing *drawing)
{
FT_Outline *ol = &drawing->outline;
if (ol->n_contours == SHRT_MAX) {
if (ol->n_points)
ol->contours[ol->n_contours] = ol->n_points - 1;
return;
}

if (ol->n_contours >= drawing->max_contours) {
drawing->max_contours *= 2;
ol->contours = realloc(ol->contours, sizeof(short) *
drawing->max_contours);
ASS_Outline *ol = &drawing->outline;
if (ol->n_contours >= ol->max_contours) {
size_t new_size = 2 * ol->max_contours;
if (!ASS_REALLOC_ARRAY(ol->contours, new_size))
return false;
ol->max_contours = new_size;
}

ol->contours[ol->n_contours] = ol->n_points - 1;
ol->n_contours++;
return true;
}

/*
Expand All @@ -93,7 +91,7 @@ static void drawing_finish(ASS_Drawing *drawing, int raw_mode)
int i;
double pbo;
FT_BBox bbox = drawing->cbox;
FT_Outline *ol = &drawing->outline;
ASS_Outline *ol = &drawing->outline;

if (drawing->library)
ass_msg(drawing->library, MSGL_V,
Expand Down Expand Up @@ -241,7 +239,7 @@ static inline void translate_point(ASS_Drawing *drawing, FT_Vector *point)
* This curve evaluator is also used in VSFilter (RTS.cpp); it's a simple
* implementation of the De Casteljau algorithm.
*/
static void drawing_evaluate_curve(ASS_Drawing *drawing,
static bool drawing_evaluate_curve(ASS_Drawing *drawing,
ASS_DrawingToken *token, char spline,
int started)
{
Expand Down Expand Up @@ -270,21 +268,18 @@ static void drawing_evaluate_curve(ASS_Drawing *drawing,
p[2].y -= y12;
}

if (!started)
drawing_add_point(drawing, &p[0], FT_CURVE_TAG_ON);
drawing_add_point(drawing, &p[1], FT_CURVE_TAG_CUBIC);
drawing_add_point(drawing, &p[2], FT_CURVE_TAG_CUBIC);
drawing_add_point(drawing, &p[3], FT_CURVE_TAG_ON);
return (started || drawing_add_point(drawing, &p[0], FT_CURVE_TAG_ON)) &&
drawing_add_point(drawing, &p[1], FT_CURVE_TAG_CUBIC) &&
drawing_add_point(drawing, &p[2], FT_CURVE_TAG_CUBIC) &&
drawing_add_point(drawing, &p[3], FT_CURVE_TAG_ON);
}

/*
* \brief Create and initialize a new drawing and return it
*/
ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib)
{
ASS_Drawing *drawing;

drawing = calloc(1, sizeof(*drawing));
ASS_Drawing *drawing = calloc(1, sizeof(*drawing));
if (!drawing)
return NULL;
drawing->cbox.xMin = drawing->cbox.yMin = INT_MAX;
Expand All @@ -293,14 +288,8 @@ ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib)
drawing->library = lib;
drawing->scale_x = 1.;
drawing->scale_y = 1.;
drawing->max_contours = GLYPH_INITIAL_CONTOURS;
drawing->max_points = GLYPH_INITIAL_POINTS;

FT_Outline_New(drawing->ftlibrary, GLYPH_INITIAL_POINTS,
GLYPH_INITIAL_CONTOURS, &drawing->outline);
drawing->outline.n_contours = 0;
drawing->outline.n_points = 0;

outline_alloc(&drawing->outline, GLYPH_INITIAL_POINTS, GLYPH_INITIAL_CONTOURS);
return drawing;
}

Expand All @@ -311,7 +300,7 @@ void ass_drawing_free(ASS_Drawing* drawing)
{
if (drawing) {
free(drawing->text);
FT_Outline_Done(drawing->ftlibrary, &drawing->outline);
outline_free(&drawing->outline);
}
free(drawing);
}
Expand Down Expand Up @@ -339,7 +328,7 @@ void ass_drawing_hash(ASS_Drawing* drawing)
/*
* \brief Convert token list to outline. Calls the line and curve evaluators.
*/
FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
{
int started = 0;
ASS_DrawingToken *token;
Expand All @@ -361,7 +350,8 @@ FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
pen = token->point;
translate_point(drawing, &pen);
if (started) {
drawing_close_shape(drawing);
if (!drawing_close_shape(drawing))
goto error;
started = 0;
}
token = token->next;
Expand All @@ -370,16 +360,19 @@ FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
FT_Vector to;
to = token->point;
translate_point(drawing, &to);
if (!started) drawing_add_point(drawing, &pen, FT_CURVE_TAG_ON);
drawing_add_point(drawing, &to, FT_CURVE_TAG_ON);
if (!started && !drawing_add_point(drawing, &pen, FT_CURVE_TAG_ON))
goto error;
if (!drawing_add_point(drawing, &to, FT_CURVE_TAG_ON))
goto error;
started = 1;
token = token->next;
break;
}
case TOKEN_CUBIC_BEZIER:
if (token_check_values(token, 3, TOKEN_CUBIC_BEZIER) &&
token->prev) {
drawing_evaluate_curve(drawing, token->prev, 0, started);
if (!drawing_evaluate_curve(drawing, token->prev, 0, started))
goto error;
token = token->next;
token = token->next;
token = token->next;
Expand All @@ -390,7 +383,8 @@ FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
case TOKEN_B_SPLINE:
if (token_check_values(token, 3, TOKEN_B_SPLINE) &&
token->prev) {
drawing_evaluate_curve(drawing, token->prev, 1, started);
if (!drawing_evaluate_curve(drawing, token->prev, 1, started))
goto error;
token = token->next;
started = 1;
} else
Expand All @@ -403,10 +397,14 @@ FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
}

// Close the last contour
if (started)
drawing_close_shape(drawing);
if (started && !drawing_close_shape(drawing))
goto error;

drawing_finish(drawing, raw_mode);
drawing_free_tokens(drawing->tokens);
return &drawing->outline;

error:
drawing_free_tokens(drawing->tokens);
return NULL;
}
7 changes: 3 additions & 4 deletions libass/ass_drawing.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include FT_OUTLINE_H

#include "ass.h"
#include "ass_bitmap.h"

typedef enum {
TOKEN_MOVE,
Expand Down Expand Up @@ -50,16 +51,14 @@ typedef struct {
double scale_y; // FontScaleY
int asc; // ascender
int desc; // descender
FT_Outline outline; // target outline
ASS_Outline outline; // target outline
FT_Vector advance; // advance (from cbox)
int hash; // hash value (for caching)

// private
FT_Library ftlibrary; // needed for font ops
ASS_Library *library;
ASS_DrawingToken *tokens; // tokenized drawing
int max_points; // current maximum size
int max_contours;
double point_scale_x;
double point_scale_y;
FT_BBox cbox; // bounding box, or let's say... VSFilter's idea of it
Expand All @@ -69,6 +68,6 @@ ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib);
void ass_drawing_free(ASS_Drawing* drawing);
void ass_drawing_set_text(ASS_Drawing* drawing, char *str, size_t n);
void ass_drawing_hash(ASS_Drawing* drawing);
FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode);
ASS_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode);

#endif /* LIBASS_DRAWING_H */
Loading

0 comments on commit 507ae26

Please sign in to comment.