gerbv
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 defined(QUARTZ)
60 # include <cairo-quartz.h>
61 #else
62 # include <cairo-xlib.h>
63 #endif
64 #include "draw.h"
65 
66 #undef DPRINTF
67 #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)
68 
69 gerbv_render_info_t screenRenderInfo;
70 
71 /* ------------------------------------------------------ */
72 void
73 render_zoom_display (gint zoomType, gdouble scaleFactor, gdouble mouseX, gdouble mouseY)
74 {
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 = (screenRenderInfo.displayHeight - mouseY) /
86  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 = MIN((gdouble)GERBV_SCALE_MAX,
93  (1 + 1/3.0)*screenRenderInfo.scaleFactorX);
94  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
95  screenRenderInfo.lowerLeftX += (oldWidth - (screenRenderInfo.displayWidth /
96  screenRenderInfo.scaleFactorX)) / 2.0;
97  screenRenderInfo.lowerLeftY += (oldHeight - (screenRenderInfo.displayHeight /
98  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 = MAX((gdouble)GERBV_SCALE_MIN,
103  (1 - 1/3.0)*screenRenderInfo.scaleFactorX);
104  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
105  screenRenderInfo.lowerLeftX += (oldWidth - (screenRenderInfo.displayWidth /
106  screenRenderInfo.scaleFactorX)) / 2.0;
107  screenRenderInfo.lowerLeftY += (oldHeight - (screenRenderInfo.displayHeight /
108  screenRenderInfo.scaleFactorY)) / 2.0;
109  break;
110  case ZOOM_FIT : /* Zoom Fit */
111  gerbv_render_zoom_to_fit_display (mainProject, &screenRenderInfo);
112  break;
113  case ZOOM_SET : /*explicit scale set by user */
114  screenRenderInfo.scaleFactorX =
115  MIN((gdouble)GERBV_SCALE_MAX, scaleFactor);
116  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
117  screenRenderInfo.lowerLeftX += (oldWidth - (screenRenderInfo.displayWidth /
118  screenRenderInfo.scaleFactorX)) / 2.0;
119  screenRenderInfo.lowerLeftY += (oldHeight - (screenRenderInfo.displayHeight /
120  screenRenderInfo.scaleFactorY)) / 2.0;
121  break;
122  default :
123  GERB_MESSAGE(_("Illegal zoom direction %d"), zoomType);
124  }
125 
126  if (zoomType == ZOOM_IN_CMOUSE || zoomType == ZOOM_OUT_CMOUSE) {
127  /* make sure the mouse is still pointing at the point calculated earlier */
128  screenRenderInfo.lowerLeftX = mouseCoordinateX - mouseX / screenRenderInfo.scaleFactorX;
129  screenRenderInfo.lowerLeftY = mouseCoordinateY - (screenRenderInfo.displayHeight - mouseY) /
130  screenRenderInfo.scaleFactorY;
131  }
132  render_refresh_rendered_image_on_screen();
133  return;
134 }
135 
136 
137 /* --------------------------------------------------------- */
143 void
144 render_calculate_zoom_from_outline(GtkWidget *widget, GdkEventButton *event)
145 {
146  int x1, y1, x2, y2, dx, dy; /* Zoom outline (UR and LL corners) */
147  double centerPointX, centerPointY;
148  int half_x, half_y; /* cache for half window dimensions */
149 
150  x1 = MIN((gdouble)screen.start_x, event->x);
151  y1 = MIN((gdouble)screen.start_y, event->y);
152  x2 = MAX((gdouble)screen.start_x, event->x);
153  y2 = MAX((gdouble)screen.start_y, event->y);
154  dx = x2-x1;
155  dy = y2-y1;
156 
157  if ((dx >= 4) && (dy >= 4)) {
158  if (screen.centered_outline_zoom) {
159  /* Centered outline mode */
160  x1 = screen.start_x - dx;
161  y1 = screen.start_y - dy;
162  dx *= 2;
163  dy *= 2;
164  }
165  half_x = (x1+x2)/2;
166  half_y = (y1+y2)/2;
167  centerPointX = half_x/screenRenderInfo.scaleFactorX + screenRenderInfo.lowerLeftX;
168  centerPointY = (screenRenderInfo.displayHeight - half_y)/screenRenderInfo.scaleFactorY +
169  screenRenderInfo.lowerLeftY;
170 
171  screenRenderInfo.scaleFactorX *=
172  MIN((double)screenRenderInfo.displayWidth / dx,
173  (double)screenRenderInfo.displayHeight / dy);
174  screenRenderInfo.scaleFactorX = MIN((gdouble)GERBV_SCALE_MAX,
175  screenRenderInfo.scaleFactorX);
176  screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
177  screenRenderInfo.lowerLeftX = centerPointX - (screenRenderInfo.displayWidth /
178  2.0 / screenRenderInfo.scaleFactorX);
179  screenRenderInfo.lowerLeftY = centerPointY - (screenRenderInfo.displayHeight /
180  2.0 / screenRenderInfo.scaleFactorY);
181  }
182  render_refresh_rendered_image_on_screen();
183 }
184 
185 /* ------------------------------------------------------ */
186 void
187 render_draw_selection_box_outline(void) {
188  GdkGC *gc;
189  GdkGCValues values;
190  GdkGCValuesMask values_mask;
191  gint x1, y1, x2, y2, dx, dy;
192 
193  memset(&values, 0, sizeof(values));
194  values.function = GDK_XOR;
195  if (!screen.zoom_outline_color.pixel)
196  gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
197  values.foreground = screen.zoom_outline_color;
198  values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
199  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
200 
201  x1 = MIN(screen.start_x, screen.last_x);
202  y1 = MIN(screen.start_y, screen.last_y);
203  x2 = MAX(screen.start_x, screen.last_x);
204  y2 = MAX(screen.start_y, screen.last_y);
205  dx = x2-x1;
206  dy = y2-y1;
207 
208  gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, x1, y1, dx, dy);
209  gdk_gc_unref(gc);
210 }
211 
212 /* --------------------------------------------------------- */
213 void
214 render_draw_zoom_outline(gboolean centered)
215 {
216  GdkGC *gc;
217  GdkGCValues values;
218  GdkGCValuesMask values_mask;
219  gint x1, y1, x2, y2, dx, dy;
220 
221  memset(&values, 0, sizeof(values));
222  values.function = GDK_XOR;
223  if (!screen.zoom_outline_color.pixel)
224  gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
225  values.foreground = screen.zoom_outline_color;
226  values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
227  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
228 
229  x1 = MIN(screen.start_x, screen.last_x);
230  y1 = MIN(screen.start_y, screen.last_y);
231  x2 = MAX(screen.start_x, screen.last_x);
232  y2 = MAX(screen.start_y, screen.last_y);
233  dx = x2-x1;
234  dy = y2-y1;
235 
236  if (centered) {
237  /* Centered outline mode */
238  x1 = screen.start_x - dx;
239  y1 = screen.start_y - dy;
240  dx *= 2;
241  dy *= 2;
242  x2 = x1+dx;
243  y2 = y1+dy;
244  }
245 
246  gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, x1, y1, dx, dy);
247  gdk_gc_unref(gc);
248 
249  /* Draw actual zoom area in dashed lines */
250  memset(&values, 0, sizeof(values));
251  values.function = GDK_XOR;
252  values.foreground = screen.zoom_outline_color;
253  values.line_style = GDK_LINE_ON_OFF_DASH;
254  values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND | GDK_GC_LINE_STYLE;
255  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values,
256  values_mask);
257 
258  if ((dy == 0) || ((double)dx/dy > (double)screen.drawing_area->allocation.width/
259  screen.drawing_area->allocation.height)) {
260  dy = dx * (double)screen.drawing_area->allocation.height/
261  screen.drawing_area->allocation.width;
262  }
263  else {
264  dx = dy * (double)screen.drawing_area->allocation.width/
265  screen.drawing_area->allocation.height;
266  }
267 
268  gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, (x1+x2-dx)/2,
269  (y1+y2-dy)/2, dx, dy);
270 
271  gdk_gc_unref(gc);
272 }
273 
274 /* ------------------------------------------------------ */
275 /* Transforms board coordinates to screen ones */
276 static void
277 render_board2screen(gdouble *X, gdouble *Y, gdouble x, gdouble y) {
278  *X = (x - screenRenderInfo.lowerLeftX) * screenRenderInfo.scaleFactorX;
279  *Y = screenRenderInfo.displayHeight - (y - screenRenderInfo.lowerLeftY)
280  * screenRenderInfo.scaleFactorY;
281 }
282 
283 /* Trims the coordinates to avoid overflows in gdk_draw_line */
284 static void
285 render_trim_point(gdouble *start_x, gdouble *start_y, gdouble last_x, gdouble last_y)
286 {
287  const gdouble max_coord = (1<<15) - 2;/* a value that causes no overflow
288  and lies out of screen */
289  gdouble dx, dy;
290 
291  if (fabs (*start_x) < max_coord && fabs (*start_y) < max_coord)
292  return;
293 
294  dx = last_x - *start_x;
295  dy = last_y - *start_y;
296 
297  if (*start_x < -max_coord) {
298  *start_x = -max_coord;
299  if (last_x > -max_coord && fabs (dx) > 0.1)
300  *start_y = last_y - (last_x + max_coord) / dx * dy;
301  }
302  if (*start_x > max_coord) {
303  *start_x = max_coord;
304  if (last_x < max_coord && fabs (dx) > 0.1)
305  *start_y = last_y - (last_x - max_coord) / dx * dy;
306  }
307 
308  dx = last_x - *start_x;
309  dy = last_y - *start_y;
310 
311  if (*start_y < -max_coord) {
312  *start_y = -max_coord;
313  if (last_y > -max_coord && fabs (dy) > 0.1)
314  *start_x = last_x - (last_y + max_coord) / dy * dx;
315  }
316  if (*start_y > max_coord) {
317  *start_y = max_coord;
318  if (last_y < max_coord && fabs (dy) > 0.1)
319  *start_x = last_x - (last_y - max_coord) / dy * dx;
320  }
321 }
322 
323 /* ------------------------------------------------------ */
326 void
328 {
329 
330  GdkGC *gc;
331  GdkGCValues values;
332  GdkGCValuesMask values_mask;
333  gdouble start_x, start_y, last_x, last_y;
334  memset(&values, 0, sizeof(values));
335  values.function = GDK_XOR;
336  values.line_width = 6;
337  if (!screen.zoom_outline_color.pixel)
338  gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
339  values.foreground = screen.zoom_outline_color;
340  values_mask = GDK_GC_FUNCTION | GDK_GC_LINE_WIDTH | GDK_GC_FOREGROUND;
341  gc = gdk_gc_new_with_values(screen.drawing_area->window, &values,
342  values_mask);
343  render_board2screen(&start_x, &start_y,
344  screen.measure_start_x, screen.measure_start_y);
345  render_board2screen(&last_x, &last_y,
346  screen.measure_stop_x, screen.measure_stop_y);
347  render_trim_point(&start_x, &start_y, last_x, last_y);
348  render_trim_point(&last_x, &last_y, start_x, start_y);
349  gdk_draw_line(screen.drawing_area->window, gc, start_x,
350  start_y, last_x, last_y);
351  gdk_gc_unref(gc);
352 } /* toggle_measure_line */
353 
354 /* ------------------------------------------------------ */
356 void
358 {
359  gdouble dx, dy;
360 
361  dx = fabs (screen.measure_start_x - screen.measure_stop_x);
362  dy = fabs (screen.measure_start_y - screen.measure_stop_y);
363 
364  screen.measure_last_x = dx;
365  screen.measure_last_y = dy;
366  callbacks_update_statusbar_measured_distance (dx, dy);
368 }
369 
370 /* ------------------------------------------------------ */
371 static void render_selection (void)
372 {
373  gerbv_selection_item_t sel_item;
374  gerbv_fileinfo_t *file;
375  gdouble pixel_width;
376  cairo_t *cr;
377  int i;
378  guint j;
379 
380  if (selection_length (&screen.selectionInfo) == 0)
381  return;
382 
383  if (screen.selectionRenderData)
384  cairo_surface_destroy (
385  (cairo_surface_t *)screen.selectionRenderData);
386 
387  screen.selectionRenderData =
388  (gpointer) cairo_surface_create_similar (
389  (cairo_surface_t *)screen.windowSurface,
390  CAIRO_CONTENT_COLOR_ALPHA,
391  screenRenderInfo.displayWidth,
392  screenRenderInfo.displayHeight);
393 
394  pixel_width = 1.0/MAX(screenRenderInfo.scaleFactorX,
395  screenRenderInfo.scaleFactorY);
396 
397  for (i = mainProject->last_loaded; i >= 0; i--) {
398  file = mainProject->file[i];
399 
400  if (!file ||
402  continue;
403 
404  for (j = 0; j < selection_length (&screen.selectionInfo); j++) {
405  sel_item = selection_get_item_by_index (
406  &screen.selectionInfo, j);
407  if (file->image != sel_item.image)
408  continue;
409 
410  /* Have selected image(s) on this file, draw it */
411 
412  cr = cairo_create(screen.selectionRenderData);
413  gerbv_render_cairo_set_scale_and_translation(cr,
414  &screenRenderInfo);
415  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.85);
416  draw_image_to_cairo_target (cr,
417  file->image, pixel_width,
418  DRAW_SELECTIONS, &screen.selectionInfo,
419  &screenRenderInfo, TRUE,
420  file->transform, TRUE);
421  cairo_destroy (cr);
422 
423  break; /* All done, go to next file */
424  }
425  }
426 }
427 
428 /* ------------------------------------------------------ */
429 void render_refresh_rendered_image_on_screen (void) {
430  GdkCursor *cursor;
431 
432  DPRINTF("----> Entering redraw_pixmap...\n");
433  cursor = gdk_cursor_new(GDK_WATCH);
434  gdk_window_set_cursor(GDK_WINDOW(screen.drawing_area->window), cursor);
435  gdk_cursor_destroy(cursor);
436 
437  if (screenRenderInfo.renderType <= GERBV_RENDER_TYPE_GDK_XOR){
438  if (screen.pixmap)
439  gdk_pixmap_unref(screen.pixmap);
440  screen.pixmap = gdk_pixmap_new(screen.drawing_area->window, screenRenderInfo.displayWidth,
441  screenRenderInfo.displayHeight, -1);
442  gerbv_render_to_pixmap_using_gdk (mainProject, screen.pixmap, &screenRenderInfo, &screen.selectionInfo,
443  &screen.selection_color);
444  DPRINTF("<---- leaving redraw_pixmap.\n");
445  }
446  else{
447  int i;
448  DPRINTF(" .... Now try rendering the drawing using cairo .... \n");
449  /*
450  * This now allows drawing several layers on top of each other.
451  * Higher layer numbers have higher priority in the Z-order.
452  */
453  for(i = mainProject->last_loaded; i >= 0; i--) {
454  if (mainProject->file[i]) {
455  cairo_t *cr;
457  cairo_surface_destroy ((cairo_surface_t *) mainProject->file[i]->privateRenderData);
459  (gpointer) cairo_surface_create_similar ((cairo_surface_t *)screen.windowSurface,
460  CAIRO_CONTENT_COLOR_ALPHA, screenRenderInfo.displayWidth,
461  screenRenderInfo.displayHeight);
462  cr= cairo_create(mainProject->file[i]->privateRenderData );
463  gerbv_render_layer_to_cairo_target (cr, mainProject->file[i], &screenRenderInfo);
464  DPRINTF(" .... calling render_image_to_cairo_target on layer %d...\n", i);
465  cairo_destroy (cr);
466  }
467  }
468 
469  render_recreate_composite_surface ();
470  }
471  /* remove watch cursor and switch back to normal cursor */
472  callbacks_switch_to_correct_cursor ();
473  callbacks_force_expose_event_for_screen();
474 }
475 
476 /* ------------------------------------------------------ */
477 void
478 render_remove_selected_objects_belonging_to_layer (
479  gerbv_selection_info_t *sel_info, gerbv_image_t *image)
480 {
481  guint i;
482 
483  for (i = 0; i < selection_length (sel_info);) {
484  gerbv_selection_item_t sItem =
485  selection_get_item_by_index (sel_info, i);
486 
487  if (image == (gerbv_image_t *) sItem.image)
488  selection_clear_item_by_index (sel_info, i);
489  else
490  i++;
491  }
492 }
493 
494 /* ------------------------------------------------------ */
495 gint
496 render_create_cairo_buffer_surface () {
497  if (screen.bufferSurface) {
498  cairo_surface_destroy (screen.bufferSurface);
499  screen.bufferSurface = NULL;
500  }
501  if (!screen.windowSurface)
502  return 0;
503 
504  screen.bufferSurface= cairo_surface_create_similar ((cairo_surface_t *)screen.windowSurface,
505  CAIRO_CONTENT_COLOR, screenRenderInfo.displayWidth,
506  screenRenderInfo.displayHeight);
507  return 1;
508 }
509 
510 /* ------------------------------------------------------ */
511 static void
512 render_find_selected_objects_and_refresh_display (gint activeFileIndex,
513  enum selection_action action)
514 {
515  enum draw_mode mode = FIND_SELECTIONS;
516 
517  /* clear the old selection array if desired */
518  if ((action == SELECTION_REPLACE)
519  && (selection_length (&screen.selectionInfo) != 0))
520  selection_clear (&screen.selectionInfo);
521 
522  if (action == SELECTION_TOGGLE)
523  mode = FIND_SELECTIONS_TOGGLE;
524 
525  /* make sure we have a bufferSurface...if we start up in FAST mode, we may not
526  have one yet, but we need it for selections */
527  if (!render_create_cairo_buffer_surface ())
528  return;
529 
530  /* call draw_image... passing the FILL_SELECTION mode to just search for
531  nets which match the selection, and fill the selection buffer with them */
532  cairo_t *cr = cairo_create (screen.bufferSurface);
533  gerbv_render_cairo_set_scale_and_translation (cr, &screenRenderInfo);
534  draw_image_to_cairo_target (cr,
535  mainProject->file[activeFileIndex]->image,
536  1.0/MAX (screenRenderInfo.scaleFactorX,
537  screenRenderInfo.scaleFactorY),
538  mode, &screen.selectionInfo, &screenRenderInfo, TRUE,
539  mainProject->file[activeFileIndex]->transform, TRUE);
540  cairo_destroy (cr);
541 
542  /* re-render the selection buffer layer */
543  if (screenRenderInfo.renderType <= GERBV_RENDER_TYPE_GDK_XOR) {
544  render_refresh_rendered_image_on_screen ();
545  } else {
546  render_recreate_composite_surface ();
547  callbacks_force_expose_event_for_screen ();
548  }
549 }
550 
551 /* ------------------------------------------------------ */
552 void
553 render_fill_selection_buffer_from_mouse_click (gint mouseX, gint mouseY,
554  gint activeFileIndex, enum selection_action action)
555 {
556  screen.selectionInfo.lowerLeftX = mouseX;
557  screen.selectionInfo.lowerLeftY = mouseY;
558  /* no need to populate the upperright coordinates for a point_click */
559  screen.selectionInfo.type = GERBV_SELECTION_POINT_CLICK;
560  render_find_selected_objects_and_refresh_display (
561  activeFileIndex, action);
562 }
563 
564 /* ------------------------------------------------------ */
565 void
566 render_fill_selection_buffer_from_mouse_drag (gint corner1X, gint corner1Y,
567  gint corner2X, gint corner2Y,
568  gint activeFileIndex, enum selection_action action)
569 {
570  /* figure out the lower left corner of the box */
571  screen.selectionInfo.lowerLeftX = MIN(corner1X, corner2X);
572  screen.selectionInfo.lowerLeftY = MIN(corner1Y, corner2Y);
573  /* figure out the upper right corner of the box */
574  screen.selectionInfo.upperRightX = MAX(corner1X, corner2X);
575  screen.selectionInfo.upperRightY = MAX(corner1Y, corner2Y);
576 
577  screen.selectionInfo.type = GERBV_SELECTION_DRAG_BOX;
578  render_find_selected_objects_and_refresh_display (
579  activeFileIndex, action);
580 }
581 
582 /* ------------------------------------------------------ */
583 void render_recreate_composite_surface ()
584 {
585  gint i;
586 
587  if (!render_create_cairo_buffer_surface())
588  return;
589 
590  cairo_t *cr= cairo_create(screen.bufferSurface);
591  /* fill the background with the appropriate color */
592  cairo_set_source_rgba (cr, (double) mainProject->background.red/G_MAXUINT16,
593  (double) mainProject->background.green/G_MAXUINT16,
594  (double) mainProject->background.blue/G_MAXUINT16, 1);
595  cairo_paint (cr);
596 
597  for(i = mainProject->last_loaded; i >= 0; i--) {
598  if (mainProject->file[i] && mainProject->file[i]->isVisible) {
599  cairo_set_source_surface (cr, (cairo_surface_t *) mainProject->file[i]->privateRenderData,
600  0, 0);
601  /* ignore alpha if we are in high-speed render mode */
602  if (((double) mainProject->file[i]->alpha < 65535)&&(screenRenderInfo.renderType != GERBV_RENDER_TYPE_GDK_XOR)) {
603  cairo_paint_with_alpha(cr,(double) mainProject->file[i]->alpha/G_MAXUINT16);
604  }
605  else {
606  cairo_paint (cr);
607  }
608  }
609  }
610 
611  /* render the selection layer at the end */
612  if (selection_length (&screen.selectionInfo) != 0) {
613  render_selection ();
614  cairo_set_source_surface (cr, (cairo_surface_t *) screen.selectionRenderData,
615  0, 0);
616  cairo_paint_with_alpha (cr,1.0);
617  }
618  cairo_destroy (cr);
619 }
620 
621 /* ------------------------------------------------------ */
622 void render_project_to_cairo_target (cairo_t *cr) {
623  /* fill the background with the appropriate color */
624  cairo_set_source_rgba (cr, (double) mainProject->background.red/G_MAXUINT16,
625  (double) mainProject->background.green/G_MAXUINT16,
626  (double) mainProject->background.blue/G_MAXUINT16, 1);
627  cairo_paint (cr);
628 
629  cairo_set_source_surface (cr, (cairo_surface_t *) screen.bufferSurface, 0 , 0);
630 
631  cairo_paint (cr);
632 }
633 
634 void
635 render_free_screen_resources (void) {
636  if (screen.selectionRenderData)
637  cairo_surface_destroy ((cairo_surface_t *)
638  screen.selectionRenderData);
639  if (screen.bufferSurface)
640  cairo_surface_destroy ((cairo_surface_t *)
641  screen.bufferSurface);
642  if (screen.windowSurface)
643  cairo_surface_destroy ((cairo_surface_t *)
644  screen.windowSurface);
645  if (screen.pixmap)
646  gdk_pixmap_unref(screen.pixmap);
647 }
648 
649 
650 /* ------------------------------------------------------------------ */
656 {
657  int i;
658  gerbv_stats_t *stats;
659  gerbv_stats_t *instats;
660 
661  /* Create new stats structure to hold report for whole project
662  * (i.e. all layers together) */
663  stats = gerbv_stats_new();
664 
665  /* Loop through open layers and compile statistics by accumulating reports from each layer */
666  for (i = 0; i <= mainProject->last_loaded; i++) {
667  if (mainProject->file[i] && mainProject->file[i]->isVisible &&
669  instats = mainProject->file[i]->image->gerbv_stats;
670  gerbv_stats_add_layer(stats, instats, i+1);
671  }
672  }
673  return stats;
674 }
675 
676 
677 /* ------------------------------------------------------------------ */
683 {
684  int i;
685  gerbv_drill_stats_t *stats;
686  gerbv_drill_stats_t *instats;
687 
688  stats = gerbv_drill_stats_new();
689 
690  /* Loop through open layers and compile statistics by accumulating reports from each layer */
691  for(i = mainProject->last_loaded; i >= 0; i--) {
692  if (mainProject->file[i] &&
693  mainProject->file[i]->isVisible &&
695  instats = mainProject->file[i]->image->drill_stats;
696  /* add this batch of stats. Send the layer
697  * index for error reporting */
698  gerbv_drill_stats_add_layer(stats, instats, i+1);
699  }
700  }
701  return stats;
702 }
703 
Header info for the GUI callback functions.
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:45
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:781
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:1025
The main header file for the libgerbv library.
@ GERBV_RENDER_TYPE_GDK_XOR
Definition: gerbv.h:368
@ GERBV_SELECTION_POINT_CLICK
Definition: gerbv.h:355
@ GERBV_SELECTION_DRAG_BOX
Definition: gerbv.h:356
@ GERBV_LAYERTYPE_RS274X
Definition: gerbv.h:328
@ GERBV_LAYERTYPE_DRILL
Definition: gerbv.h:329
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:201
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:144
gerbv_stats_t * generate_gerber_analysis(void)
Definition: render.c:655
void render_draw_measure_distance(void)
Displays a measured distance graphically on screen and in statusbar.
Definition: render.c:357
void render_toggle_measure_line(void)
Draws/erases measure line.
Definition: render.c:327
gerbv_drill_stats_t * generate_drill_analysis(void)
Definition: render.c:682
Header info for the rendering support functions for gerbv.
Header info for the selection support functions for libgerbv.
guint16 alpha
Definition: gerbv.h:738
gerbv_image_t * image
Definition: gerbv.h:736
gerbv_user_transformation_t transform
Definition: gerbv.h:743
gpointer privateRenderData
Definition: gerbv.h:740
gboolean isVisible
Definition: gerbv.h:739
gerbv_stats_t * gerbv_stats
Definition: gerbv.h:730
gerbv_layertype_t layertype
Definition: gerbv.h:722
gerbv_drill_stats_t * drill_stats
Definition: gerbv.h:731
gerbv_fileinfo_t ** file
Definition: gerbv.h:752
gboolean show_invisible_selection
Definition: gerbv.h:757
GdkColor background
Definition: gerbv.h:750
int last_loaded
Definition: gerbv.h:754
gdouble lowerLeftY
Definition: gerbv.h:778
gdouble scaleFactorX
Definition: gerbv.h:775
gint displayHeight
Definition: gerbv.h:781
gdouble lowerLeftX
Definition: gerbv.h:777
gerbv_render_types_t renderType
Definition: gerbv.h:779
gdouble scaleFactorY
Definition: gerbv.h:776