/* * cairo.c - Cairo graphics back-end * * Written 2016 by Werner Almesberger * Copyright 2016 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include "util.h" #include "style.h" #include "text.h" #include "gfx.h" #include "cairo.h" #if 0 #include #include #include #include "util.h" #include "style.h" #include "text.h" #include "fig.h" #endif struct cairo_ctx { cairo_t *cr; cairo_surface_t *s; }; /* * FIG works with 1/1200 in * KiCad works with mil * 1 point = 1/72 in */ static inline int cx(int x) { return x / 5; } static inline int xc(int x) { return x * 5; } static inline int cy(int y) { return y / 5; } static inline float pt(int x) { return cx(x) * 72 * 1.5 / 1200.0; } static void set_color(cairo_t *cr, int color) { uint32_t c; if (color < 0) return; c = color_rgb[color]; cairo_set_source_rgb(cr, (c >> 16) / 255.0, ((c >> 8) & 255) / 255.0, (c & 255) / 255.0); } static void paint(cairo_t *cr, int color, int fill_color) { if (fill_color != COLOR_NONE) { set_color(cr, fill_color); if (color == COLOR_NONE) cairo_fill(cr); else cairo_fill_preserve(cr); } if (color != COLOR_NONE) { set_color(cr, color); cairo_stroke(cr); } } /* ----- General items ----------------------------------------------------- */ static void cr_poly(void *ctx, int points, int x[points], int y[points], int color, int fill_color, unsigned layer) { struct cairo_ctx *cc = ctx; bool closed; int i; if (points < 2) return; closed = x[0] == x[points - 1] && y[0] == y[points - 1]; cairo_new_path(cc->cr); cairo_move_to(cc->cr, cx(x[0]), cy(y[0])); for (i = 1; i != points - closed; i++) cairo_line_to(cc->cr, cx(x[i]), cy(y[i])); if (closed) cairo_close_path(cc->cr); paint(cc->cr, color, fill_color); } static void cr_circ(void *ctx, int x, int y, int r, int color, int fill_color, unsigned layer) { struct cairo_ctx *cc = ctx; cairo_new_path(cc->cr); cairo_arc(cc->cr, cx(x), cy(y), cx(r), 0, 2 * M_PI); paint(cc->cr, color, fill_color); } static void cr_arc(void *ctx, int x, int y, int r, int sa, int ea, int color, int fill_color, unsigned layer) { struct cairo_ctx *cc = ctx; cairo_new_path(cc->cr); cairo_arc(cc->cr, cx(x), cy(y), cx(r), -ea / 180.0 * M_PI, -sa / 180.0 * M_PI); paint(cc->cr, color, fill_color); } #define TEXT_STRETCH 1.3 static void cr_text(void *ctx, int x, int y, const char *s, unsigned size, enum text_align align, int rot, unsigned color, unsigned layer) { struct cairo_ctx *cc = ctx; cairo_text_extents_t ext; cairo_matrix_t m; cairo_set_font_size(cc->cr, cx(size) * TEXT_STRETCH); cairo_text_extents(cc->cr, s, &ext); set_color(cc->cr, color); cairo_move_to(cc->cr, cx(x), cy(y)); cairo_get_matrix(cc->cr, &m); cairo_rotate(cc->cr, -rot / 180.0 * M_PI); switch (align) { case text_min: break; case text_mid: cairo_rel_move_to(cc->cr, -ext.width / 2.0, 0); break; case text_max: cairo_rel_move_to(cc->cr, -ext.width, 0); break; default: abort(); } cairo_show_text(cc->cr, s); cairo_set_matrix(cc->cr, &m); } static unsigned cr_text_width(void *ctx, const char *s, unsigned size) { struct cairo_ctx *cc = ctx; cairo_text_extents_t ext; cairo_set_font_size(cc->cr, cx(size) * TEXT_STRETCH); cairo_text_extents(cc->cr, s, &ext); return xc(ext.width); } /* ----- Initializatio and termination ------------------------------------- */ static void *cr_init(const char *template, int n_vars, const char **vars) { struct cairo_ctx *cc; cc = alloc_type(struct cairo_ctx); cc->s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 2000, 1414); cc->cr = cairo_create(cc->s); set_color(cc->cr, COLOR_WHITE); cairo_paint(cc->cr); cairo_select_font_face(cc->cr, "Helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_line_width(cc->cr, 3); return cc; } static void cr_end(void *ctx) { struct cairo_ctx *cc = ctx; cairo_surface_write_to_png(cc->s, "test.png"); cairo_surface_destroy(cc->s); } /* ----- Operations -------------------------------------------------------- */ const struct gfx_ops cairo_ops = { // .line = cr_line, @@@ later .poly = cr_poly, .circ = cr_circ, .arc = cr_arc, .text = cr_text, .text_width = cr_text_width, .init = cr_init, .end = cr_end, };