finished first version of Cairo export

This commit is contained in:
Mario Hüttel 2018-07-22 16:38:26 +02:00
parent f765e27ce8
commit 4c5784c3a4
3 changed files with 66 additions and 14 deletions

View File

@ -24,9 +24,9 @@
#include <cairo-pdf.h> #include <cairo-pdf.h>
struct cairo_layer { struct cairo_layer {
cairo_t *cr; cairo_t *cr;
cairo_surface_t *rec; cairo_surface_t *rec;
struct layer_info *linfo; struct layer_info *linfo;
}; };
static void revert_inherited_transform(struct cairo_layer *layers) static void revert_inherited_transform(struct cairo_layer *layers)
@ -35,7 +35,7 @@ static void revert_inherited_transform(struct cairo_layer *layers)
for (i = 0; i < MAX_LAYERS; i++) { for (i = 0; i < MAX_LAYERS; i++) {
if (layers[i].cr == NULL) if (layers[i].cr == NULL)
continue; continue;
cairo_restore(layers[i].cr); cairo_restore(layers[i].cr);
} }
} }
@ -101,7 +101,7 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
continue; continue;
/* Apply settings */ /* Apply settings */
cairo_set_line_width(cr, (gfx->width_absolute ? gfx->width_absolute : 1)); cairo_set_line_width(cr, (gfx->width_absolute ? gfx->width_absolute/scale : 1));
switch (gfx->path_render_type) { switch (gfx->path_render_type) {
case PATH_FLUSH: case PATH_FLUSH:
@ -134,7 +134,9 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
break; break;
case GRAPHIC_BOX: case GRAPHIC_BOX:
case GRAPHIC_POLYGON: case GRAPHIC_POLYGON:
cairo_set_line_width(cr, 0.1/scale);
cairo_close_path(cr); cairo_close_path(cr);
cairo_stroke_preserve(cr); // Prevent graphic glitches
cairo_fill(cr); cairo_fill(cr);
break; break;
} }
@ -145,13 +147,15 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale) void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale)
{ {
cairo_surface_t *surface; cairo_surface_t *pdf_surface;
cairo_t *cr; cairo_t *pdf_cr;
struct layer_info *linfo; struct layer_info *linfo;
struct cairo_layer *layers; struct cairo_layer *layers;
struct cairo_layer *lay; struct cairo_layer *lay;
GList *info_list; GList *info_list;
int i; int i;
double rec_x0, rec_y0, rec_width, rec_height;
double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN;
layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer)); layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer));
@ -171,7 +175,7 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p
NULL); NULL);
lay->cr = cairo_create(layers[(unsigned int)linfo->layer].rec); lay->cr = cairo_create(layers[(unsigned int)linfo->layer].rec);
cairo_scale(lay->cr, 1, -1); // Fix coordinate system cairo_scale(lay->cr, 1, -1); // Fix coordinate system
cairo_set_source_rgb(lay->cr, 1, 0, 0); cairo_set_source_rgb(lay->cr, linfo->color.red, linfo->color.green, linfo->color.blue);
} else { } else {
printf("Layer number (%d) too high!\n", linfo->layer); printf("Layer number (%d) too high!\n", linfo->layer);
goto ret_clear_layers; goto ret_clear_layers;
@ -181,16 +185,64 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p
render_cell(cell, layers, scale); render_cell(cell, layers, scale);
/* Todo: Tranfer all layers in order to output file */ /* get size of image and top left coordinate */
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
linfo = (struct layer_info *)info_list->data;
if (linfo->layer >= MAX_LAYERS) {
printf("Layer outside of Spec.\n");
continue;
}
/* Print size */
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
&rec_width, &rec_height);
printf("Size of layer %d: %lf -- %lf\n", linfo->layer,
rec_width, rec_height);
/* update bounding box */
xmin = MIN(xmin, rec_x0);
xmax = MAX(xmax, rec_x0);
ymin = MIN(ymin, rec_y0);
ymax = MAX(ymax, rec_y0);
xmin = MIN(xmin, rec_x0+rec_width);
xmax = MAX(xmax, rec_x0+rec_width);
ymin = MIN(ymin, rec_y0+rec_height);
ymax = MAX(ymax, rec_y0+rec_height);
}
printf("Bounding box: (%lf,%lf) -- (%lf,%lf)\n", xmin, ymin, xmax, ymax);
pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin);
pdf_cr = cairo_create(pdf_surface);
/* Write layers to PDF */
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
linfo = (struct layer_info *)info_list->data;
if (linfo->layer >= MAX_LAYERS) {
printf("Layer outside of Spec.\n");
continue;
}
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);
}
cairo_show_page(pdf_cr);
cairo_destroy(pdf_cr);
cairo_surface_destroy(pdf_surface);
ret_clear_layers: ret_clear_layers:
for (i = 0; i < MAX_LAYERS; i++) { for (i = 0; i < MAX_LAYERS; i++) {
lay = &layers[i]; lay = &layers[i];
cairo_destroy(lay->cr); if(lay->cr) {
cairo_surface_destroy(lay->rec); cairo_destroy(lay->cr);
cairo_surface_destroy(lay->rec);
}
} }
free(layers); free(layers);
printf("cairo export not yet implemented!\n"); printf("cairo export finished. It might still be buggy!\n");
} }

View File

@ -37,8 +37,6 @@
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__) #define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__)
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) #define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__)
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
enum record { enum record {
INVALID = 0x0000, INVALID = 0x0000,

View File

@ -5,6 +5,8 @@
#include <glib.h> #include <glib.h>
#define CELL_NAME_MAX (100) #define CELL_NAME_MAX (100)
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1, GRAPHIC_BOX}; enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1, GRAPHIC_BOX};
enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2}; enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2};