Index: trunk/scconfig/plugins.h
===================================================================
--- trunk/scconfig/plugins.h (revision 27397)
+++ trunk/scconfig/plugins.h (revision 27398)
@@ -125,7 +125,6 @@
plugin_def("hid_batch", "batch process (no-gui HID)", sbuildin, 1, 1)
plugin_def("hid_gtk2_gdk", "GTK2 GUI, software render", sbuildin, 1, 1)
plugin_def("hid_gtk2_gl", "GTK2 GUI, opengl render", sbuildin, 1, 1)
-plugin_def("hid_gtk3_cairo", "#GTK3 GUI, cairo render", sdisable, 0, 0)
plugin_def("hid_lesstif", "the lesstif gui", sbuildin, 1, 0)
plugin_def("hid_remote", "remote HID server", sdisable, 0, 0)
@@ -155,7 +154,6 @@
plugin_dep("hid_gtk2_gdk", "lib_gtk_common", 01)
plugin_dep("hid_gtk2_gl", "lib_gtk_common", 01)
plugin_dep("hid_gtk2_gl", "lib_hid_gl", 01)
-plugin_dep("hid_gtk3_cairo", "lib_gtk_common", 0)
plugin_dep("hid_lesstif", "lib_hid_common", 0)
plugin_dep("import_dsn", "lib_compat_help", 0)
plugin_dep("import_dsn", "lib_gensexpr", 0)
Index: trunk/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c
===================================================================
--- trunk/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (revision 27397)
+++ trunk/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (nonexistent)
@@ -1,1592 +0,0 @@
-/*
- * COPYRIGHT
- *
- * pcb-rnd, interactive printed circuit board design
- * (this file is based on PCB, interactive printed circuit board design)
- * Copyright (C) 1994,1995,1996 Thomas Nau
- * pcb-rnd Copyright (C) 2017-2019 Alain Vigne
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * Contact:
- * Project page: http://repo.hu/projects/pcb-rnd
- * lead developer: http://repo.hu/projects/pcb-rnd/contact.html
- * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
- *
- */
-
-#include "config.h"
-#include "hidlib_conf.h"
-
-#include
-
-#include "crosshair.h"
-#include "draw.h"
-#include "grid.h"
-#include "color.h"
-#include "color_cache.h"
-#include "hid_attrib.h"
-#include "funchash_core.h"
-
-#include "../src_plugins/lib_gtk_common/pcb_gtk.h"
-#include "../src_plugins/lib_gtk_common/glue_common.h"
-#include "../src_plugins/lib_gtk_common/coord_conv.h"
-
-#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h"
-#include "../src_plugins/lib_gtk_common/lib_gtk_config.h"
-
-#include "../src_plugins/lib_hid_common/clip.h"
-
-extern pcb_hid_t gtk3_cairo_hid;
-static void ghid_cairo_screen_update(void);
-
-/* Sets priv->u_gc to the "right" GC to use (wrt mask or window)
-*/
-#define USE_GC(gc) if (!use_gc(gc)) return
-
-//static int cur_mask = -1;
-//static int mask_seq = 0;
-static pcb_composite_op_t curr_drawing_mode;
-
-typedef struct render_priv_s {
- GdkRGBA bg_color; /* cached back-ground color */
- GdkRGBA offlimits_color; /* cached external board color */
- GdkRGBA grid_color; /* cached grid color */
- GdkRGBA crosshair_color; /* cached crosshair color */
-
- cairo_t *cr; /* pointer to current drawing context */
- cairo_t *cr_target; /* pointer to destination widget drawing context */
-
- cairo_surface_t *surf_da; /* cairo surface connected to port->drawing_area */
- cairo_t *cr_drawing_area; /* cairo context created from surf_da */
-
- cairo_surface_t *surf_layer; /* cairo surface for temporary layer composition */
- cairo_t *cr_layer; /* cairo context created from surf_layer */
-
- //GdkPixmap *pixmap, *mask;
-
- //GdkGC *bg_gc;
- //GdkGC *offlimits_gc;
- //GdkGC *mask_gc;
- //GdkGC *u_gc;
- //GdkGC *grid_gc;
- pcb_bool clip;
- GdkRectangle clip_rect;
- int xor_mode; /* 1 if drawn in XOR mode, 0 otherwise*/
- int attached_invalidate_depth;
- int mark_invalidate_depth;
-
- /* color cache for set_color */
- pcb_clrcache_t ccache;
- int ccache_inited;
-} render_priv_t;
-
-typedef struct hid_gc_s {
- pcb_core_gc_t core_gc;
- pcb_hid_t *me_pointer;
-
- pcb_color_t pcolor;
- GdkRGBA color; /* current color for this GC. */
-
- pcb_coord_t width;
- cairo_line_cap_t cap;
- cairo_line_join_t join;
- gchar xor_mask;
- //gint mask_seq;
-} hid_gc_s;
-
-static void copy_color(GdkRGBA * dest, GdkRGBA * source)
-{
- dest->red = source->red;
- dest->green = source->green;
- dest->blue = source->blue;
- dest->alpha = source->alpha;
-}
-
-static const gchar *get_color_name(pcb_gtk_color_t * color)
-{
- static char tmp[16];
-
- if (!color)
- return "#000000";
-
- sprintf(tmp, "#%2.2x%2.2x%2.2x",
- (int) (color->red * 255) & 0xff, (int) (color->green * 255) & 0xff, (int) (color->blue * 255) & 0xff);
- return tmp;
-}
-
-/* Returns TRUE if inclr has been successfully converted to color. */
-static pcb_bool map_color(const pcb_color_t *inclr, pcb_gtk_color_t *color)
-{
- if (!color || !ghidgui->port.top_window)
- return FALSE;
-
- color->red = inclr->fr;
- color->green = inclr->fg;
- color->blue = inclr->fb;
- color->alpha = inclr->fa;
-
- return TRUE;
-}
-
-static void cr_draw_line(cairo_t * cr, int fill, double x1, double y1, double x2, double y2)
-{
- if (cr == NULL)
- return;
-
- cairo_move_to(cr, x1, y1);
- cairo_line_to(cr, x2, y2);
-TODO("gtk3: What means 'fill a line'? cairo_fill is not appropriate if path is only a line.")
- if (fill)
- cairo_fill(cr);
- else
- cairo_stroke(cr);
-}
-
-static void cr_destroy_surf_and_context(cairo_surface_t ** psurf, cairo_t ** pcr)
-{
- if (*psurf)
- cairo_surface_destroy(*psurf);
- if (*pcr)
- cairo_destroy(*pcr);
-
- *psurf = NULL;
- *pcr = NULL;
-}
-
-/* First, frees previous surface and context, then creates new ones, similar to drawing_area. */
-static void cr_create_similar_surface_and_context(cairo_surface_t ** psurf, cairo_t ** pcr, void *vport)
-{
- pcb_gtk_port_t *port = vport;
- cairo_surface_t *surface;
- cairo_t *cr;
-
- cr_destroy_surf_and_context(psurf, pcr);
-
- surface = gdk_window_create_similar_surface(gtk_widget_get_window(port->drawing_area),
- CAIRO_CONTENT_COLOR_ALPHA,
- gtk_widget_get_allocated_width(port->drawing_area),
- gtk_widget_get_allocated_height(port->drawing_area));
- cr = cairo_create(surface);
- *psurf = surface;
- *pcr = cr;
-}
-
-/* Creates or reuses a context to render a single layer group with "union" type of shape rendering. */
-static void start_subcomposite(void)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- cairo_t *cr;
-
- if (priv->surf_layer == NULL)
- cr_create_similar_surface_and_context(&priv->surf_layer, &priv->cr_layer, &ghidgui->port);
- cr = priv->cr_layer;
- cairo_save(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_paint(cr);
- cairo_restore(cr);
- cairo_set_operator(priv->cr, CAIRO_OPERATOR_SOURCE);
- priv->cr = priv->cr_layer;
-}
-
-/* Applies the layer composited so far, to the target, using translucency. */
-static void end_subcomposite(void)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
-
- cairo_set_operator(priv->cr_target, CAIRO_OPERATOR_OVER);
- cairo_set_source_surface(priv->cr_target, priv->surf_layer, 0, 0);
- cairo_paint_with_alpha(priv->cr_target, pcbhl_conf.appearance.layer_alpha);
- priv->cr = priv->cr_target;
-}
-
-static int ghid_cairo_set_layer_group(pcb_hid_t *hid, pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform)
-{
- /* draw anything */
- return 1;
-}
-
-static void ghid_cairo_end_layer_group(pcb_hid_t *hid)
-{
- end_subcomposite();
-}
-
-TODO(": misleading comment or broken code")
-/* Do not clean up internal structures, as they will be used probably elsewhere. */
-static void ghid_cairo_destroy_gc(pcb_hid_gc_t gc)
-{
- g_free(gc);
-}
-
-/* called from pcb_hid_t->make_gc() . Use only this to hold pointers, do not
- own references, avoid costly memory allocation that needs to be destroyed with
- ghid_cairo_destroy_gc(). */
-static pcb_hid_gc_t ghid_cairo_make_gc(pcb_hid_t *hid)
-{
- pcb_hid_gc_t rv;
-
- rv = g_new0(hid_gc_s, 1);
- rv->me_pointer = >k3_cairo_hid;
- rv->pcolor = pcbhl_conf.appearance.color.background;
- return rv;
-}
-
-TODO("gtk3: check if clipping is not necessary")
-//static void set_clip(render_priv_t * priv, cairo_t * cr)
-//{
-// if (cr == NULL)
-// return;
-//
-// if (priv->clip) {
-// gdk_cairo_rectangle(cr, &priv->clip_rect);
-// cairo_clip(cr);
-// }
-// else {
-// /*FIXME: do nothing if no clipping ? */
-// //cairo_mask(cr, NULL);
-// //gdk_gc_set_clip_mask(gc, NULL);
-// }
-//}
-
-static inline void ghid_cairo_draw_grid_global(pcb_hidlib_t *hidlib, cairo_t *cr)
-{
- //render_priv_t *priv = gport->render_priv;
- pcb_coord_t x, y, x1, y1, x2, y2, grd;
- int n, i;
- static GdkPoint *points = NULL;
- static int npoints = 0;
-
- x1 = pcb_grid_fit(MAX(0, SIDE_X(&ghidgui->port.view, ghidgui->port.view.x0)), hidlib->grid, hidlib->grid_ox);
- y1 = pcb_grid_fit(MAX(0, SIDE_Y(&ghidgui->port.view, ghidgui->port.view.y0)), hidlib->grid, hidlib->grid_oy);
- x2 = pcb_grid_fit(MIN(hidlib->size_x, SIDE_X(&ghidgui->port.view, ghidgui->port.view.x0 + ghidgui->port.view.width - 1)), hidlib->grid, hidlib->grid_ox);
- y2 = pcb_grid_fit(MIN(hidlib->size_y, SIDE_Y(&ghidgui->port.view, ghidgui->port.view.y0 + ghidgui->port.view.height - 1)), hidlib->grid, hidlib->grid_oy);
-
- grd = hidlib->grid;
-
- if (Vz(grd) < pcb_conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px) {
- if (!pcb_conf_hid_gtk.plugins.hid_gtk.global_grid.sparse)
- return;
- grd *= (pcb_conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px / Vz(grd));
- }
-
- if (x1 > x2) {
- pcb_coord_t tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- if (y1 > y2) {
- pcb_coord_t tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- if (Vx(x1) < 0)
- x1 += grd;
- if (Vy(y1) < 0)
- y1 += grd;
- if (Vx(x2) >= ghidgui->port.view.canvas_width)
- x2 -= grd;
- if (Vy(y2) >= ghidgui->port.view.canvas_height)
- y2 -= grd;
-
-
- n = (x2 - x1) / grd + 1;
- if (n > npoints) {
- npoints = n + 10;
- points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint));
- }
- n = 0;
- for (x = x1; x <= x2; x += grd) {
- points[n].x = Vx(x);
- n++;
- }
- if (n == 0)
- return;
-
- /* Draw N points... is this the most efficient ? At least, it works.
- From cairo development :
- " cairo_move_to (cr, x, y);
- . cairo_line_to (cr, x, y);
- . .. repeat for each point ..
- .
- . cairo_stroke (cr);
- .
- . Within the implementation (and test suite) we call these "degenerate"
- . paths and we explicitly support drawing round caps for such degenerate
- . paths. So this should work perfectly for the case of
- . CAIRO_LINE_CAP_ROUND and you'll get the diameter controlled by
- . cairo_set_line_width just like you want.
- "
- */
- for (y = y1; y <= y2; y += grd) {
- for (i = 0; i < n; i++) {
- points[i].y = Vy(y);
- cairo_move_to(cr, points[i].x, points[i].y);
- cairo_line_to(cr, points[i].x, points[i].y);
- }
- cairo_stroke(cr);
- }
-}
-
-static void ghid_cairo_draw_grid_local_(pcb_hidlib_t *hidlib, pcb_coord_t cx, pcb_coord_t cy, int radius)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- cairo_t *cr = priv->cr_target;
- static GdkPoint *points_base = NULL;
- static GdkPoint *points_abs = NULL;
- static int apoints = 0, npoints = 0, old_radius = 0;
- static pcb_coord_t last_grid = 0;
- int recalc = 0, n, r2;
- pcb_coord_t x, y;
-
- /* PI is approximated with 3.25 here - allows a minimal overallocation, speeds up calculations */
- r2 = radius * radius;
- n = r2 * 3 + r2 / 4 + 1;
- if (n > apoints) {
- apoints = n;
- points_base = (GdkPoint *) realloc(points_base, apoints * sizeof(GdkPoint));
- points_abs = (GdkPoint *) realloc(points_abs, apoints * sizeof(GdkPoint));
- }
-
- if (radius != old_radius) {
- old_radius = radius;
- recalc = 1;
- }
-
- if (last_grid != hidlib->grid) {
- last_grid = hidlib->grid;
- recalc = 1;
- }
-
- /* recaculate the 'filled circle' mask (base relative coords) if grid or radius changed */
- if (recalc) {
-
- npoints = 0;
- for (y = -radius; y <= radius; y++) {
- int y2 = y * y;
- for (x = -radius; x <= radius; x++) {
- if (x * x + y2 < r2) {
- points_base[npoints].x = x * hidlib->grid;
- points_base[npoints].y = y * hidlib->grid;
- npoints++;
- }
- }
- }
- }
-
- /* calculate absolute positions */
- for (n = 0; n < npoints; n++) {
- points_abs[n].x = Vx(points_base[n].x + cx);
- points_abs[n].y = Vy(points_base[n].y + cy);
- cairo_move_to(cr, points_abs[n].x, points_abs[n].y);
- cairo_line_to(cr, points_abs[n].x, points_abs[n].y);
- }
- cairo_stroke(cr);
- //gdk_draw_points(gport->drawable, priv->grid_gc, points_abs, npoints);
-}
-
-static int grid_local_have_old = 0, grid_local_old_r = 0;
-static pcb_coord_t grid_local_old_x, grid_local_old_y;
-
-static void ghid_cairo_draw_grid_local(pcb_hidlib_t *hidlib, pcb_coord_t cx, pcb_coord_t cy)
-{
- if (grid_local_have_old) {
- ghid_cairo_draw_grid_local_(hidlib, grid_local_old_x, grid_local_old_y, grid_local_old_r);
- grid_local_have_old = 0;
- }
-
- if (!pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.enable)
- return;
-
- if ((Vz(hidlib->grid) < PCB_MIN_GRID_DISTANCE) || (!pcbhl_conf.editor.draw_grid))
- return;
-
- /* cx and cy are the actual cursor snapped to wherever - round them to the nearest real grid point */
- cx = (cx / hidlib->grid) * hidlib->grid + hidlib->grid_ox;
- cy = (cy / hidlib->grid) * hidlib->grid + hidlib->grid_oy;
-
- grid_local_have_old = 1;
- ghid_cairo_draw_grid_local_(hidlib, cx, cy, pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.radius);
- grid_local_old_x = cx;
- grid_local_old_y = cy;
- grid_local_old_r = pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.radius;
-}
-
-static void ghid_cairo_draw_grid(pcb_hidlib_t *hidlib)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- cairo_t *cr = priv->cr_target;
-
- if (cr == NULL)
- return;
-
- grid_local_have_old = 0;
-
- if (!pcbhl_conf.editor.draw_grid)
- return;
- //if (!priv->grid_gc) {
- // if (gdk_color_parse(pcbhl_conf.appearance.color.grid, &gport->grid_color)) {
- // gport->grid_color.red ^= gport->bg_color.red;
- // gport->grid_color.green ^= gport->bg_color.green;
- // gport->grid_color.blue ^= gport->bg_color.blue;
- // gdk_color_alloc(gport->colormap, &gport->grid_color);
- // }
- // priv->grid_gc = gdk_gc_new(gport->drawable);
- // gdk_gc_set_function(priv->grid_gc, GDK_XOR);
- // gdk_gc_set_foreground(priv->grid_gc, &gport->grid_color);
- // gdk_gc_set_clip_origin(priv->grid_gc, 0, 0);
- // set_clip(priv, priv->grid_gc);
- //}
-
- cairo_save(cr);
-TODO("gtk3: deal with gc")
- cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
- cairo_set_line_width(cr, 1.0);
- gdk_cairo_set_source_rgba(cr, &priv->grid_color);
-
- if (pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.enable) {
- ghid_cairo_draw_grid_local(hidlib, grid_local_old_x, grid_local_old_y);
- cairo_restore(cr);
- return;
- }
-
- ghid_cairo_draw_grid_global(hidlib, cr);
- cairo_restore(cr);
-}
-
-/* ------------------------------------------------------------ */
-static void ghid_cairo_draw_bg_image(pcb_hidlib_t *hidlib)
-{
- static GdkPixbuf *pixbuf;
- GdkInterpType interp_type;
- gint src_x, src_y, dst_x, dst_y, w, h, w_src, h_src;
- static gint w_scaled, h_scaled;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- if (!ghidgui->bg_pixbuf)
- return;
-
- src_x = ghidgui->port.view.x0;
- src_y = ghidgui->port.view.y0;
- dst_x = 0;
- dst_y = 0;
-
- if (src_x < 0) {
- dst_x = -src_x;
- src_x = 0;
- }
- if (src_y < 0) {
- dst_y = -src_y;
- src_y = 0;
- }
-
- w = hidlib->size_x / ghidgui->port.view.coord_per_px;
- h = hidlib->size_y / ghidgui->port.view.coord_per_px;
- src_x = src_x / ghidgui->port.view.coord_per_px;
- src_y = src_y / ghidgui->port.view.coord_per_px;
- dst_x = dst_x / ghidgui->port.view.coord_per_px;
- dst_y = dst_y / ghidgui->port.view.coord_per_px;
-
- if (w_scaled != w || h_scaled != h) {
- if (pixbuf)
- g_object_unref(G_OBJECT(pixbuf));
-
- w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
- h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
- if (w > w_src && h > h_src)
- interp_type = GDK_INTERP_NEAREST;
- else
- interp_type = GDK_INTERP_BILINEAR;
-
- pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type);
- w_scaled = w;
- h_scaled = h;
- }
-
- if (pixbuf) {
- gdk_cairo_set_source_pixbuf(priv->cr, pixbuf, src_x, src_y);
- cairo_rectangle(priv->cr, dst_x, dst_y, ghidgui->port.view.canvas_width, ghidgui->port.view.canvas_height);
- cairo_fill(priv->cr);
- //gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, priv->bg_gc,
- // src_x, src_y, dst_x, dst_y, w - src_x, h - src_y, GDK_RGB_DITHER_NORMAL, 0, 0);
- }
-}
-
-static void ghid_cairo_render_burst(pcb_hid_t *hid, pcb_burst_op_t op, const pcb_box_t *screen)
-{
- pcb_gui->coord_per_pix = ghidgui->port.view.coord_per_px;
-}
-
-/* Drawing modes usually cycle from RESET to (POSITIVE | NEGATIVE) to FLUSH. screen is not used in this HID. */
-static void ghid_cairo_set_drawing_mode(pcb_hid_t *hid, pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
-
- if (!priv->cr) {
- //abort();
- return;
- }
-
- switch(op) {
- case PCB_HID_COMP_RESET:
- //ghid_sketch_setup(priv);
- start_subcomposite();
-
- /* clear the canvas */
- //priv->clip_color.pixel = 0;
- //if (priv->clear_gc == NULL)
- // priv->clear_gc = gdk_gc_new(priv->out_clip);
- //gdk_gc_set_foreground(priv->clear_gc, &priv->clip_color);
- //set_clip(priv, priv->clear_gc);
- //gdk_draw_rectangle(priv->out_clip, priv->clear_gc, TRUE, 0, 0, gport->view.canvas_width, gport->view.canvas_height);
- break;
-
- case PCB_HID_COMP_POSITIVE:
- case PCB_HID_COMP_POSITIVE_XOR:
- //priv->clip_color.pixel = 1;
- cairo_set_operator(priv->cr, CAIRO_OPERATOR_SOURCE);
- break;
-
- case PCB_HID_COMP_NEGATIVE:
- //priv->clip_color.pixel = 0;
- cairo_set_operator(priv->cr, CAIRO_OPERATOR_CLEAR);
- break;
-
- case PCB_HID_COMP_FLUSH:
- if (direct)
- end_subcomposite();
- else {
- priv->cr = priv->cr_target;
- cairo_mask_surface(priv->cr, priv->surf_layer, 0, 0);
- cairo_fill(priv->cr);
- }
- //cairo_paint_with_alpha(priv->cr, pcbhl_conf.appearance.layer_alpha);
- //cairo_paint_with_alpha(priv->cr, 1.0);
-
- //if (priv->copy_gc == NULL)
- // priv->copy_gc = gdk_gc_new(priv->out_pixel);
- //gdk_gc_set_clip_mask(priv->copy_gc, priv->sketch_clip);
- //gdk_gc_set_clip_origin(priv->copy_gc, 0, 0);
- //gdk_draw_drawable(priv->base_pixel, priv->copy_gc, priv->sketch_pixel, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height);
- //
- //priv->out_pixel = priv->base_pixel;
- //priv->out_clip = NULL;
- break;
- }
- curr_drawing_mode = op;
-}
-
-typedef struct {
- int color_set;
- pcb_gtk_color_t color;
- int xor_set;
- pcb_gtk_color_t xor_color;
-} pcb_gtk_color_cache_t;
-
-
-/* Config helper functions for when the user changes color preferences.
- set_special colors used in the gtkhid.
- */
-//static void set_special_grid_color(void)
-//{
-// render_priv_t *priv = gport->render_priv;
-// int red, green, blue;
-//
-// //if (!gport->colormap)
-// // return;
-//
-// red = priv->grid_color.red;
-// green = priv->grid_color.green;
-// blue = priv->grid_color.blue;
-// pcb_conf_setf(CFR_DESIGN, "appearance/color/grid", -1, "#%02x%02x%02x", red, green, blue);
-// map_color_string(pcbhl_conf.appearance.color.grid, &priv->grid_color);
-//
-// config_color_button_update(&ghidgui->common, pcb_conf_get_field("appearance/color/grid"), -1);
-//
-// //if (priv->grid_gc)
-// // gdk_gc_set_foreground(priv->grid_gc, &gport->grid_color);
-//}
-
-/* Assign "identified" colors to background, offlimits and grid cached structures */
-static void ghid_cairo_set_special_colors(conf_native_t * cfg)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
-
- if (((CFT_COLOR *) cfg->val.color == &pcbhl_conf.appearance.color.background) /*&& priv->bg_gc */ ) {
- if (map_color(&cfg->val.color[0], &priv->bg_color)) {
- //gdk_gc_set_foreground(priv->bg_gc, &priv->bg_color);
- //set_special_grid_color();
- }
- }
- else if (((CFT_COLOR *) cfg->val.color == &pcbhl_conf.appearance.color.off_limit) /*&& priv->offlimits_gc */ ) {
- if (map_color(&cfg->val.color[0], &priv->offlimits_color)) {
- //gdk_gc_set_foreground(priv->offlimits_gc, &priv->offlimits_color);
- }
- }
- else if (((CFT_COLOR *) cfg->val.color == &pcbhl_conf.appearance.color.grid) /*&& priv->grid_gc */ ) {
- if (map_color(&cfg->val.color[0], &priv->grid_color)) {
- //set_special_grid_color();
- }
- }
-}
-
-static void ghid_cairo_set_color(pcb_hid_gc_t gc, const pcb_color_t *color)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- const char *name = color->str;
-
- if (name == NULL) {
- fprintf(stderr, "ghid_cairo_set_color(): name = NULL, setting to magenta\n");
- color = pcb_color_magenta;
- }
-
- gc->pcolor = *color;
-
- //if (!gc->gc)
- // return;
- //if (gport->colormap == 0)
- // gport->colormap = gtk_widget_get_colormap(gport->top_window);
-
- if (pcb_color_is_drill(color)) {
- copy_color(&gc->color, &priv->offlimits_color);
- //gdk_cairo_set_source_rgba(cr, &priv->offlimits_color);
- //gdk_gc_set_foreground(gc->gc, &gport->offlimits_color);
- }
- else {
- pcb_gtk_color_cache_t *cc;
-
- if (!priv->ccache_inited) {
- pcb_clrcache_init(&priv->ccache, sizeof(pcb_gtk_color_cache_t), NULL);
- priv->ccache_inited = 1;
- }
- cc = pcb_clrcache_get(&priv->ccache, color, 1);
- if (!cc->color_set) {
- map_color(color, &cc->color);
- cc->color_set = 1;
- }
- //if (gc->xor_mask) {
- // if (!cc->xor_set) {
- // cc->xor_color.red = cc->color.red ^ gport->bg_color.red;
- // cc->xor_color.green = cc->color.green ^ gport->bg_color.green;
- // cc->xor_color.blue = cc->color.blue ^ gport->bg_color.blue;
- // gdk_color_alloc(gport->colormap, &cc->xor_color);
- // cc->xor_set = 1;
- // }
- // gdk_gc_set_foreground(gc->gc, &cc->xor_color);
- //}
- //else {
- // gdk_gc_set_foreground(gc->gc, &cc->color);
- //}
- cc->color.alpha = 1.0;
- copy_color(&gc->color, &cc->color);
- }
-}
-
-static void ghid_cairo_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style)
-{
- cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
- cairo_line_join_t join = CAIRO_LINE_JOIN_MITER;
-
- switch (style) {
- case pcb_cap_round:
- cap = CAIRO_LINE_CAP_ROUND;
- join = CAIRO_LINE_JOIN_ROUND;
- break;
- case pcb_cap_square:
- cap = CAIRO_LINE_CAP_SQUARE;
- join = CAIRO_LINE_JOIN_MITER;
- break;
- default:
- assert(!"unhandled cap");
- }
- gc->cap = cap;
- gc->join = join;
-
- //if (gc->gc)
- // gdk_gc_set_line_attributes(WHICH_GC(gc), Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join);
-}
-
-static void ghid_cairo_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width)
-{
- //render_priv_t *priv = gport->render_priv;
-
- //if (priv->cr == NULL)
- // return;
-
- gc->width = width;
- //cairo_set_line_width(priv->cr, Vz(gc->width));
- //if (gc->gc)
- // gdk_gc_set_line_attributes(WHICH_GC(gc), Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join);
-}
-
-static void ghid_cairo_set_draw_xor(pcb_hid_gc_t gc, int xor_mask)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
-
- priv->xor_mode = (xor_mask) ? 1 : 0;
- //gc->xor_mask = xor_mask;
- //if (!gc->gc)
- // return;
- //gdk_gc_set_function(gc->gc, xor_mask ? GDK_XOR : GDK_COPY);
- //ghid_cairo_set_color(gc, gc->pcolor.str);
-}
-
-static int use_gc(pcb_hid_gc_t gc)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- cairo_t *cr = priv->cr;
- //GdkWindow *window = gtk_widget_get_window(gport->top_window);
-
- if (gc->me_pointer != >k3_cairo_hid) {
- fprintf(stderr, "Fatal: GC from another HID passed to GTK HID\n");
- abort();
- }
-
- if (cr == NULL)
- return 0;
-
- //ghid_cairo_set_color(gc, gc->pcolor.str);
- gdk_cairo_set_source_rgba(cr, &gc->color);
-
- /* negative line width means "unit is pixels", so -1 is "1 pixel", -5 is "5 pixels", regardless of the zoom. */
- if (gc->width <= 0)
- cairo_set_line_width(cr, 1.0 - gc->width);
- else
- cairo_set_line_width(cr, Vz(gc->width));
-
- //ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap);
- cairo_set_line_cap(cr, gc->cap);
- cairo_set_line_join(cr, gc->join);
-
-
- //if (!gc->gc) {
- // gc->gc = gdk_gc_new(window);
- // ghid_cairo_set_color(gc, gc->colorname);
- // ghid_cairo_set_line_width(gc, gc->width);
- // ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap);
- // ghid_cairo_set_draw_xor(gc, gc->xor_mask);
- // gdk_gc_set_clip_origin(gc->gc, 0, 0);
- //}
- //if (gc->mask_seq != mask_seq) {
- // if (mask_seq)
- // gdk_gc_set_clip_mask(gc->gc, gport->mask);
- // else
- // set_clip(priv, gc->gc);
- // gc->mask_seq = mask_seq;
- //}
- //priv->u_gc = WHICH_GC(gc);
- return 1;
-}
-
-static void ghid_cairo_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
-{
- double dx1, dy1, dx2, dy2;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- dx1 = Vx((double) x1);
- dy1 = Vy((double) y1);
- dx2 = Vx((double) x2);
- dy2 = Vy((double) y2);
-
- if (!pcb_line_clip
- (0, 0, ghidgui->port.view.canvas_width, ghidgui->port.view.canvas_height, &dx1, &dy1, &dx2, &dy2, gc->width / ghidgui->port.view.coord_per_px))
- return;
-
- USE_GC(gc);
- cr_draw_line(priv->cr, FALSE, dx1, dy1, dx2, dy2);
- //gdk_draw_line(gport->drawable, priv->u_gc, dx1, dy1, dx2, dy2);
-}
-
-/* Draws an arc from center (cx, cy), cx>0 to the right, cy>0 to the bottom, using
- xradius on X axis, and yradius on Y axis, sweeping a delta_angle from start_angle.
-
- Angles (in degres) originate at 9 o'clock and are positive CCW (counter clock wise).
- delta_angle sweeps the angle from start_angle, CW if negative. */
-static void ghid_cairo_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy,
- pcb_coord_t xradius, pcb_coord_t yradius, pcb_angle_t start_angle, pcb_angle_t delta_angle)
-{
- double w, h, radius, angle1, angle2;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- w = ghidgui->port.view.canvas_width * ghidgui->port.view.coord_per_px;
- h = ghidgui->port.view.canvas_height * ghidgui->port.view.coord_per_px;
- radius = (xradius > yradius) ? xradius : yradius;
- if (SIDE_X(&ghidgui->port.view, cx) < ghidgui->port.view.x0 - radius
- || SIDE_X(&ghidgui->port.view, cx) > ghidgui->port.view.x0 + w + radius
- || SIDE_Y(&ghidgui->port.view, cy) < ghidgui->port.view.y0 - radius || SIDE_Y(&ghidgui->port.view, cy) > ghidgui->port.view.y0 + h + radius)
- return;
-
- USE_GC(gc);
-
- if ((delta_angle > 360.0) || (delta_angle < -360.0)) {
- start_angle = 0;
- delta_angle = 360;
- }
-
- if (pcbhl_conf.editor.view.flip_x) {
- start_angle = 180 - start_angle;
- delta_angle = -delta_angle;
- }
- if (pcbhl_conf.editor.view.flip_y) {
- start_angle = -start_angle;
- delta_angle = -delta_angle;
- }
- /* make sure we fall in the -180 to +180 range */
- start_angle = pcb_normalize_angle(start_angle);
- if (start_angle >= 180)
- start_angle -= 360;
-
- /* cairo lib. originates angles at 3 o'clock, positive traveling CW, requires angle1 < angle2 */
- angle1 = (180.0 - start_angle);
- angle2 = (delta_angle < 0) ? (angle1 - delta_angle) : angle1;
- if (delta_angle > 0) {
- angle1 = (180.0 - start_angle - delta_angle);
- }
- angle1 *= (M_PI / 180.0);
- angle2 *= (M_PI / 180.0);
- cairo_save(priv->cr);
-TODO("gtk3: this will draw an arc of a circle, not an ellipse! Explore matrix transformation here.")
- cairo_arc(priv->cr, pcb_round(Vxd(cx)), pcb_round(Vyd(cy)), Vzd(radius), angle1, angle2);
- cairo_stroke(priv->cr);
- cairo_restore(priv->cr);
- //gdk_draw_arc(gport->drawable, priv->u_gc, 0,
- // pcb_round(Vxd(cx) - Vzd(xradius) + 0.5), pcb_round(Vyd(cy) - Vzd(yradius) + 0.5),
- // pcb_round(vrx2), pcb_round(vry2), (start_angle + 180) * 64, delta_angle * 64);
-}
-
-static void cr_draw_rect(pcb_hid_gc_t gc, int fill, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
-{
- gint w, h, lw;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- if (priv->cr == NULL)
- return;
-
- lw = gc->width;
- w = ghidgui->port.view.canvas_width * ghidgui->port.view.coord_per_px;
- h = ghidgui->port.view.canvas_height * ghidgui->port.view.coord_per_px;
-
- if ((SIDE_X(&ghidgui->port.view, x1) < ghidgui->port.view.x0 - lw && SIDE_X(&ghidgui->port.view, x2) < ghidgui->port.view.x0 - lw)
- || (SIDE_X(&ghidgui->port.view, x1) > ghidgui->port.view.x0 + w + lw && SIDE_X(&ghidgui->port.view, x2) > ghidgui->port.view.x0 + w + lw)
- || (SIDE_Y(&ghidgui->port.view, y1) < ghidgui->port.view.y0 - lw && SIDE_Y(&ghidgui->port.view, y2) < ghidgui->port.view.y0 - lw)
- || (SIDE_Y(&ghidgui->port.view, y1) > ghidgui->port.view.y0 + h + lw && SIDE_Y(&ghidgui->port.view, y2) > ghidgui->port.view.y0 + h + lw))
- return;
-
- x1 = Vx(x1);
- y1 = Vy(y1);
- x2 = Vx(x2);
- y2 = Vy(y2);
-
- if (x1 > x2) {
- gint xt = x1;
- x1 = x2;
- x2 = xt;
- }
- if (y1 > y2) {
- gint yt = y1;
- y1 = y2;
- y2 = yt;
- }
-
- USE_GC(gc);
- cairo_rectangle(priv->cr, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
- //gdk_draw_rectangle(gport->drawable, priv->u_gc, FALSE, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
-
- if (fill)
- cairo_fill(priv->cr);
- else
- cairo_stroke(priv->cr);
-}
-
-static void cr_paint_from_surface(cairo_t * cr, cairo_surface_t * surface)
-{
- cairo_set_source_surface(cr, surface, 0, 0);
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_paint_with_alpha(cr, 1.0);
-}
-
-static void ghid_cairo_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
-{
- cr_draw_rect(gc, FALSE, x1, y1,x2, y2);
-}
-
-static void ghid_cairo_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
-{
- cr_draw_rect(gc, TRUE, x1, y1,x2, y2);
-}
-
-static void ghid_cairo_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius)
-{
- gint w, h, vr;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- if (priv->cr == NULL)
- return;
-
- w = ghidgui->port.view.canvas_width * ghidgui->port.view.coord_per_px;
- h = ghidgui->port.view.canvas_height * ghidgui->port.view.coord_per_px;
- if (SIDE_X(&ghidgui->port.view, cx) < ghidgui->port.view.x0 - radius
- || SIDE_X(&ghidgui->port.view, cx) > ghidgui->port.view.x0 + w + radius
- || SIDE_Y(&ghidgui->port.view, cy) < ghidgui->port.view.y0 - radius || SIDE_Y(&ghidgui->port.view, cy) > ghidgui->port.view.y0 + h + radius)
- return;
-
- USE_GC(gc);
- vr = Vz(radius);
- cairo_arc(priv->cr, Vx(cx), Vy(cy), vr, 0.0, 2 * M_PI);
- cairo_fill(priv->cr);
- //gdk_draw_arc(gport->drawable, priv->u_gc, TRUE, Vx(cx) - vr, Vy(cy) - vr, vr * 2, vr * 2, 0, 360 * 64);
-}
-
-/* Intentional code duplication from ghid_cairo_fill_polygon_offs(), for performance */
-static void ghid_cairo_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y)
-{
- int i;
- render_priv_t *priv = ghidgui->port.render_priv;
- cairo_t *cr = priv->cr;
- int _x, _y;
-
- if (priv->cr == NULL)
- return;
-
- USE_GC(gc);
-
- for (i = 0; i < n_coords; i++) {
- _x = Vx(x[i]);
- _y = Vy(y[i]);
- if (i == 0)
- cairo_move_to(cr, _x, _y);
- else
- cairo_line_to(cr, _x, _y);
- }
- cairo_fill(cr);
-}
-
-static void ghid_cairo_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy)
-{
- int i;
- render_priv_t *priv = ghidgui->port.render_priv;
- cairo_t *cr = priv->cr;
- int _x, _y;
-
- if (priv->cr == NULL)
- return;
-
- USE_GC(gc);
-
- for (i = 0; i < n_coords; i++) {
- _x = Vx(x[i]);
- _y = Vy(y[i]);
- if (i == 0)
- cairo_move_to(cr, _x + Vz(dx), _y + Vz(dy));
- else
- cairo_line_to(cr, _x + Vz(dx), _y + Vz(dy));
- }
- cairo_fill(cr);
-}
-
-/* Fills the drawing with only bg_color */
-static void erase_with_background_color(cairo_t * cr, GdkRGBA * bg_color)
-{
- gdk_cairo_set_source_rgba(cr, bg_color);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- cairo_paint_with_alpha(cr, 1.0);
-}
-
-static void redraw_region(pcb_hidlib_t *hidlib, GdkRectangle *rect)
-{
- int eleft, eright, etop, ebottom;
- pcb_hid_expose_ctx_t ctx;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- if (priv->cr_drawing_area == NULL)
- return;
-
- if (rect != NULL) {
- priv->clip_rect = *rect;
- priv->clip = pcb_true;
- }
- else {
- priv->clip_rect.x = 0;
- priv->clip_rect.y = 0;
- priv->clip_rect.width = ghidgui->port.view.canvas_width;
- priv->clip_rect.height = ghidgui->port.view.canvas_height;
- priv->clip = pcb_false;
- }
-
- //set_clip(priv, priv->bg_gc);
- //set_clip(priv, priv->offlimits_gc);
- //set_clip(priv, priv->mask_gc);
- //set_clip(priv, priv->grid_gc);
-
- ctx.view.X1 = MIN(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1));
- ctx.view.Y1 = MIN(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1));
- ctx.view.X2 = MAX(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1));
- ctx.view.Y2 = MAX(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1));
-
- ctx.view.X1 = MAX(0, MIN(hidlib->size_x, ctx.view.X1));
- ctx.view.X2 = MAX(0, MIN(hidlib->size_x, ctx.view.X2));
- ctx.view.Y1 = MAX(0, MIN(hidlib->size_y, ctx.view.Y1));
- ctx.view.Y2 = MAX(0, MIN(hidlib->size_y, ctx.view.Y2));
-
- eleft = Vx(0);
- eright = Vx(hidlib->size_x);
- etop = Vy(0);
- ebottom = Vy(hidlib->size_y);
- if (eleft > eright) {
- int tmp = eleft;
- eleft = eright;
- eright = tmp;
- }
- if (etop > ebottom) {
- int tmp = etop;
- etop = ebottom;
- ebottom = tmp;
- }
-
- /* Paints only on the drawing_area */
- priv->cr = priv->cr_drawing_area;
- priv->cr_target = priv->cr_drawing_area;
-
- erase_with_background_color(priv->cr, &priv->bg_color);
-
- gdk_cairo_set_source_rgba(priv->cr, &priv->offlimits_color);
- if (eleft > 0) {
- cairo_rectangle(priv->cr, 0.0, 0.0, eleft, ghidgui->port.view.canvas_height);
- }
- else
- eleft = 0;
- if (eright < ghidgui->port.view.canvas_width) {
- cairo_rectangle(priv->cr, eright, 0.0, ghidgui->port.view.canvas_width - eright, ghidgui->port.view.canvas_height);
- }
- else
- eright = ghidgui->port.view.canvas_width;
- if (etop > 0) {
- cairo_rectangle(priv->cr, eleft, 0.0, eright - eleft + 1, etop);
- }
- else
- etop = 0;
- if (ebottom < ghidgui->port.view.canvas_height) {
- cairo_rectangle(priv->cr, eleft, ebottom, eright - eleft + 1, ghidgui->port.view.canvas_height - ebottom);
- }
- else
- ebottom = ghidgui->port.view.canvas_height;
-
- cairo_fill(priv->cr);
- //gdk_draw_rectangle(gport->drawable, priv->bg_gc, 1, eleft, etop, eright - eleft + 1, ebottom - etop + 1);
-
- ghid_cairo_draw_bg_image(hidlib);
-
- pcbhl_expose_main(>k3_cairo_hid, &ctx, NULL);
- ghid_cairo_draw_grid(hidlib);
-
- /* Draws "GUI" information on top of design */
- priv->cr = priv->cr_drawing_area;
- /* In some cases we are called with the crosshair still off */
- if (priv->attached_invalidate_depth == 0)
- pcbhl_draw_attached(hidlib, 0);
-
- /* In some cases we are called with the mark still off */
- if (priv->mark_invalidate_depth == 0)
- pcbhl_draw_marks(hidlib, 0);
-
- priv->clip = pcb_false;
-
- /* Rest the clip for bg_gc, as it is used outside this function */
- //gdk_gc_set_clip_mask(priv->bg_gc, NULL);
- ghid_cairo_screen_update();
-}
-
-static int preview_lock = 0;
-static void ghid_cairo_invalidate_lr(pcb_hid_t *hid, pcb_coord_t left, pcb_coord_t right, pcb_coord_t top, pcb_coord_t bottom)
-{
- pcb_hidlib_t *hidlib = ghidgui->hidlib;
- int dleft, dright, dtop, dbottom;
- int minx, maxx, miny, maxy;
- GdkRectangle rect;
-
- dleft = Vx(left);
- dright = Vx(right);
- dtop = Vy(top);
- dbottom = Vy(bottom);
-
- minx = MIN(dleft, dright);
- maxx = MAX(dleft, dright);
- miny = MIN(dtop, dbottom);
- maxy = MAX(dtop, dbottom);
-
- rect.x = minx;
- rect.y = miny;
- rect.width = maxx - minx;
- rect.height = maxy - miny;
-
- redraw_region(hidlib, &rect);
- if (!preview_lock) {
- preview_lock++;
- pcb_gtk_previews_invalidate_lr(minx, maxx, miny, maxy);
- preview_lock--;
- }
-
- ghid_cairo_screen_update();
-}
-
-static void ghid_cairo_invalidate_all(pcb_hid_t *hid)
-{
- pcb_hidlib_t *hidlib = ghidgui->hidlib;
-
- if (ghidgui && ghidgui->topwin.menu.menu_bar) {
- redraw_region(hidlib, NULL);
- if (!preview_lock) {
- preview_lock++;
- pcb_gtk_previews_invalidate_all();
- preview_lock--;
- }
- ghid_cairo_screen_update();
- }
-}
-
-static void ghid_cairo_notify_crosshair_change(pcb_hid_t *hid, pcb_bool changes_complete)
-{
- pcb_hidlib_t *hidlib = ghidgui->hidlib;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- /* We sometimes get called before the GUI is up */
- if (ghidgui->port.drawing_area == NULL)
- return;
-
- /* Keeps track of calls (including XOR draw mode), and draws only when complete and final. */
- if (changes_complete)
- priv->attached_invalidate_depth--;
- else
- priv->attached_invalidate_depth = 1 + priv->xor_mode;
-
- if (changes_complete && ghidgui->port.drawing_area != NULL && priv->attached_invalidate_depth <= 0) {
- /* Queues a GTK redraw when changes are complete */
- ghid_cairo_invalidate_all(pcb_gui);
- priv->attached_invalidate_depth = 0;
- }
-}
-
-static void ghid_cairo_notify_mark_change(pcb_hid_t *hid, pcb_bool changes_complete)
-{
- pcb_hidlib_t *hidlib = ghidgui->hidlib;
- render_priv_t *priv = ghidgui->port.render_priv;
-
- /* We sometimes get called before the GUI is up */
- if (ghidgui->port.drawing_area == NULL)
- return;
-
- if (changes_complete)
- priv->mark_invalidate_depth--;
-
- if (priv->mark_invalidate_depth < 0) {
- priv->mark_invalidate_depth = 0;
- /* A mismatch of changes_complete == pcb_false and == pcb_true notifications
- is not expected to occur, but we will try to handle it gracefully.
- As we know the mark will have been shown already, we must
- repaint the entire view to be sure not to leave an artefact.
- */
- ghid_cairo_invalidate_all(pcb_gui);
- return;
- }
-
- if (priv->mark_invalidate_depth == 0)
- pcbhl_draw_marks(hidlib, 0);
-
- if (!changes_complete) {
- priv->mark_invalidate_depth++;
- }
- else if (ghidgui->port.drawing_area != NULL) {
- /* Queue a GTK expose when changes are complete */
- ghid_draw_area_update(&ghidgui->port, NULL);
- }
-}
-
-static void draw_right_cross(cairo_t * cr, gint x, gint y)
-{
- //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
-
- cr_draw_line(cr, FALSE, x, 0, x, ghidgui->port.view.canvas_height);
- cr_draw_line(cr, FALSE, 0, y, ghidgui->port.view.canvas_width, y);
- //gdk_draw_line(window, xor_gc, x, 0, x, gport->view.canvas_height);
- //gdk_draw_line(window, xor_gc, 0, y, gport->view.canvas_width, y);
-}
-
-static void draw_slanted_cross(cairo_t * xor_gc, gint x, gint y)
-{
- //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
- gint x0, y0, x1, y1;
-
- x0 = x + (ghidgui->port.view.canvas_height - y);
- x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
- x1 = x - y;
- x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
- y0 = y + (ghidgui->port.view.canvas_width - x);
- y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
- y1 = y - x;
- y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
- cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
- //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
-
- x0 = x - (ghidgui->port.view.canvas_height - y);
- x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
- x1 = x + y;
- x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
- y0 = y + x;
- y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
- y1 = y - (ghidgui->port.view.canvas_width - x);
- y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
- cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
- //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
-}
-
-static void draw_dozen_cross(cairo_t * xor_gc, gint x, gint y)
-{
- //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
- gint x0, y0, x1, y1;
- gdouble tan60 = sqrt(3);
-
- x0 = x + (ghidgui->port.view.canvas_height - y) / tan60;
- x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
- x1 = x - y / tan60;
- x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
- y0 = y + (ghidgui->port.view.canvas_width - x) * tan60;
- y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
- y1 = y - x * tan60;
- y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
- cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
- //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
-
- x0 = x + (ghidgui->port.view.canvas_height - y) * tan60;
- x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
- x1 = x - y * tan60;
- x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
- y0 = y + (ghidgui->port.view.canvas_width - x) / tan60;
- y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
- y1 = y - x / tan60;
- y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
- cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
- //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
-
- x0 = x - (ghidgui->port.view.canvas_height - y) / tan60;
- x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
- x1 = x + y / tan60;
- x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
- y0 = y + x * tan60;
- y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
- y1 = y - (ghidgui->port.view.canvas_width - x) * tan60;
- y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
- cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
- //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
-
- x0 = x - (ghidgui->port.view.canvas_height - y) * tan60;
- x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
- x1 = x + y * tan60;
- x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
- y0 = y + x / tan60;
- y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
- y1 = y - (ghidgui->port.view.canvas_width - x) / tan60;
- y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
- cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
- //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
-}
-
-static void draw_crosshair(cairo_t * xor_gc, gint x, gint y)
-{
- static enum pcb_crosshair_shape_e prev = pcb_ch_shape_basic;
-
- if (ghidgui->port.view.crosshair_x < 0 || !ghidgui->topwin.active || !ghidgui->port.view.has_entered)
- return;
-
- draw_right_cross(xor_gc, x, y);
- if (prev == pcb_ch_shape_union_jack)
- draw_slanted_cross(xor_gc, x, y);
- if (prev == pcb_ch_shape_dozen)
- draw_dozen_cross(xor_gc, x, y);
- prev = pcbhl_conf.editor.crosshair_shape_idx;
-}
-
-static void show_crosshair(gboolean paint_new_location)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
- //GtkStyle *style = gtk_widget_get_style(gport->drawing_area);
- gint x, y;
- static gint x_prev = -1, y_prev = -1;
- //static cairo_t *xor_gc;
- //static GdkColor cross_color;
- cairo_t *cr;
-
- if (ghidgui->port.view.crosshair_x < 0 || !ghidgui->topwin.active || !ghidgui->port.view.has_entered) {
- x_prev = y_prev = -1; /* if leaving the drawing area, invalidate last known coord to make sure we redraw on reenter, even on the same coords */
- return;
- }
-
-TODO("gtk3: when CrossColor changed from config")
- map_color(&pcbhl_conf.appearance.color.cross, &priv->crosshair_color);
- //cr = priv->cr_drawing_area;
- cr = priv->cr;
- gdk_cairo_set_source_rgba(cr, &priv->crosshair_color);
- cairo_set_line_width(cr, 1.0);
-
- //if (!xor_gc) {
- // xor_gc = gdk_gc_new(window);
- // gdk_gc_copy(xor_gc, style->white_gc);
- // gdk_gc_set_function(xor_gc, GDK_XOR);
- // gdk_gc_set_clip_origin(xor_gc, 0, 0);
- // set_clip(priv, xor_gc);
-TODO("gtk3:FIXME: when CrossColor changed from config")
- // map_color(&pcbhl_conf.appearance.color.cross, &cross_color);
- //}
- x = Vx(ghidgui->port.view.crosshair_x);
- y = Vy(ghidgui->port.view.crosshair_y);
-
- //gdk_gc_set_foreground(xor_gc, &cross_color);
-
- if (x_prev >= 0 && !paint_new_location)
- draw_crosshair(cr, x_prev, y_prev);
-
- if (x >= 0 && paint_new_location) {
- draw_crosshair(cr, x, y);
- x_prev = x;
- y_prev = y;
- }
- else
- x_prev = y_prev = -1;
-}
-
-static void ghid_cairo_init_renderer(int *argc, char ***argv, void *vport)
-{
- pcb_gtk_port_t *port = vport;
-
- /* Init any GC's required */
- port->render_priv = g_new0(render_priv_t, 1);
- port->render_priv->cr = NULL;
- port->render_priv->surf_da = NULL;
- port->render_priv->cr_drawing_area = NULL;
-}
-
-static void ghid_cairo_shutdown_renderer(void *vport)
-{
- pcb_gtk_port_t *port = vport;
- render_priv_t *priv = port->render_priv;
-
- cairo_surface_destroy(priv->surf_da);
- priv->surf_da = NULL;
- cairo_destroy(priv->cr_drawing_area);
- priv->cr_drawing_area = NULL;
- priv->cr = NULL;
-
- g_free(port->render_priv);
- port->render_priv = NULL;
-}
-
-static void ghid_cairo_init_drawing_widget(GtkWidget * widget, void *vport)
-{
-}
-
-/* Callback function only applied to drawing_area, after some resizing or initialisation. */
-static void ghid_cairo_drawing_area_configure_hook(void *vport)
-{
- pcb_gtk_port_t *port = vport;
- static int done_once = 0;
- render_priv_t *priv = port->render_priv;
- cairo_t *cr;
-
- ghidgui->port.drawing_allowed = pcb_true;
-
- if (!done_once) {
- //priv->bg_gc = gdk_gc_new(port->drawable);
- //gdk_gc_set_foreground(priv->bg_gc, &port->bg_color);
- //gdk_gc_set_clip_origin(priv->bg_gc, 0, 0);
- //
- //priv->offlimits_gc = gdk_gc_new(port->drawable);
- //gdk_gc_set_foreground(priv->offlimits_gc, &port->offlimits_color);
- //gdk_gc_set_clip_origin(priv->offlimits_gc, 0, 0);
-
- if (!map_color(&pcbhl_conf.appearance.color.background, &priv->bg_color))
- map_color(pcb_color_white, &priv->bg_color);
-
- if (!map_color(&pcbhl_conf.appearance.color.off_limit, &priv->offlimits_color))
- map_color(pcb_color_white, &priv->offlimits_color);
-
- if (!map_color(&pcbhl_conf.appearance.color.grid, &priv->grid_color))
- map_color(pcb_color_blue, &priv->grid_color);
- //set_special_grid_color();
-
- //if (port->mask) {
- // gdk_pixmap_unref(port->mask);
- // port->mask = gdk_pixmap_new(0, port->view.canvas_width, port->view.canvas_height, 1);
- //}
- done_once = 1;
- }
-
- /* Creates a single cairo surface/context for off-line painting */
- cr_create_similar_surface_and_context(&priv->surf_da, &priv->cr_drawing_area, port);
- cr_create_similar_surface_and_context(&priv->surf_layer, &priv->cr_layer, port);
- priv->cr = priv->cr_drawing_area;
-}
-
-/* GtkDrawingArea -> GtkWidget "draw" signal Call-Back function */
-static gboolean ghid_cairo_drawing_area_expose_cb(GtkWidget * widget, pcb_gtk_expose_t * p, void *vport)
-{
- pcb_gtk_port_t *port = vport;
- render_priv_t *priv = port->render_priv;
- //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
-
- //gdk_draw_drawable(window, priv->bg_gc, port->pixmap,
- // ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
-
- cr_paint_from_surface(p, priv->surf_da);
-
- priv->cr = p;
- show_crosshair(TRUE);
- priv->cr = priv->cr_drawing_area;
-
- return FALSE;
-}
-
-static void ghid_cairo_screen_update(void)
-{
- render_priv_t *priv = ghidgui->port.render_priv;
- //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
-
- if (priv->cr == NULL)
- return;
-
- //gdk_draw_drawable(window, priv->bg_gc, gport->pixmap, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height);
- //show_crosshair(TRUE);
- gtk_widget_queue_draw(ghidgui->port.drawing_area);
-}
-
-static void ghid_cairo_port_drawing_realize_cb(GtkWidget * widget, gpointer data)
-{
-}
-
-static gboolean ghid_cairo_preview_expose(GtkWidget * widget, pcb_gtk_expose_t * p,
- pcb_hid_expose_t expcall, pcb_hid_expose_ctx_t *ctx)
-{
- //GdkWindow *window = gtk_widget_get_window(widget);
- //GdkDrawable *save_drawable;
- GtkAllocation allocation; /* Assuming widget is a drawing widget, get the Rectangle allowed for drawing. */
- pcb_gtk_view_t save_view;
- int save_width, save_height;
- double xz, yz, vw, vh;
- render_priv_t *priv = ghidgui->port.render_priv;
- pcb_coord_t ox1 = ctx->view.X1, oy1 = ctx->view.Y1, ox2 = ctx->view.X2, oy2 = ctx->view.Y2;
- pcb_coord_t save_cpp;
-
- vw = ctx->view.X2 - ctx->view.X1;
- vh = ctx->view.Y2 - ctx->view.Y1;
-
- /* Setup drawable and zoom factor for drawing routines
- */
- //save_drawable = gport->drawable;
- save_view = ghidgui->port.view;
- save_width = ghidgui->port.view.canvas_width;
- save_height = ghidgui->port.view.canvas_height;
- save_cpp = pcb_gui->coord_per_pix;
-
- gtk_widget_get_allocation(widget, &allocation);
- xz = vw / (double) allocation.width;
- yz = vh / (double) allocation.height;
- if (xz > yz)
- ghidgui->port.view.coord_per_px = xz;
- else
- ghidgui->port.view.coord_per_px = yz;
-
- //gport->drawable = window;
- ghidgui->port.view.canvas_width = allocation.width;
- ghidgui->port.view.canvas_height = allocation.height;
- ghidgui->port.view.width = allocation.width * ghidgui->port.view.coord_per_px;
- ghidgui->port.view.height = allocation.height * ghidgui->port.view.coord_per_px;
- ghidgui->port.view.x0 = (vw - ghidgui->port.view.width) / 2 + ctx->view.X1;
- ghidgui->port.view.y0 = (vh - ghidgui->port.view.height) / 2 + ctx->view.Y1;
-
- PCB_GTK_PREVIEW_TUNE_EXTENT(ctx, allocation);
- pcb_gui->coord_per_pix = ghidgui->port.view.coord_per_px;
-
- /* Change current pointer to draw in this widget, draws, then come back to pointer to drawing_area. */
- priv->cr_target = p;
- priv->cr = p;
- cairo_save(p);
- /* clear background */
- erase_with_background_color(p, &priv->bg_color);
- /* calls the off-line drawing routine */
- expcall(>k3_cairo_hid, ctx);
- cairo_restore(p);
- priv->cr = priv->cr_drawing_area;
- //gport->drawable = save_drawable;
-
- /* restore the original context and priv */
- ctx->view.X1 = ox1; ctx->view.X2 = ox2; ctx->view.Y1 = oy1; ctx->view.Y2 = oy2;
- pcb_gui->coord_per_pix = save_cpp;
- ghidgui->port.view = save_view;
- ghidgui->port.view.canvas_width = save_width;
- ghidgui->port.view.canvas_height = save_height;
-
- return FALSE;
-}
-
-static GtkWidget *ghid_cairo_new_drawing_widget(pcb_gtk_impl_t *common)
-{
- GtkWidget *w = gtk_drawing_area_new();
-
- g_signal_connect(G_OBJECT(w), "draw", G_CALLBACK(common->drawing_area_expose), common->gport);
-
- return w;
-}
-
-
-void ghid_cairo_install(pcb_gtk_impl_t *impl, pcb_hid_t *hid)
-{
- if (impl != NULL) {
- impl->new_drawing_widget = ghid_cairo_new_drawing_widget;
- impl->init_drawing_widget = ghid_cairo_init_drawing_widget;
- impl->drawing_realize = ghid_cairo_port_drawing_realize_cb;
- impl->drawing_area_expose = ghid_cairo_drawing_area_expose_cb;
- impl->preview_expose = ghid_cairo_preview_expose;
- //impl->invalidate_all = ghid_cairo_invalidate_all;
- impl->set_special_colors = ghid_cairo_set_special_colors;
- impl->init_renderer = ghid_cairo_init_renderer;
- impl->screen_update = ghid_cairo_screen_update;
- impl->draw_grid_local = ghid_cairo_draw_grid_local;
- impl->drawing_area_configure_hook = ghid_cairo_drawing_area_configure_hook;
- impl->shutdown_renderer = ghid_cairo_shutdown_renderer;
- impl->get_color_name = get_color_name;
- impl->map_color = map_color;
- }
-
- if (hid != NULL) {
- hid->invalidate_lr = ghid_cairo_invalidate_lr;
- hid->invalidate_all = ghid_cairo_invalidate_all;
- hid->notify_crosshair_change = ghid_cairo_notify_crosshair_change;
- hid->notify_mark_change = ghid_cairo_notify_mark_change;
- hid->set_layer_group = ghid_cairo_set_layer_group;
- hid->end_layer = ghid_cairo_end_layer_group;
- hid->make_gc = ghid_cairo_make_gc;
- hid->destroy_gc = ghid_cairo_destroy_gc;
- hid->render_burst = ghid_cairo_render_burst;
- hid->set_drawing_mode = ghid_cairo_set_drawing_mode;
- hid->set_color = ghid_cairo_set_color;
- hid->set_line_cap = ghid_cairo_set_line_cap;
- hid->set_line_width = ghid_cairo_set_line_width;
- hid->set_draw_xor = ghid_cairo_set_draw_xor;
- hid->draw_line = ghid_cairo_draw_line;
- hid->draw_arc = ghid_cairo_draw_arc;
- hid->draw_rect = ghid_cairo_draw_rect;
- hid->fill_circle = ghid_cairo_fill_circle;
- hid->fill_polygon = ghid_cairo_fill_polygon;
- hid->fill_polygon_offs = ghid_cairo_fill_polygon_offs;
- hid->fill_rect = ghid_cairo_fill_rect;
- }
-}
Index: trunk/src_plugins/hid_gtk3_cairo/Plug.tmpasm
===================================================================
--- trunk/src_plugins/hid_gtk3_cairo/Plug.tmpasm (revision 27397)
+++ trunk/src_plugins/hid_gtk3_cairo/Plug.tmpasm (nonexistent)
@@ -1,20 +0,0 @@
-put /local/pcb/mod {hid_gtk3_cairo}
-put /local/pcb/mod/OBJS_C99 [@
- $(PLUGDIR)/hid_gtk3_cairo/gtkhid-main.o
- $(PLUGDIR)/hid_gtk3_cairo/gtkhid-cairo.o
-@]
-
-switch /local/pcb/hid_gtk3_cairo/controls
- case {disable} end;
- default
- put /local/pcb/mod/CFLAGS /target/libs/gui/gtk3/cflags
- put /local/pcb/mod/LDFLAGS /target/libs/gui/gtk3/ldflags
- append /local/pcb/CFLAGS { -DPCB_GTK3=1 }
- end
-end
-
-switch /local/pcb/hid_gtk3_cairo/controls
- case {buildin} include /local/pcb/tmpasm/buildin; end;
- case {plugin} include /local/pcb/tmpasm/plugin; end;
- case {disable} include /local/pcb/tmpasm/disable; end;
-end
Index: trunk/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup
===================================================================
--- trunk/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (revision 27397)
+++ trunk/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (nonexistent)
@@ -1,7 +0,0 @@
-$class hid
-$short #GTK3 GUI, cairo render
-$long GUI: the GTK3 HID, using cairo for rendering
-$state WIP
-default disable-all
-dep lib_gtk_common
-autoload 1
Index: trunk/src_plugins/hid_gtk3_cairo/gtkhid-main.c
===================================================================
--- trunk/src_plugins/hid_gtk3_cairo/gtkhid-main.c (revision 27397)
+++ trunk/src_plugins/hid_gtk3_cairo/gtkhid-main.c (nonexistent)
@@ -1,46 +0,0 @@
-#include "config.h"
-
-#include
-
-#include "plugins.h"
-#include "hid_init.h"
-
-#include "../src_plugins/lib_gtk_common/glue_common.h"
-#include "../src_plugins/lib_gtk_common/glue_hid.h"
-
-const char *ghid_cairo_cookie = "gtk3 hid, cairo";
-
-pcb_hid_t gtk3_cairo_hid;
-
-extern void ghid_cairo_install(pcb_gtk_impl_t *impl, pcb_hid_t *hid);
-
-int gtk3_cairo_parse_arguments(pcb_hid_t *hid, int *argc, char ***argv)
-{
- ghid_glue_common_init(ghid_cairo_cookie);
- ghid_cairo_install(&ghidgui->impl, hid);
- return gtkhid_parse_arguments(hid, argc, argv);
-}
-
-int pplg_check_ver_hid_gtk3_cairo(int ver_needed) { return 0; }
-
-void pplg_uninit_hid_gtk3_cairo(void)
-{
- ghid_glue_common_uninit(ghid_cairo_cookie);
-}
-
-int pplg_init_hid_gtk3_cairo(void)
-{
- PCB_API_CHK_VER;
-
- ghid_glue_hid_init(>k3_cairo_hid);
-
- gtk3_cairo_hid.parse_arguments = gtk3_cairo_parse_arguments;
- ghid_cairo_install(NULL, >k3_cairo_hid);
-
- gtk3_cairo_hid.name = "gtk3_cairo";
- gtk3_cairo_hid.description = "Gtk3 - The Gimp Toolkit, with cairo rendering";
-
- pcb_hid_register_hid(>k3_cairo_hid);
-
- return 0;
-}
Index: trunk/src_plugins/hid_gtk3_cairo/Makefile
===================================================================
--- trunk/src_plugins/hid_gtk3_cairo/Makefile (revision 27397)
+++ trunk/src_plugins/hid_gtk3_cairo/Makefile (nonexistent)
@@ -1,6 +0,0 @@
-all:
- cd ../../src && $(MAKE) mod_hid_gtk3_cairo
-
-clean:
- rm *.o *.so 2>/dev/null ; true
-
Index: trunk/src_plugins/lib_gtk_common/Plug.tmpasm
===================================================================
--- trunk/src_plugins/lib_gtk_common/Plug.tmpasm (revision 27397)
+++ trunk/src_plugins/lib_gtk_common/Plug.tmpasm (revision 27398)
@@ -27,15 +27,6 @@
$(PLUGDIR)/lib_gtk_common/glue_hid.o
@]
-switch /local/pcb/hid_gtk3_cairo/controls
- case {disable} end;
- default
- append /local/pcb/mod/OBJS_C99 [@
- $(PLUGDIR)/lib_gtk_common/wt_trunc_text.o
- @]
- end
-end
-
switch /local/pcb/lib_gtk_common/controls
case {disable} end;
default
Index: trunk/src_plugins/lib_gtk_common/wt_trunc_text.c
===================================================================
--- trunk/src_plugins/lib_gtk_common/wt_trunc_text.c (revision 27397)
+++ trunk/src_plugins/lib_gtk_common/wt_trunc_text.c (revision 27398)
@@ -26,6 +26,9 @@
* mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
*/
+/* This widget was for the gtk3 port - gtk2 does not use it at the moment
+ so it is not compiled. A gtk4 or gtkN port may need it. */
+
#include "wt_trunc_text.h"
static gpointer gtk_trunctext_parent_class = NULL;
Index: trunk/src_plugins/plugins_ALL.tmpasm
===================================================================
--- trunk/src_plugins/plugins_ALL.tmpasm (revision 27397)
+++ trunk/src_plugins/plugins_ALL.tmpasm (revision 27398)
@@ -48,7 +48,6 @@
include {../src_plugins/hid_batch/Plug.tmpasm}
include {../src_plugins/hid_gtk2_gdk/Plug.tmpasm}
include {../src_plugins/hid_gtk2_gl/Plug.tmpasm}
-include {../src_plugins/hid_gtk3_cairo/Plug.tmpasm}
include {../src_plugins/hid_lesstif/Plug.tmpasm}
include {../src_plugins/hid_remote/Plug.tmpasm}
include {../src_plugins/import_calay/Plug.tmpasm}
Index: work/obsolete/hid_gtk3_cairo/Makefile
===================================================================
--- work/obsolete/hid_gtk3_cairo/Makefile (nonexistent)
+++ work/obsolete/hid_gtk3_cairo/Makefile (revision 27398)
@@ -0,0 +1,6 @@
+all:
+ cd ../../src && $(MAKE) mod_hid_gtk3_cairo
+
+clean:
+ rm *.o *.so 2>/dev/null ; true
+
Index: work/obsolete/hid_gtk3_cairo/Plug.tmpasm
===================================================================
--- work/obsolete/hid_gtk3_cairo/Plug.tmpasm (nonexistent)
+++ work/obsolete/hid_gtk3_cairo/Plug.tmpasm (revision 27398)
@@ -0,0 +1,20 @@
+put /local/pcb/mod {hid_gtk3_cairo}
+put /local/pcb/mod/OBJS_C99 [@
+ $(PLUGDIR)/hid_gtk3_cairo/gtkhid-main.o
+ $(PLUGDIR)/hid_gtk3_cairo/gtkhid-cairo.o
+@]
+
+switch /local/pcb/hid_gtk3_cairo/controls
+ case {disable} end;
+ default
+ put /local/pcb/mod/CFLAGS /target/libs/gui/gtk3/cflags
+ put /local/pcb/mod/LDFLAGS /target/libs/gui/gtk3/ldflags
+ append /local/pcb/CFLAGS { -DPCB_GTK3=1 }
+ end
+end
+
+switch /local/pcb/hid_gtk3_cairo/controls
+ case {buildin} include /local/pcb/tmpasm/buildin; end;
+ case {plugin} include /local/pcb/tmpasm/plugin; end;
+ case {disable} include /local/pcb/tmpasm/disable; end;
+end
Index: work/obsolete/hid_gtk3_cairo/gtkhid-cairo.c
===================================================================
--- work/obsolete/hid_gtk3_cairo/gtkhid-cairo.c (nonexistent)
+++ work/obsolete/hid_gtk3_cairo/gtkhid-cairo.c (revision 27398)
@@ -0,0 +1,1592 @@
+/*
+ * COPYRIGHT
+ *
+ * pcb-rnd, interactive printed circuit board design
+ * (this file is based on PCB, interactive printed circuit board design)
+ * Copyright (C) 1994,1995,1996 Thomas Nau
+ * pcb-rnd Copyright (C) 2017-2019 Alain Vigne
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/pcb-rnd
+ * lead developer: http://repo.hu/projects/pcb-rnd/contact.html
+ * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
+ *
+ */
+
+#include "config.h"
+#include "hidlib_conf.h"
+
+#include
+
+#include "crosshair.h"
+#include "draw.h"
+#include "grid.h"
+#include "color.h"
+#include "color_cache.h"
+#include "hid_attrib.h"
+#include "funchash_core.h"
+
+#include "../src_plugins/lib_gtk_common/pcb_gtk.h"
+#include "../src_plugins/lib_gtk_common/glue_common.h"
+#include "../src_plugins/lib_gtk_common/coord_conv.h"
+
+#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h"
+#include "../src_plugins/lib_gtk_common/lib_gtk_config.h"
+
+#include "../src_plugins/lib_hid_common/clip.h"
+
+extern pcb_hid_t gtk3_cairo_hid;
+static void ghid_cairo_screen_update(void);
+
+/* Sets priv->u_gc to the "right" GC to use (wrt mask or window)
+*/
+#define USE_GC(gc) if (!use_gc(gc)) return
+
+//static int cur_mask = -1;
+//static int mask_seq = 0;
+static pcb_composite_op_t curr_drawing_mode;
+
+typedef struct render_priv_s {
+ GdkRGBA bg_color; /* cached back-ground color */
+ GdkRGBA offlimits_color; /* cached external board color */
+ GdkRGBA grid_color; /* cached grid color */
+ GdkRGBA crosshair_color; /* cached crosshair color */
+
+ cairo_t *cr; /* pointer to current drawing context */
+ cairo_t *cr_target; /* pointer to destination widget drawing context */
+
+ cairo_surface_t *surf_da; /* cairo surface connected to port->drawing_area */
+ cairo_t *cr_drawing_area; /* cairo context created from surf_da */
+
+ cairo_surface_t *surf_layer; /* cairo surface for temporary layer composition */
+ cairo_t *cr_layer; /* cairo context created from surf_layer */
+
+ //GdkPixmap *pixmap, *mask;
+
+ //GdkGC *bg_gc;
+ //GdkGC *offlimits_gc;
+ //GdkGC *mask_gc;
+ //GdkGC *u_gc;
+ //GdkGC *grid_gc;
+ pcb_bool clip;
+ GdkRectangle clip_rect;
+ int xor_mode; /* 1 if drawn in XOR mode, 0 otherwise*/
+ int attached_invalidate_depth;
+ int mark_invalidate_depth;
+
+ /* color cache for set_color */
+ pcb_clrcache_t ccache;
+ int ccache_inited;
+} render_priv_t;
+
+typedef struct hid_gc_s {
+ pcb_core_gc_t core_gc;
+ pcb_hid_t *me_pointer;
+
+ pcb_color_t pcolor;
+ GdkRGBA color; /* current color for this GC. */
+
+ pcb_coord_t width;
+ cairo_line_cap_t cap;
+ cairo_line_join_t join;
+ gchar xor_mask;
+ //gint mask_seq;
+} hid_gc_s;
+
+static void copy_color(GdkRGBA * dest, GdkRGBA * source)
+{
+ dest->red = source->red;
+ dest->green = source->green;
+ dest->blue = source->blue;
+ dest->alpha = source->alpha;
+}
+
+static const gchar *get_color_name(pcb_gtk_color_t * color)
+{
+ static char tmp[16];
+
+ if (!color)
+ return "#000000";
+
+ sprintf(tmp, "#%2.2x%2.2x%2.2x",
+ (int) (color->red * 255) & 0xff, (int) (color->green * 255) & 0xff, (int) (color->blue * 255) & 0xff);
+ return tmp;
+}
+
+/* Returns TRUE if inclr has been successfully converted to color. */
+static pcb_bool map_color(const pcb_color_t *inclr, pcb_gtk_color_t *color)
+{
+ if (!color || !ghidgui->port.top_window)
+ return FALSE;
+
+ color->red = inclr->fr;
+ color->green = inclr->fg;
+ color->blue = inclr->fb;
+ color->alpha = inclr->fa;
+
+ return TRUE;
+}
+
+static void cr_draw_line(cairo_t * cr, int fill, double x1, double y1, double x2, double y2)
+{
+ if (cr == NULL)
+ return;
+
+ cairo_move_to(cr, x1, y1);
+ cairo_line_to(cr, x2, y2);
+TODO("gtk3: What means 'fill a line'? cairo_fill is not appropriate if path is only a line.")
+ if (fill)
+ cairo_fill(cr);
+ else
+ cairo_stroke(cr);
+}
+
+static void cr_destroy_surf_and_context(cairo_surface_t ** psurf, cairo_t ** pcr)
+{
+ if (*psurf)
+ cairo_surface_destroy(*psurf);
+ if (*pcr)
+ cairo_destroy(*pcr);
+
+ *psurf = NULL;
+ *pcr = NULL;
+}
+
+/* First, frees previous surface and context, then creates new ones, similar to drawing_area. */
+static void cr_create_similar_surface_and_context(cairo_surface_t ** psurf, cairo_t ** pcr, void *vport)
+{
+ pcb_gtk_port_t *port = vport;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ cr_destroy_surf_and_context(psurf, pcr);
+
+ surface = gdk_window_create_similar_surface(gtk_widget_get_window(port->drawing_area),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ gtk_widget_get_allocated_width(port->drawing_area),
+ gtk_widget_get_allocated_height(port->drawing_area));
+ cr = cairo_create(surface);
+ *psurf = surface;
+ *pcr = cr;
+}
+
+/* Creates or reuses a context to render a single layer group with "union" type of shape rendering. */
+static void start_subcomposite(void)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ cairo_t *cr;
+
+ if (priv->surf_layer == NULL)
+ cr_create_similar_surface_and_context(&priv->surf_layer, &priv->cr_layer, &ghidgui->port);
+ cr = priv->cr_layer;
+ cairo_save(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr);
+ cairo_restore(cr);
+ cairo_set_operator(priv->cr, CAIRO_OPERATOR_SOURCE);
+ priv->cr = priv->cr_layer;
+}
+
+/* Applies the layer composited so far, to the target, using translucency. */
+static void end_subcomposite(void)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ cairo_set_operator(priv->cr_target, CAIRO_OPERATOR_OVER);
+ cairo_set_source_surface(priv->cr_target, priv->surf_layer, 0, 0);
+ cairo_paint_with_alpha(priv->cr_target, pcbhl_conf.appearance.layer_alpha);
+ priv->cr = priv->cr_target;
+}
+
+static int ghid_cairo_set_layer_group(pcb_hid_t *hid, pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform)
+{
+ /* draw anything */
+ return 1;
+}
+
+static void ghid_cairo_end_layer_group(pcb_hid_t *hid)
+{
+ end_subcomposite();
+}
+
+TODO(": misleading comment or broken code")
+/* Do not clean up internal structures, as they will be used probably elsewhere. */
+static void ghid_cairo_destroy_gc(pcb_hid_gc_t gc)
+{
+ g_free(gc);
+}
+
+/* called from pcb_hid_t->make_gc() . Use only this to hold pointers, do not
+ own references, avoid costly memory allocation that needs to be destroyed with
+ ghid_cairo_destroy_gc(). */
+static pcb_hid_gc_t ghid_cairo_make_gc(pcb_hid_t *hid)
+{
+ pcb_hid_gc_t rv;
+
+ rv = g_new0(hid_gc_s, 1);
+ rv->me_pointer = >k3_cairo_hid;
+ rv->pcolor = pcbhl_conf.appearance.color.background;
+ return rv;
+}
+
+TODO("gtk3: check if clipping is not necessary")
+//static void set_clip(render_priv_t * priv, cairo_t * cr)
+//{
+// if (cr == NULL)
+// return;
+//
+// if (priv->clip) {
+// gdk_cairo_rectangle(cr, &priv->clip_rect);
+// cairo_clip(cr);
+// }
+// else {
+// /*FIXME: do nothing if no clipping ? */
+// //cairo_mask(cr, NULL);
+// //gdk_gc_set_clip_mask(gc, NULL);
+// }
+//}
+
+static inline void ghid_cairo_draw_grid_global(pcb_hidlib_t *hidlib, cairo_t *cr)
+{
+ //render_priv_t *priv = gport->render_priv;
+ pcb_coord_t x, y, x1, y1, x2, y2, grd;
+ int n, i;
+ static GdkPoint *points = NULL;
+ static int npoints = 0;
+
+ x1 = pcb_grid_fit(MAX(0, SIDE_X(&ghidgui->port.view, ghidgui->port.view.x0)), hidlib->grid, hidlib->grid_ox);
+ y1 = pcb_grid_fit(MAX(0, SIDE_Y(&ghidgui->port.view, ghidgui->port.view.y0)), hidlib->grid, hidlib->grid_oy);
+ x2 = pcb_grid_fit(MIN(hidlib->size_x, SIDE_X(&ghidgui->port.view, ghidgui->port.view.x0 + ghidgui->port.view.width - 1)), hidlib->grid, hidlib->grid_ox);
+ y2 = pcb_grid_fit(MIN(hidlib->size_y, SIDE_Y(&ghidgui->port.view, ghidgui->port.view.y0 + ghidgui->port.view.height - 1)), hidlib->grid, hidlib->grid_oy);
+
+ grd = hidlib->grid;
+
+ if (Vz(grd) < pcb_conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px) {
+ if (!pcb_conf_hid_gtk.plugins.hid_gtk.global_grid.sparse)
+ return;
+ grd *= (pcb_conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px / Vz(grd));
+ }
+
+ if (x1 > x2) {
+ pcb_coord_t tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+ if (y1 > y2) {
+ pcb_coord_t tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
+ if (Vx(x1) < 0)
+ x1 += grd;
+ if (Vy(y1) < 0)
+ y1 += grd;
+ if (Vx(x2) >= ghidgui->port.view.canvas_width)
+ x2 -= grd;
+ if (Vy(y2) >= ghidgui->port.view.canvas_height)
+ y2 -= grd;
+
+
+ n = (x2 - x1) / grd + 1;
+ if (n > npoints) {
+ npoints = n + 10;
+ points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint));
+ }
+ n = 0;
+ for (x = x1; x <= x2; x += grd) {
+ points[n].x = Vx(x);
+ n++;
+ }
+ if (n == 0)
+ return;
+
+ /* Draw N points... is this the most efficient ? At least, it works.
+ From cairo development :
+ " cairo_move_to (cr, x, y);
+ . cairo_line_to (cr, x, y);
+ . .. repeat for each point ..
+ .
+ . cairo_stroke (cr);
+ .
+ . Within the implementation (and test suite) we call these "degenerate"
+ . paths and we explicitly support drawing round caps for such degenerate
+ . paths. So this should work perfectly for the case of
+ . CAIRO_LINE_CAP_ROUND and you'll get the diameter controlled by
+ . cairo_set_line_width just like you want.
+ "
+ */
+ for (y = y1; y <= y2; y += grd) {
+ for (i = 0; i < n; i++) {
+ points[i].y = Vy(y);
+ cairo_move_to(cr, points[i].x, points[i].y);
+ cairo_line_to(cr, points[i].x, points[i].y);
+ }
+ cairo_stroke(cr);
+ }
+}
+
+static void ghid_cairo_draw_grid_local_(pcb_hidlib_t *hidlib, pcb_coord_t cx, pcb_coord_t cy, int radius)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ cairo_t *cr = priv->cr_target;
+ static GdkPoint *points_base = NULL;
+ static GdkPoint *points_abs = NULL;
+ static int apoints = 0, npoints = 0, old_radius = 0;
+ static pcb_coord_t last_grid = 0;
+ int recalc = 0, n, r2;
+ pcb_coord_t x, y;
+
+ /* PI is approximated with 3.25 here - allows a minimal overallocation, speeds up calculations */
+ r2 = radius * radius;
+ n = r2 * 3 + r2 / 4 + 1;
+ if (n > apoints) {
+ apoints = n;
+ points_base = (GdkPoint *) realloc(points_base, apoints * sizeof(GdkPoint));
+ points_abs = (GdkPoint *) realloc(points_abs, apoints * sizeof(GdkPoint));
+ }
+
+ if (radius != old_radius) {
+ old_radius = radius;
+ recalc = 1;
+ }
+
+ if (last_grid != hidlib->grid) {
+ last_grid = hidlib->grid;
+ recalc = 1;
+ }
+
+ /* recaculate the 'filled circle' mask (base relative coords) if grid or radius changed */
+ if (recalc) {
+
+ npoints = 0;
+ for (y = -radius; y <= radius; y++) {
+ int y2 = y * y;
+ for (x = -radius; x <= radius; x++) {
+ if (x * x + y2 < r2) {
+ points_base[npoints].x = x * hidlib->grid;
+ points_base[npoints].y = y * hidlib->grid;
+ npoints++;
+ }
+ }
+ }
+ }
+
+ /* calculate absolute positions */
+ for (n = 0; n < npoints; n++) {
+ points_abs[n].x = Vx(points_base[n].x + cx);
+ points_abs[n].y = Vy(points_base[n].y + cy);
+ cairo_move_to(cr, points_abs[n].x, points_abs[n].y);
+ cairo_line_to(cr, points_abs[n].x, points_abs[n].y);
+ }
+ cairo_stroke(cr);
+ //gdk_draw_points(gport->drawable, priv->grid_gc, points_abs, npoints);
+}
+
+static int grid_local_have_old = 0, grid_local_old_r = 0;
+static pcb_coord_t grid_local_old_x, grid_local_old_y;
+
+static void ghid_cairo_draw_grid_local(pcb_hidlib_t *hidlib, pcb_coord_t cx, pcb_coord_t cy)
+{
+ if (grid_local_have_old) {
+ ghid_cairo_draw_grid_local_(hidlib, grid_local_old_x, grid_local_old_y, grid_local_old_r);
+ grid_local_have_old = 0;
+ }
+
+ if (!pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.enable)
+ return;
+
+ if ((Vz(hidlib->grid) < PCB_MIN_GRID_DISTANCE) || (!pcbhl_conf.editor.draw_grid))
+ return;
+
+ /* cx and cy are the actual cursor snapped to wherever - round them to the nearest real grid point */
+ cx = (cx / hidlib->grid) * hidlib->grid + hidlib->grid_ox;
+ cy = (cy / hidlib->grid) * hidlib->grid + hidlib->grid_oy;
+
+ grid_local_have_old = 1;
+ ghid_cairo_draw_grid_local_(hidlib, cx, cy, pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.radius);
+ grid_local_old_x = cx;
+ grid_local_old_y = cy;
+ grid_local_old_r = pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.radius;
+}
+
+static void ghid_cairo_draw_grid(pcb_hidlib_t *hidlib)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ cairo_t *cr = priv->cr_target;
+
+ if (cr == NULL)
+ return;
+
+ grid_local_have_old = 0;
+
+ if (!pcbhl_conf.editor.draw_grid)
+ return;
+ //if (!priv->grid_gc) {
+ // if (gdk_color_parse(pcbhl_conf.appearance.color.grid, &gport->grid_color)) {
+ // gport->grid_color.red ^= gport->bg_color.red;
+ // gport->grid_color.green ^= gport->bg_color.green;
+ // gport->grid_color.blue ^= gport->bg_color.blue;
+ // gdk_color_alloc(gport->colormap, &gport->grid_color);
+ // }
+ // priv->grid_gc = gdk_gc_new(gport->drawable);
+ // gdk_gc_set_function(priv->grid_gc, GDK_XOR);
+ // gdk_gc_set_foreground(priv->grid_gc, &gport->grid_color);
+ // gdk_gc_set_clip_origin(priv->grid_gc, 0, 0);
+ // set_clip(priv, priv->grid_gc);
+ //}
+
+ cairo_save(cr);
+TODO("gtk3: deal with gc")
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_width(cr, 1.0);
+ gdk_cairo_set_source_rgba(cr, &priv->grid_color);
+
+ if (pcb_conf_hid_gtk.plugins.hid_gtk.local_grid.enable) {
+ ghid_cairo_draw_grid_local(hidlib, grid_local_old_x, grid_local_old_y);
+ cairo_restore(cr);
+ return;
+ }
+
+ ghid_cairo_draw_grid_global(hidlib, cr);
+ cairo_restore(cr);
+}
+
+/* ------------------------------------------------------------ */
+static void ghid_cairo_draw_bg_image(pcb_hidlib_t *hidlib)
+{
+ static GdkPixbuf *pixbuf;
+ GdkInterpType interp_type;
+ gint src_x, src_y, dst_x, dst_y, w, h, w_src, h_src;
+ static gint w_scaled, h_scaled;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ if (!ghidgui->bg_pixbuf)
+ return;
+
+ src_x = ghidgui->port.view.x0;
+ src_y = ghidgui->port.view.y0;
+ dst_x = 0;
+ dst_y = 0;
+
+ if (src_x < 0) {
+ dst_x = -src_x;
+ src_x = 0;
+ }
+ if (src_y < 0) {
+ dst_y = -src_y;
+ src_y = 0;
+ }
+
+ w = hidlib->size_x / ghidgui->port.view.coord_per_px;
+ h = hidlib->size_y / ghidgui->port.view.coord_per_px;
+ src_x = src_x / ghidgui->port.view.coord_per_px;
+ src_y = src_y / ghidgui->port.view.coord_per_px;
+ dst_x = dst_x / ghidgui->port.view.coord_per_px;
+ dst_y = dst_y / ghidgui->port.view.coord_per_px;
+
+ if (w_scaled != w || h_scaled != h) {
+ if (pixbuf)
+ g_object_unref(G_OBJECT(pixbuf));
+
+ w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
+ h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
+ if (w > w_src && h > h_src)
+ interp_type = GDK_INTERP_NEAREST;
+ else
+ interp_type = GDK_INTERP_BILINEAR;
+
+ pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type);
+ w_scaled = w;
+ h_scaled = h;
+ }
+
+ if (pixbuf) {
+ gdk_cairo_set_source_pixbuf(priv->cr, pixbuf, src_x, src_y);
+ cairo_rectangle(priv->cr, dst_x, dst_y, ghidgui->port.view.canvas_width, ghidgui->port.view.canvas_height);
+ cairo_fill(priv->cr);
+ //gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, priv->bg_gc,
+ // src_x, src_y, dst_x, dst_y, w - src_x, h - src_y, GDK_RGB_DITHER_NORMAL, 0, 0);
+ }
+}
+
+static void ghid_cairo_render_burst(pcb_hid_t *hid, pcb_burst_op_t op, const pcb_box_t *screen)
+{
+ pcb_gui->coord_per_pix = ghidgui->port.view.coord_per_px;
+}
+
+/* Drawing modes usually cycle from RESET to (POSITIVE | NEGATIVE) to FLUSH. screen is not used in this HID. */
+static void ghid_cairo_set_drawing_mode(pcb_hid_t *hid, pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ if (!priv->cr) {
+ //abort();
+ return;
+ }
+
+ switch(op) {
+ case PCB_HID_COMP_RESET:
+ //ghid_sketch_setup(priv);
+ start_subcomposite();
+
+ /* clear the canvas */
+ //priv->clip_color.pixel = 0;
+ //if (priv->clear_gc == NULL)
+ // priv->clear_gc = gdk_gc_new(priv->out_clip);
+ //gdk_gc_set_foreground(priv->clear_gc, &priv->clip_color);
+ //set_clip(priv, priv->clear_gc);
+ //gdk_draw_rectangle(priv->out_clip, priv->clear_gc, TRUE, 0, 0, gport->view.canvas_width, gport->view.canvas_height);
+ break;
+
+ case PCB_HID_COMP_POSITIVE:
+ case PCB_HID_COMP_POSITIVE_XOR:
+ //priv->clip_color.pixel = 1;
+ cairo_set_operator(priv->cr, CAIRO_OPERATOR_SOURCE);
+ break;
+
+ case PCB_HID_COMP_NEGATIVE:
+ //priv->clip_color.pixel = 0;
+ cairo_set_operator(priv->cr, CAIRO_OPERATOR_CLEAR);
+ break;
+
+ case PCB_HID_COMP_FLUSH:
+ if (direct)
+ end_subcomposite();
+ else {
+ priv->cr = priv->cr_target;
+ cairo_mask_surface(priv->cr, priv->surf_layer, 0, 0);
+ cairo_fill(priv->cr);
+ }
+ //cairo_paint_with_alpha(priv->cr, pcbhl_conf.appearance.layer_alpha);
+ //cairo_paint_with_alpha(priv->cr, 1.0);
+
+ //if (priv->copy_gc == NULL)
+ // priv->copy_gc = gdk_gc_new(priv->out_pixel);
+ //gdk_gc_set_clip_mask(priv->copy_gc, priv->sketch_clip);
+ //gdk_gc_set_clip_origin(priv->copy_gc, 0, 0);
+ //gdk_draw_drawable(priv->base_pixel, priv->copy_gc, priv->sketch_pixel, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height);
+ //
+ //priv->out_pixel = priv->base_pixel;
+ //priv->out_clip = NULL;
+ break;
+ }
+ curr_drawing_mode = op;
+}
+
+typedef struct {
+ int color_set;
+ pcb_gtk_color_t color;
+ int xor_set;
+ pcb_gtk_color_t xor_color;
+} pcb_gtk_color_cache_t;
+
+
+/* Config helper functions for when the user changes color preferences.
+ set_special colors used in the gtkhid.
+ */
+//static void set_special_grid_color(void)
+//{
+// render_priv_t *priv = gport->render_priv;
+// int red, green, blue;
+//
+// //if (!gport->colormap)
+// // return;
+//
+// red = priv->grid_color.red;
+// green = priv->grid_color.green;
+// blue = priv->grid_color.blue;
+// pcb_conf_setf(CFR_DESIGN, "appearance/color/grid", -1, "#%02x%02x%02x", red, green, blue);
+// map_color_string(pcbhl_conf.appearance.color.grid, &priv->grid_color);
+//
+// config_color_button_update(&ghidgui->common, pcb_conf_get_field("appearance/color/grid"), -1);
+//
+// //if (priv->grid_gc)
+// // gdk_gc_set_foreground(priv->grid_gc, &gport->grid_color);
+//}
+
+/* Assign "identified" colors to background, offlimits and grid cached structures */
+static void ghid_cairo_set_special_colors(conf_native_t * cfg)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ if (((CFT_COLOR *) cfg->val.color == &pcbhl_conf.appearance.color.background) /*&& priv->bg_gc */ ) {
+ if (map_color(&cfg->val.color[0], &priv->bg_color)) {
+ //gdk_gc_set_foreground(priv->bg_gc, &priv->bg_color);
+ //set_special_grid_color();
+ }
+ }
+ else if (((CFT_COLOR *) cfg->val.color == &pcbhl_conf.appearance.color.off_limit) /*&& priv->offlimits_gc */ ) {
+ if (map_color(&cfg->val.color[0], &priv->offlimits_color)) {
+ //gdk_gc_set_foreground(priv->offlimits_gc, &priv->offlimits_color);
+ }
+ }
+ else if (((CFT_COLOR *) cfg->val.color == &pcbhl_conf.appearance.color.grid) /*&& priv->grid_gc */ ) {
+ if (map_color(&cfg->val.color[0], &priv->grid_color)) {
+ //set_special_grid_color();
+ }
+ }
+}
+
+static void ghid_cairo_set_color(pcb_hid_gc_t gc, const pcb_color_t *color)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ const char *name = color->str;
+
+ if (name == NULL) {
+ fprintf(stderr, "ghid_cairo_set_color(): name = NULL, setting to magenta\n");
+ color = pcb_color_magenta;
+ }
+
+ gc->pcolor = *color;
+
+ //if (!gc->gc)
+ // return;
+ //if (gport->colormap == 0)
+ // gport->colormap = gtk_widget_get_colormap(gport->top_window);
+
+ if (pcb_color_is_drill(color)) {
+ copy_color(&gc->color, &priv->offlimits_color);
+ //gdk_cairo_set_source_rgba(cr, &priv->offlimits_color);
+ //gdk_gc_set_foreground(gc->gc, &gport->offlimits_color);
+ }
+ else {
+ pcb_gtk_color_cache_t *cc;
+
+ if (!priv->ccache_inited) {
+ pcb_clrcache_init(&priv->ccache, sizeof(pcb_gtk_color_cache_t), NULL);
+ priv->ccache_inited = 1;
+ }
+ cc = pcb_clrcache_get(&priv->ccache, color, 1);
+ if (!cc->color_set) {
+ map_color(color, &cc->color);
+ cc->color_set = 1;
+ }
+ //if (gc->xor_mask) {
+ // if (!cc->xor_set) {
+ // cc->xor_color.red = cc->color.red ^ gport->bg_color.red;
+ // cc->xor_color.green = cc->color.green ^ gport->bg_color.green;
+ // cc->xor_color.blue = cc->color.blue ^ gport->bg_color.blue;
+ // gdk_color_alloc(gport->colormap, &cc->xor_color);
+ // cc->xor_set = 1;
+ // }
+ // gdk_gc_set_foreground(gc->gc, &cc->xor_color);
+ //}
+ //else {
+ // gdk_gc_set_foreground(gc->gc, &cc->color);
+ //}
+ cc->color.alpha = 1.0;
+ copy_color(&gc->color, &cc->color);
+ }
+}
+
+static void ghid_cairo_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style)
+{
+ cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
+ cairo_line_join_t join = CAIRO_LINE_JOIN_MITER;
+
+ switch (style) {
+ case pcb_cap_round:
+ cap = CAIRO_LINE_CAP_ROUND;
+ join = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case pcb_cap_square:
+ cap = CAIRO_LINE_CAP_SQUARE;
+ join = CAIRO_LINE_JOIN_MITER;
+ break;
+ default:
+ assert(!"unhandled cap");
+ }
+ gc->cap = cap;
+ gc->join = join;
+
+ //if (gc->gc)
+ // gdk_gc_set_line_attributes(WHICH_GC(gc), Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join);
+}
+
+static void ghid_cairo_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width)
+{
+ //render_priv_t *priv = gport->render_priv;
+
+ //if (priv->cr == NULL)
+ // return;
+
+ gc->width = width;
+ //cairo_set_line_width(priv->cr, Vz(gc->width));
+ //if (gc->gc)
+ // gdk_gc_set_line_attributes(WHICH_GC(gc), Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join);
+}
+
+static void ghid_cairo_set_draw_xor(pcb_hid_gc_t gc, int xor_mask)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ priv->xor_mode = (xor_mask) ? 1 : 0;
+ //gc->xor_mask = xor_mask;
+ //if (!gc->gc)
+ // return;
+ //gdk_gc_set_function(gc->gc, xor_mask ? GDK_XOR : GDK_COPY);
+ //ghid_cairo_set_color(gc, gc->pcolor.str);
+}
+
+static int use_gc(pcb_hid_gc_t gc)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ cairo_t *cr = priv->cr;
+ //GdkWindow *window = gtk_widget_get_window(gport->top_window);
+
+ if (gc->me_pointer != >k3_cairo_hid) {
+ fprintf(stderr, "Fatal: GC from another HID passed to GTK HID\n");
+ abort();
+ }
+
+ if (cr == NULL)
+ return 0;
+
+ //ghid_cairo_set_color(gc, gc->pcolor.str);
+ gdk_cairo_set_source_rgba(cr, &gc->color);
+
+ /* negative line width means "unit is pixels", so -1 is "1 pixel", -5 is "5 pixels", regardless of the zoom. */
+ if (gc->width <= 0)
+ cairo_set_line_width(cr, 1.0 - gc->width);
+ else
+ cairo_set_line_width(cr, Vz(gc->width));
+
+ //ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap);
+ cairo_set_line_cap(cr, gc->cap);
+ cairo_set_line_join(cr, gc->join);
+
+
+ //if (!gc->gc) {
+ // gc->gc = gdk_gc_new(window);
+ // ghid_cairo_set_color(gc, gc->colorname);
+ // ghid_cairo_set_line_width(gc, gc->width);
+ // ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap);
+ // ghid_cairo_set_draw_xor(gc, gc->xor_mask);
+ // gdk_gc_set_clip_origin(gc->gc, 0, 0);
+ //}
+ //if (gc->mask_seq != mask_seq) {
+ // if (mask_seq)
+ // gdk_gc_set_clip_mask(gc->gc, gport->mask);
+ // else
+ // set_clip(priv, gc->gc);
+ // gc->mask_seq = mask_seq;
+ //}
+ //priv->u_gc = WHICH_GC(gc);
+ return 1;
+}
+
+static void ghid_cairo_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
+{
+ double dx1, dy1, dx2, dy2;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ dx1 = Vx((double) x1);
+ dy1 = Vy((double) y1);
+ dx2 = Vx((double) x2);
+ dy2 = Vy((double) y2);
+
+ if (!pcb_line_clip
+ (0, 0, ghidgui->port.view.canvas_width, ghidgui->port.view.canvas_height, &dx1, &dy1, &dx2, &dy2, gc->width / ghidgui->port.view.coord_per_px))
+ return;
+
+ USE_GC(gc);
+ cr_draw_line(priv->cr, FALSE, dx1, dy1, dx2, dy2);
+ //gdk_draw_line(gport->drawable, priv->u_gc, dx1, dy1, dx2, dy2);
+}
+
+/* Draws an arc from center (cx, cy), cx>0 to the right, cy>0 to the bottom, using
+ xradius on X axis, and yradius on Y axis, sweeping a delta_angle from start_angle.
+
+ Angles (in degres) originate at 9 o'clock and are positive CCW (counter clock wise).
+ delta_angle sweeps the angle from start_angle, CW if negative. */
+static void ghid_cairo_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy,
+ pcb_coord_t xradius, pcb_coord_t yradius, pcb_angle_t start_angle, pcb_angle_t delta_angle)
+{
+ double w, h, radius, angle1, angle2;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ w = ghidgui->port.view.canvas_width * ghidgui->port.view.coord_per_px;
+ h = ghidgui->port.view.canvas_height * ghidgui->port.view.coord_per_px;
+ radius = (xradius > yradius) ? xradius : yradius;
+ if (SIDE_X(&ghidgui->port.view, cx) < ghidgui->port.view.x0 - radius
+ || SIDE_X(&ghidgui->port.view, cx) > ghidgui->port.view.x0 + w + radius
+ || SIDE_Y(&ghidgui->port.view, cy) < ghidgui->port.view.y0 - radius || SIDE_Y(&ghidgui->port.view, cy) > ghidgui->port.view.y0 + h + radius)
+ return;
+
+ USE_GC(gc);
+
+ if ((delta_angle > 360.0) || (delta_angle < -360.0)) {
+ start_angle = 0;
+ delta_angle = 360;
+ }
+
+ if (pcbhl_conf.editor.view.flip_x) {
+ start_angle = 180 - start_angle;
+ delta_angle = -delta_angle;
+ }
+ if (pcbhl_conf.editor.view.flip_y) {
+ start_angle = -start_angle;
+ delta_angle = -delta_angle;
+ }
+ /* make sure we fall in the -180 to +180 range */
+ start_angle = pcb_normalize_angle(start_angle);
+ if (start_angle >= 180)
+ start_angle -= 360;
+
+ /* cairo lib. originates angles at 3 o'clock, positive traveling CW, requires angle1 < angle2 */
+ angle1 = (180.0 - start_angle);
+ angle2 = (delta_angle < 0) ? (angle1 - delta_angle) : angle1;
+ if (delta_angle > 0) {
+ angle1 = (180.0 - start_angle - delta_angle);
+ }
+ angle1 *= (M_PI / 180.0);
+ angle2 *= (M_PI / 180.0);
+ cairo_save(priv->cr);
+TODO("gtk3: this will draw an arc of a circle, not an ellipse! Explore matrix transformation here.")
+ cairo_arc(priv->cr, pcb_round(Vxd(cx)), pcb_round(Vyd(cy)), Vzd(radius), angle1, angle2);
+ cairo_stroke(priv->cr);
+ cairo_restore(priv->cr);
+ //gdk_draw_arc(gport->drawable, priv->u_gc, 0,
+ // pcb_round(Vxd(cx) - Vzd(xradius) + 0.5), pcb_round(Vyd(cy) - Vzd(yradius) + 0.5),
+ // pcb_round(vrx2), pcb_round(vry2), (start_angle + 180) * 64, delta_angle * 64);
+}
+
+static void cr_draw_rect(pcb_hid_gc_t gc, int fill, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
+{
+ gint w, h, lw;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ if (priv->cr == NULL)
+ return;
+
+ lw = gc->width;
+ w = ghidgui->port.view.canvas_width * ghidgui->port.view.coord_per_px;
+ h = ghidgui->port.view.canvas_height * ghidgui->port.view.coord_per_px;
+
+ if ((SIDE_X(&ghidgui->port.view, x1) < ghidgui->port.view.x0 - lw && SIDE_X(&ghidgui->port.view, x2) < ghidgui->port.view.x0 - lw)
+ || (SIDE_X(&ghidgui->port.view, x1) > ghidgui->port.view.x0 + w + lw && SIDE_X(&ghidgui->port.view, x2) > ghidgui->port.view.x0 + w + lw)
+ || (SIDE_Y(&ghidgui->port.view, y1) < ghidgui->port.view.y0 - lw && SIDE_Y(&ghidgui->port.view, y2) < ghidgui->port.view.y0 - lw)
+ || (SIDE_Y(&ghidgui->port.view, y1) > ghidgui->port.view.y0 + h + lw && SIDE_Y(&ghidgui->port.view, y2) > ghidgui->port.view.y0 + h + lw))
+ return;
+
+ x1 = Vx(x1);
+ y1 = Vy(y1);
+ x2 = Vx(x2);
+ y2 = Vy(y2);
+
+ if (x1 > x2) {
+ gint xt = x1;
+ x1 = x2;
+ x2 = xt;
+ }
+ if (y1 > y2) {
+ gint yt = y1;
+ y1 = y2;
+ y2 = yt;
+ }
+
+ USE_GC(gc);
+ cairo_rectangle(priv->cr, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+ //gdk_draw_rectangle(gport->drawable, priv->u_gc, FALSE, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+
+ if (fill)
+ cairo_fill(priv->cr);
+ else
+ cairo_stroke(priv->cr);
+}
+
+static void cr_paint_from_surface(cairo_t * cr, cairo_surface_t * surface)
+{
+ cairo_set_source_surface(cr, surface, 0, 0);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_paint_with_alpha(cr, 1.0);
+}
+
+static void ghid_cairo_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
+{
+ cr_draw_rect(gc, FALSE, x1, y1,x2, y2);
+}
+
+static void ghid_cairo_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
+{
+ cr_draw_rect(gc, TRUE, x1, y1,x2, y2);
+}
+
+static void ghid_cairo_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius)
+{
+ gint w, h, vr;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ if (priv->cr == NULL)
+ return;
+
+ w = ghidgui->port.view.canvas_width * ghidgui->port.view.coord_per_px;
+ h = ghidgui->port.view.canvas_height * ghidgui->port.view.coord_per_px;
+ if (SIDE_X(&ghidgui->port.view, cx) < ghidgui->port.view.x0 - radius
+ || SIDE_X(&ghidgui->port.view, cx) > ghidgui->port.view.x0 + w + radius
+ || SIDE_Y(&ghidgui->port.view, cy) < ghidgui->port.view.y0 - radius || SIDE_Y(&ghidgui->port.view, cy) > ghidgui->port.view.y0 + h + radius)
+ return;
+
+ USE_GC(gc);
+ vr = Vz(radius);
+ cairo_arc(priv->cr, Vx(cx), Vy(cy), vr, 0.0, 2 * M_PI);
+ cairo_fill(priv->cr);
+ //gdk_draw_arc(gport->drawable, priv->u_gc, TRUE, Vx(cx) - vr, Vy(cy) - vr, vr * 2, vr * 2, 0, 360 * 64);
+}
+
+/* Intentional code duplication from ghid_cairo_fill_polygon_offs(), for performance */
+static void ghid_cairo_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y)
+{
+ int i;
+ render_priv_t *priv = ghidgui->port.render_priv;
+ cairo_t *cr = priv->cr;
+ int _x, _y;
+
+ if (priv->cr == NULL)
+ return;
+
+ USE_GC(gc);
+
+ for (i = 0; i < n_coords; i++) {
+ _x = Vx(x[i]);
+ _y = Vy(y[i]);
+ if (i == 0)
+ cairo_move_to(cr, _x, _y);
+ else
+ cairo_line_to(cr, _x, _y);
+ }
+ cairo_fill(cr);
+}
+
+static void ghid_cairo_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy)
+{
+ int i;
+ render_priv_t *priv = ghidgui->port.render_priv;
+ cairo_t *cr = priv->cr;
+ int _x, _y;
+
+ if (priv->cr == NULL)
+ return;
+
+ USE_GC(gc);
+
+ for (i = 0; i < n_coords; i++) {
+ _x = Vx(x[i]);
+ _y = Vy(y[i]);
+ if (i == 0)
+ cairo_move_to(cr, _x + Vz(dx), _y + Vz(dy));
+ else
+ cairo_line_to(cr, _x + Vz(dx), _y + Vz(dy));
+ }
+ cairo_fill(cr);
+}
+
+/* Fills the drawing with only bg_color */
+static void erase_with_background_color(cairo_t * cr, GdkRGBA * bg_color)
+{
+ gdk_cairo_set_source_rgba(cr, bg_color);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint_with_alpha(cr, 1.0);
+}
+
+static void redraw_region(pcb_hidlib_t *hidlib, GdkRectangle *rect)
+{
+ int eleft, eright, etop, ebottom;
+ pcb_hid_expose_ctx_t ctx;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ if (priv->cr_drawing_area == NULL)
+ return;
+
+ if (rect != NULL) {
+ priv->clip_rect = *rect;
+ priv->clip = pcb_true;
+ }
+ else {
+ priv->clip_rect.x = 0;
+ priv->clip_rect.y = 0;
+ priv->clip_rect.width = ghidgui->port.view.canvas_width;
+ priv->clip_rect.height = ghidgui->port.view.canvas_height;
+ priv->clip = pcb_false;
+ }
+
+ //set_clip(priv, priv->bg_gc);
+ //set_clip(priv, priv->offlimits_gc);
+ //set_clip(priv, priv->mask_gc);
+ //set_clip(priv, priv->grid_gc);
+
+ ctx.view.X1 = MIN(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1));
+ ctx.view.Y1 = MIN(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1));
+ ctx.view.X2 = MAX(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1));
+ ctx.view.Y2 = MAX(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1));
+
+ ctx.view.X1 = MAX(0, MIN(hidlib->size_x, ctx.view.X1));
+ ctx.view.X2 = MAX(0, MIN(hidlib->size_x, ctx.view.X2));
+ ctx.view.Y1 = MAX(0, MIN(hidlib->size_y, ctx.view.Y1));
+ ctx.view.Y2 = MAX(0, MIN(hidlib->size_y, ctx.view.Y2));
+
+ eleft = Vx(0);
+ eright = Vx(hidlib->size_x);
+ etop = Vy(0);
+ ebottom = Vy(hidlib->size_y);
+ if (eleft > eright) {
+ int tmp = eleft;
+ eleft = eright;
+ eright = tmp;
+ }
+ if (etop > ebottom) {
+ int tmp = etop;
+ etop = ebottom;
+ ebottom = tmp;
+ }
+
+ /* Paints only on the drawing_area */
+ priv->cr = priv->cr_drawing_area;
+ priv->cr_target = priv->cr_drawing_area;
+
+ erase_with_background_color(priv->cr, &priv->bg_color);
+
+ gdk_cairo_set_source_rgba(priv->cr, &priv->offlimits_color);
+ if (eleft > 0) {
+ cairo_rectangle(priv->cr, 0.0, 0.0, eleft, ghidgui->port.view.canvas_height);
+ }
+ else
+ eleft = 0;
+ if (eright < ghidgui->port.view.canvas_width) {
+ cairo_rectangle(priv->cr, eright, 0.0, ghidgui->port.view.canvas_width - eright, ghidgui->port.view.canvas_height);
+ }
+ else
+ eright = ghidgui->port.view.canvas_width;
+ if (etop > 0) {
+ cairo_rectangle(priv->cr, eleft, 0.0, eright - eleft + 1, etop);
+ }
+ else
+ etop = 0;
+ if (ebottom < ghidgui->port.view.canvas_height) {
+ cairo_rectangle(priv->cr, eleft, ebottom, eright - eleft + 1, ghidgui->port.view.canvas_height - ebottom);
+ }
+ else
+ ebottom = ghidgui->port.view.canvas_height;
+
+ cairo_fill(priv->cr);
+ //gdk_draw_rectangle(gport->drawable, priv->bg_gc, 1, eleft, etop, eright - eleft + 1, ebottom - etop + 1);
+
+ ghid_cairo_draw_bg_image(hidlib);
+
+ pcbhl_expose_main(>k3_cairo_hid, &ctx, NULL);
+ ghid_cairo_draw_grid(hidlib);
+
+ /* Draws "GUI" information on top of design */
+ priv->cr = priv->cr_drawing_area;
+ /* In some cases we are called with the crosshair still off */
+ if (priv->attached_invalidate_depth == 0)
+ pcbhl_draw_attached(hidlib, 0);
+
+ /* In some cases we are called with the mark still off */
+ if (priv->mark_invalidate_depth == 0)
+ pcbhl_draw_marks(hidlib, 0);
+
+ priv->clip = pcb_false;
+
+ /* Rest the clip for bg_gc, as it is used outside this function */
+ //gdk_gc_set_clip_mask(priv->bg_gc, NULL);
+ ghid_cairo_screen_update();
+}
+
+static int preview_lock = 0;
+static void ghid_cairo_invalidate_lr(pcb_hid_t *hid, pcb_coord_t left, pcb_coord_t right, pcb_coord_t top, pcb_coord_t bottom)
+{
+ pcb_hidlib_t *hidlib = ghidgui->hidlib;
+ int dleft, dright, dtop, dbottom;
+ int minx, maxx, miny, maxy;
+ GdkRectangle rect;
+
+ dleft = Vx(left);
+ dright = Vx(right);
+ dtop = Vy(top);
+ dbottom = Vy(bottom);
+
+ minx = MIN(dleft, dright);
+ maxx = MAX(dleft, dright);
+ miny = MIN(dtop, dbottom);
+ maxy = MAX(dtop, dbottom);
+
+ rect.x = minx;
+ rect.y = miny;
+ rect.width = maxx - minx;
+ rect.height = maxy - miny;
+
+ redraw_region(hidlib, &rect);
+ if (!preview_lock) {
+ preview_lock++;
+ pcb_gtk_previews_invalidate_lr(minx, maxx, miny, maxy);
+ preview_lock--;
+ }
+
+ ghid_cairo_screen_update();
+}
+
+static void ghid_cairo_invalidate_all(pcb_hid_t *hid)
+{
+ pcb_hidlib_t *hidlib = ghidgui->hidlib;
+
+ if (ghidgui && ghidgui->topwin.menu.menu_bar) {
+ redraw_region(hidlib, NULL);
+ if (!preview_lock) {
+ preview_lock++;
+ pcb_gtk_previews_invalidate_all();
+ preview_lock--;
+ }
+ ghid_cairo_screen_update();
+ }
+}
+
+static void ghid_cairo_notify_crosshair_change(pcb_hid_t *hid, pcb_bool changes_complete)
+{
+ pcb_hidlib_t *hidlib = ghidgui->hidlib;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ /* We sometimes get called before the GUI is up */
+ if (ghidgui->port.drawing_area == NULL)
+ return;
+
+ /* Keeps track of calls (including XOR draw mode), and draws only when complete and final. */
+ if (changes_complete)
+ priv->attached_invalidate_depth--;
+ else
+ priv->attached_invalidate_depth = 1 + priv->xor_mode;
+
+ if (changes_complete && ghidgui->port.drawing_area != NULL && priv->attached_invalidate_depth <= 0) {
+ /* Queues a GTK redraw when changes are complete */
+ ghid_cairo_invalidate_all(pcb_gui);
+ priv->attached_invalidate_depth = 0;
+ }
+}
+
+static void ghid_cairo_notify_mark_change(pcb_hid_t *hid, pcb_bool changes_complete)
+{
+ pcb_hidlib_t *hidlib = ghidgui->hidlib;
+ render_priv_t *priv = ghidgui->port.render_priv;
+
+ /* We sometimes get called before the GUI is up */
+ if (ghidgui->port.drawing_area == NULL)
+ return;
+
+ if (changes_complete)
+ priv->mark_invalidate_depth--;
+
+ if (priv->mark_invalidate_depth < 0) {
+ priv->mark_invalidate_depth = 0;
+ /* A mismatch of changes_complete == pcb_false and == pcb_true notifications
+ is not expected to occur, but we will try to handle it gracefully.
+ As we know the mark will have been shown already, we must
+ repaint the entire view to be sure not to leave an artefact.
+ */
+ ghid_cairo_invalidate_all(pcb_gui);
+ return;
+ }
+
+ if (priv->mark_invalidate_depth == 0)
+ pcbhl_draw_marks(hidlib, 0);
+
+ if (!changes_complete) {
+ priv->mark_invalidate_depth++;
+ }
+ else if (ghidgui->port.drawing_area != NULL) {
+ /* Queue a GTK expose when changes are complete */
+ ghid_draw_area_update(&ghidgui->port, NULL);
+ }
+}
+
+static void draw_right_cross(cairo_t * cr, gint x, gint y)
+{
+ //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
+
+ cr_draw_line(cr, FALSE, x, 0, x, ghidgui->port.view.canvas_height);
+ cr_draw_line(cr, FALSE, 0, y, ghidgui->port.view.canvas_width, y);
+ //gdk_draw_line(window, xor_gc, x, 0, x, gport->view.canvas_height);
+ //gdk_draw_line(window, xor_gc, 0, y, gport->view.canvas_width, y);
+}
+
+static void draw_slanted_cross(cairo_t * xor_gc, gint x, gint y)
+{
+ //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
+ gint x0, y0, x1, y1;
+
+ x0 = x + (ghidgui->port.view.canvas_height - y);
+ x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
+ x1 = x - y;
+ x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
+ y0 = y + (ghidgui->port.view.canvas_width - x);
+ y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
+ y1 = y - x;
+ y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
+ cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
+ //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
+
+ x0 = x - (ghidgui->port.view.canvas_height - y);
+ x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
+ x1 = x + y;
+ x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
+ y0 = y + x;
+ y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
+ y1 = y - (ghidgui->port.view.canvas_width - x);
+ y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
+ cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
+ //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
+}
+
+static void draw_dozen_cross(cairo_t * xor_gc, gint x, gint y)
+{
+ //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
+ gint x0, y0, x1, y1;
+ gdouble tan60 = sqrt(3);
+
+ x0 = x + (ghidgui->port.view.canvas_height - y) / tan60;
+ x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
+ x1 = x - y / tan60;
+ x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
+ y0 = y + (ghidgui->port.view.canvas_width - x) * tan60;
+ y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
+ y1 = y - x * tan60;
+ y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
+ cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
+ //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
+
+ x0 = x + (ghidgui->port.view.canvas_height - y) * tan60;
+ x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
+ x1 = x - y * tan60;
+ x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
+ y0 = y + (ghidgui->port.view.canvas_width - x) / tan60;
+ y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
+ y1 = y - x / tan60;
+ y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
+ cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
+ //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
+
+ x0 = x - (ghidgui->port.view.canvas_height - y) / tan60;
+ x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
+ x1 = x + y / tan60;
+ x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
+ y0 = y + x * tan60;
+ y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
+ y1 = y - (ghidgui->port.view.canvas_width - x) * tan60;
+ y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
+ cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
+ //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
+
+ x0 = x - (ghidgui->port.view.canvas_height - y) * tan60;
+ x0 = MAX(0, MIN(x0, ghidgui->port.view.canvas_width));
+ x1 = x + y * tan60;
+ x1 = MAX(0, MIN(x1, ghidgui->port.view.canvas_width));
+ y0 = y + x / tan60;
+ y0 = MAX(0, MIN(y0, ghidgui->port.view.canvas_height));
+ y1 = y - (ghidgui->port.view.canvas_width - x) / tan60;
+ y1 = MAX(0, MIN(y1, ghidgui->port.view.canvas_height));
+ cr_draw_line(ghidgui->port.render_priv->cr, FALSE, x0, y0, x1, y1);
+ //gdk_draw_line(window, xor_gc, x0, y0, x1, y1);
+}
+
+static void draw_crosshair(cairo_t * xor_gc, gint x, gint y)
+{
+ static enum pcb_crosshair_shape_e prev = pcb_ch_shape_basic;
+
+ if (ghidgui->port.view.crosshair_x < 0 || !ghidgui->topwin.active || !ghidgui->port.view.has_entered)
+ return;
+
+ draw_right_cross(xor_gc, x, y);
+ if (prev == pcb_ch_shape_union_jack)
+ draw_slanted_cross(xor_gc, x, y);
+ if (prev == pcb_ch_shape_dozen)
+ draw_dozen_cross(xor_gc, x, y);
+ prev = pcbhl_conf.editor.crosshair_shape_idx;
+}
+
+static void show_crosshair(gboolean paint_new_location)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
+ //GtkStyle *style = gtk_widget_get_style(gport->drawing_area);
+ gint x, y;
+ static gint x_prev = -1, y_prev = -1;
+ //static cairo_t *xor_gc;
+ //static GdkColor cross_color;
+ cairo_t *cr;
+
+ if (ghidgui->port.view.crosshair_x < 0 || !ghidgui->topwin.active || !ghidgui->port.view.has_entered) {
+ x_prev = y_prev = -1; /* if leaving the drawing area, invalidate last known coord to make sure we redraw on reenter, even on the same coords */
+ return;
+ }
+
+TODO("gtk3: when CrossColor changed from config")
+ map_color(&pcbhl_conf.appearance.color.cross, &priv->crosshair_color);
+ //cr = priv->cr_drawing_area;
+ cr = priv->cr;
+ gdk_cairo_set_source_rgba(cr, &priv->crosshair_color);
+ cairo_set_line_width(cr, 1.0);
+
+ //if (!xor_gc) {
+ // xor_gc = gdk_gc_new(window);
+ // gdk_gc_copy(xor_gc, style->white_gc);
+ // gdk_gc_set_function(xor_gc, GDK_XOR);
+ // gdk_gc_set_clip_origin(xor_gc, 0, 0);
+ // set_clip(priv, xor_gc);
+TODO("gtk3:FIXME: when CrossColor changed from config")
+ // map_color(&pcbhl_conf.appearance.color.cross, &cross_color);
+ //}
+ x = Vx(ghidgui->port.view.crosshair_x);
+ y = Vy(ghidgui->port.view.crosshair_y);
+
+ //gdk_gc_set_foreground(xor_gc, &cross_color);
+
+ if (x_prev >= 0 && !paint_new_location)
+ draw_crosshair(cr, x_prev, y_prev);
+
+ if (x >= 0 && paint_new_location) {
+ draw_crosshair(cr, x, y);
+ x_prev = x;
+ y_prev = y;
+ }
+ else
+ x_prev = y_prev = -1;
+}
+
+static void ghid_cairo_init_renderer(int *argc, char ***argv, void *vport)
+{
+ pcb_gtk_port_t *port = vport;
+
+ /* Init any GC's required */
+ port->render_priv = g_new0(render_priv_t, 1);
+ port->render_priv->cr = NULL;
+ port->render_priv->surf_da = NULL;
+ port->render_priv->cr_drawing_area = NULL;
+}
+
+static void ghid_cairo_shutdown_renderer(void *vport)
+{
+ pcb_gtk_port_t *port = vport;
+ render_priv_t *priv = port->render_priv;
+
+ cairo_surface_destroy(priv->surf_da);
+ priv->surf_da = NULL;
+ cairo_destroy(priv->cr_drawing_area);
+ priv->cr_drawing_area = NULL;
+ priv->cr = NULL;
+
+ g_free(port->render_priv);
+ port->render_priv = NULL;
+}
+
+static void ghid_cairo_init_drawing_widget(GtkWidget * widget, void *vport)
+{
+}
+
+/* Callback function only applied to drawing_area, after some resizing or initialisation. */
+static void ghid_cairo_drawing_area_configure_hook(void *vport)
+{
+ pcb_gtk_port_t *port = vport;
+ static int done_once = 0;
+ render_priv_t *priv = port->render_priv;
+ cairo_t *cr;
+
+ ghidgui->port.drawing_allowed = pcb_true;
+
+ if (!done_once) {
+ //priv->bg_gc = gdk_gc_new(port->drawable);
+ //gdk_gc_set_foreground(priv->bg_gc, &port->bg_color);
+ //gdk_gc_set_clip_origin(priv->bg_gc, 0, 0);
+ //
+ //priv->offlimits_gc = gdk_gc_new(port->drawable);
+ //gdk_gc_set_foreground(priv->offlimits_gc, &port->offlimits_color);
+ //gdk_gc_set_clip_origin(priv->offlimits_gc, 0, 0);
+
+ if (!map_color(&pcbhl_conf.appearance.color.background, &priv->bg_color))
+ map_color(pcb_color_white, &priv->bg_color);
+
+ if (!map_color(&pcbhl_conf.appearance.color.off_limit, &priv->offlimits_color))
+ map_color(pcb_color_white, &priv->offlimits_color);
+
+ if (!map_color(&pcbhl_conf.appearance.color.grid, &priv->grid_color))
+ map_color(pcb_color_blue, &priv->grid_color);
+ //set_special_grid_color();
+
+ //if (port->mask) {
+ // gdk_pixmap_unref(port->mask);
+ // port->mask = gdk_pixmap_new(0, port->view.canvas_width, port->view.canvas_height, 1);
+ //}
+ done_once = 1;
+ }
+
+ /* Creates a single cairo surface/context for off-line painting */
+ cr_create_similar_surface_and_context(&priv->surf_da, &priv->cr_drawing_area, port);
+ cr_create_similar_surface_and_context(&priv->surf_layer, &priv->cr_layer, port);
+ priv->cr = priv->cr_drawing_area;
+}
+
+/* GtkDrawingArea -> GtkWidget "draw" signal Call-Back function */
+static gboolean ghid_cairo_drawing_area_expose_cb(GtkWidget * widget, pcb_gtk_expose_t * p, void *vport)
+{
+ pcb_gtk_port_t *port = vport;
+ render_priv_t *priv = port->render_priv;
+ //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
+
+ //gdk_draw_drawable(window, priv->bg_gc, port->pixmap,
+ // ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+
+ cr_paint_from_surface(p, priv->surf_da);
+
+ priv->cr = p;
+ show_crosshair(TRUE);
+ priv->cr = priv->cr_drawing_area;
+
+ return FALSE;
+}
+
+static void ghid_cairo_screen_update(void)
+{
+ render_priv_t *priv = ghidgui->port.render_priv;
+ //GdkWindow *window = gtk_widget_get_window(gport->drawing_area);
+
+ if (priv->cr == NULL)
+ return;
+
+ //gdk_draw_drawable(window, priv->bg_gc, gport->pixmap, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height);
+ //show_crosshair(TRUE);
+ gtk_widget_queue_draw(ghidgui->port.drawing_area);
+}
+
+static void ghid_cairo_port_drawing_realize_cb(GtkWidget * widget, gpointer data)
+{
+}
+
+static gboolean ghid_cairo_preview_expose(GtkWidget * widget, pcb_gtk_expose_t * p,
+ pcb_hid_expose_t expcall, pcb_hid_expose_ctx_t *ctx)
+{
+ //GdkWindow *window = gtk_widget_get_window(widget);
+ //GdkDrawable *save_drawable;
+ GtkAllocation allocation; /* Assuming widget is a drawing widget, get the Rectangle allowed for drawing. */
+ pcb_gtk_view_t save_view;
+ int save_width, save_height;
+ double xz, yz, vw, vh;
+ render_priv_t *priv = ghidgui->port.render_priv;
+ pcb_coord_t ox1 = ctx->view.X1, oy1 = ctx->view.Y1, ox2 = ctx->view.X2, oy2 = ctx->view.Y2;
+ pcb_coord_t save_cpp;
+
+ vw = ctx->view.X2 - ctx->view.X1;
+ vh = ctx->view.Y2 - ctx->view.Y1;
+
+ /* Setup drawable and zoom factor for drawing routines
+ */
+ //save_drawable = gport->drawable;
+ save_view = ghidgui->port.view;
+ save_width = ghidgui->port.view.canvas_width;
+ save_height = ghidgui->port.view.canvas_height;
+ save_cpp = pcb_gui->coord_per_pix;
+
+ gtk_widget_get_allocation(widget, &allocation);
+ xz = vw / (double) allocation.width;
+ yz = vh / (double) allocation.height;
+ if (xz > yz)
+ ghidgui->port.view.coord_per_px = xz;
+ else
+ ghidgui->port.view.coord_per_px = yz;
+
+ //gport->drawable = window;
+ ghidgui->port.view.canvas_width = allocation.width;
+ ghidgui->port.view.canvas_height = allocation.height;
+ ghidgui->port.view.width = allocation.width * ghidgui->port.view.coord_per_px;
+ ghidgui->port.view.height = allocation.height * ghidgui->port.view.coord_per_px;
+ ghidgui->port.view.x0 = (vw - ghidgui->port.view.width) / 2 + ctx->view.X1;
+ ghidgui->port.view.y0 = (vh - ghidgui->port.view.height) / 2 + ctx->view.Y1;
+
+ PCB_GTK_PREVIEW_TUNE_EXTENT(ctx, allocation);
+ pcb_gui->coord_per_pix = ghidgui->port.view.coord_per_px;
+
+ /* Change current pointer to draw in this widget, draws, then come back to pointer to drawing_area. */
+ priv->cr_target = p;
+ priv->cr = p;
+ cairo_save(p);
+ /* clear background */
+ erase_with_background_color(p, &priv->bg_color);
+ /* calls the off-line drawing routine */
+ expcall(>k3_cairo_hid, ctx);
+ cairo_restore(p);
+ priv->cr = priv->cr_drawing_area;
+ //gport->drawable = save_drawable;
+
+ /* restore the original context and priv */
+ ctx->view.X1 = ox1; ctx->view.X2 = ox2; ctx->view.Y1 = oy1; ctx->view.Y2 = oy2;
+ pcb_gui->coord_per_pix = save_cpp;
+ ghidgui->port.view = save_view;
+ ghidgui->port.view.canvas_width = save_width;
+ ghidgui->port.view.canvas_height = save_height;
+
+ return FALSE;
+}
+
+static GtkWidget *ghid_cairo_new_drawing_widget(pcb_gtk_impl_t *common)
+{
+ GtkWidget *w = gtk_drawing_area_new();
+
+ g_signal_connect(G_OBJECT(w), "draw", G_CALLBACK(common->drawing_area_expose), common->gport);
+
+ return w;
+}
+
+
+void ghid_cairo_install(pcb_gtk_impl_t *impl, pcb_hid_t *hid)
+{
+ if (impl != NULL) {
+ impl->new_drawing_widget = ghid_cairo_new_drawing_widget;
+ impl->init_drawing_widget = ghid_cairo_init_drawing_widget;
+ impl->drawing_realize = ghid_cairo_port_drawing_realize_cb;
+ impl->drawing_area_expose = ghid_cairo_drawing_area_expose_cb;
+ impl->preview_expose = ghid_cairo_preview_expose;
+ //impl->invalidate_all = ghid_cairo_invalidate_all;
+ impl->set_special_colors = ghid_cairo_set_special_colors;
+ impl->init_renderer = ghid_cairo_init_renderer;
+ impl->screen_update = ghid_cairo_screen_update;
+ impl->draw_grid_local = ghid_cairo_draw_grid_local;
+ impl->drawing_area_configure_hook = ghid_cairo_drawing_area_configure_hook;
+ impl->shutdown_renderer = ghid_cairo_shutdown_renderer;
+ impl->get_color_name = get_color_name;
+ impl->map_color = map_color;
+ }
+
+ if (hid != NULL) {
+ hid->invalidate_lr = ghid_cairo_invalidate_lr;
+ hid->invalidate_all = ghid_cairo_invalidate_all;
+ hid->notify_crosshair_change = ghid_cairo_notify_crosshair_change;
+ hid->notify_mark_change = ghid_cairo_notify_mark_change;
+ hid->set_layer_group = ghid_cairo_set_layer_group;
+ hid->end_layer = ghid_cairo_end_layer_group;
+ hid->make_gc = ghid_cairo_make_gc;
+ hid->destroy_gc = ghid_cairo_destroy_gc;
+ hid->render_burst = ghid_cairo_render_burst;
+ hid->set_drawing_mode = ghid_cairo_set_drawing_mode;
+ hid->set_color = ghid_cairo_set_color;
+ hid->set_line_cap = ghid_cairo_set_line_cap;
+ hid->set_line_width = ghid_cairo_set_line_width;
+ hid->set_draw_xor = ghid_cairo_set_draw_xor;
+ hid->draw_line = ghid_cairo_draw_line;
+ hid->draw_arc = ghid_cairo_draw_arc;
+ hid->draw_rect = ghid_cairo_draw_rect;
+ hid->fill_circle = ghid_cairo_fill_circle;
+ hid->fill_polygon = ghid_cairo_fill_polygon;
+ hid->fill_polygon_offs = ghid_cairo_fill_polygon_offs;
+ hid->fill_rect = ghid_cairo_fill_rect;
+ }
+}
Index: work/obsolete/hid_gtk3_cairo/gtkhid-main.c
===================================================================
--- work/obsolete/hid_gtk3_cairo/gtkhid-main.c (nonexistent)
+++ work/obsolete/hid_gtk3_cairo/gtkhid-main.c (revision 27398)
@@ -0,0 +1,46 @@
+#include "config.h"
+
+#include
+
+#include "plugins.h"
+#include "hid_init.h"
+
+#include "../src_plugins/lib_gtk_common/glue_common.h"
+#include "../src_plugins/lib_gtk_common/glue_hid.h"
+
+const char *ghid_cairo_cookie = "gtk3 hid, cairo";
+
+pcb_hid_t gtk3_cairo_hid;
+
+extern void ghid_cairo_install(pcb_gtk_impl_t *impl, pcb_hid_t *hid);
+
+int gtk3_cairo_parse_arguments(pcb_hid_t *hid, int *argc, char ***argv)
+{
+ ghid_glue_common_init(ghid_cairo_cookie);
+ ghid_cairo_install(&ghidgui->impl, hid);
+ return gtkhid_parse_arguments(hid, argc, argv);
+}
+
+int pplg_check_ver_hid_gtk3_cairo(int ver_needed) { return 0; }
+
+void pplg_uninit_hid_gtk3_cairo(void)
+{
+ ghid_glue_common_uninit(ghid_cairo_cookie);
+}
+
+int pplg_init_hid_gtk3_cairo(void)
+{
+ PCB_API_CHK_VER;
+
+ ghid_glue_hid_init(>k3_cairo_hid);
+
+ gtk3_cairo_hid.parse_arguments = gtk3_cairo_parse_arguments;
+ ghid_cairo_install(NULL, >k3_cairo_hid);
+
+ gtk3_cairo_hid.name = "gtk3_cairo";
+ gtk3_cairo_hid.description = "Gtk3 - The Gimp Toolkit, with cairo rendering";
+
+ pcb_hid_register_hid(>k3_cairo_hid);
+
+ return 0;
+}
Index: work/obsolete/hid_gtk3_cairo/hid_gtk3_cairo.pup
===================================================================
--- work/obsolete/hid_gtk3_cairo/hid_gtk3_cairo.pup (nonexistent)
+++ work/obsolete/hid_gtk3_cairo/hid_gtk3_cairo.pup (revision 27398)
@@ -0,0 +1,7 @@
+$class hid
+$short #GTK3 GUI, cairo render
+$long GUI: the GTK3 HID, using cairo for rendering
+$state WIP
+default disable-all
+dep lib_gtk_common
+autoload 1