void image_draw(struct vg_image *img) { struct vg_context *ctx = vg_current_context(); VGfloat x1, y1; VGfloat x2, y2; VGfloat x3, y3; VGfloat x4, y4; struct matrix *matrix; x1 = 0; y1 = 0; x2 = img->width; y2 = 0; x3 = img->width; y3 = img->height; x4 = 0; y4 = img->height; matrix = &ctx->state.vg.image_user_to_surface_matrix; matrix_map_point(matrix, x1, y1, &x1, &y1); matrix_map_point(matrix, x2, y2, &x2, &y2); matrix_map_point(matrix, x3, y3, &x3, &y3); matrix_map_point(matrix, x4, y4, &x4, &y4); shader_set_drawing_image(ctx->shader, VG_TRUE); shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); shader_set_image(ctx->shader, img); shader_bind(ctx->shader); renderer_texture_quad(ctx->renderer, image_texture(img), img->x, img->y, img->x + img->width, img->y + img->height, x1, y1, x2, y2, x3, y3, x4, y4); }
void vgPathTransformedBounds(VGPath path, VGfloat * minX, VGfloat * minY, VGfloat * width, VGfloat * height) { struct vg_context *ctx = vg_current_context(); struct path *p = 0; VGbitfield caps; if (path == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } if (!minX || !minY || !width || !height) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (!is_aligned(minX) || !is_aligned(minY) || !is_aligned(width) || !is_aligned(height)) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } p = (struct path*)path; caps = path_capabilities(p); if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) { vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); return; } #if 0 /* faster, but seems to have precision problems... */ path_bounding_rect(p, minX, minY, width, height); if (*width > 0 && *height > 0) { VGfloat pts[] = {*minX, *minY, *minX + *width, *minY, *minX + *width, *minY + *height, *minX, *minY + *height}; struct matrix *matrix = &ctx->state.vg.path_user_to_surface_matrix; VGfloat maxX, maxY; matrix_map_point(matrix, pts[0], pts[1], pts + 0, pts + 1); matrix_map_point(matrix, pts[2], pts[3], pts + 2, pts + 3); matrix_map_point(matrix, pts[4], pts[5], pts + 4, pts + 5); matrix_map_point(matrix, pts[6], pts[7], pts + 6, pts + 7); *minX = MIN2(pts[0], MIN2(pts[2], MIN2(pts[4], pts[6]))); *minY = MIN2(pts[1], MIN2(pts[3], MIN2(pts[5], pts[7]))); maxX = MAX2(pts[0], MAX2(pts[2], MAX2(pts[4], pts[6]))); maxY = MAX2(pts[1], MAX2(pts[3], MAX2(pts[5], pts[7]))); *width = maxX - *minX; *height = maxY - *minY; } #else { struct path *dst = path_create(VG_PATH_DATATYPE_F, 1.0, 0, 0, 0, VG_PATH_CAPABILITY_ALL); path_transform(dst, p); path_bounding_rect(dst, minX, minY, width, height); path_destroy(dst); } #endif }
static void arc_to_beziers(struct arc *arc, struct arc_cb cb, struct matrix *matrix) { int i; int n = 1; double d_eta, eta_b, cos_eta_b, sin_eta_b, a_cos_eta_b, b_sin_eta_b, a_sin_eta_b, b_cos_eta_b, x_b, y_b, x_b_dot, y_b_dot, lx, ly; double t, alpha; { /* always move to the start of the arc */ VGfloat x = arc->x1; VGfloat y = arc->y1; matrix_map_point(matrix, x, y, &x, &y); cb.move(&cb, x, y); } if (!arc->is_valid) { VGfloat x = arc->x2; VGfloat y = arc->y2; matrix_map_point(matrix, x, y, &x, &y); cb.point(&cb, x, y); return; } /* find the number of Bézier curves needed */ n = num_beziers_needed(arc); d_eta = (arc->eta2 - arc->eta1) / n; eta_b = arc->eta1; cos_eta_b = cos(eta_b); sin_eta_b = sin(eta_b); a_cos_eta_b = arc->a * cos_eta_b; b_sin_eta_b = arc->b * sin_eta_b; a_sin_eta_b = arc->a * sin_eta_b; b_cos_eta_b = arc->b * cos_eta_b; x_b = arc->cx + a_cos_eta_b * arc->cos_theta - b_sin_eta_b * arc->sin_theta; y_b = arc->cy + a_cos_eta_b * arc->sin_theta + b_sin_eta_b * arc->cos_theta; x_b_dot = -a_sin_eta_b * arc->cos_theta - b_cos_eta_b * arc->sin_theta; y_b_dot = -a_sin_eta_b * arc->sin_theta + b_cos_eta_b * arc->cos_theta; { VGfloat x = x_b, y = y_b; matrix_map_point(matrix, x, y, &x, &y); cb.point(&cb, x, y); } lx = x_b; ly = y_b; t = tan(0.5 * d_eta); alpha = sin(d_eta) * (sqrt(4 + 3 * t * t) - 1) / 3; for (i = 0; i < n; ++i) { struct bezier bezier; double xA = x_b; double yA = y_b; double xADot = x_b_dot; double yADot = y_b_dot; eta_b += d_eta; cos_eta_b = cos(eta_b); sin_eta_b = sin(eta_b); a_cos_eta_b = arc->a * cos_eta_b; b_sin_eta_b = arc->b * sin_eta_b; a_sin_eta_b = arc->a * sin_eta_b; b_cos_eta_b = arc->b * cos_eta_b; x_b = arc->cx + a_cos_eta_b * arc->cos_theta - b_sin_eta_b * arc->sin_theta; y_b = arc->cy + a_cos_eta_b * arc->sin_theta + b_sin_eta_b * arc->cos_theta; x_b_dot = -a_sin_eta_b * arc->cos_theta - b_cos_eta_b * arc->sin_theta; y_b_dot = -a_sin_eta_b * arc->sin_theta + b_cos_eta_b * arc->cos_theta; bezier_init(&bezier, lx, ly, (float) (xA + alpha * xADot), (float) (yA + alpha * yADot), (float) (x_b - alpha * x_b_dot), (float) (y_b - alpha * y_b_dot), (float) x_b, (float) y_b); #if 0 debug_printf("%d) Bezier (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n", i, bezier.x1, bezier.y1, bezier.x2, bezier.y2, bezier.x3, bezier.y3, bezier.x4, bezier.y4); #endif bezier_transform(&bezier, matrix); cb.bezier(&cb, &bezier); lx = x_b; ly = y_b; } }
static VGboolean find_angles(struct arc *arc) { double vec0[2], vec1[2]; double lambda1, lambda2; double angle; struct matrix matrix; if (floatIsZero(arc->a) || floatIsZero(arc->b)) { return VG_FALSE; } /* map the points to an identity circle */ matrix_load_identity(&matrix); matrix_scale(&matrix, 1.f, arc->a/arc->b); matrix_rotate(&matrix, -arc->theta); matrix_map_point(&matrix, arc->x1, arc->y1, &arc->x1, &arc->y1); matrix_map_point(&matrix, arc->x2, arc->y2, &arc->x2, &arc->y2); matrix_map_point(&matrix, arc->cx, arc->cy, &arc->cx, &arc->cy); #if DEBUG_ARCS debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n", matrix.m[0], matrix.m[1], matrix.m[2], matrix.m[3], matrix.m[4], matrix.m[5], matrix.m[6], matrix.m[7], matrix.m[8]); debug_printf("Endpoints [%f, %f], [%f, %f]\n", arc->x1, arc->y1, arc->x2, arc->y2); #endif vec0[0] = arc->x1 - arc->cx; vec0[1] = arc->y1 - arc->cy; vec1[0] = arc->x2 - arc->cx; vec1[1] = arc->y2 - arc->cy; #if DEBUG_ARCS debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n", vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy); #endif lambda1 = vector_orientation(vec0); if (isnan(lambda1)) lambda1 = 0.f; if (arc->type == VG_SCWARC_TO || arc->type == VG_SCCWARC_TO) angle = vector_angles(vec0, vec1); else if (arc->type == VG_LCWARC_TO || arc->type == VG_LCCWARC_TO) { angle = 2*M_PI - vector_angles(vec0, vec1); } else abort(); if (isnan(angle)) angle = M_PI; if (arc->type == VG_SCWARC_TO || arc->type == VG_LCWARC_TO) lambda2 = lambda1 - angle; else lambda2 = lambda1 + angle; #if DEBUG_ARCS debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2); #endif #if 0 arc->eta1 = atan2(sin(lambda1) / arc->b, cos(lambda1) / arc->a); arc->eta2 = atan2(sin(lambda2) / arc->b, cos(lambda2) / arc->a); /* make sure we have eta1 <= eta2 <= eta1 + 2 PI */ arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi); /* the preceding correction fails if we have exactly et2 - eta1 = 2 PI it reduces the interval to zero length */ if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) { arc->eta2 += 2 * M_PI; } #else arc->eta1 = lambda1; arc->eta2 = lambda2; #endif return VG_TRUE; }