diff options
Diffstat (limited to 'libass/ass_outline.c')
-rw-r--r-- | libass/ass_outline.c | 164 |
1 files changed, 73 insertions, 91 deletions
diff --git a/libass/ass_outline.c b/libass/ass_outline.c index 8abc29f..a1dfa1e 100644 --- a/libass/ass_outline.c +++ b/libass/ass_outline.c @@ -27,7 +27,7 @@ bool outline_alloc(ASS_Outline *outline, size_t n_points, size_t n_contours) { outline->contours = malloc(sizeof(size_t) * n_contours); - outline->points = malloc(sizeof(FT_Vector) * n_points); + outline->points = malloc(sizeof(ASS_Vector) * n_points); outline->tags = malloc(n_points); if (!outline->contours || !outline->points || !outline->tags) { outline_free(outline); @@ -65,7 +65,10 @@ bool outline_convert(ASS_Outline *outline, const FT_Outline *source) size_t n = source->contours[i] - start + 1; // skip degenerate 2-point contours from broken fonts if (n >= 3) { - memcpy(outline->points + outline->n_points, source->points + start, sizeof(FT_Vector) * n); + for (size_t k = 0; k < n; k++) { + outline->points[outline->n_points + k].x = source->points[start + k].x; + outline->points[outline->n_points + k].y = source->points[start + k].y; + } memcpy(outline->tags + outline->n_points, source->tags + start, n); outline->n_points += n; @@ -87,7 +90,7 @@ bool outline_copy(ASS_Outline *outline, const ASS_Outline *source) return false; memcpy(outline->contours, source->contours, sizeof(size_t) * source->n_contours); - memcpy(outline->points, source->points, sizeof(FT_Vector) * source->n_points); + memcpy(outline->points, source->points, sizeof(ASS_Vector) * source->n_points); memcpy(outline->tags, source->tags, source->n_points); outline->n_contours = source->n_contours; outline->n_points = source->n_points; @@ -110,7 +113,7 @@ void outline_free(ASS_Outline *outline) /* * \brief Add a single point to a contour. */ -bool outline_add_point(ASS_Outline *outline, FT_Vector pt, char tag) +bool outline_add_point(ASS_Outline *outline, ASS_Vector pt, char tag) { if (outline->n_points >= outline->max_points) { size_t new_size = 2 * outline->max_points; @@ -143,7 +146,7 @@ bool outline_close_contour(ASS_Outline *outline) } -void outline_translate(const ASS_Outline *outline, FT_Pos dx, FT_Pos dy) +void outline_translate(const ASS_Outline *outline, int32_t dx, int32_t dy) { for (size_t i = 0; i < outline->n_points; i++) { outline->points[i].x += dx; @@ -154,42 +157,29 @@ void outline_translate(const ASS_Outline *outline, FT_Pos dx, FT_Pos dy) void outline_transform(const ASS_Outline *outline, const FT_Matrix *matrix) { for (size_t i = 0; i < outline->n_points; i++) { - FT_Pos x = FT_MulFix(outline->points[i].x, matrix->xx) + - FT_MulFix(outline->points[i].y, matrix->xy); - FT_Pos y = FT_MulFix(outline->points[i].x, matrix->yx) + - FT_MulFix(outline->points[i].y, matrix->yy); + int32_t x = FT_MulFix(outline->points[i].x, matrix->xx) + + FT_MulFix(outline->points[i].y, matrix->xy); + int32_t y = FT_MulFix(outline->points[i].x, matrix->yx) + + FT_MulFix(outline->points[i].y, matrix->yy); outline->points[i].x = x; outline->points[i].y = y; } } -void outline_update_cbox(const ASS_Outline *outline, FT_BBox *cbox) -{ - if (!outline) - return; - - for (size_t i = 0; i < outline->n_points; i++) { - cbox->xMin = FFMIN(cbox->xMin, outline->points[i].x); - cbox->xMax = FFMAX(cbox->xMax, outline->points[i].x); - cbox->yMin = FFMIN(cbox->yMin, outline->points[i].y); - cbox->yMax = FFMAX(cbox->yMax, outline->points[i].y); - } -} - -void outline_get_cbox(const ASS_Outline *outline, FT_BBox *cbox) +void outline_get_cbox(const ASS_Outline *outline, ASS_Rect *cbox) { if (!outline->n_points) { - cbox->xMin = cbox->xMax = 0; - cbox->yMin = cbox->yMax = 0; + cbox->x_min = cbox->x_max = 0; + cbox->y_min = cbox->y_max = 0; return; } - cbox->xMin = cbox->xMax = outline->points[0].x; - cbox->yMin = cbox->yMax = outline->points[0].y; + cbox->x_min = cbox->x_max = outline->points[0].x; + cbox->y_min = cbox->y_max = outline->points[0].y; for (size_t i = 1; i < outline->n_points; i++) { - cbox->xMin = FFMIN(cbox->xMin, outline->points[i].x); - cbox->xMax = FFMAX(cbox->xMax, outline->points[i].x); - cbox->yMin = FFMIN(cbox->yMin, outline->points[i].y); - cbox->yMax = FFMAX(cbox->yMax, outline->points[i].y); + cbox->x_min = FFMIN(cbox->x_min, outline->points[i].x); + cbox->x_max = FFMAX(cbox->x_max, outline->points[i].x); + cbox->y_min = FFMIN(cbox->y_min, outline->points[i].y); + cbox->y_max = FFMAX(cbox->y_max, outline->points[i].y); } } @@ -245,15 +235,7 @@ void outline_get_cbox(const ASS_Outline *outline, FT_BBox *cbox) typedef struct { - int32_t x, y; -} OutlinePoint; - -typedef struct { - double x, y; -} Vector; - -typedef struct { - Vector v; + ASS_DVector v; double len; } Normal; @@ -268,9 +250,9 @@ typedef struct { // skip flags for first and last point int first_skip, last_skip; // normal at first and last point - Vector first_normal, last_normal; + ASS_DVector first_normal, last_normal; // first and last point of current contour - OutlinePoint first_point, last_point; + ASS_Vector first_point, last_point; // cosinus of maximal angle that do not require cap double merge_cos; @@ -289,7 +271,7 @@ typedef struct { /** * \brief 2D vector dot product */ -static inline double vec_dot(Vector vec1, Vector vec2) +static inline double vec_dot(ASS_DVector vec1, ASS_DVector vec2) { return vec1.x * vec2.x + vec1.y * vec2.y; } @@ -297,7 +279,7 @@ static inline double vec_dot(Vector vec1, Vector vec2) /** * \brief 2D vector cross product */ -static inline double vec_crs(Vector vec1, Vector vec2) +static inline double vec_crs(ASS_DVector vec1, ASS_DVector vec2) { return vec1.x * vec2.y - vec1.y * vec2.x; } @@ -305,7 +287,7 @@ static inline double vec_crs(Vector vec1, Vector vec2) /** * \brief 2D vector length */ -static inline double vec_len(Vector vec) +static inline double vec_len(ASS_DVector vec) { return sqrt(vec.x * vec.x + vec.y * vec.y); } @@ -320,20 +302,20 @@ static inline double vec_len(Vector vec) * \param dir destination outline flags * \return false on allocation failure */ -static bool emit_point(StrokerState *str, OutlinePoint pt, - Vector offs, char tag, int dir) +static bool emit_point(StrokerState *str, ASS_Vector pt, + ASS_DVector offs, char tag, int dir) { int32_t dx = (int32_t) (str->xbord * offs.x); int32_t dy = (int32_t) (str->ybord * offs.y); if (dir & 1) { - FT_Vector res = { pt.x + dx, pt.y + dy }; + ASS_Vector res = { pt.x + dx, pt.y + dy }; res.y = -res.y; if (!outline_add_point(str->result[0], res, tag)) return false; } if (dir & 2) { - FT_Vector res = { pt.x - dx, pt.y - dy }; + ASS_Vector res = { pt.x - dx, pt.y - dy }; res.y = -res.y; if (!outline_add_point(str->result[1], res, tag)) return false; @@ -348,14 +330,14 @@ static bool emit_point(StrokerState *str, OutlinePoint pt, * \param offs offset in normal space * \param dir destination outline flags */ -static void fix_first_point(StrokerState *str, OutlinePoint pt, - Vector offs, int dir) +static void fix_first_point(StrokerState *str, ASS_Vector pt, + ASS_DVector offs, int dir) { int32_t dx = (int32_t) (str->xbord * offs.x); int32_t dy = (int32_t) (str->ybord * offs.y); if (dir & 1) { - FT_Vector res = { pt.x + dx, pt.y + dy }; + ASS_Vector res = { pt.x + dx, pt.y + dy }; res.y = -res.y; ASS_Outline *ol = str->result[0]; size_t first = ol->n_contours ? @@ -363,7 +345,7 @@ static void fix_first_point(StrokerState *str, OutlinePoint pt, ol->points[first] = res; } if (dir & 2) { - FT_Vector res = { pt.x - dx, pt.y - dy }; + ASS_Vector res = { pt.x - dx, pt.y - dy }; res.y = -res.y; ASS_Outline *ol = str->result[1]; size_t first = ol->n_contours ? @@ -383,11 +365,11 @@ static void fix_first_point(StrokerState *str, OutlinePoint pt, * \param dir destination outline flags * \return false on allocation failure */ -static bool process_arc(StrokerState *str, OutlinePoint pt, - Vector normal0, Vector normal1, +static bool process_arc(StrokerState *str, ASS_Vector pt, + ASS_DVector normal0, ASS_DVector normal1, const double *mul, int level, int dir) { - Vector center; + ASS_DVector center; center.x = (normal0.x + normal1.x) * mul[level]; center.y = (normal0.y + normal1.y) * mul[level]; if (level) @@ -407,13 +389,13 @@ static bool process_arc(StrokerState *str, OutlinePoint pt, * \param dir destination outline flags * \return false on allocation failure */ -static bool draw_arc(StrokerState *str, OutlinePoint pt, - Vector normal0, Vector normal1, double c, int dir) +static bool draw_arc(StrokerState *str, ASS_Vector pt, + ASS_DVector normal0, ASS_DVector normal1, double c, int dir) { const int max_subdiv = 15; double mul[max_subdiv + 1]; - Vector center; + ASS_DVector center; bool small_angle = true; if (c < 0) { double mul = dir & 2 ? -sqrt(0.5) : sqrt(0.5); @@ -444,7 +426,7 @@ static bool draw_arc(StrokerState *str, OutlinePoint pt, * \param dir destination outline flags * \return false on allocation failure */ -static bool draw_circle(StrokerState *str, OutlinePoint pt, int dir) +static bool draw_circle(StrokerState *str, ASS_Vector pt, int dir) { const int max_subdiv = 15; double mul[max_subdiv + 1], c = 0; @@ -457,7 +439,7 @@ static bool draw_circle(StrokerState *str, OutlinePoint pt, int dir) } mul[pos] = 1 / (1 + c); - Vector normal[4] = { + ASS_DVector normal[4] = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; return process_arc(str, pt, normal[0], normal[1], mul + pos, max_subdiv - pos, dir) && @@ -474,8 +456,8 @@ static bool draw_circle(StrokerState *str, OutlinePoint pt, int dir) * \param dir destination outline flags * \return false on allocation failure */ -static bool start_segment(StrokerState *str, OutlinePoint pt, - Vector normal, int dir) +static bool start_segment(StrokerState *str, ASS_Vector pt, + ASS_DVector normal, int dir) { if (str->contour_start) { str->contour_start = false; @@ -485,7 +467,7 @@ static bool start_segment(StrokerState *str, OutlinePoint pt, return true; } - Vector prev = str->last_normal; + ASS_DVector prev = str->last_normal; double c = vec_dot(prev, normal); if (c > str->merge_cos) { // merge without cap double mul = 1 / (1 + c); @@ -501,7 +483,7 @@ static bool start_segment(StrokerState *str, OutlinePoint pt, if (dir & skip_dir) { if (!emit_point(str, pt, prev, FT_CURVE_TAG_ON, ~str->last_skip & skip_dir)) return false; - Vector zero_normal = {0, 0}; + ASS_DVector zero_normal = {0, 0}; if (!emit_point(str, pt, zero_normal, FT_CURVE_TAG_ON, skip_dir)) return false; } @@ -514,7 +496,7 @@ static bool start_segment(StrokerState *str, OutlinePoint pt, /** * \brief Same as emit_point() but also updates skip flags */ -static bool emit_first_point(StrokerState *str, OutlinePoint pt, int dir) +static bool emit_first_point(StrokerState *str, ASS_Vector pt, int dir) { str->last_skip &= ~dir; return emit_point(str, pt, str->last_normal, FT_CURVE_TAG_ON, dir); @@ -528,7 +510,7 @@ static bool emit_first_point(StrokerState *str, OutlinePoint pt, int dir) * \param first true if the skipped part is at start of the segment * \return false on allocation failure */ -static bool prepare_skip(StrokerState *str, OutlinePoint pt, int dir, bool first) +static bool prepare_skip(StrokerState *str, ASS_Vector pt, int dir, bool first) { if (first) str->first_skip |= dir; @@ -545,16 +527,16 @@ static bool prepare_skip(StrokerState *str, OutlinePoint pt, int dir, bool first * \param dir destination outline flags * \return false on allocation failure */ -static bool add_line(StrokerState *str, OutlinePoint pt, int dir) +static bool add_line(StrokerState *str, ASS_Vector pt, int dir) { int32_t dx = pt.x - str->last_point.x; int32_t dy = pt.y - str->last_point.y; if (dx > -str->eps && dx < str->eps && dy > -str->eps && dy < str->eps) return true; - Vector deriv = { dy * str->yscale, -dx * str->xscale }; + ASS_DVector deriv = { dy * str->yscale, -dx * str->xscale }; double scale = 1 / vec_len(deriv); - Vector normal = { deriv.x * scale, deriv.y * scale }; + ASS_DVector normal = { deriv.x * scale, deriv.y * scale }; if (!start_segment(str, str->last_point, normal, dir)) return false; if (!emit_first_point(str, str->last_point, dir)) @@ -575,7 +557,7 @@ static bool add_line(StrokerState *str, OutlinePoint pt, int dir) * \return false if error is too large */ static bool estimate_quadratic_error(StrokerState *str, double c, double s, - const Normal *normal, Vector *result) + const Normal *normal, ASS_DVector *result) { // check radial error if (!((3 + c) * (3 + c) < str->err_q * (1 + c))) @@ -604,8 +586,8 @@ static bool estimate_quadratic_error(StrokerState *str, double c, double s, * \param first true if the current part is at start of the segment * \return false on allocation failure */ -static bool process_quadratic(StrokerState *str, const OutlinePoint *pt, - const Vector *deriv, const Normal *normal, +static bool process_quadratic(StrokerState *str, const ASS_Vector *pt, + const ASS_DVector *deriv, const Normal *normal, int dir, bool first) { double c = vec_dot(normal[0].v, normal[1].v); @@ -624,13 +606,13 @@ static bool process_quadratic(StrokerState *str, const OutlinePoint *pt, if (!prepare_skip(str, pt[0], skip_dir, first)) return false; if (f0 < 0 || f1 < 0) { - Vector zero_normal = {0, 0}; + ASS_DVector zero_normal = {0, 0}; if (!emit_point(str, pt[0], zero_normal, FT_CURVE_TAG_ON, skip_dir) || !emit_point(str, pt[2], zero_normal, FT_CURVE_TAG_ON, skip_dir)) return false; } else { double mul = f0 / abs_s; - Vector offs = { normal[0].v.x * mul, normal[0].v.y * mul }; + ASS_DVector offs = { normal[0].v.x * mul, normal[0].v.y * mul }; if (!emit_point(str, pt[0], offs, FT_CURVE_TAG_ON, skip_dir)) return false; } @@ -645,7 +627,7 @@ static bool process_quadratic(StrokerState *str, const OutlinePoint *pt, check_dir ^= skip_dir; } - Vector result; + ASS_DVector result; if (check_dir && estimate_quadratic_error(str, c, s, normal, &result)) { if (!emit_first_point(str, pt[0], check_dir)) return false; @@ -658,7 +640,7 @@ static bool process_quadratic(StrokerState *str, const OutlinePoint *pt, } } - OutlinePoint next[5]; + ASS_Vector next[5]; next[1].x = pt[0].x + pt[1].x; next[1].y = pt[0].y + pt[1].y; next[3].x = pt[1].x + pt[2].x; @@ -672,7 +654,7 @@ static bool process_quadratic(StrokerState *str, const OutlinePoint *pt, next[0] = pt[0]; next[4] = pt[2]; - Vector next_deriv[3]; + ASS_DVector next_deriv[3]; next_deriv[0].x = deriv[0].x / 2; next_deriv[0].y = deriv[0].y / 2; next_deriv[2].x = deriv[1].x / 2; @@ -707,7 +689,7 @@ static bool process_quadratic(StrokerState *str, const OutlinePoint *pt, * \param dir destination outline flags * \return false on allocation failure */ -static bool add_quadratic(StrokerState *str, const OutlinePoint *pt, int dir) +static bool add_quadratic(StrokerState *str, const ASS_Vector *pt, int dir) { int32_t dx0 = pt[1].x - pt[0].x; int32_t dy0 = pt[1].y - pt[0].y; @@ -719,7 +701,7 @@ static bool add_quadratic(StrokerState *str, const OutlinePoint *pt, int dir) if (dx1 > -str->eps && dx1 < str->eps && dy1 > -str->eps && dy1 < str->eps) return add_line(str, pt[2], dir); - Vector deriv[2] = { + ASS_DVector deriv[2] = { { dy0 * str->yscale, -dx0 * str->xscale }, { dy1 * str->yscale, -dx1 * str->xscale } }; @@ -770,7 +752,7 @@ enum { */ static int estimate_cubic_error(StrokerState *str, double c, double s, const double *dc, const double *ds, - const Normal *normal, Vector *result, + const Normal *normal, ASS_DVector *result, int check_flags, int dir) { double t = (ds[0] + ds[1]) / (dc[0] + dc[1]), c1 = 1 + c, ss = s * s; @@ -871,8 +853,8 @@ static int estimate_cubic_error(StrokerState *str, double c, double s, * \param first true if the current part is at start of the segment * \return false on allocation failure */ -static bool process_cubic(StrokerState *str, const OutlinePoint *pt, - const Vector *deriv, const Normal *normal, +static bool process_cubic(StrokerState *str, const ASS_Vector *pt, + const ASS_DVector *deriv, const Normal *normal, int dir, bool first) { double c = vec_dot(normal[0].v, normal[1].v); @@ -910,13 +892,13 @@ static bool process_cubic(StrokerState *str, const OutlinePoint *pt, if (!prepare_skip(str, pt[0], skip_dir, first)) return false; if (f0 < 0 || f1 < 0) { - Vector zero_normal = {0, 0}; + ASS_DVector zero_normal = {0, 0}; if (!emit_point(str, pt[0], zero_normal, FT_CURVE_TAG_ON, skip_dir) || !emit_point(str, pt[3], zero_normal, FT_CURVE_TAG_ON, skip_dir)) return false; } else { double mul = f0 / abs_s; - Vector offs = { normal[0].v.x * mul, normal[0].v.y * mul }; + ASS_DVector offs = { normal[0].v.x * mul, normal[0].v.y * mul }; if (!emit_point(str, pt[0], offs, FT_CURVE_TAG_ON, skip_dir)) return false; } @@ -974,7 +956,7 @@ static bool process_cubic(StrokerState *str, const OutlinePoint *pt, } } - Vector result[2]; + ASS_DVector result[2]; if (check_dir) check_dir = estimate_cubic_error(str, c, s, dc, ds, normal, result, flags, check_dir); @@ -991,7 +973,7 @@ static bool process_cubic(StrokerState *str, const OutlinePoint *pt, } } - OutlinePoint next[7], center; + ASS_Vector next[7], center; next[1].x = pt[0].x + pt[1].x; next[1].y = pt[0].y + pt[1].y; center.x = pt[1].x + pt[2].x + 2; @@ -1015,7 +997,7 @@ static bool process_cubic(StrokerState *str, const OutlinePoint *pt, next[0] = pt[0]; next[6] = pt[3]; - Vector next_deriv[5], center_deriv; + ASS_DVector next_deriv[5], center_deriv; next_deriv[0].x = deriv[0].x / 2; next_deriv[0].y = deriv[0].y / 2; center_deriv.x = deriv[1].x / 2; @@ -1099,7 +1081,7 @@ static bool process_cubic(StrokerState *str, const OutlinePoint *pt, * \param dir destination outline flags * \return false on allocation failure */ -static bool add_cubic(StrokerState *str, const OutlinePoint *pt, int dir) +static bool add_cubic(StrokerState *str, const ASS_Vector *pt, int dir) { int flags = 9; @@ -1129,7 +1111,7 @@ static bool add_cubic(StrokerState *str, const OutlinePoint *pt, int dir) int32_t dx1 = pt[flags >> 2].x - pt[flags & 3].x; int32_t dy1 = pt[flags >> 2].y - pt[flags & 3].y; - Vector deriv[3] = { + ASS_DVector deriv[3] = { { dy0 * str->yscale, -dx0 * str->xscale }, { dy1 * str->yscale, -dx1 * str->xscale }, { dy2 * str->yscale, -dx2 * str->xscale } @@ -1230,7 +1212,7 @@ bool outline_stroke(ASS_Outline *result, ASS_Outline *result1, const int dir = 3; for (size_t i = 0, j = 0; i < path->n_contours; i++) { - OutlinePoint start, p[4]; + ASS_Vector start, p[4]; int process_end = 1; enum Status st; |