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-quartz.h>
64 #include <cairo-xlib.h>
70 #define dprintf if(DEBUG) printf
72 /**Global variable to keep track of what's happening on the screen.
73 Declared extern in gerbv_screen.h
75 extern gerbv_screen_t screen
;
77 extern gerbv_render_info_t screenRenderInfo
;
81 render_layer_to_cairo_target_without_transforming(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo );
85 render_check_scale_factor_limits (void) {
86 if ((screenRenderInfo
.scaleFactorX
> 20000)||(screenRenderInfo
.scaleFactorY
> 20000)) {
87 screenRenderInfo
.scaleFactorX
= 20000;
88 screenRenderInfo
.scaleFactorY
= 20000;
94 /* ------------------------------------------------------ */
96 render_zoom_display (gint zoomType
, gdouble scaleFactor
, gdouble mouseX
, gdouble mouseY
) {
97 /*double us_midx, us_midy;*/ /* unscaled translation for screen center */
98 /*int half_w, half_h;*/ /* cache for half window dimensions */
99 gdouble mouseCoordinateX
= 0.0;
100 gdouble mouseCoordinateY
= 0.0;
101 double oldWidth
, oldHeight
;
104 half_w = screenRenderInfo.displayWidth / 2;
105 half_h = screenRenderInfo.displayHeight / 2;
108 oldWidth
= screenRenderInfo
.displayWidth
/ screenRenderInfo
.scaleFactorX
;
109 oldHeight
= screenRenderInfo
.displayHeight
/ screenRenderInfo
.scaleFactorY
;
110 if (zoomType
== ZOOM_IN_CMOUSE
|| zoomType
== ZOOM_OUT_CMOUSE
) {
111 /* calculate what user coordinate the mouse is pointing at */
112 mouseCoordinateX
= mouseX
/ screenRenderInfo
.scaleFactorX
+ screenRenderInfo
.lowerLeftX
;
113 mouseCoordinateY
= (screenRenderInfo
.displayHeight
- mouseY
) /
114 screenRenderInfo
.scaleFactorY
+ screenRenderInfo
.lowerLeftY
;
118 us_midx = screenRenderInfo.lowerLeftX + (screenRenderInfo.displayWidth / 2.0 )/
119 screenRenderInfo.scaleFactorX;
120 us_midy = screenRenderInfo.lowerLeftY + (screenRenderInfo.displayHeight / 2.0 )/
121 screenRenderInfo.scaleFactorY;
125 case ZOOM_IN
: /* Zoom In */
126 case ZOOM_IN_CMOUSE
: /* Zoom In Around Mouse Pointer */
127 screenRenderInfo
.scaleFactorX
+= screenRenderInfo
.scaleFactorX
/3;
128 screenRenderInfo
.scaleFactorY
+= screenRenderInfo
.scaleFactorY
/3;
129 (void) render_check_scale_factor_limits ();
130 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
131 screenRenderInfo
.scaleFactorX
)) / 2.0;
132 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
133 screenRenderInfo
.scaleFactorY
)) / 2.0;
135 case ZOOM_OUT
: /* Zoom Out */
136 case ZOOM_OUT_CMOUSE
: /* Zoom Out Around Mouse Pointer */
137 if ((screenRenderInfo
.scaleFactorX
> 10)&&(screenRenderInfo
.scaleFactorY
> 10)) {
138 screenRenderInfo
.scaleFactorX
-= screenRenderInfo
.scaleFactorX
/3;
139 screenRenderInfo
.scaleFactorY
-= screenRenderInfo
.scaleFactorY
/3;
140 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
141 screenRenderInfo
.scaleFactorX
)) / 2.0;
142 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
143 screenRenderInfo
.scaleFactorY
)) / 2.0;
146 case ZOOM_FIT
: /* Zoom Fit */
147 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
149 case ZOOM_SET
: /*explicit scale set by user */
150 screenRenderInfo
.scaleFactorX
= scaleFactor
;
151 screenRenderInfo
.scaleFactorY
= scaleFactor
;
152 (void) render_check_scale_factor_limits ();
153 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
154 screenRenderInfo
.scaleFactorX
)) / 2.0;
155 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
156 screenRenderInfo
.scaleFactorY
)) / 2.0;
159 GERB_MESSAGE("Illegal zoom direction %d\n", zoomType
);
162 if (zoomType
== ZOOM_IN_CMOUSE
|| zoomType
== ZOOM_OUT_CMOUSE
) {
163 /* make sure the mouse is still pointing at the point calculated earlier */
164 screenRenderInfo
.lowerLeftX
= mouseCoordinateX
- mouseX
/ screenRenderInfo
.scaleFactorX
;
165 screenRenderInfo
.lowerLeftY
= mouseCoordinateY
- (screenRenderInfo
.displayHeight
- mouseY
) /
166 screenRenderInfo
.scaleFactorY
;
168 render_refresh_rendered_image_on_screen();
173 /* --------------------------------------------------------- */
174 /** Will determine the outline of the zoomed regions.
175 * In case region to be zoomed is too small (which correspondes
176 * e.g. to a double click) it is interpreted as a right-click
177 * and will be used to identify a part from the CURRENT selection,
178 * which is drawn on screen*/
180 render_calculate_zoom_from_outline(GtkWidget
*widget
, GdkEventButton
*event
)
182 int x1
, y1
, x2
, y2
, dx
, dy
; /* Zoom outline (UR and LL corners) */
183 double centerPointX
, centerPointY
;
184 int half_x
, half_y
; /* cache for half window dimensions */
186 x1
= MIN(screen
.start_x
, event
->x
);
187 y1
= MIN(screen
.start_y
, event
->y
);
188 x2
= MAX(screen
.start_x
, event
->x
);
189 y2
= MAX(screen
.start_y
, event
->y
);
193 if ((dx
>= 4) && (dy
>= 4)) {
194 if (screen
.centered_outline_zoom
) {
195 /* Centered outline mode */
196 x1
= screen
.start_x
- dx
;
197 y1
= screen
.start_y
- dy
;
203 centerPointX
= half_x
/screenRenderInfo
.scaleFactorX
+ screenRenderInfo
.lowerLeftX
;
204 centerPointY
= (screenRenderInfo
.displayHeight
- half_y
)/screenRenderInfo
.scaleFactorY
+
205 screenRenderInfo
.lowerLeftY
;
207 screenRenderInfo
.scaleFactorX
*= MIN(((double)screenRenderInfo
.displayWidth
/ dx
),
208 ((double)screenRenderInfo
.displayHeight
/ dy
));
209 screenRenderInfo
.scaleFactorY
= screenRenderInfo
.scaleFactorX
;
210 (void) render_check_scale_factor_limits ();
211 screenRenderInfo
.lowerLeftX
= centerPointX
- (screenRenderInfo
.displayWidth
/
212 2.0 / screenRenderInfo
.scaleFactorX
);
213 screenRenderInfo
.lowerLeftY
= centerPointY
- (screenRenderInfo
.displayHeight
/
214 2.0 / screenRenderInfo
.scaleFactorY
);
216 render_refresh_rendered_image_on_screen();
219 /* ------------------------------------------------------ */
221 render_draw_selection_box_outline(void) {
224 GdkGCValuesMask values_mask
;
225 gint x1
, y1
, x2
, y2
, dx
, dy
;
227 memset(&values
, 0, sizeof(values
));
228 values
.function
= GDK_XOR
;
229 if (!screen
.zoom_outline_color
.pixel
)
230 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
231 values
.foreground
= screen
.zoom_outline_color
;
232 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
233 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
, values_mask
);
235 x1
= MIN(screen
.start_x
, screen
.last_x
);
236 y1
= MIN(screen
.start_y
, screen
.last_y
);
237 x2
= MAX(screen
.start_x
, screen
.last_x
);
238 y2
= MAX(screen
.start_y
, screen
.last_y
);
242 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, x1
, y1
, dx
, dy
);
246 /* --------------------------------------------------------- */
248 render_draw_zoom_outline(gboolean centered
)
252 GdkGCValuesMask values_mask
;
253 gint x1
, y1
, x2
, y2
, dx
, dy
;
255 memset(&values
, 0, sizeof(values
));
256 values
.function
= GDK_XOR
;
257 if (!screen
.zoom_outline_color
.pixel
)
258 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
259 values
.foreground
= screen
.zoom_outline_color
;
260 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
261 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
, values_mask
);
263 x1
= MIN(screen
.start_x
, screen
.last_x
);
264 y1
= MIN(screen
.start_y
, screen
.last_y
);
265 x2
= MAX(screen
.start_x
, screen
.last_x
);
266 y2
= MAX(screen
.start_y
, screen
.last_y
);
271 /* Centered outline mode */
272 x1
= screen
.start_x
- dx
;
273 y1
= screen
.start_y
- dy
;
280 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, x1
, y1
, dx
, dy
);
283 /* Draw actual zoom area in dashed lines */
284 memset(&values
, 0, sizeof(values
));
285 values
.function
= GDK_XOR
;
286 values
.foreground
= screen
.zoom_outline_color
;
287 values
.line_style
= GDK_LINE_ON_OFF_DASH
;
288 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
| GDK_GC_LINE_STYLE
;
289 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
,
292 if ((dy
== 0) || ((double)dx
/dy
> (double)screen
.drawing_area
->allocation
.width
/
293 screen
.drawing_area
->allocation
.height
)) {
294 dy
= dx
* (double)screen
.drawing_area
->allocation
.height
/
295 screen
.drawing_area
->allocation
.width
;
298 dx
= dy
* (double)screen
.drawing_area
->allocation
.width
/
299 screen
.drawing_area
->allocation
.height
;
302 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, (x1
+x2
-dx
)/2,
303 (y1
+y2
-dy
)/2, dx
, dy
);
308 /* ------------------------------------------------------ */
309 /* Transforms board coordinates to screen ones */
311 render_board2screen(gdouble
*X
, gdouble
*Y
, gdouble x
, gdouble y
) {
312 *X
= (x
- screenRenderInfo
.lowerLeftX
) * screenRenderInfo
.scaleFactorX
;
313 *Y
= screenRenderInfo
.displayHeight
- (y
- screenRenderInfo
.lowerLeftY
)
314 * screenRenderInfo
.scaleFactorY
;
317 /* Trims the coordinates to avoid overflows in gdk_draw_line */
319 render_trim_point(gdouble
*start_x
, gdouble
*start_y
, gdouble last_x
, gdouble last_y
)
321 const gdouble max_coord
= (1<<15) - 2;/* a value that causes no overflow
322 and lies out of screen */
325 if (fabs (*start_x
) < max_coord
&& fabs (*start_y
) < max_coord
)
328 dx
= last_x
- *start_x
;
329 dy
= last_y
- *start_y
;
331 if (*start_x
< -max_coord
) {
332 *start_x
= -max_coord
;
333 if (last_x
> -max_coord
&& fabs (dx
) > 0.1)
334 *start_y
= last_y
- (last_x
+ max_coord
) / dx
* dy
;
336 if (*start_x
> max_coord
) {
337 *start_x
= max_coord
;
338 if (last_x
< max_coord
&& fabs (dx
) > 0.1)
339 *start_y
= last_y
- (last_x
- max_coord
) / dx
* dy
;
342 dx
= last_x
- *start_x
;
343 dy
= last_y
- *start_y
;
345 if (*start_y
< -max_coord
) {
346 *start_y
= -max_coord
;
347 if (last_y
> -max_coord
&& fabs (dy
) > 0.1)
348 *start_x
= last_x
- (last_y
+ max_coord
) / dy
* dx
;
350 if (*start_y
> max_coord
) {
351 *start_y
= max_coord
;
352 if (last_y
< max_coord
&& fabs (dy
) > 0.1)
353 *start_x
= last_x
- (last_y
- max_coord
) / dy
* dx
;
357 /* ------------------------------------------------------ */
358 /** Draws/erases measure line
361 render_toggle_measure_line(void)
366 GdkGCValuesMask values_mask
;
367 gdouble start_x
, start_y
, last_x
, last_y
;
368 memset(&values
, 0, sizeof(values
));
369 values
.function
= GDK_XOR
;
370 if (!screen
.zoom_outline_color
.pixel
)
371 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
372 values
.foreground
= screen
.zoom_outline_color
;
373 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
374 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
,
376 render_board2screen(&start_x
, &start_y
,
377 screen
.measure_start_x
, screen
.measure_start_y
);
378 render_board2screen(&last_x
, &last_y
,
379 screen
.measure_last_x
, screen
.measure_last_y
);
380 render_trim_point(&start_x
, &start_y
, last_x
, last_y
);
381 render_trim_point(&last_x
, &last_y
, start_x
, start_y
);
382 gdk_draw_line(screen
.drawing_area
->window
, gc
, start_x
,
383 start_y
, last_x
, last_y
);
385 } /* toggle_measure_line */
387 /* ------------------------------------------------------ */
388 /** Displays a measured distance graphically on screen and in statusbar. */
390 render_draw_measure_distance(void)
392 gdouble x1
, y1
, x2
, y2
;
395 x1
= MIN(screen
.measure_start_x
, screen
.measure_last_x
);
396 y1
= MIN(screen
.measure_start_y
, screen
.measure_last_y
);
397 x2
= MAX(screen
.measure_start_x
, screen
.measure_last_x
);
398 y2
= MAX(screen
.measure_start_y
, screen
.measure_last_y
);
402 screen
.win
.lastMeasuredX
= dx
;
403 screen
.win
.lastMeasuredY
= dy
;
404 callbacks_update_statusbar_measured_distance (dx
, dy
);
405 render_toggle_measure_line();
406 } /* draw_measure_distance */
408 /* ------------------------------------------------------ */
409 void render_selection_layer (void){
412 if (screen
.selectionRenderData
)
413 cairo_surface_destroy ((cairo_surface_t
*) screen
.selectionRenderData
);
414 screen
.selectionRenderData
=
415 (gpointer
) cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
416 CAIRO_CONTENT_COLOR_ALPHA
, screenRenderInfo
.displayWidth
,
417 screenRenderInfo
.displayHeight
);
418 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
) {
419 cr
= cairo_create(screen
.selectionRenderData
);
420 gerbv_render_cairo_set_scale_and_translation(cr
, &screenRenderInfo
);
421 cairo_set_source_rgba (cr
, 1.0, 1.0, 1.0, 0.85);
422 /* for now, assume everything in the selection buffer is from one image */
423 gerbv_image_t
*matchImage
;
425 if (screen
.selectionInfo
.selectedNodeArray
->len
> 0) {
426 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
427 gerbv_selection_item_t
, 0);
428 matchImage
= (gerbv_image_t
*) sItem
.image
;
429 dprintf(" .... calling render_image_to_cairo_target on selection layer...\n");
430 for(j
= mainProject
->last_loaded
; j
>= 0; j
--) {
431 if ((mainProject
->file
[j
]) && (mainProject
->file
[j
]->image
== matchImage
)) {
432 draw_image_to_cairo_target (cr
, mainProject
->file
[j
]->image
,
433 1.0/MAX(screenRenderInfo
.scaleFactorX
,
434 screenRenderInfo
.scaleFactorY
),
435 DRAW_SELECTIONS
, &screen
.selectionInfo
, &screenRenderInfo
,
436 TRUE
, mainProject
->file
[j
]->transform
, TRUE
);
444 /* ------------------------------------------------------ */
445 void render_refresh_rendered_image_on_screen (void) {
448 dprintf("----> Entering redraw_pixmap...\n");
449 cursor
= gdk_cursor_new(GDK_WATCH
);
450 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
), cursor
);
451 gdk_cursor_destroy(cursor
);
453 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
){
455 gdk_pixmap_unref(screen
.pixmap
);
456 screen
.pixmap
= gdk_pixmap_new(screen
.drawing_area
->window
, screenRenderInfo
.displayWidth
,
457 screenRenderInfo
.displayHeight
, -1);
458 gerbv_render_to_pixmap_using_gdk (mainProject
, screen
.pixmap
, &screenRenderInfo
, &screen
.selectionInfo
,
459 &screen
.selection_color
);
460 dprintf("<---- leaving redraw_pixmap.\n");
464 dprintf(" .... Now try rendering the drawing using cairo .... \n");
466 * This now allows drawing several layers on top of each other.
467 * Higher layer numbers have higher priority in the Z-order.
469 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
470 if (mainProject
->file
[i
]) {
472 if (mainProject
->file
[i
]->privateRenderData
)
473 cairo_surface_destroy ((cairo_surface_t
*) mainProject
->file
[i
]->privateRenderData
);
474 mainProject
->file
[i
]->privateRenderData
=
475 (gpointer
) cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
476 CAIRO_CONTENT_COLOR_ALPHA
, screenRenderInfo
.displayWidth
,
477 screenRenderInfo
.displayHeight
);
478 cr
= cairo_create(mainProject
->file
[i
]->privateRenderData
);
479 gerbv_render_layer_to_cairo_target (cr
, mainProject
->file
[i
], &screenRenderInfo
);
480 dprintf(" .... calling render_image_to_cairo_target on layer %d...\n", i
);
484 /* render the selection layer */
485 render_selection_layer();
487 render_recreate_composite_surface ();
489 /* remove watch cursor and switch back to normal cursor */
490 callbacks_switch_to_correct_cursor ();
491 callbacks_force_expose_event_for_screen();
494 /* ------------------------------------------------------ */
496 render_clear_selection_buffer (void){
497 if (screen
.selectionInfo
.type
== GERBV_SELECTION_EMPTY
)
500 g_array_remove_range (screen
.selectionInfo
.selectedNodeArray
, 0,
501 screen
.selectionInfo
.selectedNodeArray
->len
);
502 screen
.selectionInfo
.type
= GERBV_SELECTION_EMPTY
;
503 callbacks_update_selected_object_message (FALSE
);
507 render_remove_selected_objects_belonging_to_layer (gint index
) {
510 for (i
=screen
.selectionInfo
.selectedNodeArray
->len
-1; i
>=0; i
--) {
511 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
512 gerbv_selection_item_t
, i
);
514 gerbv_image_t
*matchImage
= (gerbv_image_t
*) sItem
.image
;
515 if (mainProject
->file
[index
]->image
== matchImage
) {
516 g_array_remove_index (screen
.selectionInfo
.selectedNodeArray
, index
);
519 callbacks_update_selected_object_message (FALSE
);
522 /* ------------------------------------------------------ */
524 render_create_cairo_buffer_surface () {
525 if (screen
.bufferSurface
) {
526 cairo_surface_destroy (screen
.bufferSurface
);
527 screen
.bufferSurface
= NULL
;
529 if (!screen
.windowSurface
)
532 screen
.bufferSurface
= cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
533 CAIRO_CONTENT_COLOR
, screenRenderInfo
.displayWidth
,
534 screenRenderInfo
.displayHeight
);
538 /* ------------------------------------------------------ */
540 render_find_selected_objects_and_refresh_display (gint activeFileIndex
, gboolean eraseOldSelection
){
541 /* clear the old selection array if desired */
542 if ((eraseOldSelection
)&&(screen
.selectionInfo
.selectedNodeArray
->len
))
543 g_array_remove_range (screen
.selectionInfo
.selectedNodeArray
, 0,
544 screen
.selectionInfo
.selectedNodeArray
->len
);
546 /* make sure we have a bufferSurface...if we start up in FAST mode, we may not
547 have one yet, but we need it for selections */
548 if (!render_create_cairo_buffer_surface())
551 /* call draw_image... passing the FILL_SELECTION mode to just search for
552 nets which match the selection, and fill the selection buffer with them */
553 cairo_t
*cr
= cairo_create(screen
.bufferSurface
);
554 gerbv_render_cairo_set_scale_and_translation(cr
,&screenRenderInfo
);
555 draw_image_to_cairo_target (cr
, mainProject
->file
[activeFileIndex
]->image
,
556 1.0/MAX(screenRenderInfo
.scaleFactorX
, screenRenderInfo
.scaleFactorY
),
557 FIND_SELECTIONS
, &screen
.selectionInfo
, &screenRenderInfo
, TRUE
,
558 mainProject
->file
[activeFileIndex
]->transform
, TRUE
);
560 /* if the selection array is empty, switch the "mode" to empty to make it
561 easier to check if it is holding anything */
562 if (!screen
.selectionInfo
.selectedNodeArray
->len
)
563 screen
.selectionInfo
.type
= GERBV_SELECTION_EMPTY
;
564 /* re-render the selection buffer layer */
565 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
){
566 render_refresh_rendered_image_on_screen ();
569 render_selection_layer();
570 render_recreate_composite_surface ();
571 callbacks_force_expose_event_for_screen();
575 /* ------------------------------------------------------ */
577 render_fill_selection_buffer_from_mouse_click (gint mouseX
, gint mouseY
, gint activeFileIndex
,
578 gboolean eraseOldSelection
) {
579 screen
.selectionInfo
.lowerLeftX
= mouseX
;
580 screen
.selectionInfo
.lowerLeftY
= mouseY
;
581 /* no need to populate the upperright coordinates for a point_click */
582 screen
.selectionInfo
.type
= GERBV_SELECTION_POINT_CLICK
;
583 render_find_selected_objects_and_refresh_display (activeFileIndex
, eraseOldSelection
);
586 /* ------------------------------------------------------ */
588 render_fill_selection_buffer_from_mouse_drag (gint corner1X
, gint corner1Y
,
589 gint corner2X
, gint corner2Y
, gint activeFileIndex
, gboolean eraseOldSelection
) {
590 /* figure out the lower left corner of the box */
591 screen
.selectionInfo
.lowerLeftX
= MIN(corner1X
, corner2X
);
592 screen
.selectionInfo
.lowerLeftY
= MIN(corner1Y
, corner2Y
);
593 /* figure out the upper right corner of the box */
594 screen
.selectionInfo
.upperRightX
= MAX(corner1X
, corner2X
);
595 screen
.selectionInfo
.upperRightY
= MAX(corner1Y
, corner2Y
);
597 screen
.selectionInfo
.type
= GERBV_SELECTION_DRAG_BOX
;
598 render_find_selected_objects_and_refresh_display (activeFileIndex
, eraseOldSelection
);
601 /* ------------------------------------------------------ */
602 void render_recreate_composite_surface () {
605 if (!render_create_cairo_buffer_surface())
608 cairo_t
*cr
= cairo_create(screen
.bufferSurface
);
609 /* fill the background with the appropriate color */
610 cairo_set_source_rgba (cr
, (double) mainProject
->background
.red
/G_MAXUINT16
,
611 (double) mainProject
->background
.green
/G_MAXUINT16
,
612 (double) mainProject
->background
.blue
/G_MAXUINT16
, 1);
615 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
616 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
) {
617 cairo_set_source_surface (cr
, (cairo_surface_t
*) mainProject
->file
[i
]->privateRenderData
,
619 /* ignore alpha if we are in high-speed render mode */
620 if (((double) mainProject
->file
[i
]->alpha
< 65535)&&(screenRenderInfo
.renderType
!= GERBV_RENDER_TYPE_GDK_XOR
)) {
621 cairo_paint_with_alpha(cr
,(double) mainProject
->file
[i
]->alpha
/G_MAXUINT16
);
628 /* render the selection layer at the end */
629 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
) {
630 cairo_set_source_surface (cr
, (cairo_surface_t
*) screen
.selectionRenderData
,
632 cairo_paint_with_alpha (cr
,1.0);
637 /* ------------------------------------------------------ */
638 void render_project_to_cairo_target (cairo_t
*cr
) {
639 /* fill the background with the appropriate color */
640 cairo_set_source_rgba (cr
, (double) mainProject
->background
.red
/G_MAXUINT16
,
641 (double) mainProject
->background
.green
/G_MAXUINT16
,
642 (double) mainProject
->background
.blue
/G_MAXUINT16
, 1);
645 cairo_set_source_surface (cr
, (cairo_surface_t
*) screen
.bufferSurface
, 0 , 0);
651 render_free_screen_resources (void) {
652 if (screen
.selectionRenderData
)
653 cairo_surface_destroy ((cairo_surface_t
*)
654 screen
.selectionRenderData
);
655 if (screen
.bufferSurface
)
656 cairo_surface_destroy ((cairo_surface_t
*)
657 screen
.bufferSurface
);
658 if (screen
.windowSurface
)
659 cairo_surface_destroy ((cairo_surface_t
*)
660 screen
.windowSurface
);
662 gdk_pixmap_unref(screen
.pixmap
);
666 /* ------------------------------------------------------------------ */
667 /*! This fills out the project's Gerber statistics table.
668 * It is called from within callbacks.c when the user
669 * asks for a Gerber report. */
671 generate_gerber_analysis(void)
674 gerbv_stats_t
*stats
;
675 gerbv_stats_t
*instats
;
677 /* Create new stats structure to hold report for whole project
678 * (i.e. all layers together) */
679 stats
= gerbv_stats_new();
681 /* Loop through open layers and compile statistics by accumulating reports from each layer */
682 for (i
= 0; i
<= mainProject
->last_loaded
; i
++) {
683 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
&&
684 (mainProject
->file
[i
]->image
->layertype
== GERBV_LAYERTYPE_RS274X
) ) {
685 instats
= mainProject
->file
[i
]->image
->gerbv_stats
;
686 gerbv_stats_add_layer(stats
, instats
, i
+1);
693 /* ------------------------------------------------------------------ */
694 /*! This fills out the project's Drill statistics table.
695 * It is called from within callbacks.c when the user
696 * asks for a Drill report. */
697 gerbv_drill_stats_t
*
698 generate_drill_analysis(void)
701 gerbv_drill_stats_t
*stats
;
702 gerbv_drill_stats_t
*instats
;
704 stats
= gerbv_drill_stats_new();
706 /* Loop through open layers and compile statistics by accumulating reports from each layer */
707 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
708 if (mainProject
->file
[i
] &&
709 mainProject
->file
[i
]->isVisible
&&
710 (mainProject
->file
[i
]->image
->layertype
== GERBV_LAYERTYPE_DRILL
) ) {
711 instats
= mainProject
->file
[i
]->image
->drill_stats
;
712 /* add this batch of stats. Send the layer
713 * index for error reporting */
714 gerbv_drill_stats_add_layer(stats
, instats
, i
+1);