diff --git a/src/hvif-cairo.c b/src/hvif-cairo.c index 071ddde..5231701 100644 --- a/src/hvif-cairo.c +++ b/src/hvif-cairo.c @@ -1,6 +1,7 @@ #include "hvif-light.h" #include +#include #include #include @@ -14,6 +15,26 @@ * 3. Put everything together */ +/* TODO: Gradients + * - Check the various forms + * - How is the gradient oriented in the picture + * - Apply transformation matrix + * - Color space + */ + +void +cairo_matrix_init_from_matrix(cairo_matrix_t* matrix, const hvif_matrix* hvif_matrix) +{ + cairo_matrix_init(matrix, + hvif_matrix->xx, + hvif_matrix->yx, + hvif_matrix->xy, + hvif_matrix->yy, + hvif_matrix->x0, + hvif_matrix->y0 + ); +} + void create_path(cairo_t* cr, hvif_path* path) { @@ -23,26 +44,93 @@ create_path(cairo_t* cr, hvif_path* path) hvif_point p = path->points[3 * i]; hvif_point cp1 = path->points[3 * i + 1]; hvif_point cp2 = path->points[3 * i + 2]; - cairo_curve_to(cr, cp1.x, cp1.y, cp2.x, cp2.y, p.x, p.y); + uint8_t command = path_command_at(path, i); + if (command == PATH_COMMAND_CURVE) + cairo_curve_to(cr, cp1.x, cp1.y, cp2.x, cp2.y, p.x, p.y); + else + cairo_line_to(cr, p.x, p.y); } if (path->closed) cairo_close_path(cr); } +void +create_style(cairo_t* cr, hvif_style* style) +{ + assert(style->num_stops > 0); + cairo_pattern_t *pat; + + switch (style->gradient_type) { + case GRADIENT_LINEAR: + printf("GRADIENT_LINEAR\n"); + pat = cairo_pattern_create_linear(-64, 32, 64, 32); + break; + case GRADIENT_CIRCULAR: + printf("GRADIENT_CIRCULAR\n"); + pat = cairo_pattern_create_radial(0, 0, 0, 0, 0, 64); + break; + case GRADIENT_DIAMOND: + printf("GRADIENT_DIAMOND\n"); + assert(false); + break; + case GRADIENT_CONIC: + printf("GRADIENT_CONIC\n"); + assert(false); + break; + case GRADIENT_XY: + printf("GRADIENT_XY\n"); + assert(false); + break; + case GRADIENT_SQRT_XY: + printf("GRADIENT_SQRT_XY\n"); + assert(false); + break; + } + + for (unsigned i = 0; i < style->num_stops; ++i) { + printf("stop %f\n", style->offsets[i]); + hvif_color c = style->colors[i]; + cairo_pattern_add_color_stop_rgba(pat, style->offsets[i], + COLOR_GET_RED(c) / 255.0, + COLOR_GET_GREEN(c) / 255.0, + COLOR_GET_BLUE(c) / 255.0, + COLOR_GET_ALPHA(c) / 255.0); + } + + cairo_matrix_t transformation; + cairo_matrix_init_from_matrix(&transformation, &style->transformation); + if (cairo_matrix_invert(&transformation) != CAIRO_STATUS_SUCCESS) { + printf("could not invert style transformation\n"); + exit(1); + } + cairo_pattern_set_matrix(pat, &transformation); + + cairo_rectangle(cr, 0, 0, 64, 64); + cairo_set_source(cr, pat); + cairo_fill(cr); + cairo_pattern_destroy(pat); +} + bool hvif_render_image(const char* filename, hvif_image* image) { cairo_surface_t* surface = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 254, 254); + /* cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 254, 254); */ + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 65, 64); cairo_t* cr = cairo_create(surface); - cairo_scale(cr, 4.0, 4.0); + /* cairo_scale(cr, 4.0, 4.0); */ + cairo_scale(cr, 1.0, 1.0); cairo_set_line_width(cr, 0.2); double r = 0; double delta = 1.0 / image->num_shapes; + printf("styles %u\n", image->num_styles); + create_style(cr, &image->styles[0]); + +/* for (unsigned i = 0; i < image->num_shapes; ++i) { cairo_set_source_rgb(cr, r, 0, 0); r = r + delta; @@ -57,6 +145,7 @@ hvif_render_image(const char* filename, hvif_image* image) cairo_stroke(cr); } } + */ cairo_destroy(cr);