static void get_point_size(GF_Matrix2D *mat, Fixed *w, Fixed *h) { GF_Point2D pt; pt.x = mat->m[0] + mat->m[1]; pt.y = mat->m[3] + mat->m[4]; *w = *h = gf_divfix(FLT2FIX(1.41421356f) , gf_v2d_len(&pt)); }
/*flattening algo taken from libart but passed to sqrt tests for line distance to avoid 16.16 fixed overflow*/ static GF_Err gf_subdivide_cubic(GF_Path *gp, Fixed x0, Fixed y0, Fixed x1, Fixed y1, Fixed x2, Fixed y2, Fixed x3, Fixed y3, Fixed fineness) { GF_Point2D pt; Fixed x3_0, y3_0, z3_0, z1_0, z1_dot, z2_dot, z1_perp, z2_perp; Fixed max_perp; Fixed x_m, y_m, xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2; GF_Err e; pt.x = x3_0 = x3 - x0; pt.y = y3_0 = y3 - y0; /*z3_0 is dist z0-z3*/ z3_0 = gf_v2d_len(&pt); pt.x = x1 - x0; pt.y = y1 - y0; z1_0 = gf_v2d_len(&pt); if ((z3_0*100 < FIX_ONE) && (z1_0*100 < FIX_ONE)) goto nosubdivide; /* perp is distance from line, multiplied by dist z0-z3 */ max_perp = gf_mulfix(fineness, z3_0); z1_perp = gf_mulfix((y1 - y0), x3_0) - gf_mulfix((x1 - x0), y3_0); if (ABS(z1_perp) > max_perp) goto subdivide; z2_perp = gf_mulfix((y3 - y2), x3_0) - gf_mulfix((x3 - x2), y3_0); if (ABS(z2_perp) > max_perp) goto subdivide; z1_dot = gf_mulfix((x1 - x0), x3_0) + gf_mulfix((y1 - y0), y3_0); if ((z1_dot < 0) && (ABS(z1_dot) > max_perp)) goto subdivide; z2_dot = gf_mulfix((x3 - x2), x3_0) + gf_mulfix((y3 - y2), y3_0); if ((z2_dot < 0) && (ABS(z2_dot) > max_perp)) goto subdivide; if (gf_divfix(z1_dot + z1_dot, z3_0) > z3_0) goto subdivide; if (gf_divfix(z2_dot + z2_dot, z3_0) > z3_0) goto subdivide; nosubdivide: /* don't subdivide */ return gf_path_add_line_to(gp, x3, y3); subdivide: xa1 = (x0 + x1) / 2; ya1 = (y0 + y1) / 2; xa2 = (x0 + 2 * x1 + x2) / 4; ya2 = (y0 + 2 * y1 + y2) / 4; xb1 = (x1 + 2 * x2 + x3) / 4; yb1 = (y1 + 2 * y2 + y3) / 4; xb2 = (x2 + x3) / 2; yb2 = (y2 + y3) / 2; x_m = (xa2 + xb1) / 2; y_m = (ya2 + yb1) / 2; /*safeguard for numerical stability*/ if ( (ABS(x_m-x0) < FIX_EPSILON) && (ABS(y_m-y0) < FIX_EPSILON)) return gf_path_add_line_to(gp, x3, y3); if ( (ABS(x3-x_m) < FIX_EPSILON) && (ABS(y3-y_m) < FIX_EPSILON)) return gf_path_add_line_to(gp, x3, y3); e = gf_subdivide_cubic(gp, x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, fineness); if (e) return e; return gf_subdivide_cubic(gp, x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, fineness); }