2 * gEDA - GNU Electronic Design Automation
4 * render.c -- this file is a part of gerbv.
6 * Copyright (C) 2007 Stuart Brorson (SDB@cloud9.net)
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.
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.
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
26 \brief Rendering support functions for libgerbv
47 #include <libgen.h> /* dirname */
55 #include "callbacks.h"
56 #include "interface.h"
60 #include <cairo-win32.h>
62 #include <cairo-xlib.h>
68 #define dprintf if(DEBUG) printf
70 /**Global variable to keep track of what's happening on the screen.
71 Declared extern in gerbv_screen.h
73 extern gerbv_screen_t screen
;
75 extern gerbv_render_info_t screenRenderInfo
;
79 render_layer_to_cairo_target_without_transforming(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo );
83 render_check_scale_factor_limits (void) {
84 if ((screenRenderInfo
.scaleFactorX
> 5000)||(screenRenderInfo
.scaleFactorY
> 5000)) {
85 screenRenderInfo
.scaleFactorX
= 5000;
86 screenRenderInfo
.scaleFactorY
= 5000;
92 /* ------------------------------------------------------ */
94 render_zoom_display (gint zoomType
, gdouble scaleFactor
, gdouble mouseX
, gdouble mouseY
) {
95 double us_midx
, us_midy
; /* unscaled translation for screen center */
96 int half_w
, half_h
; /* cache for half window dimensions */
97 gdouble mouseCoordinateX
= 0.0;
98 gdouble mouseCoordinateY
= 0.0;
99 double oldWidth
, oldHeight
;
101 half_w
= screenRenderInfo
.displayWidth
/ 2;
102 half_h
= screenRenderInfo
.displayHeight
/ 2;
104 oldWidth
= screenRenderInfo
.displayWidth
/ screenRenderInfo
.scaleFactorX
;
105 oldHeight
= screenRenderInfo
.displayHeight
/ screenRenderInfo
.scaleFactorY
;
106 if (zoomType
== ZOOM_IN_CMOUSE
|| zoomType
== ZOOM_OUT_CMOUSE
) {
107 /* calculate what user coordinate the mouse is pointing at */
108 mouseCoordinateX
= mouseX
/ screenRenderInfo
.scaleFactorX
+ screenRenderInfo
.lowerLeftX
;
109 mouseCoordinateY
= (screenRenderInfo
.displayHeight
- mouseY
) /
110 screenRenderInfo
.scaleFactorY
+ screenRenderInfo
.lowerLeftY
;
113 us_midx
= screenRenderInfo
.lowerLeftX
+ (screenRenderInfo
.displayWidth
/ 2.0 )/
114 screenRenderInfo
.scaleFactorX
;
115 us_midy
= screenRenderInfo
.lowerLeftY
+ (screenRenderInfo
.displayHeight
/ 2.0 )/
116 screenRenderInfo
.scaleFactorY
;
119 case ZOOM_IN
: /* Zoom In */
120 case ZOOM_IN_CMOUSE
: /* Zoom In Around Mouse Pointer */
121 screenRenderInfo
.scaleFactorX
+= screenRenderInfo
.scaleFactorX
/3;
122 screenRenderInfo
.scaleFactorY
+= screenRenderInfo
.scaleFactorY
/3;
123 (void) render_check_scale_factor_limits ();
124 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
125 screenRenderInfo
.scaleFactorX
)) / 2.0;
126 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
127 screenRenderInfo
.scaleFactorY
)) / 2.0;
129 case ZOOM_OUT
: /* Zoom Out */
130 case ZOOM_OUT_CMOUSE
: /* Zoom Out Around Mouse Pointer */
131 if ((screenRenderInfo
.scaleFactorX
> 10)&&(screenRenderInfo
.scaleFactorY
> 10)) {
132 screenRenderInfo
.scaleFactorX
-= screenRenderInfo
.scaleFactorX
/3;
133 screenRenderInfo
.scaleFactorY
-= screenRenderInfo
.scaleFactorY
/3;
134 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
135 screenRenderInfo
.scaleFactorX
)) / 2.0;
136 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
137 screenRenderInfo
.scaleFactorY
)) / 2.0;
140 case ZOOM_FIT
: /* Zoom Fit */
141 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
143 case ZOOM_SET
: /*explicit scale set by user */
144 screenRenderInfo
.scaleFactorX
= scaleFactor
;
145 screenRenderInfo
.scaleFactorY
= scaleFactor
;
146 (void) render_check_scale_factor_limits ();
147 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
148 screenRenderInfo
.scaleFactorX
)) / 2.0;
149 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
150 screenRenderInfo
.scaleFactorY
)) / 2.0;
153 GERB_MESSAGE("Illegal zoom direction %d\n", zoomType
);
156 if (zoomType
== ZOOM_IN_CMOUSE
|| zoomType
== ZOOM_OUT_CMOUSE
) {
157 /* make sure the mouse is still pointing at the point calculated earlier */
158 screenRenderInfo
.lowerLeftX
= mouseCoordinateX
- mouseX
/ screenRenderInfo
.scaleFactorX
;
159 screenRenderInfo
.lowerLeftY
= mouseCoordinateY
- (screenRenderInfo
.displayHeight
- mouseY
) /
160 screenRenderInfo
.scaleFactorY
;
162 render_refresh_rendered_image_on_screen();
167 /* --------------------------------------------------------- */
168 /** Will determine the outline of the zoomed regions.
169 * In case region to be zoomed is too small (which correspondes
170 * e.g. to a double click) it is interpreted as a right-click
171 * and will be used to identify a part from the CURRENT selection,
172 * which is drawn on screen*/
174 render_calculate_zoom_from_outline(GtkWidget
*widget
, GdkEventButton
*event
)
176 int x1
, y1
, x2
, y2
, dx
, dy
; /* Zoom outline (UR and LL corners) */
177 double centerPointX
, centerPointY
;
178 int half_x
, half_y
; /* cache for half window dimensions */
180 x1
= MIN(screen
.start_x
, event
->x
);
181 y1
= MIN(screen
.start_y
, event
->y
);
182 x2
= MAX(screen
.start_x
, event
->x
);
183 y2
= MAX(screen
.start_y
, event
->y
);
187 if ((dx
>= 4) && (dy
>= 4)) {
188 if (screen
.centered_outline_zoom
) {
189 /* Centered outline mode */
190 x1
= screen
.start_x
- dx
;
191 y1
= screen
.start_y
- dy
;
197 centerPointX
= half_x
/screenRenderInfo
.scaleFactorX
+ screenRenderInfo
.lowerLeftX
;
198 centerPointY
= (screenRenderInfo
.displayHeight
- half_y
)/screenRenderInfo
.scaleFactorY
+
199 screenRenderInfo
.lowerLeftY
;
201 screenRenderInfo
.scaleFactorX
*= MIN(((double)screenRenderInfo
.displayWidth
/ dx
),
202 ((double)screenRenderInfo
.displayHeight
/ dy
));
203 screenRenderInfo
.scaleFactorY
= screenRenderInfo
.scaleFactorX
;
204 (void) render_check_scale_factor_limits ();
205 screenRenderInfo
.lowerLeftX
= centerPointX
- (screenRenderInfo
.displayWidth
/
206 2.0 / screenRenderInfo
.scaleFactorX
);
207 screenRenderInfo
.lowerLeftY
= centerPointY
- (screenRenderInfo
.displayHeight
/
208 2.0 / screenRenderInfo
.scaleFactorY
);
210 render_refresh_rendered_image_on_screen();
213 /* ------------------------------------------------------ */
215 render_draw_selection_box_outline(void) {
218 GdkGCValuesMask values_mask
;
219 gint x1
, y1
, x2
, y2
, dx
, dy
;
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
);
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
);
236 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, x1
, y1
, dx
, dy
);
240 /* --------------------------------------------------------- */
242 render_draw_zoom_outline(gboolean centered
)
246 GdkGCValuesMask values_mask
;
247 gint x1
, y1
, x2
, y2
, dx
, dy
;
249 memset(&values
, 0, sizeof(values
));
250 values
.function
= GDK_XOR
;
251 if (!screen
.zoom_outline_color
.pixel
)
252 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
253 values
.foreground
= screen
.zoom_outline_color
;
254 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
255 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
, values_mask
);
257 x1
= MIN(screen
.start_x
, screen
.last_x
);
258 y1
= MIN(screen
.start_y
, screen
.last_y
);
259 x2
= MAX(screen
.start_x
, screen
.last_x
);
260 y2
= MAX(screen
.start_y
, screen
.last_y
);
265 /* Centered outline mode */
266 x1
= screen
.start_x
- dx
;
267 y1
= screen
.start_y
- dy
;
274 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, x1
, y1
, dx
, dy
);
277 /* Draw actual zoom area in dashed lines */
278 memset(&values
, 0, sizeof(values
));
279 values
.function
= GDK_XOR
;
280 values
.foreground
= screen
.zoom_outline_color
;
281 values
.line_style
= GDK_LINE_ON_OFF_DASH
;
282 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
| GDK_GC_LINE_STYLE
;
283 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
,
286 if ((dy
== 0) || ((double)dx
/dy
> (double)screen
.drawing_area
->allocation
.width
/
287 screen
.drawing_area
->allocation
.height
)) {
288 dy
= dx
* (double)screen
.drawing_area
->allocation
.height
/
289 screen
.drawing_area
->allocation
.width
;
292 dx
= dy
* (double)screen
.drawing_area
->allocation
.width
/
293 screen
.drawing_area
->allocation
.height
;
296 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, (x1
+x2
-dx
)/2,
297 (y1
+y2
-dy
)/2, dx
, dy
);
302 /* ------------------------------------------------------ */
303 /* Transforms board coordinates to screen ones */
305 render_board2screen(gdouble
*X
, gdouble
*Y
, gdouble x
, gdouble y
) {
306 *X
= (x
- screenRenderInfo
.lowerLeftX
) * screenRenderInfo
.scaleFactorX
;
307 *Y
= screenRenderInfo
.displayHeight
- (y
- screenRenderInfo
.lowerLeftY
)
308 * screenRenderInfo
.scaleFactorY
;
311 /* Trims the coordinates to avoid overflows in gdk_draw_line */
313 render_trim_point(gdouble
*start_x
, gdouble
*start_y
, gdouble last_x
, gdouble last_y
)
315 const gdouble max_coord
= (1<<15) - 2;/* a value that causes no overflow
316 and lies out of screen */
319 if (fabs (*start_x
) < max_coord
&& fabs (*start_y
) < max_coord
)
322 dx
= last_x
- *start_x
;
323 dy
= last_y
- *start_y
;
325 if (*start_x
< -max_coord
) {
326 *start_x
= -max_coord
;
327 if (last_x
> -max_coord
&& fabs (dx
) > 0.1)
328 *start_y
= last_y
- (last_x
+ max_coord
) / dx
* dy
;
330 if (*start_x
> max_coord
) {
331 *start_x
= max_coord
;
332 if (last_x
< max_coord
&& fabs (dx
) > 0.1)
333 *start_y
= last_y
- (last_x
- max_coord
) / dx
* dy
;
336 dx
= last_x
- *start_x
;
337 dy
= last_y
- *start_y
;
339 if (*start_y
< -max_coord
) {
340 *start_y
= -max_coord
;
341 if (last_y
> -max_coord
&& fabs (dy
) > 0.1)
342 *start_x
= last_x
- (last_y
+ max_coord
) / dy
* dx
;
344 if (*start_y
> max_coord
) {
345 *start_y
= max_coord
;
346 if (last_y
< max_coord
&& fabs (dy
) > 0.1)
347 *start_x
= last_x
- (last_y
- max_coord
) / dy
* dx
;
351 /* ------------------------------------------------------ */
352 /** Draws/erases measure line
355 render_toggle_measure_line(void)
360 GdkGCValuesMask values_mask
;
361 gdouble start_x
, start_y
, last_x
, last_y
;
362 memset(&values
, 0, sizeof(values
));
363 values
.function
= GDK_XOR
;
364 if (!screen
.zoom_outline_color
.pixel
)
365 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
366 values
.foreground
= screen
.zoom_outline_color
;
367 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
368 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
,
370 render_board2screen(&start_x
, &start_y
,
371 screen
.measure_start_x
, screen
.measure_start_y
);
372 render_board2screen(&last_x
, &last_y
,
373 screen
.measure_last_x
, screen
.measure_last_y
);
374 render_trim_point(&start_x
, &start_y
, last_x
, last_y
);
375 render_trim_point(&last_x
, &last_y
, start_x
, start_y
);
376 gdk_draw_line(screen
.drawing_area
->window
, gc
, start_x
,
377 start_y
, last_x
, last_y
);
379 } /* toggle_measure_line */
381 /* ------------------------------------------------------ */
382 /** Displays a measured distance graphically on screen and in statusbar. */
384 render_draw_measure_distance(void)
386 gdouble x1
, y1
, x2
, y2
;
389 x1
= MIN(screen
.measure_start_x
, screen
.measure_last_x
);
390 y1
= MIN(screen
.measure_start_y
, screen
.measure_last_y
);
391 x2
= MAX(screen
.measure_start_x
, screen
.measure_last_x
);
392 y2
= MAX(screen
.measure_start_y
, screen
.measure_last_y
);
396 screen
.win
.lastMeasuredX
= dx
;
397 screen
.win
.lastMeasuredY
= dy
;
398 callbacks_update_statusbar_measured_distance (dx
, dy
);
399 render_toggle_measure_line();
400 } /* draw_measure_distance */
402 /* ------------------------------------------------------ */
403 void render_selection_layer (void){
406 if (screen
.selectionRenderData
)
407 cairo_surface_destroy ((cairo_surface_t
*) screen
.selectionRenderData
);
408 screen
.selectionRenderData
=
409 (gpointer
) cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
410 CAIRO_CONTENT_COLOR_ALPHA
, screenRenderInfo
.displayWidth
,
411 screenRenderInfo
.displayHeight
);
412 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
) {
413 cr
= cairo_create(screen
.selectionRenderData
);
414 gerbv_render_cairo_set_scale_and_translation(cr
, &screenRenderInfo
);
415 cairo_set_source_rgba (cr
, 1.0, 1.0, 1.0, 0.85);
416 /* for now, assume everything in the selection buffer is from one image */
417 gerbv_image_t
*matchImage
;
419 if (screen
.selectionInfo
.selectedNodeArray
->len
> 0) {
420 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
421 gerbv_selection_item_t
, 0);
422 matchImage
= (gerbv_image_t
*) sItem
.image
;
423 dprintf(" .... calling render_image_to_cairo_target on selection layer...\n");
424 for(j
= mainProject
->last_loaded
; j
>= 0; j
--) {
425 if ((mainProject
->file
[j
]) && (mainProject
->file
[j
]->image
== matchImage
)) {
426 draw_image_to_cairo_target (cr
, mainProject
->file
[j
]->image
,
427 1.0/MAX(screenRenderInfo
.scaleFactorX
,
428 screenRenderInfo
.scaleFactorY
),
429 DRAW_SELECTIONS
, &screen
.selectionInfo
, &screenRenderInfo
,
430 TRUE
, mainProject
->file
[j
]->transform
);
438 /* ------------------------------------------------------ */
439 void render_refresh_rendered_image_on_screen (void) {
442 dprintf("----> Entering redraw_pixmap...\n");
443 cursor
= gdk_cursor_new(GDK_WATCH
);
444 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
), cursor
);
445 gdk_cursor_destroy(cursor
);
447 if (screenRenderInfo
.renderType
< 2){
449 gdk_pixmap_unref(screen
.pixmap
);
450 screen
.pixmap
= gdk_pixmap_new(screen
.drawing_area
->window
, screenRenderInfo
.displayWidth
,
451 screenRenderInfo
.displayHeight
, -1);
452 gerbv_render_to_pixmap_using_gdk (mainProject
, screen
.pixmap
, &screenRenderInfo
, &screen
.selectionInfo
,
453 &screen
.selection_color
);
454 dprintf("<---- leaving redraw_pixmap.\n");
458 dprintf(" .... Now try rendering the drawing using cairo .... \n");
460 * This now allows drawing several layers on top of each other.
461 * Higher layer numbers have higher priority in the Z-order.
463 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
464 if (mainProject
->file
[i
]) {
466 if (mainProject
->file
[i
]->privateRenderData
)
467 cairo_surface_destroy ((cairo_surface_t
*) mainProject
->file
[i
]->privateRenderData
);
468 mainProject
->file
[i
]->privateRenderData
=
469 (gpointer
) cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
470 CAIRO_CONTENT_COLOR_ALPHA
, screenRenderInfo
.displayWidth
,
471 screenRenderInfo
.displayHeight
);
472 cr
= cairo_create(mainProject
->file
[i
]->privateRenderData
);
473 gerbv_render_layer_to_cairo_target (cr
, mainProject
->file
[i
], &screenRenderInfo
);
474 dprintf(" .... calling render_image_to_cairo_target on layer %d...\n", i
);
478 /* render the selection layer */
479 render_selection_layer();
481 render_recreate_composite_surface ();
483 /* remove watch cursor and switch back to normal cursor */
484 callbacks_switch_to_correct_cursor ();
485 callbacks_force_expose_event_for_screen();
488 /* ------------------------------------------------------ */
490 render_clear_selection_buffer (void){
491 if (screen
.selectionInfo
.type
== GERBV_SELECTION_EMPTY
)
494 g_array_remove_range (screen
.selectionInfo
.selectedNodeArray
, 0,
495 screen
.selectionInfo
.selectedNodeArray
->len
);
496 screen
.selectionInfo
.type
= GERBV_SELECTION_EMPTY
;
497 callbacks_update_selected_object_message (FALSE
);
501 render_remove_selected_objects_belonging_to_layer (gint index
) {
504 for (i
=screen
.selectionInfo
.selectedNodeArray
->len
-1; i
>=0; i
--) {
505 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
506 gerbv_selection_item_t
, i
);
508 gerbv_image_t
*matchImage
= (gerbv_image_t
*) sItem
.image
;
509 if (mainProject
->file
[index
]->image
== matchImage
) {
510 g_array_remove_index (screen
.selectionInfo
.selectedNodeArray
, index
);
513 callbacks_update_selected_object_message (FALSE
);
516 /* ------------------------------------------------------ */
518 render_create_cairo_buffer_surface () {
519 if (screen
.bufferSurface
) {
520 cairo_surface_destroy (screen
.bufferSurface
);
521 screen
.bufferSurface
= NULL
;
523 if (!screen
.windowSurface
)
526 screen
.bufferSurface
= cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
527 CAIRO_CONTENT_COLOR
, screenRenderInfo
.displayWidth
,
528 screenRenderInfo
.displayHeight
);
532 /* ------------------------------------------------------ */
534 render_find_selected_objects_and_refresh_display (gint activeFileIndex
, gboolean eraseOldSelection
){
535 /* clear the old selection array if desired */
536 if ((eraseOldSelection
)&&(screen
.selectionInfo
.selectedNodeArray
->len
))
537 g_array_remove_range (screen
.selectionInfo
.selectedNodeArray
, 0,
538 screen
.selectionInfo
.selectedNodeArray
->len
);
540 /* make sure we have a bufferSurface...if we start up in FAST mode, we may not
541 have one yet, but we need it for selections */
542 if (!render_create_cairo_buffer_surface())
545 /* call draw_image... passing the FILL_SELECTION mode to just search for
546 nets which match the selection, and fill the selection buffer with them */
547 cairo_t
*cr
= cairo_create(screen
.bufferSurface
);
548 gerbv_render_cairo_set_scale_and_translation(cr
,&screenRenderInfo
);
549 draw_image_to_cairo_target (cr
, mainProject
->file
[activeFileIndex
]->image
,
550 1.0/MAX(screenRenderInfo
.scaleFactorX
, screenRenderInfo
.scaleFactorY
),
551 FIND_SELECTIONS
, &screen
.selectionInfo
, &screenRenderInfo
, TRUE
,
552 mainProject
->file
[activeFileIndex
]->transform
);
554 /* if the selection array is empty, switch the "mode" to empty to make it
555 easier to check if it is holding anything */
556 if (!screen
.selectionInfo
.selectedNodeArray
->len
)
557 screen
.selectionInfo
.type
= GERBV_SELECTION_EMPTY
;
558 /* re-render the selection buffer layer */
559 if (screenRenderInfo
.renderType
< 2){
560 render_refresh_rendered_image_on_screen ();
563 render_selection_layer();
564 render_recreate_composite_surface ();
565 callbacks_force_expose_event_for_screen();
569 /* ------------------------------------------------------ */
571 render_fill_selection_buffer_from_mouse_click (gint mouseX
, gint mouseY
, gint activeFileIndex
,
572 gboolean eraseOldSelection
) {
573 screen
.selectionInfo
.lowerLeftX
= mouseX
;
574 screen
.selectionInfo
.lowerLeftY
= mouseY
;
575 /* no need to populate the upperright coordinates for a point_click */
576 screen
.selectionInfo
.type
= GERBV_SELECTION_POINT_CLICK
;
577 render_find_selected_objects_and_refresh_display (activeFileIndex
, eraseOldSelection
);
580 /* ------------------------------------------------------ */
582 render_fill_selection_buffer_from_mouse_drag (gint corner1X
, gint corner1Y
,
583 gint corner2X
, gint corner2Y
, gint activeFileIndex
, gboolean eraseOldSelection
) {
584 /* figure out the lower left corner of the box */
585 screen
.selectionInfo
.lowerLeftX
= MIN(corner1X
, corner2X
);
586 screen
.selectionInfo
.lowerLeftY
= MIN(corner1Y
, corner2Y
);
587 /* figure out the upper right corner of the box */
588 screen
.selectionInfo
.upperRightX
= MAX(corner1X
, corner2X
);
589 screen
.selectionInfo
.upperRightY
= MAX(corner1Y
, corner2Y
);
591 screen
.selectionInfo
.type
= GERBV_SELECTION_DRAG_BOX
;
592 render_find_selected_objects_and_refresh_display (activeFileIndex
, eraseOldSelection
);
595 /* ------------------------------------------------------ */
596 void render_recreate_composite_surface () {
599 if (!render_create_cairo_buffer_surface())
602 cairo_t
*cr
= cairo_create(screen
.bufferSurface
);
603 /* fill the background with the appropriate color */
604 cairo_set_source_rgba (cr
, (double) mainProject
->background
.red
/G_MAXUINT16
,
605 (double) mainProject
->background
.green
/G_MAXUINT16
,
606 (double) mainProject
->background
.blue
/G_MAXUINT16
, 1);
609 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
610 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
) {
611 cairo_set_source_surface (cr
, (cairo_surface_t
*) mainProject
->file
[i
]->privateRenderData
,
613 /* ignore alpha if we are in high-speed render mode */
614 if (((double) mainProject
->file
[i
]->alpha
< 65535)&&(screenRenderInfo
.renderType
!= 1)) {
615 cairo_paint_with_alpha(cr
,(double) mainProject
->file
[i
]->alpha
/G_MAXUINT16
);
622 /* render the selection layer at the end */
623 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
) {
624 cairo_set_source_surface (cr
, (cairo_surface_t
*) screen
.selectionRenderData
,
626 cairo_paint_with_alpha (cr
,1.0);
631 /* ------------------------------------------------------ */
632 void render_project_to_cairo_target (cairo_t
*cr
) {
633 /* fill the background with the appropriate color */
634 cairo_set_source_rgba (cr
, (double) mainProject
->background
.red
/G_MAXUINT16
,
635 (double) mainProject
->background
.green
/G_MAXUINT16
,
636 (double) mainProject
->background
.blue
/G_MAXUINT16
, 1);
639 cairo_set_source_surface (cr
, (cairo_surface_t
*) screen
.bufferSurface
, 0 , 0);
645 render_free_screen_resources (void) {
646 if (screen
.selectionRenderData
)
647 cairo_surface_destroy ((cairo_surface_t
*)
648 screen
.selectionRenderData
);
649 if (screen
.bufferSurface
)
650 cairo_surface_destroy ((cairo_surface_t
*)
651 screen
.bufferSurface
);
652 if (screen
.windowSurface
)
653 cairo_surface_destroy ((cairo_surface_t
*)
654 screen
.windowSurface
);
656 gdk_pixmap_unref(screen
.pixmap
);
660 /* ------------------------------------------------------------------ */
661 /*! This fills out the project's Gerber statistics table.
662 * It is called from within callbacks.c when the user
663 * asks for a Gerber report. */
665 generate_gerber_analysis(void)
668 gerbv_stats_t
*stats
;
669 gerbv_stats_t
*instats
;
671 /* Create new stats structure to hold report for whole project
672 * (i.e. all layers together) */
673 stats
= gerbv_stats_new();
675 /* Loop through open layers and compile statistics by accumulating reports from each layer */
676 for (i
= 0; i
<= mainProject
->last_loaded
; i
++) {
677 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
&&
678 (mainProject
->file
[i
]->image
->layertype
== GERBV_LAYERTYPE_RS274X
) ) {
679 instats
= mainProject
->file
[i
]->image
->gerbv_stats
;
680 gerbv_stats_add_layer(stats
, instats
, i
+1);
687 /* ------------------------------------------------------------------ */
688 /*! This fills out the project's Drill statistics table.
689 * It is called from within callbacks.c when the user
690 * asks for a Drill report. */
691 gerbv_drill_stats_t
*
692 generate_drill_analysis(void)
695 gerbv_drill_stats_t
*stats
;
696 gerbv_drill_stats_t
*instats
;
698 stats
= gerbv_drill_stats_new();
700 /* Loop through open layers and compile statistics by accumulating reports from each layer */
701 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
702 if (mainProject
->file
[i
] &&
703 mainProject
->file
[i
]->isVisible
&&
704 (mainProject
->file
[i
]->image
->layertype
== GERBV_LAYERTYPE_DRILL
) ) {
705 instats
= mainProject
->file
[i
]->image
->drill_stats
;
706 /* add this batch of stats. Send the layer
707 * index for error reporting */
708 gerbv_drill_stats_add_layer(stats
, instats
, i
+1);