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