X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=example.c;h=3dab2bace2093f70bc9d1a0625418ae45c810a8d;hb=6bf209a934fc0b73a4e0dabddbb8de1e4ec5d799;hp=f6deceda741f2708fd7518af64ef05431de7958b;hpb=10646b914b4d4f82f315e14d25de17dcd75dca34;p=libsvgtiny-pixbuf.git diff --git a/example.c b/example.c index f6deced..3dab2ba 100644 --- a/example.c +++ b/example.c @@ -5,13 +5,18 @@ #include /* read */ #include +#include +#include #include +/* Convenient typedefs for libsvgtiny */ +typedef struct svgtiny_diagram diagram_t; + /** * Render an svgtiny path using cairo. */ -void render_path(cairo_t *cr, float scale, struct svgtiny_shape *path) { +void render_path(cairo_t *cr, struct svgtiny_shape *path) { unsigned int j; cairo_new_path(cr); @@ -19,8 +24,8 @@ void render_path(cairo_t *cr, float scale, struct svgtiny_shape *path) { switch ((int) path->path[j]) { case svgtiny_PATH_MOVE: cairo_move_to(cr, - scale * path->path[j + 1], - scale * path->path[j + 2]); + path->path[j + 1], + path->path[j + 2]); j += 3; break; case svgtiny_PATH_CLOSE: @@ -29,18 +34,18 @@ void render_path(cairo_t *cr, float scale, struct svgtiny_shape *path) { break; case svgtiny_PATH_LINE: cairo_line_to(cr, - scale * path->path[j + 1], - scale * path->path[j + 2]); + path->path[j + 1], + path->path[j + 2]); j += 3; break; case svgtiny_PATH_BEZIER: cairo_curve_to(cr, - scale * path->path[j + 1], - scale * path->path[j + 2], - scale * path->path[j + 3], - scale * path->path[j + 4], - scale * path->path[j + 5], - scale * path->path[j + 6]); + path->path[j + 1], + path->path[j + 2], + path->path[j + 3], + path->path[j + 4], + path->path[j + 5], + path->path[j + 6]); j += 7; break; default: @@ -60,25 +65,23 @@ void render_path(cairo_t *cr, float scale, struct svgtiny_shape *path) { svgtiny_RED(path->stroke) / 255.0, svgtiny_GREEN(path->stroke) / 255.0, svgtiny_BLUE(path->stroke) / 255.0); - cairo_set_line_width(cr, scale * path->stroke_width); + cairo_set_line_width(cr, path->stroke_width); cairo_stroke_preserve(cr); } } /* - * @brief Parse an SVG file into an svgtiny_diagram structure. + * @brief Parse an SVG file into a diagram_t structure. * * @param path * The path to the SVG file. * - * @return If successful, a pointer to an @c svgtiny_diagram structure - * is returned; if not, @c NULL is returned. You are expected to @c + * @return If successful, a pointer to a @c diagram_t structure is + * returned; if not, @c NULL is returned. You are expected to @c * svgtiny_free the result if it is valid. */ -struct svgtiny_diagram* svgtiny_diagram_from_path(char* path, - int width, - int height) { - struct svgtiny_diagram *diagram; +diagram_t* svgtiny_diagram_from_path(char* path, int width, int height) { + diagram_t *diagram; int fd; size_t bytecount; @@ -152,50 +155,48 @@ struct svgtiny_diagram* svgtiny_diagram_from_path(char* path, return diagram; } -int main(int argc, char** argv) { - int exit_code = 0; - - char* svgpath; - char* pngpath; - int pngwidth = 1024, pngheight = 1024; - - float scale = 1.0; - struct svgtiny_diagram *diagram; - cairo_surface_t *surface; - cairo_t *cr = 0; - cairo_status_t cr_status; - +/* + * @brief Create a cairo context from a libsvgtiny diagram. + * + * @param diagram + * A pointer to a valid libsvgtiny diagram. + * + * @return If successful, a pointer to a @c cairo_t context structure + * is returned; if not, @c NULL is returned. You are expected to @c + * cairo_destroy the result if it is valid. + */ +cairo_t* cairo_context_from_diagram(diagram_t* diagram) { + cairo_t* cr; + cairo_surface_t* surface; + cairo_status_t crs; unsigned int i; - /* Parse arguments, and maybe print usage */ - if (argc < 3) { - printf("Usage: %s INPUT OUTPUT\n", argv[0]); - printf("Convert an SVG file (INPUT) to a PNG file (OUTPUT)\n"); - return 2; - } - - svgpath = argv[1]; - pngpath = argv[2]; - - diagram = svgtiny_diagram_from_path(svgpath, pngwidth, pngheight); - surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, - pngwidth, - pngheight); - if (!surface) { - fprintf(stderr, "cairo_image_surface_create failed\n"); - exit_code = 1; - goto cleanup; + diagram->width, + diagram->height); + + crs = cairo_surface_status(surface); + if (crs != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, + "cairo_image_surface_create failed: %s\n", + cairo_status_to_string(crs)); + cairo_surface_destroy(surface); + return NULL; } cr = cairo_create(surface); - cr_status = cairo_status(cr); - if (cr_status != CAIRO_STATUS_SUCCESS) { + crs = cairo_status(cr); + + /* Immediately destroy the surface which is now accessible as + cr->target */ + cairo_surface_destroy(surface); + + if (crs != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "cairo_create failed: %s\n", - cairo_status_to_string(cr_status)); - exit_code = 1; - goto cleanup; + cairo_status_to_string(crs)); + cairo_destroy(cr); + return NULL; } cairo_set_source_rgb(cr, 1, 1, 1); @@ -206,7 +207,7 @@ int main(int argc, char** argv) { /* If this shape is a path, just render it. */ if (diagram->shape[i].path) { - render_path(cr, scale, &diagram->shape[i]); + render_path(cr, &diagram->shape[i]); } /* If this shape is text... */ @@ -220,37 +221,70 @@ int main(int argc, char** argv) { /* Then move to the actual position of the text within the shape... */ cairo_move_to(cr, - scale * diagram->shape[i].text_x, - scale * diagram->shape[i].text_y); + diagram->shape[i].text_x, + diagram->shape[i].text_y); /* and draw it. */ cairo_show_text(cr, diagram->shape[i].text); } } - /* Check the status again. */ - cr_status = cairo_status(cr); - if (cr_status != CAIRO_STATUS_SUCCESS) { - fprintf(stderr, "cairo error: %s\n", - cairo_status_to_string(cr_status)); - exit_code = 1; - goto cleanup; + + /* Check the status again just for good measure? */ + crs = cairo_status(cr); + if (crs != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, + "cairo error: %s\n", + cairo_status_to_string(crs)); + cairo_destroy(cr); + return NULL; } - cr_status = cairo_surface_write_to_png(surface, pngpath); - if (cr_status != CAIRO_STATUS_SUCCESS) { - fprintf(stderr, "cairo error: %s\n", - cairo_status_to_string(cr_status)); - exit_code = 1; - goto cleanup; + return cr; +} + +int main(int argc, char** argv) { + char* svgpath; + char* pngpath; + int pngwidth = 1024, pngheight = 1024; + + diagram_t* diagram; + cairo_t *cr = 0; + + GdkPixbuf* pb; + + /* Parse arguments, and maybe print usage */ + if (argc < 3) { + printf("Usage: %s INPUT OUTPUT\n", argv[0]); + printf("Convert an SVG file (INPUT) to a PNG file (OUTPUT)\n"); + return 2; } -cleanup: - if (cr) { - cairo_destroy(cr); + svgpath = argv[1]; + pngpath = argv[2]; + + diagram = svgtiny_diagram_from_path(svgpath, pngwidth, pngheight); + if (!diagram) { + return 1; + } + + cr = cairo_context_from_diagram(diagram); + if (!cr) { + svgtiny_free(diagram); + return 1; + } + + pb = gdk_pixbuf_get_from_surface(cairo_get_target(cr), + 0, + 0, + pngwidth, + pngheight); + + + if (pb) { + gdk_pixbuf_save(pb, pngpath, "png", NULL, NULL); + g_object_unref(pb); } - cairo_surface_destroy(surface); - svgtiny_free(diagram); - return exit_code; + return 0; }