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
;
103 half_w
= screenRenderInfo
.displayWidth
/ 2;
104 half_h
= screenRenderInfo
.displayHeight
/ 2;
106 oldWidth
= screenRenderInfo
.displayWidth
/ screenRenderInfo
.scaleFactorX
;
107 oldHeight
= screenRenderInfo
.displayHeight
/ screenRenderInfo
.scaleFactorY
;
108 if (zoomType
== ZOOM_IN_CMOUSE
|| zoomType
== ZOOM_OUT_CMOUSE
) {
109 /* calculate what user coordinate the mouse is pointing at */
110 mouseCoordinateX
= mouseX
/ screenRenderInfo
.scaleFactorX
+ screenRenderInfo
.lowerLeftX
;
111 mouseCoordinateY
= (screenRenderInfo
.displayHeight
- mouseY
) /
112 screenRenderInfo
.scaleFactorY
+ screenRenderInfo
.lowerLeftY
;
115 us_midx
= screenRenderInfo
.lowerLeftX
+ (screenRenderInfo
.displayWidth
/ 2.0 )/
116 screenRenderInfo
.scaleFactorX
;
117 us_midy
= screenRenderInfo
.lowerLeftY
+ (screenRenderInfo
.displayHeight
/ 2.0 )/
118 screenRenderInfo
.scaleFactorY
;
121 case ZOOM_IN
: /* Zoom In */
122 case ZOOM_IN_CMOUSE
: /* Zoom In Around Mouse Pointer */
123 screenRenderInfo
.scaleFactorX
+= screenRenderInfo
.scaleFactorX
/3;
124 screenRenderInfo
.scaleFactorY
+= screenRenderInfo
.scaleFactorY
/3;
125 (void) render_check_scale_factor_limits ();
126 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
127 screenRenderInfo
.scaleFactorX
)) / 2.0;
128 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
129 screenRenderInfo
.scaleFactorY
)) / 2.0;
131 case ZOOM_OUT
: /* Zoom Out */
132 case ZOOM_OUT_CMOUSE
: /* Zoom Out Around Mouse Pointer */
133 if ((screenRenderInfo
.scaleFactorX
> 10)&&(screenRenderInfo
.scaleFactorY
> 10)) {
134 screenRenderInfo
.scaleFactorX
-= screenRenderInfo
.scaleFactorX
/3;
135 screenRenderInfo
.scaleFactorY
-= screenRenderInfo
.scaleFactorY
/3;
136 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
137 screenRenderInfo
.scaleFactorX
)) / 2.0;
138 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
139 screenRenderInfo
.scaleFactorY
)) / 2.0;
142 case ZOOM_FIT
: /* Zoom Fit */
143 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
145 case ZOOM_SET
: /*explicit scale set by user */
146 screenRenderInfo
.scaleFactorX
= scaleFactor
;
147 screenRenderInfo
.scaleFactorY
= scaleFactor
;
148 (void) render_check_scale_factor_limits ();
149 screenRenderInfo
.lowerLeftX
+= (oldWidth
- (screenRenderInfo
.displayWidth
/
150 screenRenderInfo
.scaleFactorX
)) / 2.0;
151 screenRenderInfo
.lowerLeftY
+= (oldHeight
- (screenRenderInfo
.displayHeight
/
152 screenRenderInfo
.scaleFactorY
)) / 2.0;
155 GERB_MESSAGE("Illegal zoom direction %d\n", zoomType
);
158 if (zoomType
== ZOOM_IN_CMOUSE
|| zoomType
== ZOOM_OUT_CMOUSE
) {
159 /* make sure the mouse is still pointing at the point calculated earlier */
160 screenRenderInfo
.lowerLeftX
= mouseCoordinateX
- mouseX
/ screenRenderInfo
.scaleFactorX
;
161 screenRenderInfo
.lowerLeftY
= mouseCoordinateY
- (screenRenderInfo
.displayHeight
- mouseY
) /
162 screenRenderInfo
.scaleFactorY
;
164 render_refresh_rendered_image_on_screen();
169 /* --------------------------------------------------------- */
170 /** Will determine the outline of the zoomed regions.
171 * In case region to be zoomed is too small (which correspondes
172 * e.g. to a double click) it is interpreted as a right-click
173 * and will be used to identify a part from the CURRENT selection,
174 * which is drawn on screen*/
176 render_calculate_zoom_from_outline(GtkWidget
*widget
, GdkEventButton
*event
)
178 int x1
, y1
, x2
, y2
, dx
, dy
; /* Zoom outline (UR and LL corners) */
179 double centerPointX
, centerPointY
;
180 int half_x
, half_y
; /* cache for half window dimensions */
182 x1
= MIN(screen
.start_x
, event
->x
);
183 y1
= MIN(screen
.start_y
, event
->y
);
184 x2
= MAX(screen
.start_x
, event
->x
);
185 y2
= MAX(screen
.start_y
, event
->y
);
189 if ((dx
>= 4) && (dy
>= 4)) {
190 if (screen
.centered_outline_zoom
) {
191 /* Centered outline mode */
192 x1
= screen
.start_x
- dx
;
193 y1
= screen
.start_y
- dy
;
199 centerPointX
= half_x
/screenRenderInfo
.scaleFactorX
+ screenRenderInfo
.lowerLeftX
;
200 centerPointY
= (screenRenderInfo
.displayHeight
- half_y
)/screenRenderInfo
.scaleFactorY
+
201 screenRenderInfo
.lowerLeftY
;
203 screenRenderInfo
.scaleFactorX
*= MIN(((double)screenRenderInfo
.displayWidth
/ dx
),
204 ((double)screenRenderInfo
.displayHeight
/ dy
));
205 screenRenderInfo
.scaleFactorY
= screenRenderInfo
.scaleFactorX
;
206 (void) render_check_scale_factor_limits ();
207 screenRenderInfo
.lowerLeftX
= centerPointX
- (screenRenderInfo
.displayWidth
/
208 2.0 / screenRenderInfo
.scaleFactorX
);
209 screenRenderInfo
.lowerLeftY
= centerPointY
- (screenRenderInfo
.displayHeight
/
210 2.0 / screenRenderInfo
.scaleFactorY
);
212 render_refresh_rendered_image_on_screen();
215 /* ------------------------------------------------------ */
217 render_draw_selection_box_outline(void) {
220 GdkGCValuesMask values_mask
;
221 gint x1
, y1
, x2
, y2
, dx
, dy
;
223 memset(&values
, 0, sizeof(values
));
224 values
.function
= GDK_XOR
;
225 if (!screen
.zoom_outline_color
.pixel
)
226 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
227 values
.foreground
= screen
.zoom_outline_color
;
228 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
229 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
, values_mask
);
231 x1
= MIN(screen
.start_x
, screen
.last_x
);
232 y1
= MIN(screen
.start_y
, screen
.last_y
);
233 x2
= MAX(screen
.start_x
, screen
.last_x
);
234 y2
= MAX(screen
.start_y
, screen
.last_y
);
238 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, x1
, y1
, dx
, dy
);
242 /* --------------------------------------------------------- */
244 render_draw_zoom_outline(gboolean centered
)
248 GdkGCValuesMask values_mask
;
249 gint x1
, y1
, x2
, y2
, dx
, dy
;
251 memset(&values
, 0, sizeof(values
));
252 values
.function
= GDK_XOR
;
253 if (!screen
.zoom_outline_color
.pixel
)
254 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
255 values
.foreground
= screen
.zoom_outline_color
;
256 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
257 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
, values_mask
);
259 x1
= MIN(screen
.start_x
, screen
.last_x
);
260 y1
= MIN(screen
.start_y
, screen
.last_y
);
261 x2
= MAX(screen
.start_x
, screen
.last_x
);
262 y2
= MAX(screen
.start_y
, screen
.last_y
);
267 /* Centered outline mode */
268 x1
= screen
.start_x
- dx
;
269 y1
= screen
.start_y
- dy
;
276 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, x1
, y1
, dx
, dy
);
279 /* Draw actual zoom area in dashed lines */
280 memset(&values
, 0, sizeof(values
));
281 values
.function
= GDK_XOR
;
282 values
.foreground
= screen
.zoom_outline_color
;
283 values
.line_style
= GDK_LINE_ON_OFF_DASH
;
284 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
| GDK_GC_LINE_STYLE
;
285 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
,
288 if ((dy
== 0) || ((double)dx
/dy
> (double)screen
.drawing_area
->allocation
.width
/
289 screen
.drawing_area
->allocation
.height
)) {
290 dy
= dx
* (double)screen
.drawing_area
->allocation
.height
/
291 screen
.drawing_area
->allocation
.width
;
294 dx
= dy
* (double)screen
.drawing_area
->allocation
.width
/
295 screen
.drawing_area
->allocation
.height
;
298 gdk_draw_rectangle(screen
.drawing_area
->window
, gc
, FALSE
, (x1
+x2
-dx
)/2,
299 (y1
+y2
-dy
)/2, dx
, dy
);
304 /* ------------------------------------------------------ */
305 /* Transforms board coordinates to screen ones */
307 render_board2screen(gdouble
*X
, gdouble
*Y
, gdouble x
, gdouble y
) {
308 *X
= (x
- screenRenderInfo
.lowerLeftX
) * screenRenderInfo
.scaleFactorX
;
309 *Y
= screenRenderInfo
.displayHeight
- (y
- screenRenderInfo
.lowerLeftY
)
310 * screenRenderInfo
.scaleFactorY
;
313 /* Trims the coordinates to avoid overflows in gdk_draw_line */
315 render_trim_point(gdouble
*start_x
, gdouble
*start_y
, gdouble last_x
, gdouble last_y
)
317 const gdouble max_coord
= (1<<15) - 2;/* a value that causes no overflow
318 and lies out of screen */
321 if (fabs (*start_x
) < max_coord
&& fabs (*start_y
) < max_coord
)
324 dx
= last_x
- *start_x
;
325 dy
= last_y
- *start_y
;
327 if (*start_x
< -max_coord
) {
328 *start_x
= -max_coord
;
329 if (last_x
> -max_coord
&& fabs (dx
) > 0.1)
330 *start_y
= last_y
- (last_x
+ max_coord
) / dx
* dy
;
332 if (*start_x
> max_coord
) {
333 *start_x
= max_coord
;
334 if (last_x
< max_coord
&& fabs (dx
) > 0.1)
335 *start_y
= last_y
- (last_x
- max_coord
) / dx
* dy
;
338 dx
= last_x
- *start_x
;
339 dy
= last_y
- *start_y
;
341 if (*start_y
< -max_coord
) {
342 *start_y
= -max_coord
;
343 if (last_y
> -max_coord
&& fabs (dy
) > 0.1)
344 *start_x
= last_x
- (last_y
+ max_coord
) / dy
* dx
;
346 if (*start_y
> max_coord
) {
347 *start_y
= max_coord
;
348 if (last_y
< max_coord
&& fabs (dy
) > 0.1)
349 *start_x
= last_x
- (last_y
- max_coord
) / dy
* dx
;
353 /* ------------------------------------------------------ */
354 /** Draws/erases measure line
357 render_toggle_measure_line(void)
362 GdkGCValuesMask values_mask
;
363 gdouble start_x
, start_y
, last_x
, last_y
;
364 memset(&values
, 0, sizeof(values
));
365 values
.function
= GDK_XOR
;
366 if (!screen
.zoom_outline_color
.pixel
)
367 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen
.zoom_outline_color
, FALSE
, TRUE
);
368 values
.foreground
= screen
.zoom_outline_color
;
369 values_mask
= GDK_GC_FUNCTION
| GDK_GC_FOREGROUND
;
370 gc
= gdk_gc_new_with_values(screen
.drawing_area
->window
, &values
,
372 render_board2screen(&start_x
, &start_y
,
373 screen
.measure_start_x
, screen
.measure_start_y
);
374 render_board2screen(&last_x
, &last_y
,
375 screen
.measure_last_x
, screen
.measure_last_y
);
376 render_trim_point(&start_x
, &start_y
, last_x
, last_y
);
377 render_trim_point(&last_x
, &last_y
, start_x
, start_y
);
378 gdk_draw_line(screen
.drawing_area
->window
, gc
, start_x
,
379 start_y
, last_x
, last_y
);
381 } /* toggle_measure_line */
383 /* ------------------------------------------------------ */
384 /** Displays a measured distance graphically on screen and in statusbar. */
386 render_draw_measure_distance(void)
388 gdouble x1
, y1
, x2
, y2
;
391 x1
= MIN(screen
.measure_start_x
, screen
.measure_last_x
);
392 y1
= MIN(screen
.measure_start_y
, screen
.measure_last_y
);
393 x2
= MAX(screen
.measure_start_x
, screen
.measure_last_x
);
394 y2
= MAX(screen
.measure_start_y
, screen
.measure_last_y
);
398 screen
.win
.lastMeasuredX
= dx
;
399 screen
.win
.lastMeasuredY
= dy
;
400 callbacks_update_statusbar_measured_distance (dx
, dy
);
401 render_toggle_measure_line();
402 } /* draw_measure_distance */
404 /* ------------------------------------------------------ */
405 void render_selection_layer (void){
408 if (screen
.selectionRenderData
)
409 cairo_surface_destroy ((cairo_surface_t
*) screen
.selectionRenderData
);
410 screen
.selectionRenderData
=
411 (gpointer
) cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
412 CAIRO_CONTENT_COLOR_ALPHA
, screenRenderInfo
.displayWidth
,
413 screenRenderInfo
.displayHeight
);
414 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
) {
415 cr
= cairo_create(screen
.selectionRenderData
);
416 gerbv_render_cairo_set_scale_and_translation(cr
, &screenRenderInfo
);
417 cairo_set_source_rgba (cr
, 1.0, 1.0, 1.0, 0.85);
418 /* for now, assume everything in the selection buffer is from one image */
419 gerbv_image_t
*matchImage
;
421 if (screen
.selectionInfo
.selectedNodeArray
->len
> 0) {
422 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
423 gerbv_selection_item_t
, 0);
424 matchImage
= (gerbv_image_t
*) sItem
.image
;
425 dprintf(" .... calling render_image_to_cairo_target on selection layer...\n");
426 for(j
= mainProject
->last_loaded
; j
>= 0; j
--) {
427 if ((mainProject
->file
[j
]) && (mainProject
->file
[j
]->image
== matchImage
)) {
428 draw_image_to_cairo_target (cr
, mainProject
->file
[j
]->image
,
429 1.0/MAX(screenRenderInfo
.scaleFactorX
,
430 screenRenderInfo
.scaleFactorY
),
431 DRAW_SELECTIONS
, &screen
.selectionInfo
, &screenRenderInfo
,
432 TRUE
, mainProject
->file
[j
]->transform
, TRUE
);
440 /* ------------------------------------------------------ */
441 void render_refresh_rendered_image_on_screen (void) {
444 dprintf("----> Entering redraw_pixmap...\n");
445 cursor
= gdk_cursor_new(GDK_WATCH
);
446 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
), cursor
);
447 gdk_cursor_destroy(cursor
);
449 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
){
451 gdk_pixmap_unref(screen
.pixmap
);
452 screen
.pixmap
= gdk_pixmap_new(screen
.drawing_area
->window
, screenRenderInfo
.displayWidth
,
453 screenRenderInfo
.displayHeight
, -1);
454 gerbv_render_to_pixmap_using_gdk (mainProject
, screen
.pixmap
, &screenRenderInfo
, &screen
.selectionInfo
,
455 &screen
.selection_color
);
456 dprintf("<---- leaving redraw_pixmap.\n");
460 dprintf(" .... Now try rendering the drawing using cairo .... \n");
462 * This now allows drawing several layers on top of each other.
463 * Higher layer numbers have higher priority in the Z-order.
465 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
466 if (mainProject
->file
[i
]) {
468 if (mainProject
->file
[i
]->privateRenderData
)
469 cairo_surface_destroy ((cairo_surface_t
*) mainProject
->file
[i
]->privateRenderData
);
470 mainProject
->file
[i
]->privateRenderData
=
471 (gpointer
) cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
472 CAIRO_CONTENT_COLOR_ALPHA
, screenRenderInfo
.displayWidth
,
473 screenRenderInfo
.displayHeight
);
474 cr
= cairo_create(mainProject
->file
[i
]->privateRenderData
);
475 gerbv_render_layer_to_cairo_target (cr
, mainProject
->file
[i
], &screenRenderInfo
);
476 dprintf(" .... calling render_image_to_cairo_target on layer %d...\n", i
);
480 /* render the selection layer */
481 render_selection_layer();
483 render_recreate_composite_surface ();
485 /* remove watch cursor and switch back to normal cursor */
486 callbacks_switch_to_correct_cursor ();
487 callbacks_force_expose_event_for_screen();
490 /* ------------------------------------------------------ */
492 render_clear_selection_buffer (void){
493 if (screen
.selectionInfo
.type
== GERBV_SELECTION_EMPTY
)
496 g_array_remove_range (screen
.selectionInfo
.selectedNodeArray
, 0,
497 screen
.selectionInfo
.selectedNodeArray
->len
);
498 screen
.selectionInfo
.type
= GERBV_SELECTION_EMPTY
;
499 callbacks_update_selected_object_message (FALSE
);
503 render_remove_selected_objects_belonging_to_layer (gint index
) {
506 for (i
=screen
.selectionInfo
.selectedNodeArray
->len
-1; i
>=0; i
--) {
507 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
508 gerbv_selection_item_t
, i
);
510 gerbv_image_t
*matchImage
= (gerbv_image_t
*) sItem
.image
;
511 if (mainProject
->file
[index
]->image
== matchImage
) {
512 g_array_remove_index (screen
.selectionInfo
.selectedNodeArray
, index
);
515 callbacks_update_selected_object_message (FALSE
);
518 /* ------------------------------------------------------ */
520 render_create_cairo_buffer_surface () {
521 if (screen
.bufferSurface
) {
522 cairo_surface_destroy (screen
.bufferSurface
);
523 screen
.bufferSurface
= NULL
;
525 if (!screen
.windowSurface
)
528 screen
.bufferSurface
= cairo_surface_create_similar ((cairo_surface_t
*)screen
.windowSurface
,
529 CAIRO_CONTENT_COLOR
, screenRenderInfo
.displayWidth
,
530 screenRenderInfo
.displayHeight
);
534 /* ------------------------------------------------------ */
536 render_find_selected_objects_and_refresh_display (gint activeFileIndex
, gboolean eraseOldSelection
){
537 /* clear the old selection array if desired */
538 if ((eraseOldSelection
)&&(screen
.selectionInfo
.selectedNodeArray
->len
))
539 g_array_remove_range (screen
.selectionInfo
.selectedNodeArray
, 0,
540 screen
.selectionInfo
.selectedNodeArray
->len
);
542 /* make sure we have a bufferSurface...if we start up in FAST mode, we may not
543 have one yet, but we need it for selections */
544 if (!render_create_cairo_buffer_surface())
547 /* call draw_image... passing the FILL_SELECTION mode to just search for
548 nets which match the selection, and fill the selection buffer with them */
549 cairo_t
*cr
= cairo_create(screen
.bufferSurface
);
550 gerbv_render_cairo_set_scale_and_translation(cr
,&screenRenderInfo
);
551 draw_image_to_cairo_target (cr
, mainProject
->file
[activeFileIndex
]->image
,
552 1.0/MAX(screenRenderInfo
.scaleFactorX
, screenRenderInfo
.scaleFactorY
),
553 FIND_SELECTIONS
, &screen
.selectionInfo
, &screenRenderInfo
, TRUE
,
554 mainProject
->file
[activeFileIndex
]->transform
, TRUE
);
556 /* if the selection array is empty, switch the "mode" to empty to make it
557 easier to check if it is holding anything */
558 if (!screen
.selectionInfo
.selectedNodeArray
->len
)
559 screen
.selectionInfo
.type
= GERBV_SELECTION_EMPTY
;
560 /* re-render the selection buffer layer */
561 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
){
562 render_refresh_rendered_image_on_screen ();
565 render_selection_layer();
566 render_recreate_composite_surface ();
567 callbacks_force_expose_event_for_screen();
571 /* ------------------------------------------------------ */
573 render_fill_selection_buffer_from_mouse_click (gint mouseX
, gint mouseY
, gint activeFileIndex
,
574 gboolean eraseOldSelection
) {
575 screen
.selectionInfo
.lowerLeftX
= mouseX
;
576 screen
.selectionInfo
.lowerLeftY
= mouseY
;
577 /* no need to populate the upperright coordinates for a point_click */
578 screen
.selectionInfo
.type
= GERBV_SELECTION_POINT_CLICK
;
579 render_find_selected_objects_and_refresh_display (activeFileIndex
, eraseOldSelection
);
582 /* ------------------------------------------------------ */
584 render_fill_selection_buffer_from_mouse_drag (gint corner1X
, gint corner1Y
,
585 gint corner2X
, gint corner2Y
, gint activeFileIndex
, gboolean eraseOldSelection
) {
586 /* figure out the lower left corner of the box */
587 screen
.selectionInfo
.lowerLeftX
= MIN(corner1X
, corner2X
);
588 screen
.selectionInfo
.lowerLeftY
= MIN(corner1Y
, corner2Y
);
589 /* figure out the upper right corner of the box */
590 screen
.selectionInfo
.upperRightX
= MAX(corner1X
, corner2X
);
591 screen
.selectionInfo
.upperRightY
= MAX(corner1Y
, corner2Y
);
593 screen
.selectionInfo
.type
= GERBV_SELECTION_DRAG_BOX
;
594 render_find_selected_objects_and_refresh_display (activeFileIndex
, eraseOldSelection
);
597 /* ------------------------------------------------------ */
598 void render_recreate_composite_surface () {
601 if (!render_create_cairo_buffer_surface())
604 cairo_t
*cr
= cairo_create(screen
.bufferSurface
);
605 /* fill the background with the appropriate color */
606 cairo_set_source_rgba (cr
, (double) mainProject
->background
.red
/G_MAXUINT16
,
607 (double) mainProject
->background
.green
/G_MAXUINT16
,
608 (double) mainProject
->background
.blue
/G_MAXUINT16
, 1);
611 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
612 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
) {
613 cairo_set_source_surface (cr
, (cairo_surface_t
*) mainProject
->file
[i
]->privateRenderData
,
615 /* ignore alpha if we are in high-speed render mode */
616 if (((double) mainProject
->file
[i
]->alpha
< 65535)&&(screenRenderInfo
.renderType
!= GERBV_RENDER_TYPE_GDK_XOR
)) {
617 cairo_paint_with_alpha(cr
,(double) mainProject
->file
[i
]->alpha
/G_MAXUINT16
);
624 /* render the selection layer at the end */
625 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
) {
626 cairo_set_source_surface (cr
, (cairo_surface_t
*) screen
.selectionRenderData
,
628 cairo_paint_with_alpha (cr
,1.0);
633 /* ------------------------------------------------------ */
634 void render_project_to_cairo_target (cairo_t
*cr
) {
635 /* fill the background with the appropriate color */
636 cairo_set_source_rgba (cr
, (double) mainProject
->background
.red
/G_MAXUINT16
,
637 (double) mainProject
->background
.green
/G_MAXUINT16
,
638 (double) mainProject
->background
.blue
/G_MAXUINT16
, 1);
641 cairo_set_source_surface (cr
, (cairo_surface_t
*) screen
.bufferSurface
, 0 , 0);
647 render_free_screen_resources (void) {
648 if (screen
.selectionRenderData
)
649 cairo_surface_destroy ((cairo_surface_t
*)
650 screen
.selectionRenderData
);
651 if (screen
.bufferSurface
)
652 cairo_surface_destroy ((cairo_surface_t
*)
653 screen
.bufferSurface
);
654 if (screen
.windowSurface
)
655 cairo_surface_destroy ((cairo_surface_t
*)
656 screen
.windowSurface
);
658 gdk_pixmap_unref(screen
.pixmap
);
662 /* ------------------------------------------------------------------ */
663 /*! This fills out the project's Gerber statistics table.
664 * It is called from within callbacks.c when the user
665 * asks for a Gerber report. */
667 generate_gerber_analysis(void)
670 gerbv_stats_t
*stats
;
671 gerbv_stats_t
*instats
;
673 /* Create new stats structure to hold report for whole project
674 * (i.e. all layers together) */
675 stats
= gerbv_stats_new();
677 /* Loop through open layers and compile statistics by accumulating reports from each layer */
678 for (i
= 0; i
<= mainProject
->last_loaded
; i
++) {
679 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
&&
680 (mainProject
->file
[i
]->image
->layertype
== GERBV_LAYERTYPE_RS274X
) ) {
681 instats
= mainProject
->file
[i
]->image
->gerbv_stats
;
682 gerbv_stats_add_layer(stats
, instats
, i
+1);
689 /* ------------------------------------------------------------------ */
690 /*! This fills out the project's Drill statistics table.
691 * It is called from within callbacks.c when the user
692 * asks for a Drill report. */
693 gerbv_drill_stats_t
*
694 generate_drill_analysis(void)
697 gerbv_drill_stats_t
*stats
;
698 gerbv_drill_stats_t
*instats
;
700 stats
= gerbv_drill_stats_new();
702 /* Loop through open layers and compile statistics by accumulating reports from each layer */
703 for(i
= mainProject
->last_loaded
; i
>= 0; i
--) {
704 if (mainProject
->file
[i
] &&
705 mainProject
->file
[i
]->isVisible
&&
706 (mainProject
->file
[i
]->image
->layertype
== GERBV_LAYERTYPE_DRILL
) ) {
707 instats
= mainProject
->file
[i
]->image
->drill_stats
;
708 /* add this batch of stats. Send the layer
709 * index for error reporting */
710 gerbv_drill_stats_add_layer(stats
, instats
, i
+1);