diff options
-rw-r--r-- | engines/sword25/gfx/image/art.cpp | 136 |
1 files changed, 61 insertions, 75 deletions
diff --git a/engines/sword25/gfx/image/art.cpp b/engines/sword25/gfx/image/art.cpp index 2ba102e779..3944a207c8 100644 --- a/engines/sword25/gfx/image/art.cpp +++ b/engines/sword25/gfx/image/art.cpp @@ -328,18 +328,6 @@ static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max, double x2, double y2, double x3, double y3, double flatness) { - double x3_0, y3_0; - double z3_0_dot; - double z1_dot, z2_dot; - double z1_perp, z2_perp; - double max_perp_sq; - - double x_m, y_m; - double xa1, ya1; - double xa2, ya2; - double xb1, yb1; - double xb2, yb2; - /* It's possible to optimize this routine a fair amount. First, once the _dot conditions are met, they will also be met in @@ -363,11 +351,13 @@ static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max, */ - x3_0 = x3 - x0; - y3_0 = y3 - y0; + bool subDivide = false; + + double x3_0 = x3 - x0; + double y3_0 = y3 - y0; - /* z3_0_dot is dist z0-z3 squared */ - z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0; + // z3_0_dot is dist z0-z3 squared + double z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0; if (z3_0_dot < 0.001) { /* if start and end point are almost identical, the flatness tests @@ -375,72 +365,68 @@ static void art_vpath_render_bez(ArtVpath **p_vpath, int *pn, int *pn_max, * the other two control points are the same as the start point, * too. */ - if (hypot(x1 - x0, y1 - y0) < 0.001 - && hypot(x2 - x0, y2 - y0) < 0.001) - goto nosubdivide; - else - goto subdivide; - } - - /* we can avoid subdivision if: - - z1 has distance no more than flatness from the z0-z3 line - - z1 is no more z0'ward than flatness past z0-z3 - - z1 is more z0'ward than z3'ward on the line traversing z0-z3 - - and correspondingly for z2 */ - - /* perp is distance from line, multiplied by dist z0-z3 */ - max_perp_sq = flatness * flatness * z3_0_dot; - - z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0; - if (z1_perp * z1_perp > max_perp_sq) - goto subdivide; + if (!(hypot(x1 - x0, y1 - y0) < 0.001 + && hypot(x2 - x0, y2 - y0) < 0.001)) + subDivide = true; + } else { + /* we can avoid subdivision if: - z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0; - if (z2_perp * z2_perp > max_perp_sq) - goto subdivide; + z1 has distance no more than flatness from the z0-z3 line - z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0; - if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq) - goto subdivide; + z1 is no more z0'ward than flatness past z0-z3 - z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0; - if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq) - goto subdivide; + z1 is more z0'ward than z3'ward on the line traversing z0-z3 - if (z1_dot + z1_dot > z3_0_dot) - goto subdivide; + and correspondingly for z2 */ - if (z2_dot + z2_dot > z3_0_dot) - goto subdivide; + // perp is distance from line, multiplied by dist z0-z3 + double max_perp_sq = flatness * flatness * z3_0_dot; + double z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0; + if (z1_perp * z1_perp > max_perp_sq) { + subDivide = true; + } else { + double z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0; + if (z2_perp * z2_perp > max_perp_sq) { + subDivide = true; + } else { + double z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0; + if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq) { + subDivide = true; + } else { + double z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0; + if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq) + subDivide = true; + else if (z1_dot + z1_dot > z3_0_dot) + subDivide = true; + else if (z2_dot + z2_dot > z3_0_dot) + subDivide = true; + } + } + } + } -nosubdivide: - /* don't subdivide */ - art_vpath_add_point(p_vpath, pn, pn_max, - ART_LINETO, x3, y3); - return; - -subdivide: - - xa1 = (x0 + x1) * 0.5; - ya1 = (y0 + y1) * 0.5; - xa2 = (x0 + 2 * x1 + x2) * 0.25; - ya2 = (y0 + 2 * y1 + y2) * 0.25; - xb1 = (x1 + 2 * x2 + x3) * 0.25; - yb1 = (y1 + 2 * y2 + y3) * 0.25; - xb2 = (x2 + x3) * 0.5; - yb2 = (y2 + y3) * 0.5; - x_m = (xa2 + xb1) * 0.5; - y_m = (ya2 + yb1) * 0.5; - - art_vpath_render_bez(p_vpath, pn, pn_max, - x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness); - art_vpath_render_bez(p_vpath, pn, pn_max, - x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness); + if (subDivide) { + double xa1 = (x0 + x1) * 0.5; + double ya1 = (y0 + y1) * 0.5; + double xa2 = (x0 + 2 * x1 + x2) * 0.25; + double ya2 = (y0 + 2 * y1 + y2) * 0.25; + double xb1 = (x1 + 2 * x2 + x3) * 0.25; + double yb1 = (y1 + 2 * y2 + y3) * 0.25; + double xb2 = (x2 + x3) * 0.5; + double yb2 = (y2 + y3) * 0.5; + double x_m = (xa2 + xb1) * 0.5; + double y_m = (ya2 + yb1) * 0.5; + + art_vpath_render_bez(p_vpath, pn, pn_max, + x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness); + art_vpath_render_bez(p_vpath, pn, pn_max, + x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness); + } else { + // don't subdivide + art_vpath_add_point(p_vpath, pn, pn_max, + ART_LINETO, x3, y3); + } } /** |