void graphene_matrix_untransform_bounds (const graphene_matrix_t *m, const graphene_rect_t *r, const graphene_rect_t *bounds, graphene_rect_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; graphene_rect_t rect; g_return_if_fail (m != NULL && r != NULL); g_return_if_fail (bounds != NULL); g_return_if_fail (res != NULL); if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_bounds (&inverse, r, res); return; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_intersection (r, &bounds_t, &rect)) { graphene_rect_init (res, 0.f, 0.f, 0.f, 0.f); return; } graphene_matrix_inverse (m, &inverse); graphene_matrix_project_rect_bounds (&inverse, &rect, res); }
gboolean graphene_matrix_untransform_point (const graphene_matrix_t *m, const graphene_point_t *p, const graphene_rect_t *bounds, graphene_point_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; g_return_val_if_fail (m != NULL, FALSE); g_return_val_if_fail (p != NULL, FALSE); g_return_val_if_fail (bounds != NULL, FALSE); g_return_val_if_fail (res != NULL, FALSE); if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_point (&inverse, p, res); return TRUE; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_contains_point (&bounds_t, p)) return FALSE; graphene_matrix_inverse (m, &inverse); graphene_matrix_project_point (&inverse, p, res); return TRUE; }
/** * graphene_matrix_untransform_point: * @m: a #graphene_matrix_t * @p: a #graphene_point_t * @bounds: the bounds of the transformation * @res: (out caller-allocates): return location for the * untransformed point * * Undoes the transformation of a #graphene_point_t using the * given matrix, within the given rectangular @bounds. * * Returns: %true if the point was successfully untransformed * * Since: 1.0 */ bool graphene_matrix_untransform_point (const graphene_matrix_t *m, const graphene_point_t *p, const graphene_rect_t *bounds, graphene_point_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_point (&inverse, p, res); return true; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_contains_point (&bounds_t, p)) return false; graphene_matrix_inverse (m, &inverse); graphene_matrix_project_point (&inverse, p, res); return true; }
void ops_transform_bounds_modelview (const RenderOpBuilder *builder, const graphene_rect_t *src, graphene_rect_t *dst) { const MatrixStackEntry *head; g_assert (builder->mv_stack != NULL); g_assert (builder->mv_stack->len >= 1); head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1); switch (head->metadata.category) { case GSK_TRANSFORM_CATEGORY_IDENTITY: *dst = *src; break; case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE: *dst = *src; dst->origin.x += head->metadata.translate_x; dst->origin.y += head->metadata.translate_y; break; /* TODO: Handle scale */ case GSK_TRANSFORM_CATEGORY_UNKNOWN: case GSK_TRANSFORM_CATEGORY_ANY: case GSK_TRANSFORM_CATEGORY_3D: case GSK_TRANSFORM_CATEGORY_2D: case GSK_TRANSFORM_CATEGORY_2D_AFFINE: default: graphene_matrix_transform_bounds (builder->current_modelview, src, dst); } dst->origin.x += builder->dx * head->metadata.scale_x; dst->origin.y += builder->dy * head->metadata.scale_y; }