From 59ec0c5a10adc61b783ab197f116077ca55a5afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 20 Jul 2018 22:32:23 +0200 Subject: [PATCH] cairo layer renderer --- cairo-output/cairo-output.c | 121 +++++++++++++++++++++++++++++++++++- cairo-output/cairo-output.h | 2 +- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/cairo-output/cairo-output.c b/cairo-output/cairo-output.c index 66813d6..b7f6cf0 100644 --- a/cairo-output/cairo-output.c +++ b/cairo-output/cairo-output.c @@ -29,6 +29,119 @@ struct cairo_layer { struct layer_info *linfo; }; +static void revert_inherited_transform(struct cairo_layer *layers) +{ + int i; + + for (i = 0; i < MAX_LAYERS; i++) { + if (layers[i].cr == NULL) + continue; + cairo_restore(layers[i].cr); + } +} + +static void apply_inherited_transform_to_all_layers(struct cairo_layer *layers, + const struct gds_point *origin, + double magnification, + gboolean flipping, + double rotation, + double scale) +{ + int i; + cairo_t *temp_layer_cr; + + for (i = 0; i < MAX_LAYERS; i++) { + temp_layer_cr = layers[i].cr; + if (temp_layer_cr == NULL) + continue; + + /* Save the state and apply transformation */ + cairo_save(temp_layer_cr); + cairo_translate(temp_layer_cr, (double)origin->x/scale, (double)origin->y/scale); + cairo_rotate(temp_layer_cr, M_PI*rotation/180.0); + cairo_scale(temp_layer_cr, magnification, + (flipping == TRUE ? -magnification : magnification)); + } +} + +static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, double scale) +{ + GList *instance_list; + struct gds_cell *temp_cell; + struct gds_cell_instance *cell_instance; + GList *gfx_list; + struct gds_graphics *gfx; + GList *vertex_list; + struct gds_point *vertex; + cairo_t *cr; + + /* Render child cells */ + for (instance_list = cell->child_cells; instance_list != NULL; instance_list = instance_list->next) { + cell_instance = (struct gds_cell_instance *)instance_list->data; + if ((temp_cell = cell_instance->cell_ref) != NULL) { + apply_inherited_transform_to_all_layers(layers, + &cell_instance->origin, + cell_instance->magnification, + cell_instance->flipped, + cell_instance->angle, + scale); + render_cell(temp_cell, layers, scale); + revert_inherited_transform(layers); + } + } + + /* Render graphics */ + for (gfx_list = cell->graphic_objs; gfx_list != NULL; gfx_list = gfx_list->next) { + gfx = (struct gds_graphics *)gfx_list->data; + + /* Get layer renderer */ + if (gfx->layer >= MAX_LAYERS) + continue; + if ((cr = layers[gfx->layer].cr) == NULL) + continue; + + /* Apply settings */ + cairo_set_line_width(cr, (gfx->width_absolute ? gfx->width_absolute : 1)); + + switch (gfx->path_render_type) { + case PATH_FLUSH: + cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); + break; + case PATH_ROUNDED: + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + break; + case PATH_SQUARED: + cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); + break; + } + + /* Add vertices */ + for (vertex_list = gfx->vertices; vertex_list != NULL; vertex_list = vertex_list->next) { + vertex = (struct gds_point *)vertex_list->data; + + /* If first point -> move to, else line to */ + if (vertex_list->prev == NULL) + cairo_move_to(cr, vertex->x/scale, vertex->y/scale); + else + cairo_line_to(cr, vertex->x/scale, vertex->y/scale); + + } + + /* Create graphics object */ + switch (gfx->gfx_type) { + case GRAPHIC_PATH: + cairo_stroke(cr); + break; + case GRAPHIC_POLYGON: + cairo_close_path(cr); + cairo_fill(cr); + break; + } + + } + +} + void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale) { cairo_surface_t *surface; @@ -56,7 +169,8 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p lay->rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA, NULL); lay->cr = cairo_create(layers[(unsigned int)linfo->layer].rec); - cairo_scale(lay->cr, 1/scale, 1/scale); + cairo_scale(lay->cr, 1, -1); // Fix coordinate system + cairo_set_source_rgb(lay->cr, 1, 0, 0); } else { printf("Layer number (%d) too high!\n", linfo->layer); goto ret_clear_layers; @@ -64,6 +178,11 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p } + render_cell(cell, layers, scale); + + /* Todo: Tranfer all layers in order to output file */ + + ret_clear_layers: for (i = 0; i < MAX_LAYERS; i++) { lay = &layers[i]; diff --git a/cairo-output/cairo-output.h b/cairo-output/cairo-output.h index 3e6eb25..cf7aa4f 100644 --- a/cairo-output/cairo-output.h +++ b/cairo-output/cairo-output.h @@ -23,7 +23,7 @@ #include "../layer-selector.h" #include "../gds-parser/gds-types.h" -#define MAX_LAYERS (2048) +#define MAX_LAYERS (300) void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale);