gerbv  2.10.1-dev~93f1b5
draw-gdk.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  * This file is a part of gerbv.
4  *
5  * Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
6  *
7  * $Id$
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
22  */
23 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h> /* ceil(), atan2() */
36 
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40 
41 #include <gtk/gtk.h>
42 #include "gerbv.h"
43 #include "draw-gdk.h"
44 #include "common.h"
45 
46 #undef round
47 #define round(x) ceil((double)(x))
48 
49 #define dprintf \
50  if (DEBUG) \
51  printf
52 
53 /*
54  * If you want to rotate a
55  * column vector v by t degrees using matrix M, use
56  *
57  * M = {{cos t, -sin t}, {sin t, cos t}} in M*v.
58  *
59  * From comp.graphics.algorithms Frequently Asked Questions
60  *
61  * Due reverse defintion of X-axis in GTK you have to negate
62  * angels.
63  *
64  */
65 static GdkPoint
66 rotate_point(GdkPoint point, double angle) {
67  double sint, cost;
68  GdkPoint returned;
69 
70  if (angle == 0.0)
71  return point;
72 
73  sint = sin(DEG2RAD(-angle));
74  cost = cos(DEG2RAD(-angle));
75 
76  returned.x = lround(cost * point.x - sint * point.y);
77  returned.y = lround(sint * point.x + cost * point.y);
78 
79  return returned;
80 }
81 
82 /*
83  * Aperture macro primitive 1 (Circle)
84  */
85 static void
86 gerbv_gdk_draw_prim1(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
87  const int exposure_idx = 0;
88  const int diameter_idx = 1;
89  const int x_offset_idx = 2;
90  const int y_offset_idx = 3;
91  const gint full_circle = 23360;
92  GdkGC* local_gc = gdk_gc_new(pixmap);
93  gint dia = round(fabs(s->parameter[diameter_idx] * scale));
94  gint real_x = x - dia / 2;
95  gint real_y = y - dia / 2;
96  GdkColor color;
97 
98  gdk_gc_copy(local_gc, gc);
99 
100  real_x += (int)(s->parameter[x_offset_idx] * (double)scale);
101  real_y -= (int)(s->parameter[y_offset_idx] * (double)scale);
102 
103  /* Exposure */
104  if (s->parameter[exposure_idx] == 0.0) {
105  color.pixel = 0;
106  gdk_gc_set_foreground(local_gc, &color);
107  }
108 
109  gdk_gc_set_line_attributes(
110  local_gc, 1, /* outline always 1 pixels */
111  GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
112  );
113 
114  /*
115  * A filled circle
116  */
117  gdk_draw_arc(pixmap, local_gc, 1, real_x, real_y, dia, dia, 0, full_circle);
118 
119  gdk_gc_unref(local_gc);
120 
121  return;
122 } /* gerbv_gdk_draw_prim1 */
123 
124 /*
125  * Aperture macro primitive 4 (outline)
126  * - Start point is not included in number of points.
127  * - Outline is 1 pixel.
128  */
129 static void
130 gerbv_gdk_draw_prim4(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
131  const int exposure_idx = 0;
132  const int nuf_points_idx = 1;
133  const int first_x_idx = 2;
134  const int first_y_idx = 3;
135  const int rotext_idx = 4;
136  GdkGC* local_gc = gdk_gc_new(pixmap);
137  int nuf_points, point;
138  double rotation;
139  GdkPoint* points;
140  GdkColor color;
141 
142  /* Include start point */
143  nuf_points = (int)s->parameter[nuf_points_idx] + 1;
144  points = g_new(GdkPoint, nuf_points);
145  if (!points) {
146  g_free(points);
147  return;
148  }
149 
150  rotation = s->parameter[(nuf_points - 1) * 2 + rotext_idx];
151  for (point = 0; point < nuf_points; point++) {
152  points[point].x = (int)round(scale * s->parameter[point * 2 + first_x_idx]);
153  points[point].y = -(int)round(scale * s->parameter[point * 2 + first_y_idx]);
154  if (rotation != 0.0)
155  points[point] = rotate_point(points[point], rotation);
156  points[point].x += x;
157  points[point].y += y;
158  }
159 
160  gdk_gc_copy(local_gc, gc);
161 
162  /* Exposure */
163  if (s->parameter[exposure_idx] == 0.0) {
164  color.pixel = 0;
165  gdk_gc_set_foreground(local_gc, &color);
166  }
167 
168  gdk_gc_set_line_attributes(
169  local_gc, 1, /* outline always 1 pixels */
170  GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
171  );
172  gdk_draw_polygon(pixmap, local_gc, 1, points, nuf_points);
173 
174  g_free(points);
175 
176  gdk_gc_unref(local_gc);
177 
178  return;
179 } /* gerbv_gdk_draw_prim4 */
180 
181 /*
182  * Aperture macro primitive 5 (polygon)
183  */
184 static void
185 gerbv_gdk_draw_prim5(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
186  const int exposure_idx = 0;
187  const int nuf_vertices_idx = 1;
188  const int center_x_idx = 2;
189  const int center_y_idx = 3;
190  const int diameter_idx = 4;
191  const int rotation_idx = 5;
192  int nuf_vertices, i;
193  double vertex, tick, rotation, radius;
194  GdkPoint* points;
195  GdkGC* local_gc = gdk_gc_new(pixmap);
196  GdkColor color;
197 
198  nuf_vertices = (int)s->parameter[nuf_vertices_idx];
199  points = g_new(GdkPoint, nuf_vertices);
200  if (!points) {
201  g_free(points);
202  return;
203  }
204 
205  gdk_gc_copy(local_gc, gc);
206 
207  /* Exposure */
208  if (s->parameter[exposure_idx] == 0.0) {
209  color.pixel = 0;
210  gdk_gc_set_foreground(local_gc, &color);
211  }
212 
213  tick = 2 * M_PI / (double)nuf_vertices;
214  rotation = DEG2RAD(-s->parameter[rotation_idx]);
215  radius = s->parameter[diameter_idx] / 2.0;
216  for (i = 0; i < nuf_vertices; i++) {
217  vertex = tick * (double)i + rotation;
218  points[i].x = (int)round(scale * (radius * cos(vertex) + s->parameter[center_x_idx])) + x;
219  points[i].y = (int)round(scale * (radius * sin(vertex) - s->parameter[center_y_idx])) + y;
220  }
221 
222  gdk_draw_polygon(pixmap, local_gc, 1, points, nuf_vertices);
223 
224  gdk_gc_unref(local_gc);
225 
226  g_free(points);
227  return;
228 } /* gerbv_gdk_draw_prim5 */
229 
230 /*
231  * Doesn't handle and explicit x,y yet
232  * Questions:
233  * - is "gap" distance between edges of circles or distance between
234  * center of line of circle?
235  */
236 static void
237 gerbv_gdk_draw_prim6(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
238  const int outside_dia_idx = 2;
239  const int ci_thickness_idx = 3;
240  const int gap_idx = 4;
241  const int nuf_circles_idx = 5;
242  const int ch_thickness_idx = 6;
243  const int ch_length_idx = 7;
244  const int rotation_idx = 8;
245  GdkGC* local_gc = gdk_gc_new(pixmap);
246  double real_dia;
247  double real_dia_diff;
248  int circle;
249  GdkPoint crosshair[4];
250  int point;
251 
252  gdk_gc_copy(local_gc, gc);
253  gdk_gc_set_line_attributes(
254  local_gc, (int)round(scale * s->parameter[ci_thickness_idx]), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
255  );
256 
257  real_dia = s->parameter[outside_dia_idx] - s->parameter[ci_thickness_idx] / 2.0;
258  real_dia_diff = 2 * (s->parameter[gap_idx] + s->parameter[ci_thickness_idx]);
259 
260  for (circle = 0; circle != (int)s->parameter[nuf_circles_idx]; circle++) {
261  /*
262  * Non filled circle
263  */
264  const gint full_circle = 23360;
265  gint dia = (real_dia - real_dia_diff * circle) * scale;
266  if (dia >= 0) {
267  gdk_draw_arc(pixmap, local_gc, 0, x - dia / 2, y - dia / 2, dia, dia, 0, full_circle);
268  }
269  }
270 
271  /*
272  * Cross Hair
273  */
274  memset(crosshair, 0, sizeof(GdkPoint) * 4);
275  crosshair[0].x = (int)((s->parameter[ch_length_idx] / 2.0) * scale);
276  /*crosshair[0].y = 0;*/
277  crosshair[1].x = -crosshair[0].x;
278  /*crosshair[1].y = 0;*/
279  /*crosshair[2].x = 0;*/
280  crosshair[2].y = crosshair[0].x;
281  /*crosshair[3].x = 0;*/
282  crosshair[3].y = -crosshair[0].x;
283 
284  gdk_gc_set_line_attributes(
285  local_gc, (int)round(scale * s->parameter[ch_thickness_idx]), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
286  );
287 
288  for (point = 0; point < 4; point++) {
289  crosshair[point] = rotate_point(crosshair[point], s->parameter[rotation_idx]);
290  crosshair[point].x += x;
291  crosshair[point].y += y;
292  }
293  gdk_draw_line(pixmap, local_gc, crosshair[0].x, crosshair[0].y, crosshair[1].x, crosshair[1].y);
294  gdk_draw_line(pixmap, local_gc, crosshair[2].x, crosshair[2].y, crosshair[3].x, crosshair[3].y);
295 
296  gdk_gc_unref(local_gc);
297 
298  return;
299 } /* gerbv_gdk_draw_prim6 */
300 
301 static void
302 gerbv_gdk_draw_prim7(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
303  const int outside_dia_idx = 2;
304  const int inside_dia_idx = 3;
305  const int ch_thickness_idx = 4;
306  const int rotation_idx = 5;
307  const gint full_circle = 23360;
308  GdkGCValues gc_val;
309  int diameter, i;
310  GdkGC* local_gc = gdk_gc_new(pixmap);
311  GdkPoint point[4];
312  double ci_thickness = (s->parameter[outside_dia_idx] - s->parameter[inside_dia_idx]) / 2.0;
313 
314  gdk_gc_copy(local_gc, gc);
315  gdk_gc_set_line_attributes(
316  local_gc, (int)round(scale * ci_thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
317  );
318 
319  /*
320  * Non filled circle
321  */
322  diameter = (s->parameter[inside_dia_idx] + ci_thickness) * scale;
323  gdk_draw_arc(pixmap, local_gc, 0, x - diameter / 2, y - diameter / 2, diameter, diameter, 0, full_circle);
324 
325  /*
326  * Cross hair
327  */
328  /* Calculate the end points of the crosshair */
329  /* GDK doesn't always remove all of the circle (round of error probably)
330  I extend the crosshair line with 2 (one pixel in each end) to make
331  sure all of the circle is removed with the crosshair */
332  for (i = 0; i < 4; i++) {
333  point[i].x = round((s->parameter[outside_dia_idx] / 2.0) * scale) + 2;
334  point[i].y = 0;
335  point[i] = rotate_point(point[i], s->parameter[rotation_idx] + 90 * i);
336  point[i].x += x;
337  point[i].y += y;
338  }
339 
340  gdk_gc_set_line_attributes(
341  local_gc, (int)round(scale * s->parameter[ch_thickness_idx]), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
342  );
343 
344  /* The cross hair should "cut out" parts of the circle, hence inverse */
345  gdk_gc_get_values(local_gc, &gc_val);
346  if (gc_val.foreground.pixel == 1)
347  gc_val.foreground.pixel = 0;
348  else
349  gc_val.foreground.pixel = 1;
350  gdk_gc_set_foreground(local_gc, &(gc_val.foreground));
351 
352  /* Draw the actual cross */
353  gdk_draw_line(pixmap, local_gc, point[0].x, point[0].y, point[2].x, point[2].y);
354  gdk_draw_line(pixmap, local_gc, point[1].x, point[1].y, point[3].x, point[3].y);
355 
356  gdk_gc_unref(local_gc);
357 
358  return;
359 } /* gerbv_gdk_draw_prim7 */
360 
361 /*
362  * Doesn't handle and explicit x,y yet
363  */
364 static void
365 gerbv_gdk_draw_prim20(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
366  const int exposure_idx = 0;
367  const int linewidth_idx = 1;
368  const int start_x_idx = 2;
369  const int start_y_idx = 3;
370  const int end_x_idx = 4;
371  const int end_y_idx = 5;
372  const int rotation_idx = 6;
373  const int nuf_points = 2;
374  GdkGC* local_gc = gdk_gc_new(pixmap);
375  GdkPoint points[nuf_points];
376  GdkColor color;
377  int i;
378 
379  gdk_gc_copy(local_gc, gc);
380 
381  /* Exposure */
382  if (s->parameter[exposure_idx] == 0.0) {
383  color.pixel = 0;
384  gdk_gc_set_foreground(local_gc, &color);
385  }
386 
387  gdk_gc_set_line_attributes(
388  local_gc, (int)round(scale * s->parameter[linewidth_idx]), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER
389  );
390 
391  points[0].x = (s->parameter[start_x_idx] * scale);
392  points[0].y = (s->parameter[start_y_idx] * scale);
393  points[1].x = (s->parameter[end_x_idx] * scale);
394  points[1].y = (s->parameter[end_y_idx] * scale);
395 
396  for (i = 0; i < nuf_points; i++) {
397  points[i] = rotate_point(points[i], -s->parameter[rotation_idx]);
398  points[i].x = x + points[i].x;
399  points[i].y = y - points[i].y;
400  }
401 
402  gdk_draw_line(pixmap, local_gc, points[0].x, points[0].y, points[1].x, points[1].y);
403 
404  gdk_gc_unref(local_gc);
405 
406  return;
407 } /* gerbv_gdk_draw_prim20 */
408 
409 static void
410 gerbv_gdk_draw_prim21(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
411  const int exposure_idx = 0;
412  const int width_idx = 1;
413  const int height_idx = 2;
414  const int exp_x_idx = 3;
415  const int exp_y_idx = 4;
416  const int rotation_idx = 5;
417  const int nuf_points = 4;
418  GdkPoint points[nuf_points];
419  GdkColor color;
420  GdkGC* local_gc = gdk_gc_new(pixmap);
421  int half_width, half_height;
422  int i;
423 
424  half_width = (int)round(s->parameter[width_idx] * scale / 2.0);
425  half_height = (int)round(s->parameter[height_idx] * scale / 2.0);
426 
427  points[0].x = half_width;
428  points[0].y = half_height;
429 
430  points[1].x = half_width;
431  points[1].y = -half_height;
432 
433  points[2].x = -half_width;
434  points[2].y = -half_height;
435 
436  points[3].x = -half_width;
437  points[3].y = half_height;
438 
439  for (i = 0; i < nuf_points; i++) {
440  points[i].x += (int)(s->parameter[exp_x_idx] * scale);
441  points[i].y -= (int)(s->parameter[exp_y_idx] * scale);
442  points[i] = rotate_point(points[i], s->parameter[rotation_idx]);
443  points[i].x += x;
444  points[i].y += y;
445  }
446 
447  gdk_gc_copy(local_gc, gc);
448 
449  /* Exposure */
450  if (s->parameter[exposure_idx] == 0.0) {
451  color.pixel = 0;
452  gdk_gc_set_foreground(local_gc, &color);
453  }
454 
455  gdk_draw_polygon(pixmap, local_gc, 1, points, nuf_points);
456 
457  gdk_gc_unref(local_gc);
458 
459  return;
460 } /* gerbv_gdk_draw_prim21 */
461 
462 /*
463  * Doesn't handle explicit x,y yet
464  */
465 static void
466 gerbv_gdk_draw_prim22(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
467  const int exposure_idx = 0;
468  const int width_idx = 1;
469  const int height_idx = 2;
470  const int x_lower_left_idx = 3;
471  const int y_lower_left_idx = 4;
472  const int rotation_idx = 5;
473  const int nuf_points = 4;
474  GdkPoint points[nuf_points];
475  GdkGC* local_gc = gdk_gc_new(pixmap);
476  GdkColor color;
477  int i;
478 
479  points[0].x = (int)round(s->parameter[x_lower_left_idx] * scale);
480  points[0].y = (int)round(s->parameter[y_lower_left_idx] * scale);
481 
482  points[1].x = (int)round((s->parameter[x_lower_left_idx] + s->parameter[width_idx]) * scale);
483  points[1].y = (int)round(s->parameter[y_lower_left_idx] * scale);
484 
485  points[2].x = (int)round((s->parameter[x_lower_left_idx] + s->parameter[width_idx]) * scale);
486  points[2].y = (int)round((s->parameter[y_lower_left_idx] + s->parameter[height_idx]) * scale);
487 
488  points[3].x = (int)round(s->parameter[x_lower_left_idx] * scale);
489  points[3].y = (int)round((s->parameter[y_lower_left_idx] + s->parameter[height_idx]) * scale);
490 
491  for (i = 0; i < nuf_points; i++) {
492  points[i] = rotate_point(points[i], -s->parameter[rotation_idx]);
493  points[i].x = x + points[i].x;
494  points[i].y = y - points[i].y;
495  }
496 
497  gdk_gc_copy(local_gc, gc);
498 
499  /* Exposure */
500  if (s->parameter[exposure_idx] == 0.0) {
501  color.pixel = 0;
502  gdk_gc_set_foreground(local_gc, &color);
503  }
504 
505  gdk_draw_polygon(pixmap, local_gc, 1, points, nuf_points);
506 
507  gdk_gc_unref(local_gc);
508 
509  return;
510 } /* gerbv_gdk_draw_prim22 */
511 
512 /* Keep this array in order and without holes */
513 static void (*dgk_draw_amacro_funcs[])(GdkPixmap*, GdkGC*, gerbv_simplified_amacro_t*, double, gint, gint) = {
514  [GERBV_APTYPE_MACRO_CIRCLE] = &gerbv_gdk_draw_prim1, [GERBV_APTYPE_MACRO_OUTLINE] = &gerbv_gdk_draw_prim4,
515  [GERBV_APTYPE_MACRO_POLYGON] = &gerbv_gdk_draw_prim5, [GERBV_APTYPE_MACRO_MOIRE] = &gerbv_gdk_draw_prim6,
516  [GERBV_APTYPE_MACRO_THERMAL] = &gerbv_gdk_draw_prim7, [GERBV_APTYPE_MACRO_LINE20] = &gerbv_gdk_draw_prim20,
517  [GERBV_APTYPE_MACRO_LINE21] = &gerbv_gdk_draw_prim21, [GERBV_APTYPE_MACRO_LINE22] = &gerbv_gdk_draw_prim22,
518 };
519 
520 static inline void
521 gerbv_gdk_draw_amacro(GdkPixmap* pixmap, GdkGC* gc, gerbv_simplified_amacro_t* s, double scale, gint x, gint y) {
522  dprintf("%s(): drawing simplified aperture macros:\n", __func__);
523 
524  while (s != NULL) {
525  if (s->type >= GERBV_APTYPE_MACRO_CIRCLE && s->type <= GERBV_APTYPE_MACRO_LINE22) {
526  dgk_draw_amacro_funcs[s->type](pixmap, gc, s, scale, x, y);
527  dprintf(" %s\n", gerbv_aperture_type_name(s->type));
528  } else {
529  GERB_FATAL_ERROR(_("Unknown simplified aperture macro type %d"), s->type);
530  }
531 
532  s = s->next;
533  }
534 } /* gerbv_gdk_draw_amacro */
535 
536 /*
537  * Draws a circle _centered_ at x,y with diameter dia
538  */
539 static void
540 gerbv_gdk_draw_circle(GdkPixmap* pixmap, GdkGC* gc, gint filled, gint x, gint y, gint dia) {
541  static const gint full_circle = 23360;
542  gint real_x = x - dia / 2;
543  gint real_y = y - dia / 2;
544 
545  gdk_draw_arc(pixmap, gc, filled, real_x, real_y, dia, dia, 0, full_circle);
546 
547  return;
548 } /* gerbv_gdk_draw_circle */
549 
550 /*
551  * Draws a rectangle _centered_ at x,y with sides x_side, y_side
552  */
553 static void
554 gerbv_gdk_draw_rectangle(
555  GdkPixmap* pixmap, GdkGC* gc, int filled, gint x, gint y, gint x_side, gint y_side, double angle_deg
556 ) {
557  int i;
558  GdkPoint points[4];
559 
560  points[0].x = -(x_side >> 1);
561  points[0].y = -(y_side >> 1);
562  points[1].x = x_side >> 1;
563  points[1].y = points[0].y;
564  points[2].x = points[1].x;
565  points[2].y = y_side >> 1;
566  points[3].x = points[0].x;
567  points[3].y = points[2].y;
568 
569  for (i = 0; i < 4; i++) {
570  points[i] = rotate_point(points[i], angle_deg);
571  points[i].x += x;
572  points[i].y += y;
573  }
574 
575  gdk_draw_polygon(pixmap, gc, filled, points, 4);
576 
577  return;
578 } /* gerbv_gdk_draw_rectangle */
579 
580 /*
581  * Draws an oval _centered_ at x,y with x axis x_axis and y axis y_axis
582  */
583 static void
584 gerbv_gdk_draw_oval(
585  GdkPixmap* pixmap, GdkGC* gc, int filled, gint x, gint y, gint x_axis, gint y_axis, double angle_deg
586 ) {
587  gint width;
588  GdkPoint points[2];
589  GdkGC* local_gc = gdk_gc_new(pixmap);
590 
591  gdk_gc_copy(local_gc, gc);
592 
593  if (x_axis > y_axis) {
594  /* Draw in x axis */
595  width = y_axis;
596 
597  points[0].x = -(x_axis >> 1) + (y_axis >> 1);
598  points[0].y = 0;
599  points[1].x = (x_axis >> 1) - (y_axis >> 1);
600  points[1].y = 0;
601  } else {
602  /* Draw in y axis */
603  width = x_axis;
604 
605  points[0].x = 0;
606  points[0].y = -(y_axis >> 1) + (x_axis >> 1);
607  points[1].x = 0;
608  points[1].y = (y_axis >> 1) - (x_axis >> 1);
609  }
610 
611  points[0] = rotate_point(points[0], angle_deg);
612  points[0].x += x;
613  points[0].y += y;
614  points[1] = rotate_point(points[1], angle_deg);
615  points[1].x += x;
616  points[1].y += y;
617 
618  gdk_gc_set_line_attributes(local_gc, width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_MITER);
619  gdk_draw_line(pixmap, local_gc, points[0].x, points[0].y, points[1].x, points[1].y);
620 
621  gdk_gc_unref(local_gc);
622 
623  return;
624 } /* gerbv_gdk_draw_oval */
625 
626 /*
627  * Draws an arc
628  * Draws an arc _centered_ at x,y
629  * direction: 0 counterclockwise, 1 clockwise
630  */
631 static void
632 gerbv_gdk_draw_arc(
633  GdkPixmap* pixmap, GdkGC* gc, int x, int y, gdouble width, gdouble height, double angle1, double angle2
634 ) {
635  gint real_x = round(x - width / 2);
636  gint real_y = round(y - height / 2);
637 
638  gdk_draw_arc(
639  pixmap, gc, FALSE, real_x, real_y, width, height, round(64 * fmod(angle1, 360)), round(64 * (angle2 - angle1))
640  );
641 } /* gerbv_gdk_draw_arc */
642 
643 void
644 draw_gdk_render_polygon_object(
645  gerbv_net_t* oldNet, gerbv_image_t* image, double sr_x, double sr_y, cairo_matrix_t* fullMatrix,
646  cairo_matrix_t* scaleMatrix, GdkGC* gc, GdkGC* pgc, GdkPixmap** pixmap
647 ) {
648  gerbv_net_t* currentNet;
649  gint x2, y2, cp_x = 0, cp_y = 0, cir_width = 0;
650  GdkPoint* points = NULL;
651  unsigned int pointArraySize, curr_point_idx;
652  int steps, i;
653  gdouble angleDiff, tempX, tempY;
654 
655  /* save the first net in the polygon as the "ID" net pointer
656  in case we are saving this net to the selection array */
657  curr_point_idx = 0;
658  pointArraySize = 0;
659 
660  for (currentNet = oldNet->next; currentNet != NULL; currentNet = currentNet->next) {
661  tempX = currentNet->stop_x + sr_x;
662  tempY = currentNet->stop_y + sr_y;
663  cairo_matrix_transform_point(fullMatrix, &tempX, &tempY);
664  x2 = (int)round(tempX);
665  y2 = (int)round(tempY);
666 
667  /*
668  * If circle segment, scale and translate that one too
669  */
670  if (currentNet->cirseg) {
671  tempX = currentNet->cirseg->width;
672  tempY = currentNet->cirseg->height;
673  cairo_matrix_transform_point(scaleMatrix, &tempX, &tempY);
674 
675  /* Variables can be negative after transformation */
676  tempX = fabs(tempX);
677  cir_width = (int)round(tempX);
678 
679  tempX = currentNet->cirseg->cp_x + sr_x;
680  tempY = currentNet->cirseg->cp_y + sr_y;
681  cairo_matrix_transform_point(fullMatrix, &tempX, &tempY);
682  cp_x = (int)round(tempX);
683  cp_y = (int)round(tempY);
684  }
685 
686  switch (currentNet->interpolation) {
691  if (pointArraySize < (curr_point_idx + 1)) {
692  pointArraySize = curr_point_idx + 1;
693  points = (GdkPoint*)g_realloc(points, pointArraySize * sizeof(GdkPoint));
694  }
695  points[curr_point_idx].x = x2;
696  points[curr_point_idx].y = y2;
697  curr_point_idx++;
698  break;
701  /* we need to chop up the arc into small lines for rendering
702  with GDK */
703  angleDiff = currentNet->cirseg->angle2 - currentNet->cirseg->angle1;
704  steps = (int)abs(angleDiff);
705  if (pointArraySize < (curr_point_idx + steps)) {
706  pointArraySize = curr_point_idx + steps;
707  points = (GdkPoint*)g_realloc(points, pointArraySize * sizeof(GdkPoint));
708  }
709  for (i = 0; i < steps; i++) {
710  points[curr_point_idx].x =
711  cp_x + cir_width / 2.0 * cos(DEG2RAD(currentNet->cirseg->angle1 + (angleDiff * i) / steps));
712  points[curr_point_idx].y =
713  cp_y - cir_width / 2.0 * sin(DEG2RAD(currentNet->cirseg->angle1 + (angleDiff * i) / steps));
714  curr_point_idx++;
715  }
716  break;
718  gdk_gc_copy(pgc, gc);
719  gdk_gc_set_line_attributes(pgc, 1, GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER);
720  gdk_draw_polygon(*pixmap, pgc, 1, points, curr_point_idx);
721  g_free(points);
722  points = NULL;
723  return;
724  default: GERB_COMPILE_WARNING(_("Skipped interpolation type %d"), currentNet->interpolation); break;
725  }
726  }
727  return;
728 }
729 
730 void
731 draw_gdk_apply_netstate_transformation(
732  cairo_matrix_t* fullMatrix, cairo_matrix_t* scaleMatrix, gerbv_netstate_t* state
733 ) {
734  /* apply scale factor */
735  cairo_matrix_scale(fullMatrix, state->scaleA, state->scaleB);
736  cairo_matrix_scale(scaleMatrix, state->scaleA, state->scaleB);
737  /* apply offset */
738  cairo_matrix_translate(fullMatrix, state->offsetA, state->offsetB);
739  /* apply mirror */
740  switch (state->mirrorState) {
741  case GERBV_MIRROR_STATE_FLIPA:
742  cairo_matrix_scale(fullMatrix, -1, 1);
743  cairo_matrix_scale(scaleMatrix, -1, 1);
744  break;
745  case GERBV_MIRROR_STATE_FLIPB:
746  cairo_matrix_scale(fullMatrix, 1, -1);
747  cairo_matrix_scale(scaleMatrix, -1, 1);
748  break;
749  case GERBV_MIRROR_STATE_FLIPAB:
750  cairo_matrix_scale(fullMatrix, -1, -1);
751  cairo_matrix_scale(scaleMatrix, -1, 1);
752  break;
753  default: break;
754  }
755  /* finally, apply axis select */
756  if (state->axisSelect == GERBV_AXIS_SELECT_SWAPAB) {
757  /* we do this by rotating 270 (counterclockwise, then mirroring
758  the Y axis */
759  cairo_matrix_rotate(fullMatrix, M_PI + M_PI_2);
760  cairo_matrix_scale(fullMatrix, 1, -1);
761  }
762 }
763 
764 static void
765 draw_gdk_cross(GdkPixmap* pixmap, GdkGC* gc, gint xc, gint yc, gint r) {
766  gdk_gc_set_line_attributes(gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
767  gdk_draw_line(pixmap, gc, xc - r, yc, xc + r, yc);
768  gdk_draw_line(pixmap, gc, xc, yc - r, xc, yc + r);
769 }
770 
771 /*
772  * Convert a gerber image to a GDK clip mask to be used when creating pixmap
773  */
774 int
775 draw_gdk_image_to_pixmap(
776  GdkPixmap** pixmap, gerbv_image_t* image, double scale, double trans_x, double trans_y, enum draw_mode drawMode,
777  gerbv_selection_info_t* selectionInfo, gerbv_render_info_t* renderInfo, gerbv_user_transformation_t transform
778 ) {
779  const int hole_cross_inc_px = 8;
780  GdkGC* gc = gdk_gc_new(*pixmap);
781  GdkGC* pgc = gdk_gc_new(*pixmap);
782  GdkGCValues gc_values;
783  struct gerbv_net* net;
784  gerbv_netstate_t* oldState;
785  gerbv_layer_t* oldLayer;
786  gint x1, y1, x2, y2;
787  glong xlong1, ylong1, xlong2, ylong2;
788  int p1, p2;
789  double cir_width = 0, cir_height = 0;
790  int cp_x = 0, cp_y = 0;
791  GdkColor transparent, opaque;
792  gerbv_polarity_t polarity;
793  gdouble tempX, tempY, r;
794  gdouble minX = 0, minY = 0, maxX = 0, maxY = 0;
795 
796  if (image == NULL || image->netlist == NULL) {
797  gdk_gc_unref(gc);
798  gdk_gc_unref(pgc);
799 
800  return 0;
801  }
802 
803  if (transform.inverted) {
804  if (image->info->polarity == GERBV_POLARITY_POSITIVE)
805  polarity = GERBV_POLARITY_NEGATIVE;
806  else
807  polarity = GERBV_POLARITY_POSITIVE;
808  } else {
809  polarity = image->info->polarity;
810  }
811  if (drawMode == DRAW_SELECTIONS)
812  polarity = GERBV_POLARITY_POSITIVE;
813 
814  gboolean useOptimizations = TRUE;
815  // if the user is using any transformations for this layer, then don't bother using rendering
816  // optimizations
817  if (fabs(transform.translateX) > GERBV_PRECISION_LINEAR_INCH
818  || fabs(transform.translateY) > GERBV_PRECISION_LINEAR_INCH
819  || fabs(transform.scaleX - 1) > GERBV_PRECISION_LINEAR_INCH
820  || fabs(transform.scaleY - 1) > GERBV_PRECISION_LINEAR_INCH
821  || fabs(transform.rotation) > GERBV_PRECISION_ANGLE_RAD || transform.mirrorAroundX || transform.mirrorAroundY)
822  useOptimizations = FALSE;
823 
824  // calculate the transformation matrix for the user_transformation options
825  cairo_matrix_t fullMatrix, scaleMatrix;
826  cairo_matrix_init(&fullMatrix, 1, 0, 0, 1, 0, 0);
827  cairo_matrix_init(&scaleMatrix, 1, 0, 0, 1, 0, 0);
828 
829  cairo_matrix_translate(&fullMatrix, trans_x, trans_y);
830  cairo_matrix_scale(&fullMatrix, scale, scale);
831  cairo_matrix_scale(&scaleMatrix, scale, scale);
832  /* offset image */
833 
834  cairo_matrix_translate(&fullMatrix, transform.translateX, -1 * transform.translateY);
835  // don't use mirroring for the scale matrix
836  gdouble scaleX = transform.scaleX;
837  gdouble scaleY = -1 * transform.scaleY;
838  cairo_matrix_scale(&scaleMatrix, scaleX, -1 * scaleY);
839  if (transform.mirrorAroundX)
840  scaleY *= -1;
841  if (transform.mirrorAroundY)
842  scaleX *= -1;
843 
844  cairo_matrix_scale(&fullMatrix, scaleX, scaleY);
845  /* do image rotation */
846  cairo_matrix_rotate(&fullMatrix, transform.rotation);
847  // cairo_matrix_rotate (&scaleMatrix, transform.rotation);
848 
849  /* do image rotation */
850  cairo_matrix_rotate(&fullMatrix, image->info->imageRotation);
851 
852  if (useOptimizations) {
853  minX = renderInfo->lowerLeftX;
854  minY = renderInfo->lowerLeftY;
855  maxX = renderInfo->lowerLeftX + (renderInfo->displayWidth / renderInfo->scaleFactorX);
856  maxY = renderInfo->lowerLeftY + (renderInfo->displayHeight / renderInfo->scaleFactorY);
857  }
858 
859  /* Set up the two "colors" we have */
860  opaque.pixel = 0; /* opaque will not let color through */
861  transparent.pixel = 1; /* transparent will let color through */
862 
863  /*
864  * Clear clipmask and set draw color depending image on image polarity
865  */
866  if (polarity == GERBV_POLARITY_NEGATIVE) {
867  gdk_gc_set_foreground(gc, &transparent);
868  gdk_draw_rectangle(*pixmap, gc, TRUE, 0, 0, -1, -1);
869  gdk_gc_set_foreground(gc, &opaque);
870  } else {
871  gdk_gc_set_foreground(gc, &opaque);
872  gdk_draw_rectangle(*pixmap, gc, TRUE, 0, 0, -1, -1);
873  gdk_gc_set_foreground(gc, &transparent);
874  }
875  oldLayer = image->layers;
876  oldState = image->states;
877  for (net = image->netlist->next; net != NULL; net = gerbv_image_return_next_renderable_object(net)) {
878  int repeat_X = 1, repeat_Y = 1;
879  double repeat_dist_X = 0.0, repeat_dist_Y = 0.0;
880  int repeat_i, repeat_j;
881 
882  /*
883  * If step_and_repeat (%SR%) used, repeat the drawing;
884  */
885  repeat_X = net->layer->stepAndRepeat.X;
886  repeat_Y = net->layer->stepAndRepeat.Y;
887  repeat_dist_X = net->layer->stepAndRepeat.dist_X;
888  repeat_dist_Y = net->layer->stepAndRepeat.dist_Y;
889 
890  /* check if this is a new netstate */
891  if (net->state != oldState) {
892  /* it's a new state, so recalculate the new transformation matrix
893  for it */
894  draw_gdk_apply_netstate_transformation(&fullMatrix, &scaleMatrix, net->state);
895  oldState = net->state;
896  }
897  /* check if this is a new layer */
898  /* for now, only do layer rotations in GDK rendering */
899  if (net->layer != oldLayer) {
900  cairo_matrix_rotate(&fullMatrix, net->layer->rotation);
901  oldLayer = net->layer;
902  }
903 
904  if (drawMode == DRAW_SELECTIONS) {
905  gboolean foundNet = FALSE;
906  gerbv_selection_item_t sItem;
907 
908  for (guint i = 0; i < selectionInfo->selectedNodeArray->len; i++) {
909  sItem = g_array_index(selectionInfo->selectedNodeArray, gerbv_selection_item_t, i);
910  if (sItem.net == net) {
911  foundNet = TRUE;
912  break;
913  }
914  }
915  if (!foundNet)
916  continue;
917  }
918 
919  for (repeat_i = 0; repeat_i < repeat_X; repeat_i++) {
920  for (repeat_j = 0; repeat_j < repeat_Y; repeat_j++) {
921  double sr_x = repeat_i * repeat_dist_X;
922  double sr_y = repeat_j * repeat_dist_Y;
923 
924  if ((useOptimizations)
925  && ((net->boundingBox.right + sr_x < minX) || (net->boundingBox.left + sr_x > maxX)
926  || (net->boundingBox.top + sr_y < minY) || (net->boundingBox.bottom + sr_y > maxY))) {
927  continue;
928  }
929 
930  /*
931  * If circle segment, scale and translate that one too
932  */
933  if (net->cirseg) {
934  tempX = net->cirseg->width;
935  tempY = net->cirseg->height;
936  cairo_matrix_transform_point(&scaleMatrix, &tempX, &tempY);
937 
938  /* Variables can be negative after transformation */
939  tempX = fabs(tempX);
940  tempY = fabs(tempY);
941  cir_width = tempX;
942  cir_height = tempY;
943 
944  tempX = net->cirseg->cp_x;
945  tempY = net->cirseg->cp_y;
946  cairo_matrix_transform_point(&fullMatrix, &tempX, &tempY);
947  cp_x = (int)round(tempX);
948  cp_y = (int)round(tempY);
949  }
950 
951  /*
952  * Set GdkFunction depending on if this (gerber) layer is inverted
953  * and allow for the photoplot being negative.
954  */
955  gdk_gc_set_function(gc, GDK_COPY);
956  if ((net->layer->polarity == GERBV_POLARITY_CLEAR) != (polarity == GERBV_POLARITY_NEGATIVE))
957  gdk_gc_set_foreground(gc, &opaque);
958  else
959  gdk_gc_set_foreground(gc, &transparent);
960 
961  /*
962  * Polygon Area Fill routines
963  */
964  switch (net->interpolation) {
966  draw_gdk_render_polygon_object(
967  net, image, sr_x, sr_y, &fullMatrix, &scaleMatrix, gc, pgc, pixmap
968  );
969  continue;
970  /* make sure we completely skip over any deleted nodes */
971  case GERBV_INTERPOLATION_DELETED: continue;
972  default: break;
973  }
974 
975  /*
976  * If aperture state is off we allow use of undefined apertures.
977  * This happens when gerber files starts, but hasn't decided on
978  * which aperture to use.
979  */
980  if (image->aperture[net->aperture] == NULL) {
981  /* Commenting this out since it gets emitted every time you click on the screen
982  if (net->aperture_state != GERBV_APERTURE_STATE_OFF)
983  GERB_MESSAGE("Aperture D%d is not defined", net->aperture);
984  */
985  continue;
986  }
987 
988  /*
989  * Scale points with window scaling and translate them
990  */
991  tempX = net->start_x + sr_x;
992  tempY = net->start_y + sr_y;
993  cairo_matrix_transform_point(&fullMatrix, &tempX, &tempY);
994  xlong1 = (int)round(tempX);
995  ylong1 = (int)round(tempY);
996 
997  tempX = net->stop_x + sr_x;
998  tempY = net->stop_y + sr_y;
999  cairo_matrix_transform_point(&fullMatrix, &tempX, &tempY);
1000  xlong2 = (int)round(tempX);
1001  ylong2 = (int)round(tempY);
1002 
1003  /* if the object is way outside our view window, just skip over it in order
1004  to eliminate some GDK clipping problems at high zoom levels */
1005  if ((xlong1 < -10000) && (xlong2 < -10000))
1006  continue;
1007  if ((ylong1 < -10000) && (ylong2 < -10000))
1008  continue;
1009  if ((xlong1 > 10000) && (xlong2 > 10000))
1010  continue;
1011  if ((ylong1 > 10000) && (ylong2 > 10000))
1012  continue;
1013 
1014  if (xlong1 > G_MAXINT)
1015  x1 = G_MAXINT;
1016  else if (xlong1 < G_MININT)
1017  x1 = G_MININT;
1018  else
1019  x1 = (int)xlong1;
1020 
1021  if (xlong2 > G_MAXINT)
1022  x2 = G_MAXINT;
1023  else if (xlong2 < G_MININT)
1024  x2 = G_MININT;
1025  else
1026  x2 = (int)xlong2;
1027 
1028  if (ylong1 > G_MAXINT)
1029  y1 = G_MAXINT;
1030  else if (ylong1 < G_MININT)
1031  y1 = G_MININT;
1032  else
1033  y1 = (int)ylong1;
1034 
1035  if (ylong2 > G_MAXINT)
1036  y2 = G_MAXINT;
1037  else if (ylong2 < G_MININT)
1038  y2 = G_MININT;
1039  else
1040  y2 = (int)ylong2;
1041 
1042  switch (net->aperture_state) {
1044  tempX = image->aperture[net->aperture]->parameter[0];
1045  cairo_matrix_transform_point(&scaleMatrix, &tempX, &tempY);
1046 
1047  /* Variables can be negative after transformation */
1048  tempX = fabs(tempX);
1049  p1 = (int)round(tempX);
1050 
1051  gdk_gc_set_line_attributes(
1052  gc, p1, GDK_LINE_SOLID,
1053  (image->aperture[net->aperture]->type == GERBV_APTYPE_RECTANGLE) ? GDK_CAP_PROJECTING
1054  : GDK_CAP_ROUND,
1055  GDK_JOIN_MITER
1056  );
1057 
1058  switch (net->interpolation) {
1062  GERB_MESSAGE(_("Linear != x1"));
1063  gdk_gc_set_line_attributes(gc, p1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_MITER);
1064  gdk_draw_line(*pixmap, gc, x1, y1, x2, y2);
1065  gdk_gc_set_line_attributes(gc, p1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_MITER);
1066  break;
1068  if (image->aperture[net->aperture]->type != GERBV_APTYPE_RECTANGLE) {
1069  gdk_draw_line(*pixmap, gc, x1, y1, x2, y2);
1070 
1071  if (renderInfo->show_cross_on_drill_holes
1072  && image->layertype == GERBV_LAYERTYPE_DRILL) {
1073  /* Draw crosses on drill slot start and end */
1074  r = p1 / 2.0 + hole_cross_inc_px;
1075  draw_gdk_cross(*pixmap, gc, x1, y1, r);
1076  draw_gdk_cross(*pixmap, gc, x2, y2, r);
1077  }
1078  break;
1079  }
1080 
1081  gint dx, dy;
1082  GdkPoint poly[6];
1083 
1084  tempX = image->aperture[net->aperture]->parameter[0] / 2;
1085  tempY = image->aperture[net->aperture]->parameter[1] / 2;
1086  cairo_matrix_transform_point(&scaleMatrix, &tempX, &tempY);
1087  dx = (int)round(tempX);
1088  dy = (int)round(tempY);
1089 
1090  if (x1 > x2)
1091  dx = -dx;
1092  if (y1 > y2)
1093  dy = -dy;
1094  poly[0].x = x1 - dx;
1095  poly[0].y = y1 - dy;
1096  poly[1].x = x1 - dx;
1097  poly[1].y = y1 + dy;
1098  poly[2].x = x2 - dx;
1099  poly[2].y = y2 + dy;
1100  poly[3].x = x2 + dx;
1101  poly[3].y = y2 + dy;
1102  poly[4].x = x2 + dx;
1103  poly[4].y = y2 - dy;
1104  poly[5].x = x1 + dx;
1105  poly[5].y = y1 - dy;
1106  gdk_draw_polygon(*pixmap, gc, 1, poly, 6);
1107  break;
1108 
1111  gerbv_gdk_draw_arc(
1112  *pixmap, gc, cp_x, cp_y, cir_width, cir_height,
1113  net->cirseg->angle1 + RAD2DEG(transform.rotation),
1114  net->cirseg->angle2 + RAD2DEG(transform.rotation)
1115  );
1116  break;
1117  default:
1118  GERB_COMPILE_WARNING(_("Skipped interpolation type %d"), net->interpolation);
1119  break;
1120  }
1121  break;
1122  case GERBV_APERTURE_STATE_OFF: break;
1124  tempX = image->aperture[net->aperture]->parameter[0];
1125  tempY = image->aperture[net->aperture]->parameter[1];
1126  cairo_matrix_transform_point(&scaleMatrix, &tempX, &tempY);
1127 
1128  /* Variables can be negative after transformation */
1129  tempX = fabs(tempX);
1130  tempY = fabs(tempY);
1131  p1 = (int)round(tempX);
1132  p2 = (int)round(tempY);
1133 
1134  switch (image->aperture[net->aperture]->type) {
1135  case GERBV_APTYPE_CIRCLE:
1136  gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p1);
1137 
1138  if (renderInfo->show_cross_on_drill_holes
1139  && image->layertype == GERBV_LAYERTYPE_DRILL) {
1140  r = p1 / 2.0 + hole_cross_inc_px;
1141  draw_gdk_cross(*pixmap, gc, x2, y2, r);
1142  }
1143 
1144  /*
1145  * If circle has an inner diameter we must remove
1146  * that part of the circle to make a hole in it.
1147  * We should actually support square holes too,
1148  * but due to laziness I don't.
1149  */
1150  if (p2) {
1151  gdk_gc_get_values(gc, &gc_values);
1152  if (gc_values.foreground.pixel == opaque.pixel) {
1153  gdk_gc_set_foreground(gc, &transparent);
1154  gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p2);
1155  gdk_gc_set_foreground(gc, &opaque);
1156  } else {
1157  gdk_gc_set_foreground(gc, &opaque);
1158  gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p2);
1159  gdk_gc_set_foreground(gc, &transparent);
1160  }
1161  }
1162 
1163  break;
1165  gerbv_gdk_draw_rectangle(
1166  *pixmap, gc, TRUE, x2, y2, p1, p2,
1167  RAD2DEG(transform.rotation + image->info->imageRotation)
1168  );
1169  break;
1170  case GERBV_APTYPE_OVAL:
1171  gerbv_gdk_draw_oval(
1172  *pixmap, gc, TRUE, x2, y2, p1, p2,
1173  RAD2DEG(transform.rotation + image->info->imageRotation)
1174  );
1175  break;
1176  case GERBV_APTYPE_POLYGON:
1177  /* TODO: gdk_draw_polygon() */
1178  gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p1);
1179  break;
1180  case GERBV_APTYPE_MACRO:
1181  /* TODO: check line22 and others */
1182  gerbv_gdk_draw_amacro(
1183  *pixmap, gc, image->aperture[net->aperture]->simplified, scale, x2, y2
1184  );
1185  break;
1186  default:
1187  GERB_MESSAGE(_("Unknown aperture type %d"), image->aperture[net->aperture]->type);
1188  return 0;
1189  }
1190  break;
1191  default: GERB_MESSAGE(_("Unknown aperture state %d"), net->aperture_state); return 0;
1192  }
1193  }
1194  }
1195  }
1196  /*
1197  * Destroy GCs before exiting
1198  */
1199  gdk_gc_unref(gc);
1200  gdk_gc_unref(pgc);
1201 
1202  return 1;
1203 
1204 } /* image2pixmap */
Contains basic defines.
Header info for the GDK rendering functions.
gerbv_net_t * gerbv_image_return_next_renderable_object(gerbv_net_t *oldNet)
Return the next net entry which corresponds to a unique visible object.
Definition: gerb_image.c:1259
const char * gerbv_aperture_type_name(gerbv_aperture_type_t type)
Return string name of gerbv_aperture_type_t aperture type.
Definition: gerbv.c:72
The main header file for the libgerbv library.
@ GERBV_APERTURE_STATE_OFF
Definition: gerbv.h:171
@ GERBV_APERTURE_STATE_ON
Definition: gerbv.h:172
@ GERBV_APERTURE_STATE_FLASH
Definition: gerbv.h:173
gerbv_polarity_t
Definition: gerbv.h:269
@ GERBV_POLARITY_CLEAR
Definition: gerbv.h:273
@ GERBV_POLARITY_NEGATIVE
Definition: gerbv.h:271
@ GERBV_POLARITY_POSITIVE
Definition: gerbv.h:270
@ GERBV_APTYPE_MACRO_LINE20
Definition: gerbv.h:162
@ GERBV_APTYPE_MACRO_LINE21
Definition: gerbv.h:163
@ GERBV_APTYPE_OVAL
Definition: gerbv.h:154
@ GERBV_APTYPE_MACRO_OUTLINE
Definition: gerbv.h:158
@ GERBV_APTYPE_MACRO_CIRCLE
Definition: gerbv.h:157
@ GERBV_APTYPE_MACRO
Definition: gerbv.h:156
@ GERBV_APTYPE_CIRCLE
Definition: gerbv.h:152
@ GERBV_APTYPE_POLYGON
Definition: gerbv.h:155
@ GERBV_APTYPE_MACRO_POLYGON
Definition: gerbv.h:159
@ GERBV_APTYPE_RECTANGLE
Definition: gerbv.h:153
@ GERBV_APTYPE_MACRO_THERMAL
Definition: gerbv.h:161
@ GERBV_APTYPE_MACRO_LINE22
Definition: gerbv.h:164
@ GERBV_APTYPE_MACRO_MOIRE
Definition: gerbv.h:160
@ GERBV_INTERPOLATION_LINEARx01
Definition: gerbv.h:296
@ GERBV_INTERPOLATION_PAREA_START
Definition: gerbv.h:300
@ GERBV_INTERPOLATION_LINEARx001
Definition: gerbv.h:297
@ GERBV_INTERPOLATION_DELETED
Definition: gerbv.h:302
@ GERBV_INTERPOLATION_CW_CIRCULAR
Definition: gerbv.h:298
@ GERBV_INTERPOLATION_PAREA_END
Definition: gerbv.h:301
@ GERBV_INTERPOLATION_LINEARx10
Definition: gerbv.h:295
@ GERBV_INTERPOLATION_CCW_CIRCULAR
Definition: gerbv.h:299
@ GERBV_INTERPOLATION_LINEARx1
Definition: gerbv.h:294
@ GERBV_LAYERTYPE_DRILL
Definition: gerbv.h:324
gerbv_layer_t * layers
Definition: gerbv.h:734
gerbv_layertype_t layertype
Definition: gerbv.h:732
gerbv_net_t * netlist
Definition: gerbv.h:739
gerbv_aperture_t * aperture[APERTURE_MAX]
Definition: gerbv.h:733
gerbv_netstate_t * states
Definition: gerbv.h:735
gerbv_image_info_t * info
Definition: gerbv.h:738
gerbv_step_and_repeat_t stepAndRepeat
Definition: gerbv.h:646
gerbv_polarity_t polarity
Definition: gerbv.h:649
gdouble rotation
Definition: gerbv.h:648
gerbv_render_size_t boundingBox
Definition: gerbv.h:672
gerbv_layer_t * layer
Definition: gerbv.h:679
double stop_y
Definition: gerbv.h:671
gerbv_aperture_state_t aperture_state
Definition: gerbv.h:674
double stop_x
Definition: gerbv.h:670
double start_x
Definition: gerbv.h:668
gerbv_netstate_t * state
Definition: gerbv.h:680
struct gerbv_net * next
Definition: gerbv.h:677
double start_y
Definition: gerbv.h:669
gerbv_interpolation_t interpolation
Definition: gerbv.h:675
gerbv_cirseg_t * cirseg
Definition: gerbv.h:676
int aperture
Definition: gerbv.h:673
gdouble offsetB
Definition: gerbv.h:660
gdouble scaleA
Definition: gerbv.h:661
gdouble scaleB
Definition: gerbv.h:662
gerbv_axis_select_t axisSelect
Definition: gerbv.h:656
gdouble offsetA
Definition: gerbv.h:659
gerbv_mirror_state_t mirrorState
Definition: gerbv.h:657
gdouble lowerLeftY
Definition: gerbv.h:788
gboolean show_cross_on_drill_holes
Definition: gerbv.h:792
gdouble scaleFactorX
Definition: gerbv.h:785
gint displayHeight
Definition: gerbv.h:791
gdouble lowerLeftX
Definition: gerbv.h:787
gdouble scaleFactorY
Definition: gerbv.h:786