12 #include "draw_funcs.h"
15 #include "gui-pinout-preview.h"
17 /* The Linux OpenGL ABI 1.0 spec requires that we define
18 * GL_GLEXT_PROTOTYPES before including gl.h or glx.h for extensions
19 * in order to get prototypes:
20 * http://www.opengl.org/registry/ABI/
23 #define GL_GLEXT_PROTOTYPES 1
24 #ifdef HAVE_OPENGL_GL_H
25 # include <OpenGL/gl.h>
30 #include <gtk/gtkgl.h>
31 #include "hid/common/hidgl.h"
33 #include "hid/common/draw_helpers.h"
34 #include "hid/common/trackball.h"
36 #ifdef HAVE_LIBDMALLOC
41 extern HID_DRAW ghid_graphics
;
42 extern HID_DRAW_CLASS ghid_graphics_class
;
44 static hidGC current_gc
= NULL
;
46 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
48 #define USE_GC(gc) if (!use_gc(gc)) return
50 static enum mask_mode cur_mask
= HID_MASK_OFF
;
51 static GLfloat view_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
54 {0.0, 0.0, 0.0, 1.0}};
55 static GLfloat last_modelview_matrix
[4][4] = {{1.0, 0.0, 0.0, 0.0},
58 {0.0, 0.0, 0.0, 1.0}};
59 static int global_view_2d
= 1;
61 typedef struct render_priv
{
62 GdkGLConfig
*glconfig
;
65 int subcomposite_stencil_bit
;
66 char *current_colorname
;
67 double current_alpha_mult
;
68 GTimer
*time_since_expose
;
70 /* Feature for leading the user to a particular location */
71 guint lead_user_timeout
;
72 GTimer
*lead_user_timer
;
74 Coord lead_user_radius
;
78 hidgl_instance
*hidgl
;
79 GList
*active_gc_list
;
84 typedef struct gtk_gc_struct
86 struct hidgl_gc_struct hidgl_gc
; /* Parent */
88 const char *colorname
;
94 static void draw_lead_user (hidGC gc
, render_priv
*priv
);
95 static void ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
);
98 #define BOARD_THICKNESS MM_TO_COORD(1.60)
99 #define MASK_COPPER_SPACING MM_TO_COORD(0.05)
100 #define SILK_MASK_SPACING MM_TO_COORD(0.01)
102 compute_depth (int group
)
104 static int last_depth_computed
= 0;
108 int min_copper_group
;
109 int max_copper_group
;
110 int num_copper_groups
;
111 int middle_copper_group
;
114 top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
115 bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
117 min_copper_group
= MIN (bottom_group
, top_group
);
118 max_copper_group
= MAX (bottom_group
, top_group
);
119 num_copper_groups
= max_copper_group
- min_copper_group
+ 1;
120 middle_copper_group
= min_copper_group
+ num_copper_groups
/ 2;
122 if (group
>= 0 && group
< max_group
) {
123 if (group
>= min_copper_group
&& group
<= max_copper_group
) {
124 /* XXX: IS THIS INCORRECT FOR REVERSED GROUP ORDERINGS? */
125 depth
= -(group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
;
130 } else if (SL_TYPE (group
) == SL_MASK
) {
131 if (SL_SIDE (group
) == SL_TOP_SIDE
) {
132 depth
= -((min_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
- MASK_COPPER_SPACING
);
134 depth
= -((max_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
+ MASK_COPPER_SPACING
);
136 } else if (SL_TYPE (group
) == SL_SILK
) {
137 if (SL_SIDE (group
) == SL_TOP_SIDE
) {
138 depth
= -((min_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
- MASK_COPPER_SPACING
- SILK_MASK_SPACING
);
140 depth
= -((max_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
+ MASK_COPPER_SPACING
+ SILK_MASK_SPACING
);
143 } else if (SL_TYPE (group
) == SL_INVISIBLE
) {
144 /* Same as silk, but for the back-side layer */
145 if (Settings
.ShowBottomSide
) {
146 depth
= -((min_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
- MASK_COPPER_SPACING
- SILK_MASK_SPACING
);
148 depth
= -((max_copper_group
- middle_copper_group
) * BOARD_THICKNESS
/ num_copper_groups
+ MASK_COPPER_SPACING
+ SILK_MASK_SPACING
);
150 } else if (SL_TYPE (group
) == SL_RATS
||
151 SL_TYPE (group
) == SL_PDRILL
||
152 SL_TYPE (group
) == SL_UDRILL
) {
153 /* Draw these at the depth we last rendered at */
154 depth
= last_depth_computed
;
155 } else if (SL_TYPE (group
) == SL_PASTE
||
156 SL_TYPE (group
) == SL_FAB
||
157 SL_TYPE (group
) == SL_ASSY
) {
158 /* Layer types we don't use, which draw.c asks us about, so
159 * we just return _something_ to avoid the warnign below. */
160 depth
= last_depth_computed
;
163 printf ("Unknown layer group to set depth for: %i\n", group
);
164 depth
= last_depth_computed
;
167 last_depth_computed
= depth
;
172 start_subcomposite (hidgl_instance
*hidgl
)
174 render_priv
*priv
= gport
->render_priv
;
177 /* Flush out any existing geoemtry to be rendered */
178 hidgl_flush_triangles (hidgl
);
180 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
181 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
183 stencil_bit
= hidgl_assign_clear_stencil_bit (hidgl
); /* Get a new (clean) bitplane to stencil with */
184 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
185 glStencilFunc (GL_GREATER
, stencil_bit
, stencil_bit
); /* Pass stencil test if our assigned bit is clear */
187 priv
->subcomposite_stencil_bit
= stencil_bit
;
191 end_subcomposite (hidgl_instance
*hidgl
)
193 render_priv
*priv
= gport
->render_priv
;
195 /* Flush out any existing geoemtry to be rendered */
196 hidgl_flush_triangles (hidgl
);
198 hidgl_return_stencil_bit (hidgl
, priv
->subcomposite_stencil_bit
); /* Relinquish any bitplane we previously used */
201 glStencilFunc (GL_ALWAYS
, 0, 0); /* Always pass stencil test */
202 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
204 priv
->subcomposite_stencil_bit
= 0;
208 set_depth_on_all_active_gc (render_priv
*priv
, float depth
)
212 for (iter
= priv
->active_gc_list
;
214 iter
= g_list_next (iter
))
216 hidGC gc
= iter
->data
;
218 hidgl_set_depth (gc
, depth
);
222 /* Compute group visibility based upon on copper layers only */
224 is_layer_group_visible (int group
)
227 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[group
]; entry
++)
229 int layer_idx
= PCB
->LayerGroups
.Entries
[group
][entry
];
230 if (layer_idx
>= 0 && layer_idx
< max_copper_layer
&&
231 LAYER_PTR (layer_idx
)->On
)
238 ghid_set_layer (const char *name
, int group
, int empty
)
240 render_priv
*priv
= gport
->render_priv
;
241 hidgl_instance
*hidgl
= priv
->hidgl
;
242 bool group_visible
= false;
243 bool subcomposite
= true;
245 if (group
>= 0 && group
< max_group
)
247 priv
->trans_lines
= true;
249 group_visible
= is_layer_group_visible (group
);
253 switch (SL_TYPE (group
))
256 priv
->trans_lines
= false;
257 subcomposite
= false;
258 group_visible
= PCB
->InvisibleObjectsOn
;
261 priv
->trans_lines
= true;
262 subcomposite
= false;
263 group_visible
= TEST_FLAG (SHOWMASKFLAG
, PCB
);
266 priv
->trans_lines
= true;
268 group_visible
= PCB
->ElementOn
;
274 priv
->trans_lines
= true;
276 group_visible
= true;
279 priv
->trans_lines
= true;
280 subcomposite
= false;
281 group_visible
= PCB
->RatOn
;
286 end_subcomposite (hidgl
);
288 if (group_visible
&& subcomposite
)
289 start_subcomposite (hidgl
);
291 /* Drawing is already flushed by {start,end}_subcomposite */
292 set_depth_on_all_active_gc (priv
, compute_depth (group
));
294 return group_visible
;
300 render_priv
*priv
= gport
->render_priv
;
301 hidgl_instance
*hidgl
= priv
->hidgl
;
303 end_subcomposite (hidgl
);
307 ghid_destroy_gc (hidGC gc
)
309 render_priv
*priv
= gport
->render_priv
;
311 priv
->active_gc_list
= g_list_remove (priv
->active_gc_list
, gc
);
313 hidgl_finish_gc (gc
);
320 render_priv
*priv
= gport
->render_priv
;
321 hidGC gc
= (hidGC
) g_new0 (struct gtk_gc_struct
, 1);
322 gtkGC gtk_gc
= (gtkGC
)gc
;
325 gc
->hid_draw
= &ghid_graphics
;
327 hidgl_init_gc (priv
->hidgl
, gc
);
329 gtk_gc
->colorname
= Settings
.BackgroundColor
;
330 gtk_gc
->alpha_mult
= 1.0;
332 priv
->active_gc_list
= g_list_prepend (priv
->active_gc_list
, gc
);
338 ghid_draw_grid (hidGC gc
, BoxType
*drawn_area
)
340 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
343 if (gdk_color_parse (Settings
.GridColor
, &gport
->grid_color
))
345 gport
->grid_color
.red
^= gport
->bg_color
.red
;
346 gport
->grid_color
.green
^= gport
->bg_color
.green
;
347 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
350 glDisable (GL_STENCIL_TEST
);
351 glEnable (GL_COLOR_LOGIC_OP
);
354 glColor3f (gport
->grid_color
.red
/ 65535.,
355 gport
->grid_color
.green
/ 65535.,
356 gport
->grid_color
.blue
/ 65535.);
358 hidgl_draw_grid (gc
, drawn_area
);
360 glDisable (GL_COLOR_LOGIC_OP
);
361 glEnable (GL_STENCIL_TEST
);
365 ghid_draw_bg_image (void)
367 static GLuint texture_handle
= 0;
369 if (!ghidgui
->bg_pixbuf
)
372 if (texture_handle
== 0)
374 int width
= gdk_pixbuf_get_width (ghidgui
->bg_pixbuf
);
375 int height
= gdk_pixbuf_get_height (ghidgui
->bg_pixbuf
);
376 int rowstride
= gdk_pixbuf_get_rowstride (ghidgui
->bg_pixbuf
);
377 int bits_per_sample
= gdk_pixbuf_get_bits_per_sample (ghidgui
->bg_pixbuf
);
378 int n_channels
= gdk_pixbuf_get_n_channels (ghidgui
->bg_pixbuf
);
379 unsigned char *pixels
= gdk_pixbuf_get_pixels (ghidgui
->bg_pixbuf
);
381 g_warn_if_fail (bits_per_sample
== 8);
382 g_warn_if_fail (rowstride
== width
* n_channels
);
384 glGenTextures (1, &texture_handle
);
385 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
387 /* XXX: We should proabbly determine what the maxmimum texture supported is,
388 * and if our image is larger, shrink it down using GDK pixbuf routines
389 * rather than having it fail below.
392 glTexImage2D (GL_TEXTURE_2D
, 0, GL_RGB
, width
, height
, 0,
393 (n_channels
== 4) ? GL_RGBA
: GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
396 glBindTexture (GL_TEXTURE_2D
, texture_handle
);
398 glTexEnvf (GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
399 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
400 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
401 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
402 glTexParameterf (GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
403 glEnable (GL_TEXTURE_2D
);
405 /* Render a quad with the background as a texture */
408 glTexCoord2d (0., 0.);
409 glVertex3i (0, 0, 0);
410 glTexCoord2d (1., 0.);
411 glVertex3i (PCB
->MaxWidth
, 0, 0);
412 glTexCoord2d (1., 1.);
413 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
414 glTexCoord2d (0., 1.);
415 glVertex3i (0, PCB
->MaxHeight
, 0);
418 glDisable (GL_TEXTURE_2D
);
422 ghid_use_mask (enum mask_mode mode
)
424 render_priv
*priv
= gport
->render_priv
;
425 hidgl_instance
*hidgl
= priv
->hidgl
;
426 static int stencil_bit
= 0;
428 if (mode
== cur_mask
)
431 /* Flush out any existing geoemtry to be rendered */
432 hidgl_flush_triangles (hidgl
);
436 case HID_MASK_BEFORE
:
437 /* The HID asks not to receive this mask type, so warn if we get it */
438 g_return_if_reached ();
441 /* Write '1' to the stencil buffer where the solder-mask should not be drawn. */
442 glColorMask (0, 0, 0, 0); /* Disable writting in color buffer */
443 glEnable (GL_STENCIL_TEST
); /* Enable Stencil test */
444 stencil_bit
= hidgl_assign_clear_stencil_bit (hidgl
); /* Get a new (clean) bitplane to stencil with */
445 glStencilFunc (GL_ALWAYS
, stencil_bit
, stencil_bit
); /* Always pass stencil test, write stencil_bit */
446 glStencilMask (stencil_bit
); /* Only write to our subcompositing stencil bitplane */
447 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
451 /* Drawing operations as masked to areas where the stencil buffer is '0' */
452 glColorMask (1, 1, 1, 1); /* Enable drawing of r, g, b & a */
453 glStencilFunc (GL_GEQUAL
, 0, stencil_bit
); /* Draw only where our bit of the stencil buffer is clear */
454 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
); /* Stencil buffer read only */
458 /* Disable stenciling */
459 hidgl_return_stencil_bit (hidgl
, stencil_bit
); /* Relinquish any bitplane we previously used */
460 glDisable (GL_STENCIL_TEST
); /* Disable Stencil test */
467 /* Config helper functions for when the user changes color preferences.
468 | set_special colors used in the gtkhid.
471 set_special_grid_color (void)
473 if (!gport
->colormap
)
475 gport
->grid_color
.red
^= gport
->bg_color
.red
;
476 gport
->grid_color
.green
^= gport
->bg_color
.green
;
477 gport
->grid_color
.blue
^= gport
->bg_color
.blue
;
481 ghid_set_special_colors (HID_Attribute
* ha
)
483 if (!ha
->name
|| !ha
->value
)
485 if (!strcmp (ha
->name
, "background-color"))
487 ghid_map_color_string (*(char **) ha
->value
, &gport
->bg_color
);
488 set_special_grid_color ();
490 else if (!strcmp (ha
->name
, "off-limit-color"))
492 ghid_map_color_string (*(char **) ha
->value
, &gport
->offlimits_color
);
494 else if (!strcmp (ha
->name
, "grid-color"))
496 ghid_map_color_string (*(char **) ha
->value
, &gport
->grid_color
);
497 set_special_grid_color ();
511 set_gl_color_for_gc (hidGC gc
)
513 gtkGC gtk_gc
= (gtkGC
)gc
;
514 render_priv
*priv
= gport
->render_priv
;
515 static void *cache
= NULL
;
520 if (priv
->current_colorname
!= NULL
&&
521 strcmp (priv
->current_colorname
, gtk_gc
->colorname
) == 0 &&
522 priv
->current_alpha_mult
== gtk_gc
->alpha_mult
)
525 free (priv
->current_colorname
);
526 priv
->current_colorname
= strdup (gtk_gc
->colorname
);
527 priv
->current_alpha_mult
= gtk_gc
->alpha_mult
;
529 if (gport
->colormap
== NULL
)
530 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
531 if (strcmp (gtk_gc
->colorname
, "erase") == 0)
533 r
= gport
->bg_color
.red
/ 65535.;
534 g
= gport
->bg_color
.green
/ 65535.;
535 b
= gport
->bg_color
.blue
/ 65535.;
538 else if (strcmp (gtk_gc
->colorname
, "drill") == 0)
540 r
= gport
->offlimits_color
.red
/ 65535.;
541 g
= gport
->offlimits_color
.green
/ 65535.;
542 b
= gport
->offlimits_color
.blue
/ 65535.;
547 if (hid_cache_color (0, gtk_gc
->colorname
, &cval
, &cache
))
548 cc
= (ColorCache
*) cval
.ptr
;
551 cc
= (ColorCache
*) malloc (sizeof (ColorCache
));
552 memset (cc
, 0, sizeof (*cc
));
554 hid_cache_color (1, gtk_gc
->colorname
, &cval
, &cache
);
559 if (gdk_color_parse (gtk_gc
->colorname
, &cc
->color
))
560 gdk_color_alloc (gport
->colormap
, &cc
->color
);
562 gdk_color_white (gport
->colormap
, &cc
->color
);
563 cc
->red
= cc
->color
.red
/ 65535.;
564 cc
->green
= cc
->color
.green
/ 65535.;
565 cc
->blue
= cc
->color
.blue
/ 65535.;
575 a
*= gtk_gc
->alpha_mult
;
576 if (!priv
->trans_lines
)
579 if (g
> maxi
) maxi
= g
;
580 if (b
> maxi
) maxi
= b
;
581 mult
= MIN (1 / a
, 1 / maxi
);
589 if(!priv
->in_context
)
592 hidgl_flush_triangles (gtk_gc
->hidgl_gc
.hidgl
);
593 glColor4d (r
, g
, b
, a
);
597 ghid_set_color (hidGC gc
, const char *name
)
599 gtkGC gtk_gc
= (gtkGC
)gc
;
601 gtk_gc
->colorname
= name
;
602 set_gl_color_for_gc (gc
);
606 ghid_set_alpha_mult (hidGC gc
, double alpha_mult
)
608 gtkGC gtk_gc
= (gtkGC
)gc
;
610 gtk_gc
->alpha_mult
= alpha_mult
;
611 set_gl_color_for_gc (gc
);
615 ghid_set_line_cap (hidGC gc
, EndCapStyle style
)
617 gtkGC gtk_gc
= (gtkGC
)gc
;
623 ghid_set_line_width (hidGC gc
, Coord width
)
625 gtkGC gtk_gc
= (gtkGC
)gc
;
627 gtk_gc
->width
= width
;
632 ghid_set_draw_xor (hidGC gc
, int xor)
634 /* NOT IMPLEMENTED */
636 /* Only presently called when setting up a crosshair GC.
637 * We manage our own drawing model for that anyway. */
641 ghid_set_draw_faded (hidGC gc
, int faded
)
643 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc
, faded
);
647 ghid_set_line_cap_angle (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
649 printf ("ghid_set_line_cap_angle() -- not implemented\n");
653 ghid_invalidate_current_gc (void)
661 if (gc
->hid
!= &ghid_hid
)
663 fprintf (stderr
, "Fatal: GC from another HID passed to GTK HID\n");
667 if (current_gc
== gc
)
672 set_gl_color_for_gc (gc
);
677 ghid_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
679 gtkGC gtk_gc
= (gtkGC
)gc
;
682 hidgl_draw_line (gc
, gtk_gc
->cap
, gtk_gc
->width
, x1
, y1
, x2
, y2
, gport
->view
.coord_per_px
);
686 ghid_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord xradius
, Coord yradius
,
687 Angle start_angle
, Angle delta_angle
)
689 gtkGC gtk_gc
= (gtkGC
)gc
;
692 hidgl_draw_arc (gc
, gtk_gc
->width
, cx
, cy
, xradius
, yradius
,
693 start_angle
, delta_angle
, gport
->view
.coord_per_px
);
697 ghid_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
701 hidgl_draw_rect (gc
, x1
, y1
, x2
, y2
);
706 ghid_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
710 hidgl_fill_circle (gc
, cx
, cy
, radius
, gport
->view
.coord_per_px
);
715 ghid_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
719 hidgl_fill_polygon (gc
, n_coords
, x
, y
);
723 ghid_fill_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
727 hidgl_fill_pcb_polygon (gc
, poly
, clip_box
, gport
->view
.coord_per_px
);
731 ghid_thindraw_pcb_polygon (hidGC gc
, PolygonType
*poly
, const BoxType
*clip_box
)
733 gtkGC gtk_gc
= (gtkGC
)gc
;
735 double old_alpha_mult
= gtk_gc
->alpha_mult
;
736 common_thindraw_pcb_polygon (gc
, poly
, clip_box
);
737 ghid_set_alpha_mult (gc
, gtk_gc
->alpha_mult
* 0.25);
738 hid_draw_fill_pcb_polygon (gc
, poly
, clip_box
);
739 ghid_set_alpha_mult (gc
, old_alpha_mult
);
743 ghid_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
747 hidgl_fill_rect (gc
, x1
, y1
, x2
, y2
);
751 ghid_invalidate_lr (int left
, int right
, int top
, int bottom
)
753 ghid_invalidate_all ();
756 #define MAX_ELAPSED (50. / 1000.) /* 50ms */
758 ghid_invalidate_all ()
760 render_priv
*priv
= gport
->render_priv
;
761 double elapsed
= g_timer_elapsed (priv
->time_since_expose
, NULL
);
763 ghid_draw_area_update (gport
, NULL
);
765 if (elapsed
> MAX_ELAPSED
)
766 gdk_window_process_all_updates ();
770 ghid_notify_crosshair_change (bool changes_complete
)
772 /* We sometimes get called before the GUI is up */
773 if (gport
->drawing_area
== NULL
)
776 /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */
777 ghid_invalidate_all ();
781 ghid_notify_mark_change (bool changes_complete
)
783 /* We sometimes get called before the GUI is up */
784 if (gport
->drawing_area
== NULL
)
787 /* FIXME: We could just invalidate the bounds of the mark? */
788 ghid_invalidate_all ();
792 draw_right_cross (gint x
, gint y
, gint z
)
794 glVertex3i (x
, 0, z
);
795 glVertex3i (x
, PCB
->MaxHeight
, z
);
796 glVertex3i (0, y
, z
);
797 glVertex3i (PCB
->MaxWidth
, y
, z
);
801 draw_slanted_cross (gint x
, gint y
, gint z
)
805 x0
= x
+ (PCB
->MaxHeight
- y
);
806 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
808 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
809 y0
= y
+ (PCB
->MaxWidth
- x
);
810 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
812 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
813 glVertex3i (x0
, y0
, z
);
814 glVertex3i (x1
, y1
, z
);
816 x0
= x
- (PCB
->MaxHeight
- y
);
817 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
819 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
821 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
822 y1
= y
- (PCB
->MaxWidth
- x
);
823 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
824 glVertex3i (x0
, y0
, z
);
825 glVertex3i (x1
, y1
, z
);
829 draw_dozen_cross (gint x
, gint y
, gint z
)
832 gdouble tan60
= sqrt (3);
834 x0
= x
+ (PCB
->MaxHeight
- y
) / tan60
;
835 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
837 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
838 y0
= y
+ (PCB
->MaxWidth
- x
) * tan60
;
839 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
841 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
842 glVertex3i (x0
, y0
, z
);
843 glVertex3i (x1
, y1
, z
);
845 x0
= x
+ (PCB
->MaxHeight
- y
) * tan60
;
846 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
848 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
849 y0
= y
+ (PCB
->MaxWidth
- x
) / tan60
;
850 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
852 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
853 glVertex3i (x0
, y0
, z
);
854 glVertex3i (x1
, y1
, z
);
856 x0
= x
- (PCB
->MaxHeight
- y
) / tan60
;
857 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
859 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
861 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
862 y1
= y
- (PCB
->MaxWidth
- x
) * tan60
;
863 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
864 glVertex3i (x0
, y0
, z
);
865 glVertex3i (x1
, y1
, z
);
867 x0
= x
- (PCB
->MaxHeight
- y
) * tan60
;
868 x0
= MAX(0, MIN (x0
, PCB
->MaxWidth
));
870 x1
= MAX(0, MIN (x1
, PCB
->MaxWidth
));
872 y0
= MAX(0, MIN (y0
, PCB
->MaxHeight
));
873 y1
= y
- (PCB
->MaxWidth
- x
) / tan60
;
874 y1
= MAX(0, MIN (y1
, PCB
->MaxHeight
));
875 glVertex3i (x0
, y0
, z
);
876 glVertex3i (x1
, y1
, z
);
880 draw_crosshair (hidGC gc
, render_priv
*priv
)
882 gtkGC gtk_gc
= (gtkGC
)gc
;
884 static int done_once
= 0;
885 static GdkColor cross_color
;
890 /* FIXME: when CrossColor changed from config */
891 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
894 x
= gport
->crosshair_x
;
895 y
= gport
->crosshair_y
;
896 z
= gtk_gc
->hidgl_gc
.depth
;
898 glEnable (GL_COLOR_LOGIC_OP
);
901 glColor3f (cross_color
.red
/ 65535.,
902 cross_color
.green
/ 65535.,
903 cross_color
.blue
/ 65535.);
907 draw_right_cross (x
, y
, z
);
908 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
909 draw_slanted_cross (x
, y
, z
);
910 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
911 draw_dozen_cross (x
, y
, z
);
915 glDisable (GL_COLOR_LOGIC_OP
);
919 ghid_init_renderer (int *argc
, char ***argv
, GHidPort
*port
)
923 port
->render_priv
= priv
= g_new0 (render_priv
, 1);
925 priv
->time_since_expose
= g_timer_new ();
927 gtk_gl_init(argc
, argv
);
929 /* setup GL-context */
930 priv
->glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA
|
931 GDK_GL_MODE_STENCIL
|
935 printf ("Could not setup GL-context!\n");
936 return; /* Should we abort? */
940 priv
->hidgl
= hidgl_new_instance ();
942 /* Setup HID function pointers specific to the GL renderer*/
943 ghid_graphics_class
.end_layer
= ghid_end_layer
;
944 ghid_graphics_class
.fill_pcb_polygon
= ghid_fill_pcb_polygon
;
945 ghid_graphics_class
.thindraw_pcb_polygon
= ghid_thindraw_pcb_polygon
;
949 ghid_shutdown_renderer (GHidPort
*port
)
951 render_priv
*priv
= port
->render_priv
;
953 hidgl_free_instance (priv
->hidgl
);
955 ghid_cancel_lead_user ();
956 g_free (port
->render_priv
);
957 port
->render_priv
= NULL
;
961 ghid_init_drawing_widget (GtkWidget
*widget
, GHidPort
*port
)
963 render_priv
*priv
= port
->render_priv
;
965 gtk_widget_set_gl_capability (widget
,
973 ghid_drawing_area_configure_hook (GHidPort
*port
)
978 ghid_start_drawing (GHidPort
*port
, GtkWidget
*widget
)
980 GdkGLContext
*pGlContext
= gtk_widget_get_gl_context (widget
);
981 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
983 /* make GL-context "current" */
984 if (!gdk_gl_drawable_gl_begin (pGlDrawable
, pGlContext
))
987 port
->render_priv
->in_context
= true;
989 hidgl_start_render (port
->render_priv
->hidgl
);
995 ghid_end_drawing (GHidPort
*port
, GtkWidget
*widget
)
997 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
999 hidgl_finish_render (port
->render_priv
->hidgl
);
1001 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
1002 gdk_gl_drawable_swap_buffers (pGlDrawable
);
1006 port
->render_priv
->in_context
= false;
1008 /* end drawing to current GL-context */
1009 gdk_gl_drawable_gl_end (pGlDrawable
);
1013 ghid_screen_update (void)
1018 EMark_callback (const BoxType
* b
, void *cl
)
1020 ElementType
*element
= (ElementType
*) b
;
1022 DrawEMark (element
, element
->MarkX
, element
->MarkY
, !FRONT (element
));
1027 set_object_color (AnyObjectType
*obj
, char *warn_color
, char *selected_color
,
1028 char *connected_color
, char *found_color
, char *normal_color
)
1032 if (warn_color
!= NULL
&& TEST_FLAG (WARNFLAG
, obj
)) color
= warn_color
;
1033 else if (selected_color
!= NULL
&& TEST_FLAG (SELECTEDFLAG
, obj
)) color
= selected_color
;
1034 else if (connected_color
!= NULL
&& TEST_FLAG (CONNECTEDFLAG
, obj
)) color
= connected_color
;
1035 else if (found_color
!= NULL
&& TEST_FLAG (FOUNDFLAG
, obj
)) color
= found_color
;
1036 else color
= normal_color
;
1038 hid_draw_set_color (Output
.fgGC
, color
);
1042 set_layer_object_color (LayerType
*layer
, AnyObjectType
*obj
)
1044 set_object_color (obj
, NULL
, layer
->SelectedColor
, PCB
->ConnectedColor
, PCB
->FoundColor
, layer
->Color
);
1048 set_pv_inlayer_color (PinType
*pv
, LayerType
*layer
, int type
)
1050 if (TEST_FLAG (WARNFLAG
, pv
)) hid_draw_set_color (Output
.fgGC
, PCB
->WarnColor
);
1051 else if (TEST_FLAG (SELECTEDFLAG
, pv
)) hid_draw_set_color (Output
.fgGC
, (type
== VIA_TYPE
) ? PCB
->ViaSelectedColor
1052 : PCB
->PinSelectedColor
);
1053 else if (TEST_FLAG (CONNECTEDFLAG
, pv
)) hid_draw_set_color (Output
.fgGC
, PCB
->ConnectedColor
);
1054 else if (TEST_FLAG (FOUNDFLAG
, pv
)) hid_draw_set_color (Output
.fgGC
, PCB
->FoundColor
);
1057 int top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
1058 int bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
1059 int this_group
= GetLayerGroupNumberByPointer (layer
);
1061 if (this_group
== top_group
|| this_group
== bottom_group
)
1062 hid_draw_set_color (Output
.fgGC
, (SWAP_IDENT
== (this_group
== bottom_group
)) ?
1063 PCB
->ViaColor
: PCB
->InvisibleObjectsColor
);
1065 hid_draw_set_color (Output
.fgGC
, layer
->Color
);
1070 _draw_pv_name (PinType
*pv
)
1076 if (!pv
->Name
|| !pv
->Name
[0])
1077 text
.TextString
= EMPTY (pv
->Number
);
1079 text
.TextString
= EMPTY (TEST_FLAG (SHOWNUMBERFLAG
, PCB
) ? pv
->Number
: pv
->Name
);
1081 vert
= TEST_FLAG (EDGE2FLAG
, pv
);
1085 box
.X1
= pv
->X
- pv
->Thickness
/ 2 + Settings
.PinoutTextOffsetY
;
1086 box
.Y1
= pv
->Y
- pv
->DrillingHole
/ 2 - Settings
.PinoutTextOffsetX
;
1090 box
.X1
= pv
->X
+ pv
->DrillingHole
/ 2 + Settings
.PinoutTextOffsetX
;
1091 box
.Y1
= pv
->Y
- pv
->Thickness
/ 2 + Settings
.PinoutTextOffsetY
;
1094 hid_draw_set_color (Output
.fgGC
, PCB
->PinNameColor
);
1096 text
.Flags
= NoFlags ();
1097 /* Set font height to approx 56% of pin thickness */
1098 text
.Scale
= 56 * pv
->Thickness
/ FONT_CAPHEIGHT
;
1101 text
.Direction
= vert
? 1 : 0;
1103 hid_draw_pcb_text (Output
.fgGC
, &text
, 0);
1107 _draw_pv (PinType
*pv
, bool draw_hole
)
1109 if (TEST_FLAG (THINDRAWFLAG
, PCB
))
1110 hid_draw_thin_pcb_pv (Output
.fgGC
, Output
.fgGC
, pv
, draw_hole
, false);
1112 hid_draw_fill_pcb_pv (Output
.fgGC
, Output
.bgGC
, pv
, draw_hole
, false);
1114 if (!TEST_FLAG (HOLEFLAG
, pv
) && TEST_FLAG (DISPLAYNAMEFLAG
, pv
))
1119 draw_pin (PinType
*pin
, bool draw_hole
)
1121 set_object_color ((AnyObjectType
*) pin
, PCB
->WarnColor
, PCB
->PinSelectedColor
,
1122 PCB
->ConnectedColor
, PCB
->FoundColor
, PCB
->PinColor
);
1124 _draw_pv (pin
, draw_hole
);
1128 pin_callback (const BoxType
* b
, void *cl
)
1130 PinType
*pin
= (PinType
*) b
;
1132 if (!TEST_FLAG (HOLEFLAG
, pin
) && TEST_FLAG (DISPLAYNAMEFLAG
, pin
))
1133 _draw_pv_name (pin
);
1134 draw_pin (pin
, TEST_FLAG (THINDRAWFLAG
, PCB
));
1139 pin_name_callback (const BoxType
* b
, void *cl
)
1141 PinType
*pin
= (PinType
*) b
;
1143 if (!TEST_FLAG (HOLEFLAG
, pin
) && TEST_FLAG (DISPLAYNAMEFLAG
, pin
))
1144 _draw_pv_name (pin
);
1149 pin_inlayer_callback (const BoxType
* b
, void *cl
)
1151 set_pv_inlayer_color ((PinType
*) b
, cl
, PIN_TYPE
);
1152 _draw_pv ((PinType
*) b
, false);
1157 draw_via (PinType
*via
, bool draw_hole
)
1159 set_object_color ((AnyObjectType
*) via
, PCB
->WarnColor
, PCB
->ViaSelectedColor
,
1160 PCB
->ConnectedColor
, PCB
->FoundColor
, PCB
->ViaColor
);
1162 _draw_pv (via
, draw_hole
);
1166 via_callback (const BoxType
* b
, void *cl
)
1168 draw_via ((PinType
*)b
, TEST_FLAG (THINDRAWFLAG
, PCB
));
1173 via_inlayer_callback (const BoxType
* b
, void *cl
)
1175 set_pv_inlayer_color ((PinType
*) b
, cl
, VIA_TYPE
);
1176 _draw_pv ((PinType
*) b
, TEST_FLAG (THINDRAWFLAG
, PCB
));
1181 draw_pad_name (PadType
*pad
)
1187 if (!pad
->Name
|| !pad
->Name
[0])
1188 text
.TextString
= EMPTY (pad
->Number
);
1190 text
.TextString
= EMPTY (TEST_FLAG (SHOWNUMBERFLAG
, PCB
) ? pad
->Number
: pad
->Name
);
1192 /* should text be vertical ? */
1193 vert
= (pad
->Point1
.X
== pad
->Point2
.X
);
1197 box
.X1
= pad
->Point1
.X
- pad
->Thickness
/ 2;
1198 box
.Y1
= MAX (pad
->Point1
.Y
, pad
->Point2
.Y
) + pad
->Thickness
/ 2;
1199 box
.X1
+= Settings
.PinoutTextOffsetY
;
1200 box
.Y1
-= Settings
.PinoutTextOffsetX
;
1204 box
.X1
= MIN (pad
->Point1
.X
, pad
->Point2
.X
) - pad
->Thickness
/ 2;
1205 box
.Y1
= pad
->Point1
.Y
- pad
->Thickness
/ 2;
1206 box
.X1
+= Settings
.PinoutTextOffsetX
;
1207 box
.Y1
+= Settings
.PinoutTextOffsetY
;
1210 hid_draw_set_color (Output
.fgGC
, PCB
->PinNameColor
);
1212 text
.Flags
= NoFlags ();
1213 /* Set font height to approx 90% of pad thickness */
1214 text
.Scale
= 90 * pad
->Thickness
/ FONT_CAPHEIGHT
;
1217 text
.Direction
= vert
? 1 : 0;
1219 hid_draw_pcb_text (Output
.fgGC
, &text
, 0);
1223 _draw_pad (hidGC gc
, PadType
*pad
, bool clear
, bool mask
)
1225 if (clear
&& !mask
&& pad
->Clearance
<= 0)
1228 if (TEST_FLAG (THINDRAWFLAG
, PCB
) ||
1229 (clear
&& TEST_FLAG (THINDRAWPOLYFLAG
, PCB
)))
1230 hid_draw_thin_pcb_pad (gc
, pad
, clear
, mask
);
1232 hid_draw_fill_pcb_pad (gc
, pad
, clear
, mask
);
1236 draw_pad (PadType
*pad
)
1238 set_object_color ((AnyObjectType
*)pad
, PCB
->WarnColor
,
1239 PCB
->PinSelectedColor
, PCB
->ConnectedColor
, PCB
->FoundColor
,
1240 FRONT (pad
) ? PCB
->PinColor
: PCB
->InvisibleObjectsColor
);
1242 _draw_pad (Output
.fgGC
, pad
, false, false);
1244 if (TEST_FLAG (DISPLAYNAMEFLAG
, pad
))
1245 draw_pad_name (pad
);
1249 pad_callback (const BoxType
* b
, void *cl
)
1251 PadType
*pad
= (PadType
*) b
;
1254 if (ON_SIDE (pad
, *side
)) {
1255 if (TEST_FLAG (DISPLAYNAMEFLAG
, pad
))
1256 draw_pad_name (pad
);
1264 hole_callback (const BoxType
* b
, void *cl
)
1266 PinType
*pv
= (PinType
*) b
;
1267 int plated
= cl
? *(int *) cl
: -1;
1269 if ((plated
== 0 && !TEST_FLAG (HOLEFLAG
, pv
)) ||
1270 (plated
== 1 && TEST_FLAG (HOLEFLAG
, pv
)))
1273 if (TEST_FLAG (THINDRAWFLAG
, PCB
))
1275 if (!TEST_FLAG (HOLEFLAG
, pv
))
1277 hid_draw_set_line_cap (Output
.fgGC
, Round_Cap
);
1278 hid_draw_set_line_width (Output
.fgGC
, 0);
1279 hid_draw_arc (Output
.fgGC
, pv
->X
, pv
->Y
,
1280 pv
->DrillingHole
/ 2, pv
->DrillingHole
/ 2, 0, 360);
1284 hid_draw_fill_circle (Output
.bgGC
, pv
->X
, pv
->Y
, pv
->DrillingHole
/ 2);
1286 if (TEST_FLAG (HOLEFLAG
, pv
))
1288 set_object_color ((AnyObjectType
*) pv
, PCB
->WarnColor
,
1289 PCB
->ViaSelectedColor
, NULL
, NULL
, Settings
.BlackColor
);
1291 hid_draw_set_line_cap (Output
.fgGC
, Round_Cap
);
1292 hid_draw_set_line_width (Output
.fgGC
, 0);
1293 hid_draw_arc (Output
.fgGC
, pv
->X
, pv
->Y
,
1294 pv
->DrillingHole
/ 2, pv
->DrillingHole
/ 2, 0, 360);
1300 line_callback (const BoxType
* b
, void *cl
)
1302 LayerType
*layer
= cl
;
1303 LineType
*line
= (LineType
*)b
;
1305 set_layer_object_color (layer
, (AnyObjectType
*) line
);
1306 hid_draw_pcb_line (Output
.fgGC
, line
);
1311 arc_callback (const BoxType
* b
, void *cl
)
1313 LayerType
*layer
= cl
;
1314 ArcType
*arc
= (ArcType
*)b
;
1316 set_layer_object_color (layer
, (AnyObjectType
*) arc
);
1317 hid_draw_pcb_arc (Output
.fgGC
, arc
);
1322 text_callback (const BoxType
* b
, void *cl
)
1324 LayerType
*layer
= cl
;
1325 TextType
*text
= (TextType
*)b
;
1328 if (TEST_FLAG (SELECTEDFLAG
, text
))
1329 hid_draw_set_color (Output
.fgGC
, layer
->SelectedColor
);
1331 hid_draw_set_color (Output
.fgGC
, layer
->Color
);
1332 if (layer
== &PCB
->Data
->SILKLAYER
||
1333 layer
== &PCB
->Data
->BACKSILKLAYER
)
1334 min_silk_line
= PCB
->minSlk
;
1336 min_silk_line
= PCB
->minWid
;
1337 hid_draw_pcb_text (Output
.fgGC
, text
, min_silk_line
);
1344 const BoxType
*drawn_area
;
1348 poly_callback (const BoxType
* b
, void *cl
)
1350 struct poly_info
*i
= (struct poly_info
*) cl
;
1351 PolygonType
*polygon
= (PolygonType
*)b
;
1353 set_layer_object_color (i
->layer
, (AnyObjectType
*) polygon
);
1354 hid_draw_pcb_polygon (Output
.fgGC
, polygon
, i
->drawn_area
);
1359 clearPin_callback (const BoxType
* b
, void *cl
)
1361 PinType
*pin
= (PinType
*) b
;
1362 if (TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG (THINDRAWPOLYFLAG
, PCB
))
1363 hid_draw_thin_pcb_pv (Output
.pmGC
, Output
.pmGC
, pin
, false, true);
1365 hid_draw_fill_pcb_pv (Output
.pmGC
, Output
.pmGC
, pin
, false, true);
1370 clearPad_callback (const BoxType
* b
, void *cl
)
1372 PadType
*pad
= (PadType
*) b
;
1374 if (ON_SIDE (pad
, *side
) && pad
->Mask
)
1375 _draw_pad (Output
.pmGC
, pad
, true, true);
1380 clearPin_callback_solid (const BoxType
* b
, void *cl
)
1382 PinType
*pin
= (PinType
*) b
;
1383 hid_draw_fill_pcb_pv (Output
.pmGC
, Output
.pmGC
, pin
, false, true);
1388 clearPad_callback_solid (const BoxType
* b
, void *cl
)
1390 PadType
*pad
= (PadType
*) b
;
1392 if (ON_SIDE (pad
, *side
) && pad
->Mask
)
1393 hid_draw_fill_pcb_pad (Output
.pmGC
, pad
, true, true);
1398 GhidDrawMask (int side
, BoxType
* screen
)
1400 int thin
= TEST_FLAG(THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
);
1401 LayerType
*Layer
= LAYER_PTR (side
== TOP_SIDE
? top_soldermask_layer
: bottom_soldermask_layer
);
1402 struct poly_info info
;
1403 PolygonType polygon
;
1405 OutputType
*out
= &Output
;
1409 hid_draw_set_line_width (Output
.pmGC
, 0);
1410 hid_draw_set_color (Output
.pmGC
, PCB
->MaskColor
);
1411 r_search (PCB
->Data
->pin_tree
, screen
, NULL
, clearPin_callback
, NULL
);
1412 r_search (PCB
->Data
->via_tree
, screen
, NULL
, clearPin_callback
, NULL
);
1413 r_search (PCB
->Data
->pad_tree
, screen
, NULL
, clearPad_callback
, &side
);
1414 hid_draw_set_color (Output
.pmGC
, "erase");
1417 hid_draw_use_mask (&ghid_graphics
, HID_MASK_CLEAR
);
1420 info
.drawn_area
= screen
;
1421 r_search (Layer
->polygon_tree
, screen
, NULL
, poly_callback
, &info
);
1422 r_search (Layer
->line_tree
, screen
, NULL
, line_callback
, Layer
);
1423 r_search (Layer
->arc_tree
, screen
, NULL
, arc_callback
, Layer
);
1424 r_search (Layer
->text_tree
, screen
, NULL
, text_callback
, Layer
);
1426 r_search (PCB
->Data
->pin_tree
, screen
, NULL
, clearPin_callback_solid
, NULL
);
1427 r_search (PCB
->Data
->via_tree
, screen
, NULL
, clearPin_callback_solid
, NULL
);
1428 r_search (PCB
->Data
->pad_tree
, screen
, NULL
, clearPad_callback_solid
, &side
);
1430 hid_draw_use_mask (&ghid_graphics
, HID_MASK_AFTER
);
1431 hid_draw_set_color (out
->fgGC
, PCB
->MaskColor
);
1432 ghid_set_alpha_mult (out
->fgGC
, thin
? 0.35 : 1.0);
1434 if (!PCB
->Data
->outline_valid
) {
1436 if (PCB
->Data
->outline
!= NULL
)
1437 poly_Free (&PCB
->Data
->outline
);
1439 PCB
->Data
->outline
= board_outline_poly ();
1440 PCB
->Data
->outline_valid
= true;
1443 memset (&polygon
, 0, sizeof (polygon
));
1444 polygon
.Clipped
= PCB
->Data
->outline
;
1445 polygon
.BoundingBox
= *screen
;
1446 polygon
.Flags
= NoFlags ();
1447 SET_FLAG (FULLPOLYFLAG
, &polygon
);
1448 common_fill_pcb_polygon (out
->fgGC
, &polygon
, screen
);
1449 poly_FreeContours (&polygon
.NoHoles
);
1450 /* THE GL fill_pcb_polygon doesn't work whilst masking */
1451 // hid_draw_fill_pcb_polygon (out->fgGC, &polygon, screen);
1452 // hid_draw_fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
1453 ghid_set_alpha_mult (out
->fgGC
, 1.0);
1455 hid_draw_use_mask (&ghid_graphics
, HID_MASK_OFF
);
1459 GhidDrawLayerGroup (int group
, const BoxType
* screen
)
1461 render_priv
*priv
= gport
->render_priv
;
1465 struct poly_info info
;
1467 int n_entries
= PCB
->LayerGroups
.Number
[group
];
1468 Cardinal
*layers
= PCB
->LayerGroups
.Entries
[group
];
1470 int top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
1471 int bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
1474 if (!hid_draw_set_layer (&ghid_graphics
, 0, group
, 0))
1477 /* HACK: Subcomposite each layer in a layer group separately */
1478 for (i
= n_entries
- 1; i
>= 0; i
--) {
1479 layernum
= layers
[i
];
1480 Layer
= PCB
->Data
->Layer
+ layers
[i
];
1482 is_outline
= strcmp (Layer
->Name
, "outline") == 0 ||
1483 strcmp (Layer
->Name
, "route") == 0;
1485 if (layernum
< max_copper_layer
&& Layer
->On
) {
1488 hid_draw_set_layer (&ghid_graphics
, 0, group
, 0);
1492 if (!is_outline
&& !TEST_FLAG (THINDRAWFLAG
, PCB
)) {
1493 /* Mask out drilled holes on this layer */
1494 hidgl_flush_triangles (priv
->hidgl
);
1495 glPushAttrib (GL_COLOR_BUFFER_BIT
);
1496 glColorMask (0, 0, 0, 0);
1497 hid_draw_set_color (Output
.bgGC
, PCB
->MaskColor
);
1498 if (PCB
->PinOn
) r_search (PCB
->Data
->pin_tree
, screen
, NULL
, hole_callback
, NULL
);
1499 if (PCB
->ViaOn
) r_search (PCB
->Data
->via_tree
, screen
, NULL
, hole_callback
, NULL
);
1500 hidgl_flush_triangles (priv
->hidgl
);
1504 /* draw all polygons on this layer */
1505 if (Layer
->PolygonN
) {
1507 info
.drawn_area
= screen
;
1508 r_search (Layer
->polygon_tree
, screen
, NULL
, poly_callback
, &info
);
1510 /* HACK: Subcomposite polygons separately from other layer primitives */
1511 /* Reset the compositing */
1512 hid_draw_end_layer (&ghid_graphics
);
1513 hid_draw_set_layer (&ghid_graphics
, 0, group
, 0);
1515 if (!is_outline
&& !TEST_FLAG (THINDRAWFLAG
, PCB
)) {
1516 hidgl_flush_triangles (priv
->hidgl
);
1517 glPushAttrib (GL_COLOR_BUFFER_BIT
);
1518 glColorMask (0, 0, 0, 0);
1519 /* Mask out drilled holes on this layer */
1520 if (PCB
->PinOn
) r_search (PCB
->Data
->pin_tree
, screen
, NULL
, hole_callback
, NULL
);
1521 if (PCB
->ViaOn
) r_search (PCB
->Data
->via_tree
, screen
, NULL
, hole_callback
, NULL
);
1522 hidgl_flush_triangles (priv
->hidgl
);
1527 /* Draw pins, vias and pads on this layer */
1528 if (!global_view_2d
&& !is_outline
) {
1530 (group
== bottom_group
|| group
== top_group
))
1531 r_search (PCB
->Data
->pin_tree
, screen
, NULL
, pin_name_callback
, Layer
);
1532 if (PCB
->PinOn
) r_search (PCB
->Data
->pin_tree
, screen
, NULL
, pin_inlayer_callback
, Layer
);
1533 if (PCB
->ViaOn
) r_search (PCB
->Data
->via_tree
, screen
, NULL
, via_inlayer_callback
, Layer
);
1534 if (PCB
->PinOn
&& group
== top_group
)
1537 r_search (PCB
->Data
->pad_tree
, screen
, NULL
, pad_callback
, &side
);
1539 if (PCB
->PinOn
&& group
== bottom_group
)
1542 r_search (PCB
->Data
->pad_tree
, screen
, NULL
, pad_callback
, &side
);
1546 if (TEST_FLAG (CHECKPLANESFLAG
, PCB
))
1549 r_search (Layer
->line_tree
, screen
, NULL
, line_callback
, Layer
);
1550 r_search (Layer
->arc_tree
, screen
, NULL
, arc_callback
, Layer
);
1551 r_search (Layer
->text_tree
, screen
, NULL
, text_callback
, Layer
);
1555 hid_draw_end_layer (&ghid_graphics
);
1557 return (n_entries
> 1);
1561 DrawDrillChannel (hidGC gc
, int vx
, int vy
, int vr
, int from_layer
, int to_layer
, double scale
)
1563 #define PIXELS_PER_CIRCLINE 5.
1564 #define MIN_FACES_PER_CYL 6
1565 #define MAX_FACES_PER_CYL 360
1573 slices
= M_PI
* 2 * vr
/ scale
/ PIXELS_PER_CIRCLINE
;
1575 if (slices
< MIN_FACES_PER_CYL
)
1576 slices
= MIN_FACES_PER_CYL
;
1578 if (slices
> MAX_FACES_PER_CYL
)
1579 slices
= MAX_FACES_PER_CYL
;
1581 z1
= compute_depth (from_layer
);
1582 z2
= compute_depth (to_layer
);
1587 hidgl_ensure_triangle_space (gc
, 2 * slices
);
1588 for (i
= 0; i
< slices
; i
++)
1590 x2
= radius
* cosf (((float)(i
+ 1)) * 2. * M_PI
/ (float)slices
) + vx
;
1591 y2
= radius
* sinf (((float)(i
+ 1)) * 2. * M_PI
/ (float)slices
) + vy
;
1592 hidgl_add_triangle_3D (gc
, x1
, y1
, z1
, x2
, y2
, z1
, x1
, y1
, z2
);
1593 hidgl_add_triangle_3D (gc
, x2
, y2
, z1
, x1
, y1
, z2
, x2
, y2
, z2
);
1606 draw_hole_cyl (PinType
*Pin
, struct cyl_info
*info
, int Type
)
1610 if (TEST_FLAG (WARNFLAG
, Pin
))
1611 color
= PCB
->WarnColor
;
1612 else if (TEST_FLAG (SELECTEDFLAG
, Pin
))
1613 color
= (Type
== VIA_TYPE
) ? PCB
->ViaSelectedColor
: PCB
->PinSelectedColor
;
1614 else if (TEST_FLAG (CONNECTEDFLAG
, Pin
))
1615 color
= PCB
->ConnectedColor
;
1616 else if (TEST_FLAG (FOUNDFLAG
, Pin
))
1617 color
= PCB
->FoundColor
;
1621 hid_draw_set_color (Output
.fgGC
, color
);
1622 DrawDrillChannel (Output
.fgGC
, Pin
->X
, Pin
->Y
, Pin
->DrillingHole
/ 2, info
->from_layer
, info
->to_layer
, info
->scale
);
1627 pin_hole_cyl_callback (const BoxType
* b
, void *cl
)
1629 return draw_hole_cyl ((PinType
*)b
, (struct cyl_info
*)cl
, PIN_TYPE
);
1633 via_hole_cyl_callback (const BoxType
* b
, void *cl
)
1635 return draw_hole_cyl ((PinType
*)b
, (struct cyl_info
*)cl
, VIA_TYPE
);
1639 ghid_draw_everything (BoxType
*drawn_area
)
1641 render_priv
*priv
= gport
->render_priv
;
1643 int number_phys_on_top
;
1645 /* This is the list of layer groups we will draw. */
1646 int do_group
[MAX_LAYER
];
1647 /* This is the reverse of the order in which we draw them. */
1648 int drawn_groups
[MAX_LAYER
];
1649 struct cyl_info cyl_info
;
1651 int save_show_solder
;
1657 priv
->current_colorname
= NULL
;
1659 /* Test direction of rendering */
1660 /* Look at sign of eye coordinate system z-coord when projecting a
1661 world vector along +ve Z axis, (0, 0, 1). */
1662 /* XXX: This isn't strictly correct, as I've ignored the matrix
1663 elements for homogeneous coordinates. */
1664 /* NB: last_modelview_matrix is transposed in memory! */
1665 reverse_layers
= (last_modelview_matrix
[2][2] < 0);
1667 save_show_solder
= Settings
.ShowBottomSide
;
1668 Settings
.ShowBottomSide
= reverse_layers
;
1670 PCB
->Data
->SILKLAYER
.Color
= PCB
->ElementColor
;
1671 PCB
->Data
->BACKSILKLAYER
.Color
= PCB
->InvisibleObjectsColor
;
1673 top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
1674 bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
1676 min_phys_group
= MIN (bottom_group
, top_group
);
1677 max_phys_group
= MAX (bottom_group
, top_group
);
1679 memset (do_group
, 0, sizeof (do_group
));
1680 if (global_view_2d
) {
1681 /* Draw in layer stack order when in 2D view */
1682 for (ngroups
= 0, i
= 0; i
< max_copper_layer
; i
++) {
1683 int group
= GetLayerGroupNumberByNumber (LayerStack
[i
]);
1685 if (!do_group
[group
]) {
1686 do_group
[group
] = 1;
1687 drawn_groups
[ngroups
++] = group
;
1691 /* Draw in group order when in 3D view */
1692 for (ngroups
= 0, i
= 0; i
< max_group
; i
++) {
1693 int group
= reverse_layers
? max_group
- 1 - i
: i
;
1695 if (!do_group
[group
]) {
1696 do_group
[group
] = 1;
1697 drawn_groups
[ngroups
++] = group
;
1703 * first draw all 'invisible' stuff
1705 side
= SWAP_IDENT
? TOP_SIDE
: BOTTOM_SIDE
;
1707 if (!TEST_FLAG (CHECKPLANESFLAG
, PCB
) &&
1708 hid_draw_set_layer (&ghid_graphics
, "invisible", SL (INVISIBLE
, 0), 0)) {
1709 DrawSilk (&ghid_graphics
, side
, drawn_area
);
1712 r_search (PCB
->Data
->pad_tree
, drawn_area
, NULL
, pad_callback
, &side
);
1714 hid_draw_end_layer (&ghid_graphics
);
1716 /* Draw the reverse-side solder mask if turned on */
1717 if (!global_view_2d
&&
1718 hid_draw_set_layer (&ghid_graphics
, SWAP_IDENT
? "componentmask" : "soldermask",
1719 SWAP_IDENT
? SL (MASK
, TOP
) : SL (MASK
, BOTTOM
), 0)) {
1720 GhidDrawMask (side
, drawn_area
);
1721 hid_draw_end_layer (&ghid_graphics
);
1725 /* draw all layers in layerstack order */
1726 #define FADE_FACTOR 0.8
1727 number_phys_on_top
= max_phys_group
- min_phys_group
;
1728 for (i
= ngroups
- 1; i
>= 0; i
--) {
1729 bool is_this_physical
= drawn_groups
[i
] >= min_phys_group
&&
1730 drawn_groups
[i
] <= max_phys_group
;
1731 bool is_next_physical
= i
> 0 &&
1732 drawn_groups
[i
- 1] >= min_phys_group
&&
1733 drawn_groups
[i
- 1] <= max_phys_group
;
1735 double alpha_mult
= global_view_2d
? pow (FADE_FACTOR
, i
) :
1736 (is_this_physical
? pow (FADE_FACTOR
, number_phys_on_top
) : 1.);
1738 if (is_this_physical
)
1739 number_phys_on_top
--;
1741 ghid_set_alpha_mult (Output
.fgGC
, alpha_mult
);
1742 GhidDrawLayerGroup (drawn_groups
[i
], drawn_area
);
1745 if (!global_view_2d
&& is_this_physical
&& is_next_physical
) {
1746 cyl_info
.from_layer
= drawn_groups
[i
];
1747 cyl_info
.to_layer
= drawn_groups
[i
- 1];
1748 cyl_info
.scale
= gport
->view
.coord_per_px
;
1749 hid_draw_set_color (Output
.fgGC
, "drill");
1750 ghid_set_alpha_mult (Output
.fgGC
, alpha_mult
* 0.75);
1751 if (PCB
->PinOn
) r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, pin_hole_cyl_callback
, &cyl_info
);
1752 if (PCB
->ViaOn
) r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, via_hole_cyl_callback
, &cyl_info
);
1758 ghid_set_alpha_mult (Output
.fgGC
, 1.0);
1760 if (TEST_FLAG (CHECKPLANESFLAG
, PCB
))
1763 side
= SWAP_IDENT
? BOTTOM_SIDE
: TOP_SIDE
;
1765 /* Draw pins, pads, vias below silk */
1766 if (global_view_2d
) {
1767 start_subcomposite (priv
->hidgl
);
1769 if (!TEST_FLAG (THINDRAWFLAG
, PCB
)) {
1770 /* Mask out drilled holes */
1771 hidgl_flush_triangles (priv
->hidgl
);
1772 glPushAttrib (GL_COLOR_BUFFER_BIT
);
1773 glColorMask (0, 0, 0, 0);
1774 if (PCB
->PinOn
) r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, hole_callback
, NULL
);
1775 if (PCB
->ViaOn
) r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, hole_callback
, NULL
);
1776 hidgl_flush_triangles (priv
->hidgl
);
1780 if (PCB
->PinOn
) r_search (PCB
->Data
->pad_tree
, drawn_area
, NULL
, pad_callback
, &side
);
1781 if (PCB
->PinOn
) r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, pin_callback
, NULL
);
1782 if (PCB
->ViaOn
) r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, via_callback
, NULL
);
1784 end_subcomposite (priv
->hidgl
);
1787 /* Draw the solder mask if turned on */
1788 if (hid_draw_set_layer (&ghid_graphics
, SWAP_IDENT
? "soldermask" : "componentmask",
1789 SWAP_IDENT
? SL (MASK
, BOTTOM
) : SL (MASK
, TOP
), 0)) {
1790 GhidDrawMask (side
, drawn_area
);
1791 hid_draw_end_layer (&ghid_graphics
);
1794 if (hid_draw_set_layer (&ghid_graphics
, SWAP_IDENT
? "bottomsilk" : "topsilk",
1795 SWAP_IDENT
? SL (SILK
, BOTTOM
) : SL (SILK
, TOP
), 0)) {
1796 DrawSilk (&ghid_graphics
, side
, drawn_area
);
1797 hid_draw_end_layer (&ghid_graphics
);
1800 /* Draw element Marks */
1802 r_search (PCB
->Data
->element_tree
, drawn_area
, NULL
, EMark_callback
, NULL
);
1804 /* Draw rat lines on top */
1805 if (PCB
->RatOn
&& hid_draw_set_layer (&ghid_graphics
, "rats", SL (RATS
, 0), 0)) {
1806 DrawRats (&ghid_graphics
, drawn_area
);
1807 hid_draw_end_layer (&ghid_graphics
);
1810 Settings
.ShowBottomSide
= save_show_solder
;
1815 ghid_drawing_area_expose_cb (GtkWidget
*widget
,
1819 render_priv
*priv
= port
->render_priv
;
1820 GtkAllocation allocation
;
1828 gtk_widget_get_allocation (widget
, &allocation
);
1830 ghid_start_drawing (port
, widget
);
1832 Output
.fgGC
= hid_draw_make_gc (&ghid_graphics
);
1833 Output
.bgGC
= hid_draw_make_gc (&ghid_graphics
);
1834 Output
.pmGC
= hid_draw_make_gc (&ghid_graphics
);
1836 /* If we don't have any stencil bits available,
1837 we can't use the hidgl polygon drawing routine */
1838 /* TODO: We could use the GLU tessellator though */
1839 if (hidgl_stencil_bits (priv
->hidgl
) == 0)
1840 ghid_graphics_class
.fill_pcb_polygon
= common_fill_pcb_polygon
;
1842 glEnable (GL_BLEND
);
1843 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1845 glViewport (0, 0, allocation
.width
, allocation
.height
);
1847 glEnable (GL_SCISSOR_TEST
);
1848 glScissor (ev
->area
.x
,
1849 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
1850 ev
->area
.width
, ev
->area
.height
);
1852 glMatrixMode (GL_PROJECTION
);
1854 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
1855 glMatrixMode (GL_MODELVIEW
);
1857 glTranslatef (widget
->allocation
.width
/ 2., widget
->allocation
.height
/ 2., 0);
1858 glMultMatrixf ((GLfloat
*)view_matrix
);
1859 glTranslatef (-widget
->allocation
.width
/ 2., -widget
->allocation
.height
/ 2., 0);
1860 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
1861 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
1862 ((port
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / port
->view
.coord_per_px
);
1863 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
1865 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
1867 glGetFloatv (GL_MODELVIEW_MATRIX
, (GLfloat
*)last_modelview_matrix
);
1869 glEnable (GL_STENCIL_TEST
);
1870 glClearColor (port
->offlimits_color
.red
/ 65535.,
1871 port
->offlimits_color
.green
/ 65535.,
1872 port
->offlimits_color
.blue
/ 65535.,
1876 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1877 hidgl_reset_stencil_usage (priv
->hidgl
);
1879 /* Disable the stencil test until we need it - otherwise it gets dirty */
1880 glDisable (GL_STENCIL_TEST
);
1882 glStencilFunc (GL_ALWAYS
, 0, 0);
1884 /* Test the 8 corners of a cube spanning the event */
1885 min_depth
= -50 + compute_depth (0); /* FIXME: NEED TO USE PHYSICAL GROUPS */
1886 max_depth
= 50 + compute_depth (max_copper_layer
- 1); /* FIXME: NEED TO USE PHYSICAL GROUPS */
1888 ghid_unproject_to_z_plane (ev
->area
.x
,
1890 min_depth
, &new_x
, &new_y
);
1891 max_x
= min_x
= new_x
;
1892 max_y
= min_y
= new_y
;
1894 ghid_unproject_to_z_plane (ev
->area
.x
,
1896 max_depth
, &new_x
, &new_y
);
1897 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1898 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1901 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
1903 min_depth
, &new_x
, &new_y
);
1904 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1905 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1907 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
, ev
->area
.y
,
1908 max_depth
, &new_x
, &new_y
);
1909 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1910 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1913 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
1914 ev
->area
.y
+ ev
->area
.height
,
1915 min_depth
, &new_x
, &new_y
);
1916 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1917 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1919 ghid_unproject_to_z_plane (ev
->area
.x
+ ev
->area
.width
,
1920 ev
->area
.y
+ ev
->area
.height
,
1921 max_depth
, &new_x
, &new_y
);
1922 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1923 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1926 ghid_unproject_to_z_plane (ev
->area
.x
,
1927 ev
->area
.y
+ ev
->area
.height
,
1930 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1931 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1933 ghid_unproject_to_z_plane (ev
->area
.x
,
1934 ev
->area
.y
+ ev
->area
.height
,
1937 min_x
= MIN (min_x
, new_x
); max_x
= MAX (max_x
, new_x
);
1938 min_y
= MIN (min_y
, new_y
); max_y
= MAX (max_y
, new_y
);
1940 region
.X1
= min_x
; region
.X2
= max_x
+ 1;
1941 region
.Y1
= min_y
; region
.Y2
= max_y
+ 1;
1943 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
1944 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
1945 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
1946 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
1948 glColor3f (port
->bg_color
.red
/ 65535.,
1949 port
->bg_color
.green
/ 65535.,
1950 port
->bg_color
.blue
/ 65535.);
1952 ghid_invalidate_current_gc ();
1954 /* Setup stenciling */
1955 /* Drawing operations set the stencil buffer to '1' */
1956 glStencilOp (GL_KEEP
, GL_KEEP
, GL_REPLACE
); /* Stencil pass => replace stencil value (with 1) */
1957 /* Drawing operations as masked to areas where the stencil buffer is '0' */
1958 /* glStencilFunc (GL_GREATER, 1, 1); */ /* Draw only where stencil buffer is 0 */
1960 if (global_view_2d
) {
1962 glVertex3i (0, 0, 0);
1963 glVertex3i (PCB
->MaxWidth
, 0, 0);
1964 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, 0);
1965 glVertex3i (0, PCB
->MaxHeight
, 0);
1974 top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
1975 bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
1977 min_phys_group
= MIN (bottom_group
, top_group
);
1978 max_phys_group
= MAX (bottom_group
, top_group
);
1981 for (i
= min_phys_group
; i
<= max_phys_group
; i
++) {
1982 int depth
= compute_depth (i
);
1983 glVertex3i (0, 0, depth
);
1984 glVertex3i (PCB
->MaxWidth
, 0, depth
);
1985 glVertex3i (PCB
->MaxWidth
, PCB
->MaxHeight
, depth
);
1986 glVertex3i (0, PCB
->MaxHeight
, depth
);
1991 ghid_draw_bg_image ();
1993 /* hid_expose_callback (&ghid_graphics, ®ion, 0); */
1994 ghid_draw_everything (®ion
);
1995 hidgl_flush_triangles (priv
->hidgl
);
1997 /* Set the current depth to the right value for the layer we are editing */
1998 priv
->edit_depth
= compute_depth (GetLayerGroupNumberByNumber (INDEXOFCURRENT
));
1999 hidgl_set_depth (Output
.fgGC
, priv
->edit_depth
);
2001 ghid_draw_grid (Output
.fgGC
, ®ion
);
2003 ghid_invalidate_current_gc ();
2005 DrawAttached (Output
.fgGC
);
2006 DrawMark (Output
.fgGC
);
2007 hidgl_flush_triangles (priv
->hidgl
);
2009 draw_crosshair (Output
.fgGC
, priv
);
2010 hidgl_flush_triangles (priv
->hidgl
);
2012 draw_lead_user (Output
.fgGC
, priv
);
2014 ghid_end_drawing (port
, widget
);
2016 hid_draw_destroy_gc (Output
.fgGC
);
2017 hid_draw_destroy_gc (Output
.bgGC
);
2018 hid_draw_destroy_gc (Output
.pmGC
);
2023 g_timer_start (priv
->time_since_expose
);
2028 /* This realize callback is used to work around a crash bug in some mesa
2029 * versions (observed on a machine running the intel i965 driver. It isn't
2030 * obvious why it helps, but somehow fiddling with the GL context here solves
2031 * the issue. The problem appears to have been fixed in recent mesa versions.
2034 ghid_port_drawing_realize_cb (GtkWidget
*widget
, gpointer data
)
2036 GdkGLContext
*glcontext
= gtk_widget_get_gl_context (widget
);
2037 GdkGLDrawable
*gldrawable
= gtk_widget_get_gl_drawable (widget
);
2039 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
))
2042 gdk_gl_drawable_gl_end (gldrawable
);
2047 ghid_pinout_preview_expose (GtkWidget
*widget
,
2050 GhidPinoutPreview
*pinout
= GHID_PINOUT_PREVIEW (widget
);
2051 render_priv
*priv
= gport
->render_priv
;
2052 GtkAllocation allocation
;
2053 view_data save_view
;
2054 int save_width
, save_height
;
2055 Coord save_max_width
;
2056 Coord save_max_height
;
2059 save_view
= gport
->view
;
2060 save_width
= gport
->width
;
2061 save_height
= gport
->height
;
2062 save_max_width
= PCB
->MaxWidth
;
2063 save_max_height
= PCB
->MaxHeight
;
2065 /* Setup zoom factor for drawing routines */
2067 gtk_widget_get_allocation (widget
, &allocation
);
2068 xz
= (double) pinout
->x_max
/ allocation
.width
;
2069 yz
= (double) pinout
->y_max
/ allocation
.height
;
2071 gport
->view
.coord_per_px
= xz
;
2073 gport
->view
.coord_per_px
= yz
;
2075 gport
->width
= allocation
.width
;
2076 gport
->height
= allocation
.height
;
2077 gport
->view
.width
= allocation
.width
* gport
->view
.coord_per_px
;
2078 gport
->view
.height
= allocation
.height
* gport
->view
.coord_per_px
;
2079 gport
->view
.x0
= (pinout
->x_max
- gport
->view
.width
) / 2;
2080 gport
->view
.y0
= (pinout
->y_max
- gport
->view
.height
) / 2;
2081 PCB
->MaxWidth
= pinout
->x_max
;
2082 PCB
->MaxHeight
= pinout
->y_max
;
2084 ghid_start_drawing (gport
, widget
);
2086 #if 0 /* We disable alpha blending here, as hid_expose_callback() does not
2087 * call set_layer() as appropriate for us to sub-composite rendering
2088 * from each layer when drawing a single element. If we leave alpha-
2089 * blending on, it means text and overlapping pads are rendered ugly.
2092 glEnable (GL_BLEND
);
2093 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
2096 glViewport (0, 0, allocation
.width
, allocation
.height
);
2098 #if 0 /* We disable the scissor test here, as it is interacting badly with
2099 * being handed expose events which don't cover the whole window.
2100 * As we have a double-buffered GL window, we end up with unintialised
2101 * contents remaining in the unpainted areas (outside the scissor
2102 * region), and these are being flipped onto the screen.
2104 * The debugging code below shows multiple expose events when the
2105 * window is shown the first time, some of which are very small.
2107 * XXX: There is clearly a perforamnce issue here, in that we may
2108 * be rendering the preview more times, and over a larger area
2109 * than is really required.
2112 glEnable (GL_SCISSOR_TEST
);
2113 glScissor (ev
->area
.x
,
2114 allocation
.height
- ev
->area
.height
- ev
->area
.y
,
2115 ev
->area
.width
, ev
->area
.height
);
2119 printf ("EVT: %i, %i, w=%i, h=%i, Scissor setup: glScissor (%f, %f, %f, %f);\n",
2120 ev
->area
.x
, ev
->area
.y
, ev
->area
.width
, ev
->area
.height
,
2122 (double)(allocation
.height
- ev
->area
.height
- ev
->area
.y
),
2123 (double)ev
->area
.width
,
2124 (double)ev
->area
.height
);
2127 glMatrixMode (GL_PROJECTION
);
2129 glOrtho (0, allocation
.width
, allocation
.height
, 0, -100000, 100000);
2130 glMatrixMode (GL_MODELVIEW
);
2132 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
2134 glClearColor (gport
->bg_color
.red
/ 65535.,
2135 gport
->bg_color
.green
/ 65535.,
2136 gport
->bg_color
.blue
/ 65535.,
2140 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2141 hidgl_reset_stencil_usage (priv
->hidgl
);
2143 /* Disable the stencil test until we need it - otherwise it gets dirty */
2144 glDisable (GL_STENCIL_TEST
);
2146 glStencilFunc (GL_ALWAYS
, 0, 0);
2148 /* call the drawing routine */
2149 ghid_invalidate_current_gc ();
2151 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
2152 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
2153 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
2154 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
2156 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
2157 -gport
->view
.y0
, 0);
2159 hid_expose_callback (&ghid_graphics
, NULL
, pinout
->element
);
2160 hidgl_flush_triangles (priv
->hidgl
);
2163 ghid_end_drawing (gport
, widget
);
2165 gport
->view
= save_view
;
2166 gport
->width
= save_width
;
2167 gport
->height
= save_height
;
2168 PCB
->MaxWidth
= save_max_width
;
2169 PCB
->MaxHeight
= save_max_height
;
2176 ghid_render_pixmap (int cx
, int cy
, double zoom
, int width
, int height
, int depth
)
2178 render_priv
*priv
= gport
->render_priv
;
2179 GdkGLConfig
*glconfig
;
2181 GdkGLPixmap
*glpixmap
;
2182 GdkGLContext
* glcontext
;
2183 GdkGLDrawable
* gldrawable
;
2184 view_data save_view
;
2185 int save_width
, save_height
;
2188 save_view
= gport
->view
;
2189 save_width
= gport
->width
;
2190 save_height
= gport
->height
;
2192 /* Setup rendering context for drawing routines
2195 glconfig
= gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB
|
2196 GDK_GL_MODE_STENCIL
|
2197 GDK_GL_MODE_SINGLE
);
2199 pixmap
= gdk_pixmap_new (NULL
, width
, height
, depth
);
2200 glpixmap
= gdk_pixmap_set_gl_capability (pixmap
, glconfig
, NULL
);
2201 gldrawable
= GDK_GL_DRAWABLE (glpixmap
);
2202 glcontext
= gdk_gl_context_new (gldrawable
, NULL
, TRUE
, GDK_GL_RGBA_TYPE
);
2204 /* Setup zoom factor for drawing routines */
2206 gport
->view
.coord_per_px
= zoom
;
2207 gport
->width
= width
;
2208 gport
->height
= height
;
2209 gport
->view
.width
= width
* gport
->view
.coord_per_px
;
2210 gport
->view
.height
= height
* gport
->view
.coord_per_px
;
2211 gport
->view
.x0
= gport
->view
.flip_x
? PCB
->MaxWidth
- cx
: cx
;
2212 gport
->view
.x0
-= gport
->view
.height
/ 2;
2213 gport
->view
.y0
= gport
->view
.flip_y
? PCB
->MaxHeight
- cy
: cy
;
2214 gport
->view
.y0
-= gport
->view
.width
/ 2;
2216 /* make GL-context "current" */
2217 if (!gdk_gl_drawable_gl_begin (gldrawable
, glcontext
)) {
2220 hidgl_start_render (priv
->hidgl
);
2221 gport
->render_priv
->in_context
= true;
2223 glEnable (GL_BLEND
);
2224 glBlendFunc (GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
2226 glViewport (0, 0, width
, height
);
2228 glEnable (GL_SCISSOR_TEST
);
2229 glScissor (0, 0, width
, height
);
2231 glMatrixMode (GL_PROJECTION
);
2233 glOrtho (0, width
, height
, 0, -100000, 100000);
2234 glMatrixMode (GL_MODELVIEW
);
2236 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
2238 glClearColor (gport
->bg_color
.red
/ 65535.,
2239 gport
->bg_color
.green
/ 65535.,
2240 gport
->bg_color
.blue
/ 65535.,
2244 glClear (GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2245 hidgl_reset_stencil_usage (priv
->hidgl
);
2247 /* Disable the stencil test until we need it - otherwise it gets dirty */
2248 glDisable (GL_STENCIL_TEST
);
2250 glStencilFunc (GL_ALWAYS
, 0, 0);
2252 /* call the drawing routine */
2253 ghid_invalidate_current_gc ();
2255 glScalef ((gport
->view
.flip_x
? -1. : 1.) / gport
->view
.coord_per_px
,
2256 (gport
->view
.flip_y
? -1. : 1.) / gport
->view
.coord_per_px
,
2257 ((gport
->view
.flip_x
== gport
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
2258 glTranslatef (gport
->view
.flip_x
? gport
->view
.x0
- PCB
->MaxWidth
:
2260 gport
->view
.flip_y
? gport
->view
.y0
- PCB
->MaxHeight
:
2261 -gport
->view
.y0
, 0);
2263 region
.X1
= MIN(Px(0), Px(gport
->width
+ 1));
2264 region
.Y1
= MIN(Py(0), Py(gport
->height
+ 1));
2265 region
.X2
= MAX(Px(0), Px(gport
->width
+ 1));
2266 region
.Y2
= MAX(Py(0), Py(gport
->height
+ 1));
2268 region
.X1
= MAX (0, MIN (PCB
->MaxWidth
, region
.X1
));
2269 region
.X2
= MAX (0, MIN (PCB
->MaxWidth
, region
.X2
));
2270 region
.Y1
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y1
));
2271 region
.Y2
= MAX (0, MIN (PCB
->MaxHeight
, region
.Y2
));
2273 hid_expose_callback (&ghid_graphics
, ®ion
, NULL
);
2274 hidgl_flush_triangles (priv
->hidgl
);
2279 hidgl_finish_render (priv
->hidgl
);
2281 /* end drawing to current GL-context */
2282 gport
->render_priv
->in_context
= false;
2283 gdk_gl_drawable_gl_end (gldrawable
);
2285 gdk_pixmap_unset_gl_capability (pixmap
);
2287 g_object_unref (glconfig
);
2288 g_object_unref (glcontext
);
2290 gport
->view
= save_view
;
2291 gport
->width
= save_width
;
2292 gport
->height
= save_height
;
2298 ghid_request_debug_draw (void)
2300 GHidPort
*port
= gport
;
2301 GtkWidget
*widget
= port
->drawing_area
;
2302 GtkAllocation allocation
;
2304 gtk_widget_get_allocation (widget
, &allocation
);
2306 ghid_start_drawing (port
, widget
);
2308 glViewport (0, 0, allocation
.width
, allocation
.height
);
2310 glMatrixMode (GL_PROJECTION
);
2312 glOrtho (0, allocation
.width
, allocation
.height
, 0, 0, 100);
2313 glMatrixMode (GL_MODELVIEW
);
2315 glTranslatef (0.0f
, 0.0f
, -Z_NEAR
);
2317 ghid_invalidate_current_gc ();
2319 /* Setup stenciling */
2320 glDisable (GL_STENCIL_TEST
);
2323 glScalef ((port
->view
.flip_x
? -1. : 1.) / port
->view
.coord_per_px
,
2324 (port
->view
.flip_y
? -1. : 1.) / port
->view
.coord_per_px
,
2325 ((gport
->view
.flip_x
== port
->view
.flip_y
) ? 1. : -1.) / gport
->view
.coord_per_px
);
2326 glTranslatef (port
->view
.flip_x
? port
->view
.x0
- PCB
->MaxWidth
:
2328 port
->view
.flip_y
? port
->view
.y0
- PCB
->MaxHeight
:
2331 return &ghid_graphics
;
2335 ghid_flush_debug_draw (void)
2337 render_priv
*priv
= gport
->render_priv
;
2338 GtkWidget
*widget
= gport
->drawing_area
;
2339 GdkGLDrawable
*pGlDrawable
= gtk_widget_get_gl_drawable (widget
);
2341 hidgl_flush_triangles (priv
->hidgl
);
2343 if (gdk_gl_drawable_is_double_buffered (pGlDrawable
))
2344 gdk_gl_drawable_swap_buffers (pGlDrawable
);
2350 ghid_finish_debug_draw (void)
2352 render_priv
*priv
= gport
->render_priv
;
2354 hidgl_flush_triangles (priv
->hidgl
);
2357 ghid_end_drawing (gport
, gport
->drawing_area
);
2361 determinant_2x2 (float m
[2][2])
2364 det
= m
[0][0] * m
[1][1] -
2371 determinant_4x4 (float m
[4][4])
2374 det
= m
[0][3] * m
[1][2] * m
[2][1] * m
[3][0]-m
[0][2] * m
[1][3] * m
[2][1] * m
[3][0] -
2375 m
[0][3] * m
[1][1] * m
[2][2] * m
[3][0]+m
[0][1] * m
[1][3] * m
[2][2] * m
[3][0] +
2376 m
[0][2] * m
[1][1] * m
[2][3] * m
[3][0]-m
[0][1] * m
[1][2] * m
[2][3] * m
[3][0] -
2377 m
[0][3] * m
[1][2] * m
[2][0] * m
[3][1]+m
[0][2] * m
[1][3] * m
[2][0] * m
[3][1] +
2378 m
[0][3] * m
[1][0] * m
[2][2] * m
[3][1]-m
[0][0] * m
[1][3] * m
[2][2] * m
[3][1] -
2379 m
[0][2] * m
[1][0] * m
[2][3] * m
[3][1]+m
[0][0] * m
[1][2] * m
[2][3] * m
[3][1] +
2380 m
[0][3] * m
[1][1] * m
[2][0] * m
[3][2]-m
[0][1] * m
[1][3] * m
[2][0] * m
[3][2] -
2381 m
[0][3] * m
[1][0] * m
[2][1] * m
[3][2]+m
[0][0] * m
[1][3] * m
[2][1] * m
[3][2] +
2382 m
[0][1] * m
[1][0] * m
[2][3] * m
[3][2]-m
[0][0] * m
[1][1] * m
[2][3] * m
[3][2] -
2383 m
[0][2] * m
[1][1] * m
[2][0] * m
[3][3]+m
[0][1] * m
[1][2] * m
[2][0] * m
[3][3] +
2384 m
[0][2] * m
[1][0] * m
[2][1] * m
[3][3]-m
[0][0] * m
[1][2] * m
[2][1] * m
[3][3] -
2385 m
[0][1] * m
[1][0] * m
[2][2] * m
[3][3]+m
[0][0] * m
[1][1] * m
[2][2] * m
[3][3];
2391 invert_2x2 (float m
[2][2], float out
[2][2])
2393 float scale
= 1 / determinant_2x2 (m
);
2394 out
[0][0] = m
[1][1] * scale
;
2395 out
[0][1] = -m
[0][1] * scale
;
2396 out
[1][0] = -m
[1][0] * scale
;
2397 out
[1][1] = m
[0][0] * scale
;
2402 invert_4x4 (float m
[4][4], float out
[4][4])
2404 float scale
= 1 / determinant_4x4 (m
);
2406 out
[0][0] = (m
[1][2] * m
[2][3] * m
[3][1] - m
[1][3] * m
[2][2] * m
[3][1] +
2407 m
[1][3] * m
[2][1] * m
[3][2] - m
[1][1] * m
[2][3] * m
[3][2] -
2408 m
[1][2] * m
[2][1] * m
[3][3] + m
[1][1] * m
[2][2] * m
[3][3]) * scale
;
2409 out
[0][1] = (m
[0][3] * m
[2][2] * m
[3][1] - m
[0][2] * m
[2][3] * m
[3][1] -
2410 m
[0][3] * m
[2][1] * m
[3][2] + m
[0][1] * m
[2][3] * m
[3][2] +
2411 m
[0][2] * m
[2][1] * m
[3][3] - m
[0][1] * m
[2][2] * m
[3][3]) * scale
;
2412 out
[0][2] = (m
[0][2] * m
[1][3] * m
[3][1] - m
[0][3] * m
[1][2] * m
[3][1] +
2413 m
[0][3] * m
[1][1] * m
[3][2] - m
[0][1] * m
[1][3] * m
[3][2] -
2414 m
[0][2] * m
[1][1] * m
[3][3] + m
[0][1] * m
[1][2] * m
[3][3]) * scale
;
2415 out
[0][3] = (m
[0][3] * m
[1][2] * m
[2][1] - m
[0][2] * m
[1][3] * m
[2][1] -
2416 m
[0][3] * m
[1][1] * m
[2][2] + m
[0][1] * m
[1][3] * m
[2][2] +
2417 m
[0][2] * m
[1][1] * m
[2][3] - m
[0][1] * m
[1][2] * m
[2][3]) * scale
;
2418 out
[1][0] = (m
[1][3] * m
[2][2] * m
[3][0] - m
[1][2] * m
[2][3] * m
[3][0] -
2419 m
[1][3] * m
[2][0] * m
[3][2] + m
[1][0] * m
[2][3] * m
[3][2] +
2420 m
[1][2] * m
[2][0] * m
[3][3] - m
[1][0] * m
[2][2] * m
[3][3]) * scale
;
2421 out
[1][1] = (m
[0][2] * m
[2][3] * m
[3][0] - m
[0][3] * m
[2][2] * m
[3][0] +
2422 m
[0][3] * m
[2][0] * m
[3][2] - m
[0][0] * m
[2][3] * m
[3][2] -
2423 m
[0][2] * m
[2][0] * m
[3][3] + m
[0][0] * m
[2][2] * m
[3][3]) * scale
;
2424 out
[1][2] = (m
[0][3] * m
[1][2] * m
[3][0] - m
[0][2] * m
[1][3] * m
[3][0] -
2425 m
[0][3] * m
[1][0] * m
[3][2] + m
[0][0] * m
[1][3] * m
[3][2] +
2426 m
[0][2] * m
[1][0] * m
[3][3] - m
[0][0] * m
[1][2] * m
[3][3]) * scale
;
2427 out
[1][3] = (m
[0][2] * m
[1][3] * m
[2][0] - m
[0][3] * m
[1][2] * m
[2][0] +
2428 m
[0][3] * m
[1][0] * m
[2][2] - m
[0][0] * m
[1][3] * m
[2][2] -
2429 m
[0][2] * m
[1][0] * m
[2][3] + m
[0][0] * m
[1][2] * m
[2][3]) * scale
;
2430 out
[2][0] = (m
[1][1] * m
[2][3] * m
[3][0] - m
[1][3] * m
[2][1] * m
[3][0] +
2431 m
[1][3] * m
[2][0] * m
[3][1] - m
[1][0] * m
[2][3] * m
[3][1] -
2432 m
[1][1] * m
[2][0] * m
[3][3] + m
[1][0] * m
[2][1] * m
[3][3]) * scale
;
2433 out
[2][1] = (m
[0][3] * m
[2][1] * m
[3][0] - m
[0][1] * m
[2][3] * m
[3][0] -
2434 m
[0][3] * m
[2][0] * m
[3][1] + m
[0][0] * m
[2][3] * m
[3][1] +
2435 m
[0][1] * m
[2][0] * m
[3][3] - m
[0][0] * m
[2][1] * m
[3][3]) * scale
;
2436 out
[2][2] = (m
[0][1] * m
[1][3] * m
[3][0] - m
[0][3] * m
[1][1] * m
[3][0] +
2437 m
[0][3] * m
[1][0] * m
[3][1] - m
[0][0] * m
[1][3] * m
[3][1] -
2438 m
[0][1] * m
[1][0] * m
[3][3] + m
[0][0] * m
[1][1] * m
[3][3]) * scale
;
2439 out
[2][3] = (m
[0][3] * m
[1][1] * m
[2][0] - m
[0][1] * m
[1][3] * m
[2][0] -
2440 m
[0][3] * m
[1][0] * m
[2][1] + m
[0][0] * m
[1][3] * m
[2][1] +
2441 m
[0][1] * m
[1][0] * m
[2][3] - m
[0][0] * m
[1][1] * m
[2][3]) * scale
;
2442 out
[3][0] = (m
[1][2] * m
[2][1] * m
[3][0] - m
[1][1] * m
[2][2] * m
[3][0] -
2443 m
[1][2] * m
[2][0] * m
[3][1] + m
[1][0] * m
[2][2] * m
[3][1] +
2444 m
[1][1] * m
[2][0] * m
[3][2] - m
[1][0] * m
[2][1] * m
[3][2]) * scale
;
2445 out
[3][1] = (m
[0][1] * m
[2][2] * m
[3][0] - m
[0][2] * m
[2][1] * m
[3][0] +
2446 m
[0][2] * m
[2][0] * m
[3][1] - m
[0][0] * m
[2][2] * m
[3][1] -
2447 m
[0][1] * m
[2][0] * m
[3][2] + m
[0][0] * m
[2][1] * m
[3][2]) * scale
;
2448 out
[3][2] = (m
[0][2] * m
[1][1] * m
[3][0] - m
[0][1] * m
[1][2] * m
[3][0] -
2449 m
[0][2] * m
[1][0] * m
[3][1] + m
[0][0] * m
[1][2] * m
[3][1] +
2450 m
[0][1] * m
[1][0] * m
[3][2] - m
[0][0] * m
[1][1] * m
[3][2]) * scale
;
2451 out
[3][3] = (m
[0][1] * m
[1][2] * m
[2][0] - m
[0][2] * m
[1][1] * m
[2][0] +
2452 m
[0][2] * m
[1][0] * m
[2][1] - m
[0][0] * m
[1][2] * m
[2][1] -
2453 m
[0][1] * m
[1][0] * m
[2][2] + m
[0][0] * m
[1][1] * m
[2][2]) * scale
;
2459 ghid_unproject_to_z_plane (int ex
, int ey
, Coord pcb_z
, Coord
*pcb_x
, Coord
*pcb_y
)
2462 float inv_mat
[2][2];
2466 ex = view_matrix[0][0] * vx +
2467 view_matrix[0][1] * vy +
2468 view_matrix[0][2] * vz +
2469 view_matrix[0][3] * 1;
2470 ey = view_matrix[1][0] * vx +
2471 view_matrix[1][1] * vy +
2472 view_matrix[1][2] * vz +
2473 view_matrix[1][3] * 1;
2474 UNKNOWN ez = view_matrix[2][0] * vx +
2475 view_matrix[2][1] * vy +
2476 view_matrix[2][2] * vz +
2477 view_matrix[2][3] * 1;
2479 ex - view_matrix[0][3] * 1
2480 - view_matrix[0][2] * vz
2481 = view_matrix[0][0] * vx +
2482 view_matrix[0][1] * vy;
2484 ey - view_matrix[1][3] * 1
2485 - view_matrix[1][2] * vz
2486 = view_matrix[1][0] * vx +
2487 view_matrix[1][1] * vy;
2490 /* NB: last_modelview_matrix is transposed in memory! */
2491 x
= (float)ex
- last_modelview_matrix
[3][0] * 1
2492 - last_modelview_matrix
[2][0] * pcb_z
;
2494 y
= (float)ey
- last_modelview_matrix
[3][1] * 1
2495 - last_modelview_matrix
[2][1] * pcb_z
;
2498 x = view_matrix[0][0] * vx +
2499 view_matrix[0][1] * vy;
2501 y = view_matrix[1][0] * vx +
2502 view_matrix[1][1] * vy;
2504 [view_matrix[0][0] view_matrix[0][1]] [vx] = [x]
2505 [view_matrix[1][0] view_matrix[1][1]] [vy] [y]
2508 mat
[0][0] = last_modelview_matrix
[0][0];
2509 mat
[0][1] = last_modelview_matrix
[1][0];
2510 mat
[1][0] = last_modelview_matrix
[0][1];
2511 mat
[1][1] = last_modelview_matrix
[1][1];
2513 /* if (determinant_2x2 (mat) < 0.00001) */
2514 /* printf ("Determinant is quite small\n"); */
2516 invert_2x2 (mat
, inv_mat
);
2518 *pcb_x
= (int)(inv_mat
[0][0] * x
+ inv_mat
[0][1] * y
);
2519 *pcb_y
= (int)(inv_mat
[1][0] * x
+ inv_mat
[1][1] * y
);
2524 ghid_event_to_pcb_coords (int event_x
, int event_y
, Coord
*pcb_x
, Coord
*pcb_y
)
2526 render_priv
*priv
= gport
->render_priv
;
2528 ghid_unproject_to_z_plane (event_x
, event_y
, priv
->edit_depth
, pcb_x
, pcb_y
);
2534 ghid_pcb_to_event_coords (Coord pcb_x
, Coord pcb_y
, int *event_x
, int *event_y
)
2536 render_priv
*priv
= gport
->render_priv
;
2538 /* NB: last_modelview_matrix is transposed in memory */
2539 float w
= last_modelview_matrix
[0][3] * (float)pcb_x
+
2540 last_modelview_matrix
[1][3] * (float)pcb_y
+
2541 last_modelview_matrix
[2][3] * 0. +
2542 last_modelview_matrix
[3][3] * 1.;
2544 *event_x
= (last_modelview_matrix
[0][0] * (float)pcb_x
+
2545 last_modelview_matrix
[1][0] * (float)pcb_y
+
2546 last_modelview_matrix
[2][0] * priv
->edit_depth
+
2547 last_modelview_matrix
[3][0] * 1.) / w
;
2548 *event_y
= (last_modelview_matrix
[0][1] * (float)pcb_x
+
2549 last_modelview_matrix
[1][1] * (float)pcb_y
+
2550 last_modelview_matrix
[2][1] * priv
->edit_depth
+
2551 last_modelview_matrix
[3][1] * 1.) / w
;
2557 ghid_view_2d (void *ball
, gboolean view_2d
, gpointer userdata
)
2559 global_view_2d
= view_2d
;
2560 ghid_invalidate_all ();
2564 ghid_port_rotate (void *ball
, float *quarternion
, gpointer userdata
)
2570 build_rotmatrix (view_matrix
, quarternion
);
2573 for (row
= 0; row
< 4; row
++) {
2574 printf ("[ %f", view_matrix
[row
][0]);
2575 for (column
= 1; column
< 4; column
++) {
2576 printf (",\t%f", view_matrix
[row
][column
]);
2583 ghid_invalidate_all ();
2587 #define LEAD_USER_WIDTH 0.2 /* millimeters */
2588 #define LEAD_USER_PERIOD (1000 / 20) /* 20fps (in ms) */
2589 #define LEAD_USER_VELOCITY 3. /* millimeters per second */
2590 #define LEAD_USER_ARC_COUNT 3
2591 #define LEAD_USER_ARC_SEPARATION 3. /* millimeters */
2592 #define LEAD_USER_INITIAL_RADIUS 10. /* millimetres */
2593 #define LEAD_USER_COLOR_R 1.
2594 #define LEAD_USER_COLOR_G 1.
2595 #define LEAD_USER_COLOR_B 0.
2598 draw_lead_user (hidGC gc
, render_priv
*priv
)
2600 gtkGC gtk_gc
= (gtkGC
)gc
;
2602 double radius
= priv
->lead_user_radius
;
2603 double width
= MM_TO_COORD (LEAD_USER_WIDTH
);
2604 double separation
= MM_TO_COORD (LEAD_USER_ARC_SEPARATION
);
2606 if (!priv
->lead_user
)
2609 glPushAttrib (GL_CURRENT_BIT
| GL_COLOR_BUFFER_BIT
);
2610 glEnable (GL_COLOR_LOGIC_OP
);
2612 glColor3f (LEAD_USER_COLOR_R
, LEAD_USER_COLOR_G
,LEAD_USER_COLOR_B
);
2615 /* arcs at the approrpriate radii */
2617 for (i
= 0; i
< LEAD_USER_ARC_COUNT
; i
++, radius
-= separation
)
2620 radius
+= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
2622 /* Draw an arc at radius */
2623 hidgl_draw_arc (gc
, width
, priv
->lead_user_x
, priv
->lead_user_y
,
2624 radius
, radius
, 0, 360, gport
->view
.coord_per_px
);
2627 hidgl_flush_triangles (gtk_gc
->hidgl_gc
.hidgl
);
2632 lead_user_cb (gpointer data
)
2634 render_priv
*priv
= data
;
2636 double elapsed_time
;
2638 /* Queue a redraw */
2639 ghid_invalidate_all ();
2642 elapsed_time
= g_timer_elapsed (priv
->lead_user_timer
, NULL
);
2643 g_timer_start (priv
->lead_user_timer
);
2645 step
= MM_TO_COORD (LEAD_USER_VELOCITY
* elapsed_time
);
2646 if (priv
->lead_user_radius
> step
)
2647 priv
->lead_user_radius
-= step
;
2649 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
2655 ghid_lead_user_to_location (Coord x
, Coord y
)
2657 render_priv
*priv
= gport
->render_priv
;
2659 ghid_cancel_lead_user ();
2661 priv
->lead_user
= true;
2662 priv
->lead_user_x
= x
;
2663 priv
->lead_user_y
= y
;
2664 priv
->lead_user_radius
= MM_TO_COORD (LEAD_USER_INITIAL_RADIUS
);
2665 priv
->lead_user_timeout
= g_timeout_add (LEAD_USER_PERIOD
, lead_user_cb
, priv
);
2666 priv
->lead_user_timer
= g_timer_new ();
2670 ghid_cancel_lead_user (void)
2672 render_priv
*priv
= gport
->render_priv
;
2674 if (priv
->lead_user_timeout
)
2675 g_source_remove (priv
->lead_user_timeout
);
2677 if (priv
->lead_user_timer
)
2678 g_timer_destroy (priv
->lead_user_timer
);
2680 if (priv
->lead_user
)
2681 ghid_invalidate_all ();
2683 priv
->lead_user_timeout
= 0;
2684 priv
->lead_user_timer
= NULL
;
2685 priv
->lead_user
= false;