cairo layer renderer

This commit is contained in:
Mario Hüttel 2018-07-20 22:32:23 +02:00
parent 2a615367d7
commit 59ec0c5a10
2 changed files with 121 additions and 2 deletions

View File

@ -29,6 +29,119 @@ struct cairo_layer {
struct layer_info *linfo; 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) 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 *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, lay->rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,
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/scale, 1/scale); cairo_scale(lay->cr, 1, -1); // Fix coordinate system
cairo_set_source_rgb(lay->cr, 1, 0, 0);
} 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;
@ -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: ret_clear_layers:
for (i = 0; i < MAX_LAYERS; i++) { for (i = 0; i < MAX_LAYERS; i++) {
lay = &layers[i]; lay = &layers[i];

View File

@ -23,7 +23,7 @@
#include "../layer-selector.h" #include "../layer-selector.h"
#include "../gds-parser/gds-types.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); void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale);