gerbv  2.10.1-dev~93f1b5
render.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  *
4  * render.c -- this file is a part of gerbv.
5  *
6  * Copyright (C) 2007 Stuart Brorson (SDB@cloud9.net)
7  *
8  * $Id$
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
30 #include "gerbv.h"
31 
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35 
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #endif
39 
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 
44 #ifdef HAVE_LIBGEN_H
45 #include <libgen.h> /* dirname */
46 #endif
47 
48 #include <math.h>
49 
50 #include "common.h"
51 #include "main.h"
52 #include "callbacks.h"
53 #include "interface.h"
54 #include "render.h"
55 #include "selection.h"
56 
57 #ifdef WIN32
58 #include <cairo-win32.h>
59 #elif QUARTZ
60 #include <cairo-quartz.h>
61 #else
62 #include <cairo-xlib.h>
63 #endif
64 #include "draw.h"
65 
66 #define dprintf \
67  if (DEBUG) \
68  printf
69 
70 gerbv_render_info_t screenRenderInfo;
71 
72 /* ------------------------------------------------------ */
73 void
74 render_zoom_display(gint zoomType, gdouble scaleFactor, gdouble mouseX, gdouble mouseY) {
75  gdouble mouseCoordinateX = 0.0;
76  gdouble mouseCoordinateY = 0.0;
77  double oldWidth, oldHeight;
78 
79  oldWidth = screenRenderInfo.displayWidth / screenRenderInfo.scaleFactorX;
80  oldHeight = screenRenderInfo.displayHeight / screenRenderInfo.scaleFactorY;
81 
82  if (zoomType == ZOOM_IN_CMOUSE || zoomType == ZOOM_OUT_CMOUSE) {
83  /* calculate what user coordinate the mouse is pointing at */
84  mouseCoordinateX = mouseX / screenRenderInfo.scaleFactorX + screenRenderInfo.lowerLeftX;
85  mouseCoordinateY =
86  (screenRenderInfo.displayHeight - mouseY) / screenRenderInfo.scaleFactorY + screenRenderInfo.lowerLeftY;
87  }
88 
89  switch (zoomType) {
90  case ZOOM_IN: /* Zoom In */
91  case ZOOM_IN_CMOUSE: /* Zoom In Around Mouse Pointer */
92  screenRenderInfo.scaleFactorX =
93  MIN((gdouble)GERBV_SCALE_MAX, (1 + 1 / 3.0) * screenRenderInfo.scaleFactorX);
94  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
95  screenRenderInfo.lowerLeftX +=
96  (oldWidth - (screenRenderInfo.displayWidth / screenRenderInfo.scaleFactorX)) / 2.0;
97  screenRenderInfo.lowerLeftY +=
98  (oldHeight - (screenRenderInfo.displayHeight / screenRenderInfo.scaleFactorY)) / 2.0;
99  break;
100  case ZOOM_OUT: /* Zoom Out */
101  case ZOOM_OUT_CMOUSE: /* Zoom Out Around Mouse Pointer */
102  screenRenderInfo.scaleFactorX =
103  MAX((gdouble)GERBV_SCALE_MIN, (1 - 1 / 3.0) * screenRenderInfo.scaleFactorX);
104  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
105  screenRenderInfo.lowerLeftX +=
106  (oldWidth - (screenRenderInfo.displayWidth / screenRenderInfo.scaleFactorX)) / 2.0;
107  screenRenderInfo.lowerLeftY +=
108  (oldHeight - (screenRenderInfo.displayHeight / screenRenderInfo.scaleFactorY)) / 2.0;
109  break;
110  case ZOOM_FIT: /* Zoom Fit */ gerbv_render_zoom_to_fit_display(mainProject, &screenRenderInfo); break;
111  case ZOOM_SET: /*explicit scale set by user */
112  screenRenderInfo.scaleFactorX = MIN((gdouble)GERBV_SCALE_MAX, scaleFactor);
113  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
114  screenRenderInfo.lowerLeftX +=
115  (oldWidth - (screenRenderInfo.displayWidth / screenRenderInfo.scaleFactorX)) / 2.0;
116  screenRenderInfo.lowerLeftY +=
117  (oldHeight - (screenRenderInfo.displayHeight / screenRenderInfo.scaleFactorY)) / 2.0;
118  break;
119  default: GERB_MESSAGE(_("Illegal zoom direction %d"), zoomType);
120  }
121 
122  if (zoomType == ZOOM_IN_CMOUSE || zoomType == ZOOM_OUT_CMOUSE) {
123  /* make sure the mouse is still pointing at the point calculated earlier */
124  screenRenderInfo.lowerLeftX = mouseCoordinateX - mouseX / screenRenderInfo.scaleFactorX;
125  screenRenderInfo.lowerLeftY =
126  mouseCoordinateY - (screenRenderInfo.displayHeight - mouseY) / screenRenderInfo.scaleFactorY;
127  }
128  render_refresh_rendered_image_on_screen();
129  return;
130 }
131 
132 /* --------------------------------------------------------- */
138 void
139 render_calculate_zoom_from_outline(GtkWidget* widget, GdkEventButton* event) {
140  int x1, y1, x2, y2, dx, dy; /* Zoom outline (UR and LL corners) */
141  double centerPointX, centerPointY;
142  int half_x, half_y; /* cache for half window dimensions */
143 
144  x1 = MIN((gdouble)screen.start_x, event->x);
145  y1 = MIN((gdouble)screen.start_y, event->y);
146  x2 = MAX((gdouble)screen.start_x, event->x);
147  y2 = MAX((gdouble)screen.start_y, event->y);
148  dx = x2 - x1;
149  dy = y2 - y1;
150 
151  if ((dx >= 4) && (dy >= 4)) {
152  if (screen.centered_outline_zoom) {
153  /* Centered outline mode */
154  x1 = screen.start_x - dx;
155  y1 = screen.start_y - dy;
156  dx *= 2;
157  dy *= 2;
158  }
159  half_x = (x1 + x2) / 2;
160  half_y = (y1 + y2) / 2;
161  centerPointX = half_x / screenRenderInfo.scaleFactorX + screenRenderInfo.lowerLeftX;
162  centerPointY =
163  (screenRenderInfo.displayHeight - half_y) / screenRenderInfo.scaleFactorY + screenRenderInfo.lowerLeftY;
164 
165  screenRenderInfo.scaleFactorX *=
166  MIN((double)screenRenderInfo.displayWidth / dx, (double)screenRenderInfo.displayHeight / dy);
167  screenRenderInfo.scaleFactorX = MIN((gdouble)GERBV_SCALE_MAX, screenRenderInfo.scaleFactorX);
168  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
169  screenRenderInfo.lowerLeftX =
170  centerPointX - (screenRenderInfo.displayWidth / 2.0 / screenRenderInfo.scaleFactorX);
171  screenRenderInfo.lowerLeftY =
172  centerPointY - (screenRenderInfo.displayHeight / 2.0 / screenRenderInfo.scaleFactorY);
173  }
174  render_refresh_rendered_image_on_screen();
175 }
176 
177 /* ------------------------------------------------------ */
178 void
179 render_draw_selection_box_outline(void) {
180  GdkGC* gc;
181  GdkGCValues values;
182  GdkGCValuesMask values_mask;
183  gint x1, y1, x2, y2, dx, dy;
184 
185  memset(&values, 0, sizeof(values));
186  values.function = GDK_XOR;
187  if (!screen.zoom_outline_color.pixel)
188  gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
189  values.foreground = screen.zoom_outline_color;
190  values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
191  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
192 
193  x1 = MIN(screen.start_x, screen.last_x);
194  y1 = MIN(screen.start_y, screen.last_y);
195  x2 = MAX(screen.start_x, screen.last_x);
196  y2 = MAX(screen.start_y, screen.last_y);
197  dx = x2 - x1;
198  dy = y2 - y1;
199 
200  gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, x1, y1, dx, dy);
201  gdk_gc_unref(gc);
202 }
203 
204 /* --------------------------------------------------------- */
205 void
206 render_draw_zoom_outline(gboolean centered) {
207  GdkGC* gc;
208  GdkGCValues values;
209  GdkGCValuesMask values_mask;
210  gint x1, y1, x2, y2, dx, dy;
211 
212  memset(&values, 0, sizeof(values));
213  values.function = GDK_XOR;
214  if (!screen.zoom_outline_color.pixel)
215  gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
216  values.foreground = screen.zoom_outline_color;
217  values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
218  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
219 
220  x1 = MIN(screen.start_x, screen.last_x);
221  y1 = MIN(screen.start_y, screen.last_y);
222  x2 = MAX(screen.start_x, screen.last_x);
223  y2 = MAX(screen.start_y, screen.last_y);
224  dx = x2 - x1;
225  dy = y2 - y1;
226 
227  if (centered) {
228  /* Centered outline mode */
229  x1 = screen.start_x - dx;
230  y1 = screen.start_y - dy;
231  dx *= 2;
232  dy *= 2;
233  x2 = x1 + dx;
234  y2 = y1 + dy;
235  }
236 
237  gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, x1, y1, dx, dy);
238  gdk_gc_unref(gc);
239 
240  /* Draw actual zoom area in dashed lines */
241  memset(&values, 0, sizeof(values));
242  values.function = GDK_XOR;
243  values.foreground = screen.zoom_outline_color;
244  values.line_style = GDK_LINE_ON_OFF_DASH;
245  values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND | GDK_GC_LINE_STYLE;
246  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
247 
248  if ((dy == 0)
249  || ((double)dx / dy > (double)screen.drawing_area->allocation.width / screen.drawing_area->allocation.height)) {
250  dy = dx * (double)screen.drawing_area->allocation.height / screen.drawing_area->allocation.width;
251  } else {
252  dx = dy * (double)screen.drawing_area->allocation.width / screen.drawing_area->allocation.height;
253  }
254 
255  gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, (x1 + x2 - dx) / 2, (y1 + y2 - dy) / 2, dx, dy);
256 
257  gdk_gc_unref(gc);
258 }
259 
260 /* ------------------------------------------------------ */
261 /* Transforms board coordinates to screen ones */
262 static void
263 render_board2screen(gdouble* X, gdouble* Y, gdouble x, gdouble y) {
264  *X = (x - screenRenderInfo.lowerLeftX) * screenRenderInfo.scaleFactorX;
265  *Y = screenRenderInfo.displayHeight - (y - screenRenderInfo.lowerLeftY) * screenRenderInfo.scaleFactorY;
266 }
267 
268 /* Trims the coordinates to avoid overflows in gdk_draw_line */
269 static void
270 render_trim_point(gdouble* start_x, gdouble* start_y, gdouble last_x, gdouble last_y) {
271  const gdouble max_coord = (1 << 15) - 2; /* a value that causes no overflow
272  and lies out of screen */
273  gdouble dx, dy;
274 
275  if (fabs(*start_x) < max_coord && fabs(*start_y) < max_coord)
276  return;
277 
278  dx = last_x - *start_x;
279  dy = last_y - *start_y;
280 
281  if (*start_x < -max_coord) {
282  *start_x = -max_coord;
283  if (last_x > -max_coord && fabs(dx) > 0.1)
284  *start_y = last_y - (last_x + max_coord) / dx * dy;
285  }
286  if (*start_x > max_coord) {
287  *start_x = max_coord;
288  if (last_x < max_coord && fabs(dx) > 0.1)
289  *start_y = last_y - (last_x - max_coord) / dx * dy;
290  }
291 
292  dx = last_x - *start_x;
293  dy = last_y - *start_y;
294 
295  if (*start_y < -max_coord) {
296  *start_y = -max_coord;
297  if (last_y > -max_coord && fabs(dy) > 0.1)
298  *start_x = last_x - (last_y + max_coord) / dy * dx;
299  }
300  if (*start_y > max_coord) {
301  *start_y = max_coord;
302  if (last_y < max_coord && fabs(dy) > 0.1)
303  *start_x = last_x - (last_y - max_coord) / dy * dx;
304  }
305 }
306 
307 /* ------------------------------------------------------ */
310 void
312 
313  GdkGC* gc;
314  GdkGCValues values;
315  GdkGCValuesMask values_mask;
316  gdouble start_x, start_y, last_x, last_y;
317  memset(&values, 0, sizeof(values));
318  values.function = GDK_XOR;
319  values.line_width = 6;
320  if (!screen.zoom_outline_color.pixel)
321  gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
322  values.foreground = screen.zoom_outline_color;
323  values_mask = GDK_GC_FUNCTION | GDK_GC_LINE_WIDTH | GDK_GC_FOREGROUND;
324  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
325  render_board2screen(&start_x, &start_y, screen.measure_start_x, screen.measure_start_y);
326  render_board2screen(&last_x, &last_y, screen.measure_stop_x, screen.measure_stop_y);
327  render_trim_point(&start_x, &start_y, last_x, last_y);
328  render_trim_point(&last_x, &last_y, start_x, start_y);
329  gdk_draw_line(screen.drawing_area->window, gc, start_x, start_y, last_x, last_y);
330  gdk_gc_unref(gc);
331 } /* toggle_measure_line */
332 
333 /* ------------------------------------------------------ */
335 void
337  gdouble dx, dy;
338 
339  dx = fabs(screen.measure_start_x - screen.measure_stop_x);
340  dy = fabs(screen.measure_start_y - screen.measure_stop_y);
341 
342  screen.measure_last_x = dx;
343  screen.measure_last_y = dy;
344  callbacks_update_statusbar_measured_distance(dx, dy);
346 }
347 
348 /* ------------------------------------------------------ */
349 static void
350 render_selection(void) {
351  gerbv_selection_item_t sel_item;
352  gerbv_fileinfo_t* file;
353  gdouble pixel_width;
354  cairo_t* cr;
355  int i;
356  guint j;
357 
358  if (selection_length(&screen.selectionInfo) == 0)
359  return;
360 
361  if (screen.selectionRenderData)
362  cairo_surface_destroy((cairo_surface_t*)screen.selectionRenderData);
363 
364  screen.selectionRenderData = (gpointer)cairo_surface_create_similar(
365  (cairo_surface_t*)screen.windowSurface, CAIRO_CONTENT_COLOR_ALPHA, screenRenderInfo.displayWidth,
366  screenRenderInfo.displayHeight
367  );
368 
369  pixel_width = 1.0 / MAX(screenRenderInfo.scaleFactorX, screenRenderInfo.scaleFactorY);
370 
371  for (i = mainProject->last_loaded; i >= 0; i--) {
372  file = mainProject->file[i];
373 
374  if (!file || (!mainProject->show_invisible_selection && !file->isVisible))
375  continue;
376 
377  for (j = 0; j < selection_length(&screen.selectionInfo); j++) {
378  sel_item = selection_get_item_by_index(&screen.selectionInfo, j);
379  if (file->image != sel_item.image)
380  continue;
381 
382  /* Have selected image(s) on this file, draw it */
383 
384  cr = cairo_create(screen.selectionRenderData);
385  gerbv_render_cairo_set_scale_and_translation(cr, &screenRenderInfo);
386  cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.85);
387  draw_image_to_cairo_target(
388  cr, file->image, pixel_width, DRAW_SELECTIONS, &screen.selectionInfo, &screenRenderInfo, TRUE,
389  file->transform, TRUE
390  );
391  cairo_destroy(cr);
392 
393  break; /* All done, go to next file */
394  }
395  }
396 }
397 
398 /* ------------------------------------------------------ */
399 void
400 render_refresh_rendered_image_on_screen(void) {
401  GdkCursor* cursor;
402 
403  dprintf("----> Entering redraw_pixmap...\n");
404  cursor = gdk_cursor_new(GDK_WATCH);
405  gdk_window_set_cursor(GDK_WINDOW(screen.drawing_area->window), cursor);
406  gdk_cursor_destroy(cursor);
407 
408  if (screenRenderInfo.renderType <= GERBV_RENDER_TYPE_GDK_XOR) {
409  if (screen.pixmap)
410  gdk_pixmap_unref(screen.pixmap);
411  screen.pixmap = gdk_pixmap_new(
412  screen.drawing_area->window, screenRenderInfo.displayWidth, screenRenderInfo.displayHeight, -1
413  );
414  gerbv_render_to_pixmap_using_gdk(
415  mainProject, screen.pixmap, &screenRenderInfo, &screen.selectionInfo, &screen.selection_color
416  );
417  dprintf("<---- leaving redraw_pixmap.\n");
418  } else {
419  int i;
420  dprintf(" .... Now try rendering the drawing using cairo .... \n");
421  /*
422  * This now allows drawing several layers on top of each other.
423  * Higher layer numbers have higher priority in the Z-order.
424  */
425  for (i = mainProject->last_loaded; i >= 0; i--) {
426  if (mainProject->file[i]) {
427  cairo_t* cr;
429  cairo_surface_destroy((cairo_surface_t*)mainProject->file[i]->privateRenderData);
430  mainProject->file[i]->privateRenderData = (gpointer)cairo_surface_create_similar(
431  (cairo_surface_t*)screen.windowSurface, CAIRO_CONTENT_COLOR_ALPHA, screenRenderInfo.displayWidth,
432  screenRenderInfo.displayHeight
433  );
434  cr = cairo_create(mainProject->file[i]->privateRenderData);
435  gerbv_render_layer_to_cairo_target(cr, mainProject->file[i], &screenRenderInfo);
436  dprintf(" .... calling render_image_to_cairo_target on layer %d...\n", i);
437  cairo_destroy(cr);
438  }
439  }
440 
441  render_recreate_composite_surface();
442  }
443  /* remove watch cursor and switch back to normal cursor */
444  callbacks_switch_to_correct_cursor();
445  callbacks_force_expose_event_for_screen();
446 }
447 
448 /* ------------------------------------------------------ */
449 void
450 render_remove_selected_objects_belonging_to_layer(gerbv_selection_info_t* sel_info, gerbv_image_t* image) {
451  guint i;
452 
453  for (i = 0; i < selection_length(sel_info);) {
454  gerbv_selection_item_t sItem = selection_get_item_by_index(sel_info, i);
455 
456  if (image == (gerbv_image_t*)sItem.image)
457  selection_clear_item_by_index(sel_info, i);
458  else
459  i++;
460  }
461 }
462 
463 /* ------------------------------------------------------ */
464 gint
465 render_create_cairo_buffer_surface() {
466  if (screen.bufferSurface) {
467  cairo_surface_destroy(screen.bufferSurface);
468  screen.bufferSurface = NULL;
469  }
470  if (!screen.windowSurface)
471  return 0;
472 
473  screen.bufferSurface = cairo_surface_create_similar(
474  (cairo_surface_t*)screen.windowSurface, CAIRO_CONTENT_COLOR, screenRenderInfo.displayWidth,
475  screenRenderInfo.displayHeight
476  );
477  return 1;
478 }
479 
480 /* ------------------------------------------------------ */
481 static void
482 render_find_selected_objects_and_refresh_display(gint activeFileIndex, enum selection_action action) {
483  enum draw_mode mode = FIND_SELECTIONS;
484 
485  /* clear the old selection array if desired */
486  if ((action == SELECTION_REPLACE) && (selection_length(&screen.selectionInfo) != 0))
487  selection_clear(&screen.selectionInfo);
488 
489  if (action == SELECTION_TOGGLE)
490  mode = FIND_SELECTIONS_TOGGLE;
491 
492  /* make sure we have a bufferSurface...if we start up in FAST mode, we may not
493  have one yet, but we need it for selections */
494  if (!render_create_cairo_buffer_surface())
495  return;
496 
497  /* call draw_image... passing the FILL_SELECTION mode to just search for
498  nets which match the selection, and fill the selection buffer with them */
499  cairo_t* cr = cairo_create(screen.bufferSurface);
500  gerbv_render_cairo_set_scale_and_translation(cr, &screenRenderInfo);
501  draw_image_to_cairo_target(
502  cr, mainProject->file[activeFileIndex]->image,
503  1.0 / MAX(screenRenderInfo.scaleFactorX, screenRenderInfo.scaleFactorY), mode, &screen.selectionInfo,
504  &screenRenderInfo, TRUE, mainProject->file[activeFileIndex]->transform, TRUE
505  );
506  cairo_destroy(cr);
507 
508  /* re-render the selection buffer layer */
509  if (screenRenderInfo.renderType <= GERBV_RENDER_TYPE_GDK_XOR) {
510  render_refresh_rendered_image_on_screen();
511  } else {
512  render_recreate_composite_surface();
513  callbacks_force_expose_event_for_screen();
514  }
515 }
516 
517 /* ------------------------------------------------------ */
518 void
519 render_fill_selection_buffer_from_mouse_click(
520  gint mouseX, gint mouseY, gint activeFileIndex, enum selection_action action
521 ) {
522  screen.selectionInfo.lowerLeftX = mouseX;
523  screen.selectionInfo.lowerLeftY = mouseY;
524  /* no need to populate the upperright coordinates for a point_click */
525  screen.selectionInfo.type = GERBV_SELECTION_POINT_CLICK;
526  render_find_selected_objects_and_refresh_display(activeFileIndex, action);
527 }
528 
529 /* ------------------------------------------------------ */
530 void
531 render_fill_selection_buffer_from_mouse_drag(
532  gint corner1X, gint corner1Y, gint corner2X, gint corner2Y, gint activeFileIndex, enum selection_action action
533 ) {
534  /* figure out the lower left corner of the box */
535  screen.selectionInfo.lowerLeftX = MIN(corner1X, corner2X);
536  screen.selectionInfo.lowerLeftY = MIN(corner1Y, corner2Y);
537  /* figure out the upper right corner of the box */
538  screen.selectionInfo.upperRightX = MAX(corner1X, corner2X);
539  screen.selectionInfo.upperRightY = MAX(corner1Y, corner2Y);
540 
541  screen.selectionInfo.type = GERBV_SELECTION_DRAG_BOX;
542  render_find_selected_objects_and_refresh_display(activeFileIndex, action);
543 }
544 
545 /* ------------------------------------------------------ */
546 void
547 render_recreate_composite_surface() {
548  gint i;
549 
550  if (!render_create_cairo_buffer_surface())
551  return;
552 
553  cairo_t* cr = cairo_create(screen.bufferSurface);
554  /* fill the background with the appropriate color */
555  cairo_set_source_rgba(
556  cr, (double)mainProject->background.red / G_MAXUINT16, (double)mainProject->background.green / G_MAXUINT16,
557  (double)mainProject->background.blue / G_MAXUINT16, 1
558  );
559  cairo_paint(cr);
560 
561  for (i = mainProject->last_loaded; i >= 0; i--) {
562  if (mainProject->file[i] && mainProject->file[i]->isVisible) {
563  cairo_set_source_surface(cr, (cairo_surface_t*)mainProject->file[i]->privateRenderData, 0, 0);
564  /* ignore alpha if we are in high-speed render mode */
565  if (((double)mainProject->file[i]->alpha < 65535)
566  && (screenRenderInfo.renderType != GERBV_RENDER_TYPE_GDK_XOR)) {
567  cairo_paint_with_alpha(cr, (double)mainProject->file[i]->alpha / G_MAXUINT16);
568  } else {
569  cairo_paint(cr);
570  }
571  }
572  }
573 
574  /* render the selection layer at the end */
575  if (selection_length(&screen.selectionInfo) != 0) {
576  render_selection();
577  cairo_set_source_surface(cr, (cairo_surface_t*)screen.selectionRenderData, 0, 0);
578  cairo_paint_with_alpha(cr, 1.0);
579  }
580  cairo_destroy(cr);
581 }
582 
583 /* ------------------------------------------------------ */
584 void
585 render_project_to_cairo_target(cairo_t* cr) {
586  /* fill the background with the appropriate color */
587  cairo_set_source_rgba(
588  cr, (double)mainProject->background.red / G_MAXUINT16, (double)mainProject->background.green / G_MAXUINT16,
589  (double)mainProject->background.blue / G_MAXUINT16, 1
590  );
591  cairo_paint(cr);
592 
593  cairo_set_source_surface(cr, (cairo_surface_t*)screen.bufferSurface, 0, 0);
594 
595  cairo_paint(cr);
596 }
597 
598 void
599 render_free_screen_resources(void) {
600  if (screen.selectionRenderData)
601  cairo_surface_destroy((cairo_surface_t*)screen.selectionRenderData);
602  if (screen.bufferSurface)
603  cairo_surface_destroy((cairo_surface_t*)screen.bufferSurface);
604  if (screen.windowSurface)
605  cairo_surface_destroy((cairo_surface_t*)screen.windowSurface);
606  if (screen.pixmap)
607  gdk_pixmap_unref(screen.pixmap);
608 }
609 
610 /* ------------------------------------------------------------------ */
616  int i;
617  gerbv_stats_t* stats;
618  gerbv_stats_t* instats;
619 
620  /* Create new stats structure to hold report for whole project
621  * (i.e. all layers together) */
622  stats = gerbv_stats_new();
623 
624  /* Loop through open layers and compile statistics by accumulating reports from each layer */
625  for (i = 0; i <= mainProject->last_loaded; i++) {
626  if (mainProject->file[i] && mainProject->file[i]->isVisible
628  instats = mainProject->file[i]->image->gerbv_stats;
629  gerbv_stats_add_layer(stats, instats, i + 1);
630  }
631  }
632  return stats;
633 }
634 
635 /* ------------------------------------------------------------------ */
641  int i;
642  gerbv_drill_stats_t* stats;
643  gerbv_drill_stats_t* instats;
644 
645  stats = gerbv_drill_stats_new();
646 
647  /* Loop through open layers and compile statistics by accumulating reports from each layer */
648  for (i = mainProject->last_loaded; i >= 0; i--) {
649  if (mainProject->file[i] && mainProject->file[i]->isVisible
651  instats = mainProject->file[i]->image->drill_stats;
652  /* add this batch of stats. Send the layer
653  * index for error reporting */
654  gerbv_drill_stats_add_layer(stats, instats, i + 1);
655  }
656  }
657  return stats;
658 }
Header info for the GUI callback functions.
Contains basic defines.
Header info for the cairo rendering functions and the related selection calculating functions.
void gerbv_drill_stats_add_layer(gerbv_drill_stats_t *accum_stats, gerbv_drill_stats_t *input_stats, int this_layer)
Definition: drill_stats.c:111
gerbv_drill_stats_t * gerbv_drill_stats_new(void)
Allocates a new drill_stats structure.
Definition: drill_stats.c:48
gerbv_stats_t * gerbv_stats_new(void)
Allocates a new gerbv_stats structure.
Definition: gerb_stats.c:46
void gerbv_stats_add_layer(gerbv_stats_t *accum_stats, gerbv_stats_t *input_stats, int this_layer)
Definition: gerb_stats.c:121
void gerbv_render_zoom_to_fit_display(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo)
Calculate the zoom and translations to fit the rendered scene inside the given scene size.
Definition: gerbv.c:683
void gerbv_render_layer_to_cairo_target(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo)
Render a layer to a cairo context.
Definition: gerbv.c:916
The main header file for the libgerbv library.
@ GERBV_RENDER_TYPE_GDK_XOR
Definition: gerbv.h:369
@ GERBV_SELECTION_POINT_CLICK
Definition: gerbv.h:355
@ GERBV_SELECTION_DRAG_BOX
Definition: gerbv.h:356
@ GERBV_LAYERTYPE_RS274X
Definition: gerbv.h:323
@ GERBV_LAYERTYPE_DRILL
Definition: gerbv.h:324
Header info for the GUI building functions for Gerber Viewer.
gerbv_project_t * mainProject
Global state variable to keep track of what's happening on the screen.
Definition: main.c:169
Header info for common structs and functions used for the GUI application.
void render_calculate_zoom_from_outline(GtkWidget *widget, GdkEventButton *event)
Will determine the outline of the zoomed regions.
Definition: render.c:139
gerbv_stats_t * generate_gerber_analysis(void)
Definition: render.c:615
void render_draw_measure_distance(void)
Displays a measured distance graphically on screen and in statusbar.
Definition: render.c:336
void render_toggle_measure_line(void)
Draws/erases measure line.
Definition: render.c:311
gerbv_drill_stats_t * generate_drill_analysis(void)
Definition: render.c:640
Header info for the rendering support functions for gerbv.
Header info for the selection support functions for libgerbv.
guint16 alpha
Definition: gerbv.h:748
gerbv_image_t * image
Definition: gerbv.h:746
gerbv_user_transformation_t transform
Definition: gerbv.h:754
gpointer privateRenderData
Definition: gerbv.h:750
gboolean isVisible
Definition: gerbv.h:749
gerbv_stats_t * gerbv_stats
Definition: gerbv.h:740
gerbv_layertype_t layertype
Definition: gerbv.h:732
gerbv_drill_stats_t * drill_stats
Definition: gerbv.h:741
gerbv_fileinfo_t ** file
Definition: gerbv.h:763
gboolean show_invisible_selection
Definition: gerbv.h:768
GdkColor background
Definition: gerbv.h:761
int last_loaded
Definition: gerbv.h:765
gdouble lowerLeftY
Definition: gerbv.h:788
gdouble scaleFactorX
Definition: gerbv.h:785
gint displayHeight
Definition: gerbv.h:791
gdouble lowerLeftX
Definition: gerbv.h:787
gerbv_render_types_t renderType
Definition: gerbv.h:789
gdouble scaleFactorY
Definition: gerbv.h:786