* fix building with --disable-cairo, spotted by Erik
[geda-gerbv.git] / src / render.c
blobab5bd855fdc643223bcf0592a6b07da527cf2ed4
1 /*
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)
8 * $Id$
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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
25 /** \file render.c
26 \brief Rendering support functions for libgerbv
27 \ingroup libgerbv
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
38 #ifdef HAVE_STRING_H
39 #include <string.h>
40 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
46 #ifdef HAVE_LIBGEN_H
47 #include <libgen.h> /* dirname */
48 #endif
50 #include <math.h>
52 #include "gerbv.h"
53 #include "main.h"
54 #include "callbacks.h"
55 #include "interface.h"
56 #include "render.h"
58 #ifdef RENDER_USING_GDK
59 #include "draw-gdk.h"
60 #else
61 #ifdef WIN32
62 #include <cairo-win32.h>
63 #else
64 #include <cairo-xlib.h>
65 #endif
66 #include <cairo.h>
67 #include "draw-gdk.h"
68 #include "draw.h"
69 #endif
71 #define dprintf if(DEBUG) printf
73 /**Global variable to keep track of what's happening on the screen.
74 Declared extern in gerbv_screen.h
76 extern gerbv_screen_t screen;
78 extern gerbv_render_info_t screenRenderInfo;
81 static void
82 render_layer_to_cairo_target_without_transforming(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo );
85 gboolean
86 render_check_scale_factor_limits (void) {
87 if ((screenRenderInfo.scaleFactorX > 5000)||(screenRenderInfo.scaleFactorY > 5000)) {
88 screenRenderInfo.scaleFactorX = 5000;
89 screenRenderInfo.scaleFactorY = 5000;
90 return FALSE;
92 return TRUE;
95 /* ------------------------------------------------------ */
96 void
97 render_zoom_display (gint zoomType, gdouble scaleFactor, gdouble mouseX, gdouble mouseY) {
98 double us_midx, us_midy; /* unscaled translation for screen center */
99 int half_w, half_h; /* cache for half window dimensions */
100 gdouble mouseCoordinateX = 0.0;
101 gdouble mouseCoordinateY = 0.0;
102 double oldWidth, oldHeight;
104 half_w = screenRenderInfo.displayWidth / 2;
105 half_h = screenRenderInfo.displayHeight / 2;
107 oldWidth = screenRenderInfo.displayWidth / screenRenderInfo.scaleFactorX;
108 oldHeight = screenRenderInfo.displayHeight / screenRenderInfo.scaleFactorY;
109 if (zoomType == ZOOM_IN_CMOUSE || zoomType == ZOOM_OUT_CMOUSE) {
110 /* calculate what user coordinate the mouse is pointing at */
111 mouseCoordinateX = mouseX / screenRenderInfo.scaleFactorX + screenRenderInfo.lowerLeftX;
112 mouseCoordinateY = (screenRenderInfo.displayHeight - mouseY) /
113 screenRenderInfo.scaleFactorY + screenRenderInfo.lowerLeftY;
116 us_midx = screenRenderInfo.lowerLeftX + (screenRenderInfo.displayWidth / 2.0 )/
117 screenRenderInfo.scaleFactorX;
118 us_midy = screenRenderInfo.lowerLeftY + (screenRenderInfo.displayHeight / 2.0 )/
119 screenRenderInfo.scaleFactorY;
121 switch(zoomType) {
122 case ZOOM_IN : /* Zoom In */
123 case ZOOM_IN_CMOUSE : /* Zoom In Around Mouse Pointer */
124 screenRenderInfo.scaleFactorX += screenRenderInfo.scaleFactorX/3;
125 screenRenderInfo.scaleFactorY += screenRenderInfo.scaleFactorY/3;
126 (void) render_check_scale_factor_limits ();
127 screenRenderInfo.lowerLeftX += (oldWidth - (screenRenderInfo.displayWidth /
128 screenRenderInfo.scaleFactorX)) / 2.0;
129 screenRenderInfo.lowerLeftY += (oldHeight - (screenRenderInfo.displayHeight /
130 screenRenderInfo.scaleFactorY)) / 2.0;
131 break;
132 case ZOOM_OUT : /* Zoom Out */
133 case ZOOM_OUT_CMOUSE : /* Zoom Out Around Mouse Pointer */
134 if ((screenRenderInfo.scaleFactorX > 10)&&(screenRenderInfo.scaleFactorY > 10)) {
135 screenRenderInfo.scaleFactorX -= screenRenderInfo.scaleFactorX/3;
136 screenRenderInfo.scaleFactorY -= screenRenderInfo.scaleFactorY/3;
137 screenRenderInfo.lowerLeftX += (oldWidth - (screenRenderInfo.displayWidth /
138 screenRenderInfo.scaleFactorX)) / 2.0;
139 screenRenderInfo.lowerLeftY += (oldHeight - (screenRenderInfo.displayHeight /
140 screenRenderInfo.scaleFactorY)) / 2.0;
142 break;
143 case ZOOM_FIT : /* Zoom Fit */
144 gerbv_render_zoom_to_fit_display (mainProject, &screenRenderInfo);
145 break;
146 case ZOOM_SET : /*explicit scale set by user */
147 screenRenderInfo.scaleFactorX = scaleFactor;
148 screenRenderInfo.scaleFactorY = scaleFactor;
149 (void) render_check_scale_factor_limits ();
150 screenRenderInfo.lowerLeftX += (oldWidth - (screenRenderInfo.displayWidth /
151 screenRenderInfo.scaleFactorX)) / 2.0;
152 screenRenderInfo.lowerLeftY += (oldHeight - (screenRenderInfo.displayHeight /
153 screenRenderInfo.scaleFactorY)) / 2.0;
154 break;
155 default :
156 GERB_MESSAGE("Illegal zoom direction %d\n", zoomType);
159 if (zoomType == ZOOM_IN_CMOUSE || zoomType == ZOOM_OUT_CMOUSE) {
160 /* make sure the mouse is still pointing at the point calculated earlier */
161 screenRenderInfo.lowerLeftX = mouseCoordinateX - mouseX / screenRenderInfo.scaleFactorX;
162 screenRenderInfo.lowerLeftY = mouseCoordinateY - (screenRenderInfo.displayHeight - mouseY) /
163 screenRenderInfo.scaleFactorY;
165 render_refresh_rendered_image_on_screen();
166 return;
170 /* --------------------------------------------------------- */
171 /** Will determine the outline of the zoomed regions.
172 * In case region to be zoomed is too small (which correspondes
173 * e.g. to a double click) it is interpreted as a right-click
174 * and will be used to identify a part from the CURRENT selection,
175 * which is drawn on screen*/
176 void
177 render_calculate_zoom_from_outline(GtkWidget *widget, GdkEventButton *event)
179 int x1, y1, x2, y2, dx, dy; /* Zoom outline (UR and LL corners) */
180 double centerPointX, centerPointY;
181 int half_x, half_y; /* cache for half window dimensions */
183 x1 = MIN(screen.start_x, event->x);
184 y1 = MIN(screen.start_y, event->y);
185 x2 = MAX(screen.start_x, event->x);
186 y2 = MAX(screen.start_y, event->y);
187 dx = x2-x1;
188 dy = y2-y1;
190 if ((dx >= 4) && (dy >= 4)) {
191 if (screen.centered_outline_zoom) {
192 /* Centered outline mode */
193 x1 = screen.start_x - dx;
194 y1 = screen.start_y - dy;
195 dx *= 2;
196 dy *= 2;
198 half_x = (x1+x2)/2;
199 half_y = (y1+y2)/2;
200 centerPointX = half_x/screenRenderInfo.scaleFactorX + screenRenderInfo.lowerLeftX;
201 centerPointY = (screenRenderInfo.displayHeight - half_y)/screenRenderInfo.scaleFactorY +
202 screenRenderInfo.lowerLeftY;
204 screenRenderInfo.scaleFactorX *= MIN(((double)screenRenderInfo.displayWidth / dx),
205 ((double)screenRenderInfo.displayHeight / dy));
206 screenRenderInfo.scaleFactorY = screenRenderInfo.scaleFactorX;
207 (void) render_check_scale_factor_limits ();
208 screenRenderInfo.lowerLeftX = centerPointX - (screenRenderInfo.displayWidth /
209 2.0 / screenRenderInfo.scaleFactorX);
210 screenRenderInfo.lowerLeftY = centerPointY - (screenRenderInfo.displayHeight /
211 2.0 / screenRenderInfo.scaleFactorY);
213 render_refresh_rendered_image_on_screen();
216 /* ------------------------------------------------------ */
217 void
218 render_draw_selection_box_outline(void) {
219 GdkGC *gc;
220 GdkGCValues values;
221 GdkGCValuesMask values_mask;
222 gint x1, y1, x2, y2, dx, dy;
224 memset(&values, 0, sizeof(values));
225 values.function = GDK_XOR;
226 if (!screen.zoom_outline_color.pixel)
227 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
228 values.foreground = screen.zoom_outline_color;
229 values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
230 gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
232 x1 = MIN(screen.start_x, screen.last_x);
233 y1 = MIN(screen.start_y, screen.last_y);
234 x2 = MAX(screen.start_x, screen.last_x);
235 y2 = MAX(screen.start_y, screen.last_y);
236 dx = x2-x1;
237 dy = y2-y1;
239 gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, x1, y1, dx, dy);
240 gdk_gc_unref(gc);
243 /* --------------------------------------------------------- */
244 void
245 render_draw_zoom_outline(gboolean centered)
247 GdkGC *gc;
248 GdkGCValues values;
249 GdkGCValuesMask values_mask;
250 gint x1, y1, x2, y2, dx, dy;
252 memset(&values, 0, sizeof(values));
253 values.function = GDK_XOR;
254 if (!screen.zoom_outline_color.pixel)
255 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
256 values.foreground = screen.zoom_outline_color;
257 values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
258 gc = gdk_gc_new_with_values(screen.drawing_area->window, &values, values_mask);
260 x1 = MIN(screen.start_x, screen.last_x);
261 y1 = MIN(screen.start_y, screen.last_y);
262 x2 = MAX(screen.start_x, screen.last_x);
263 y2 = MAX(screen.start_y, screen.last_y);
264 dx = x2-x1;
265 dy = y2-y1;
267 if (centered) {
268 /* Centered outline mode */
269 x1 = screen.start_x - dx;
270 y1 = screen.start_y - dy;
271 dx *= 2;
272 dy *= 2;
273 x2 = x1+dx;
274 y2 = y1+dy;
277 gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, x1, y1, dx, dy);
278 gdk_gc_unref(gc);
280 /* Draw actual zoom area in dashed lines */
281 memset(&values, 0, sizeof(values));
282 values.function = GDK_XOR;
283 values.foreground = screen.zoom_outline_color;
284 values.line_style = GDK_LINE_ON_OFF_DASH;
285 values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND | GDK_GC_LINE_STYLE;
286 gc = gdk_gc_new_with_values(screen.drawing_area->window, &values,
287 values_mask);
289 if ((dy == 0) || ((double)dx/dy > (double)screen.drawing_area->allocation.width/
290 screen.drawing_area->allocation.height)) {
291 dy = dx * (double)screen.drawing_area->allocation.height/
292 screen.drawing_area->allocation.width;
294 else {
295 dx = dy * (double)screen.drawing_area->allocation.width/
296 screen.drawing_area->allocation.height;
299 gdk_draw_rectangle(screen.drawing_area->window, gc, FALSE, (x1+x2-dx)/2,
300 (y1+y2-dy)/2, dx, dy);
302 gdk_gc_unref(gc);
306 /* ------------------------------------------------------ */
307 /** Displays a measured distance graphically on screen and in statusbar.
308 activated when using SHIFT and mouse dragged to measure distances\n
309 under win32 graphical annotations are currently disabled (GTK 2.47)*/
310 void
311 render_draw_measure_distance(void)
313 #if !defined (__MINGW32__)
315 GdkGC *gc;
316 GdkGCValues values;
317 GdkGCValuesMask values_mask;
318 #endif
319 gint x1, y1, x2, y2;
320 double dx, dy;
322 #if !defined (__MINGW32__) /*taken out because of different drawing behaviour under win32 resulting in a smear */
323 memset(&values, 0, sizeof(values));
324 values.function = GDK_XOR;
325 if (!screen.zoom_outline_color.pixel)
326 gdk_colormap_alloc_color(gdk_colormap_get_system(), &screen.zoom_outline_color, FALSE, TRUE);
327 values.foreground = screen.zoom_outline_color;
328 values_mask = GDK_GC_FUNCTION | GDK_GC_FOREGROUND;
329 gc = gdk_gc_new_with_values(screen.drawing_area->window, &values,
330 values_mask);
331 #endif
332 x1 = MIN(screen.start_x, screen.last_x);
333 y1 = MIN(screen.start_y, screen.last_y);
334 x2 = MAX(screen.start_x, screen.last_x);
335 y2 = MAX(screen.start_y, screen.last_y);
336 dx = (x2 - x1)/ screenRenderInfo.scaleFactorX;
337 dy = (y2 - y1)/ screenRenderInfo.scaleFactorY;
339 #if !defined (__MINGW32__)
340 gdk_draw_line(screen.drawing_area->window, gc, screen.start_x,
341 screen.start_y, screen.last_x, screen.last_y);
342 #endif
343 screen.win.lastMeasuredX = dx;
344 screen.win.lastMeasuredY = dy;
345 callbacks_update_statusbar_measured_distance (dx, dy);
346 #if !defined (__MINGW32__)
347 gdk_gc_unref(gc);
348 #endif
349 } /* draw_measure_distance */
351 /* ------------------------------------------------------ */
352 void render_selection_layer (void){
353 #ifndef RENDER_USING_GDK
354 cairo_t *cr;
356 if (screen.selectionRenderData)
357 cairo_surface_destroy ((cairo_surface_t *) screen.selectionRenderData);
358 screen.selectionRenderData =
359 (gpointer) cairo_surface_create_similar ((cairo_surface_t *)screen.windowSurface,
360 CAIRO_CONTENT_COLOR_ALPHA, screenRenderInfo.displayWidth,
361 screenRenderInfo.displayHeight);
362 if (screen.selectionInfo.type != GERBV_SELECTION_EMPTY) {
363 cr= cairo_create(screen.selectionRenderData);
364 gerbv_render_cairo_set_scale_and_translation(cr, &screenRenderInfo);
365 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.85);
366 /* for now, assume everything in the selection buffer is from one image */
367 gerbv_image_t *matchImage;
368 int j;
369 if (screen.selectionInfo.selectedNodeArray->len > 0) {
370 gerbv_selection_item_t sItem = g_array_index (screen.selectionInfo.selectedNodeArray,
371 gerbv_selection_item_t, 0);
372 matchImage = (gerbv_image_t *) sItem.image;
373 dprintf(" .... calling render_image_to_cairo_target on selection layer...\n");
374 for(j = mainProject->last_loaded; j >= 0; j--) {
375 if ((mainProject->file[j]) && (mainProject->file[j]->image == matchImage)) {
376 draw_image_to_cairo_target (cr, mainProject->file[j]->image,
377 mainProject->file[j]->transform.inverted,
378 1.0/MAX(screenRenderInfo.scaleFactorX,
379 screenRenderInfo.scaleFactorY),
380 DRAW_SELECTIONS, &screen.selectionInfo);
384 cairo_destroy (cr);
386 #endif
389 /* ------------------------------------------------------ */
390 void render_refresh_rendered_image_on_screen (void) {
391 GdkCursor *cursor;
393 dprintf("----> Entering redraw_pixmap...\n");
394 cursor = gdk_cursor_new(GDK_WATCH);
395 gdk_window_set_cursor(GDK_WINDOW(screen.drawing_area->window), cursor);
396 gdk_cursor_destroy(cursor);
398 if (screenRenderInfo.renderType < 2){
399 if (screen.pixmap)
400 gdk_pixmap_unref(screen.pixmap);
401 screen.pixmap = gdk_pixmap_new(screen.drawing_area->window, screenRenderInfo.displayWidth,
402 screenRenderInfo.displayHeight, -1);
403 gerbv_render_to_pixmap_using_gdk (mainProject, screen.pixmap, &screenRenderInfo, &screen.selectionInfo,
404 &screen.selection_color);
405 dprintf("<---- leaving redraw_pixmap.\n");
407 #ifndef RENDER_USING_GDK
408 else{
409 int i;
410 dprintf(" .... Now try rendering the drawing using cairo .... \n");
412 * This now allows drawing several layers on top of each other.
413 * Higher layer numbers have higher priority in the Z-order.
415 for(i = mainProject->last_loaded; i >= 0; i--) {
416 if (mainProject->file[i]) {
417 cairo_t *cr;
418 if (mainProject->file[i]->privateRenderData)
419 cairo_surface_destroy ((cairo_surface_t *) mainProject->file[i]->privateRenderData);
420 mainProject->file[i]->privateRenderData =
421 (gpointer) cairo_surface_create_similar ((cairo_surface_t *)screen.windowSurface,
422 CAIRO_CONTENT_COLOR_ALPHA, screenRenderInfo.displayWidth,
423 screenRenderInfo.displayHeight);
424 cr= cairo_create(mainProject->file[i]->privateRenderData );
425 gerbv_render_layer_to_cairo_target (cr, mainProject->file[i], &screenRenderInfo);
426 dprintf(" .... calling render_image_to_cairo_target on layer %d...\n", i);
427 cairo_destroy (cr);
430 /* render the selection layer */
431 render_selection_layer();
433 render_recreate_composite_surface ();
435 #endif
436 /* remove watch cursor and switch back to normal cursor */
437 callbacks_switch_to_correct_cursor ();
438 callbacks_force_expose_event_for_screen();
441 /* ------------------------------------------------------ */
442 void
443 render_clear_selection_buffer (void){
444 if (screen.selectionInfo.type == GERBV_SELECTION_EMPTY)
445 return;
447 g_array_remove_range (screen.selectionInfo.selectedNodeArray, 0,
448 screen.selectionInfo.selectedNodeArray->len);
449 screen.selectionInfo.type = GERBV_SELECTION_EMPTY;
450 callbacks_update_selected_object_message (FALSE);
453 void
454 render_remove_selected_objects_belonging_to_layer (gint index) {
455 int i;
457 for (i=screen.selectionInfo.selectedNodeArray->len-1; i>=0; i--) {
458 gerbv_selection_item_t sItem = g_array_index (screen.selectionInfo.selectedNodeArray,
459 gerbv_selection_item_t, i);
461 gerbv_image_t *matchImage = (gerbv_image_t *) sItem.image;
462 if (mainProject->file[index]->image == matchImage) {
463 g_array_remove_index (screen.selectionInfo.selectedNodeArray, index);
466 callbacks_update_selected_object_message (FALSE);
469 /* ------------------------------------------------------ */
470 #ifndef RENDER_USING_GDK
471 gint
472 render_create_cairo_buffer_surface () {
473 if (screen.bufferSurface) {
474 cairo_surface_destroy (screen.bufferSurface);
475 screen.bufferSurface = NULL;
477 if (!screen.windowSurface)
478 return 0;
480 screen.bufferSurface= cairo_surface_create_similar ((cairo_surface_t *)screen.windowSurface,
481 CAIRO_CONTENT_COLOR, screenRenderInfo.displayWidth,
482 screenRenderInfo.displayHeight);
483 return 1;
486 /* ------------------------------------------------------ */
487 void
488 render_find_selected_objects_and_refresh_display (gint activeFileIndex, gboolean eraseOldSelection){
489 /* clear the old selection array if desired */
490 if ((eraseOldSelection)&&(screen.selectionInfo.selectedNodeArray->len))
491 g_array_remove_range (screen.selectionInfo.selectedNodeArray, 0,
492 screen.selectionInfo.selectedNodeArray->len);
494 /* make sure we have a bufferSurface...if we start up in FAST mode, we may not
495 have one yet, but we need it for selections */
496 if (!render_create_cairo_buffer_surface())
497 return;
499 /* call draw_image... passing the FILL_SELECTION mode to just search for
500 nets which match the selection, and fill the selection buffer with them */
501 cairo_t *cr= cairo_create(screen.bufferSurface);
502 gerbv_render_cairo_set_scale_and_translation(cr,&screenRenderInfo);
503 draw_image_to_cairo_target (cr, mainProject->file[activeFileIndex]->image, mainProject->file[activeFileIndex]->transform.inverted,
504 1.0/MAX(screenRenderInfo.scaleFactorX, screenRenderInfo.scaleFactorY),
505 FIND_SELECTIONS, &screen.selectionInfo);
506 cairo_destroy (cr);
507 /* if the selection array is empty, switch the "mode" to empty to make it
508 easier to check if it is holding anything */
509 if (!screen.selectionInfo.selectedNodeArray->len)
510 screen.selectionInfo.type = GERBV_SELECTION_EMPTY;
511 /* re-render the selection buffer layer */
512 if (screenRenderInfo.renderType < 2){
513 render_refresh_rendered_image_on_screen ();
515 else {
516 render_selection_layer();
517 render_recreate_composite_surface ();
518 callbacks_force_expose_event_for_screen();
522 /* ------------------------------------------------------ */
523 void
524 render_fill_selection_buffer_from_mouse_click (gint mouseX, gint mouseY, gint activeFileIndex,
525 gboolean eraseOldSelection) {
526 screen.selectionInfo.lowerLeftX = mouseX;
527 screen.selectionInfo.lowerLeftY = mouseY;
528 /* no need to populate the upperright coordinates for a point_click */
529 screen.selectionInfo.type = GERBV_SELECTION_POINT_CLICK;
530 render_find_selected_objects_and_refresh_display (activeFileIndex, eraseOldSelection);
533 /* ------------------------------------------------------ */
534 void
535 render_fill_selection_buffer_from_mouse_drag (gint corner1X, gint corner1Y,
536 gint corner2X, gint corner2Y, gint activeFileIndex, gboolean eraseOldSelection) {
537 /* figure out the lower left corner of the box */
538 screen.selectionInfo.lowerLeftX = MIN(corner1X, corner2X);
539 screen.selectionInfo.lowerLeftY = MIN(corner1Y, corner2Y);
540 /* figure out the upper right corner of the box */
541 screen.selectionInfo.upperRightX = MAX(corner1X, corner2X);
542 screen.selectionInfo.upperRightY = MAX(corner1Y, corner2Y);
544 screen.selectionInfo.type = GERBV_SELECTION_DRAG_BOX;
545 render_find_selected_objects_and_refresh_display (activeFileIndex, eraseOldSelection);
548 /* ------------------------------------------------------ */
549 void render_recreate_composite_surface () {
550 gint i;
552 if (!render_create_cairo_buffer_surface())
553 return;
555 cairo_t *cr= cairo_create(screen.bufferSurface);
556 /* fill the background with the appropriate color */
557 cairo_set_source_rgba (cr, (double) mainProject->background.red/G_MAXUINT16,
558 (double) mainProject->background.green/G_MAXUINT16,
559 (double) mainProject->background.blue/G_MAXUINT16, 1);
560 cairo_paint (cr);
562 for(i = mainProject->last_loaded; i >= 0; i--) {
563 if (mainProject->file[i] && mainProject->file[i]->isVisible) {
564 cairo_set_source_surface (cr, (cairo_surface_t *) mainProject->file[i]->privateRenderData,
565 0, 0);
566 /* ignore alpha if we are in high-speed render mode */
567 if (((double) mainProject->file[i]->alpha < 65535)&&(screenRenderInfo.renderType != 1)) {
568 cairo_paint_with_alpha(cr,(double) mainProject->file[i]->alpha/G_MAXUINT16);
570 else {
571 cairo_paint (cr);
575 /* render the selection layer at the end */
576 if (screen.selectionInfo.type != GERBV_SELECTION_EMPTY) {
577 cairo_set_source_surface (cr, (cairo_surface_t *) screen.selectionRenderData,
578 0, 0);
579 cairo_paint_with_alpha (cr,1.0);
581 cairo_destroy (cr);
584 /* ------------------------------------------------------ */
585 void render_project_to_cairo_target (cairo_t *cr) {
586 /* fill the background with the appropriate color */
587 cairo_set_source_rgba (cr, (double) mainProject->background.red/G_MAXUINT16,
588 (double) mainProject->background.green/G_MAXUINT16,
589 (double) mainProject->background.blue/G_MAXUINT16, 1);
590 cairo_paint (cr);
592 cairo_set_source_surface (cr, (cairo_surface_t *) screen.bufferSurface, 0 , 0);
594 cairo_paint (cr);
596 #endif /* RENDER_USING_GDK */
598 void
599 render_free_screen_resources (void) {
600 #ifndef RENDER_USING_GDK
601 if (screen.selectionRenderData)
602 cairo_surface_destroy ((cairo_surface_t *)
603 screen.selectionRenderData);
604 if (screen.bufferSurface)
605 cairo_surface_destroy ((cairo_surface_t *)
606 screen.bufferSurface);
607 if (screen.windowSurface)
608 cairo_surface_destroy ((cairo_surface_t *)
609 screen.windowSurface);
610 #endif
611 if (screen.pixmap)
612 gdk_pixmap_unref(screen.pixmap);
616 /* ------------------------------------------------------------------ */
617 /*! This fills out the project's Gerber statistics table.
618 * It is called from within callbacks.c when the user
619 * asks for a Gerber report. */
620 gerbv_stats_t *
621 generate_gerber_analysis(void)
623 int i;
624 gerbv_stats_t *stats;
625 gerbv_stats_t *instats;
627 /* Create new stats structure to hold report for whole project
628 * (i.e. all layers together) */
629 stats = gerbv_stats_new();
631 /* Loop through open layers and compile statistics by accumulating reports from each layer */
632 for (i = 0; i <= mainProject->last_loaded; i++) {
633 if (mainProject->file[i] && mainProject->file[i]->isVisible &&
634 (mainProject->file[i]->image->layertype == GERBV_LAYERTYPE_RS274X) ) {
635 instats = mainProject->file[i]->image->gerbv_stats;
636 gerbv_stats_add_layer(stats, instats, i+1);
639 return stats;
643 /* ------------------------------------------------------------------ */
644 /*! This fills out the project's Drill statistics table.
645 * It is called from within callbacks.c when the user
646 * asks for a Drill report. */
647 gerbv_drill_stats_t *
648 generate_drill_analysis(void)
650 int i;
651 gerbv_drill_stats_t *stats;
652 gerbv_drill_stats_t *instats;
654 stats = gerbv_drill_stats_new();
656 /* Loop through open layers and compile statistics by accumulating reports from each layer */
657 for(i = mainProject->last_loaded; i >= 0; i--) {
658 if (mainProject->file[i] &&
659 mainProject->file[i]->isVisible &&
660 (mainProject->file[i]->image->layertype == GERBV_LAYERTYPE_DRILL) ) {
661 instats = mainProject->file[i]->image->drill_stats;
662 /* add this batch of stats. Send the layer
663 * index for error reporting */
664 gerbv_drill_stats_add_layer(stats, instats, i+1);
667 return stats;