Compare commits
	
		
			103 Commits
		
	
	
		
			gnome-3-36
			...
			wip/carlos
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 2cf9249d2b | ||
|   | f988a9caaa | ||
|   | b7366b5b53 | ||
|   | 5e8d8b9ade | ||
|   | 4726f3d5d3 | ||
|   | 91ef7515de | ||
|   | 317f6c0910 | ||
|   | 6a3d521466 | ||
|   | 1363246d44 | ||
|   | 0b6560fac4 | ||
|   | d4c3870286 | ||
|   | 4bdf9a1e70 | ||
|   | 1909977a67 | ||
|   | 655a783891 | ||
|   | a4596becc4 | ||
|   | 7015bb3efd | ||
|   | d2c762cc66 | ||
|   | 04d429b743 | ||
|   | 0b21dcfe08 | ||
|   | 7c939d78c2 | ||
|   | 8a2b82897d | ||
|   | e95c365cf0 | ||
|   | a32cb7133b | ||
|   | 967966cdee | ||
|   | 06d67b6abf | ||
|   | f15ce01e2b | ||
|   | e48516679c | ||
|   | 65a6c4c361 | ||
|   | b51c468c0f | ||
|   | 2e7d02f1ce | ||
|   | dc4fe780f7 | ||
|   | d682cdb078 | ||
|   | ff7a42b8bc | ||
|   | 4b1805c306 | ||
|   | 03c00e4944 | ||
|   | cb05b16414 | ||
|   | b9fe9c736a | ||
|   | 3dd8861fbf | ||
|   | 753066598f | ||
|   | 3da8c1bfdc | ||
|   | f8ee974628 | ||
|   | f36120757f | ||
|   | bc178b711f | ||
|   | 5dad87cfb9 | ||
|   | 0f8f607e4c | ||
|   | 282aada13a | ||
|   | 47002bf0cd | ||
|   | 3d47c7edc1 | ||
|   | bc350f37f5 | ||
|   | b55e2e1df9 | ||
|   | 43baf643d4 | ||
|   | 21b8ae10b8 | ||
|   | 425a10de11 | ||
|   | d0ef660ff6 | ||
|   | 506e06589b | ||
|   | 1d75d5aa2f | ||
|   | 645d596f9d | ||
|   | 3e967d731a | ||
|   | 167fd07e01 | ||
|   | fbd6366edd | ||
|   | 23d0bdd46d | ||
|   | 0d0834f87c | ||
|   | 676997e0af | ||
|   | 633d5d1b84 | ||
|   | f620f43353 | ||
|   | eb6e1f694a | ||
|   | 6aead84d7a | ||
|   | 5b984c1e53 | ||
|   | 7660ca2579 | ||
|   | ac52631e8a | ||
|   | 5b30a52bbd | ||
|   | a5294ce55f | ||
|   | 553372ffb7 | ||
|   | f672d6ee3b | ||
|   | ba3417667f | ||
|   | 50fa002a19 | ||
|   | f0718c7d95 | ||
|   | e74c2e42cf | ||
|   | ce64ab5449 | ||
|   | 8df3b21a51 | ||
|   | 08431a127a | ||
|   | 3f068d1138 | ||
|   | 6f0e5b0b56 | ||
|   | fe27a6ea3b | ||
|   | 1301770dcb | ||
|   | 1551b6d386 | ||
|   | a6f94696e2 | ||
|   | c389aadff9 | ||
|   | 37eda498f2 | ||
|   | 7d2df52336 | ||
|   | 5d27e5415d | ||
|   | 625773fba4 | ||
|   | 7d79ae7b07 | ||
|   | 5817779656 | ||
|   | 5f5ce08ba4 | ||
|   | 223f033780 | ||
|   | 50e0ae3cf3 | ||
|   | a8f6cada88 | ||
|   | 7f488e3e1d | ||
|   | 059d2144b2 | ||
|   | 902302a174 | ||
|   | f98ca7683c | ||
|   | 479fb0549c | 
| @@ -1,4 +1,4 @@ | ||||
| image: registry.gitlab.gnome.org/gnome/mutter/master:v3 | ||||
| image: registry.gitlab.gnome.org/gnome/mutter/master:v4 | ||||
|  | ||||
| stages: | ||||
|  - review | ||||
|   | ||||
| @@ -1,32 +1,27 @@ | ||||
| # Rebuild and push with | ||||
| # | ||||
| #     cd .gitlab-ci/ | ||||
| #     podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v3 . | ||||
| #     podman push registry.gitlab.gnome.org/gnome/mutter/master:v3 | ||||
| #     podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v4 . | ||||
| #     podman push registry.gitlab.gnome.org/gnome/mutter/master:v4 | ||||
| # | ||||
|  | ||||
| FROM fedora:31 | ||||
| FROM fedora:32 | ||||
|  | ||||
| RUN dnf -y update && dnf -y upgrade && \ | ||||
|     dnf install -y 'dnf-command(builddep)' && \ | ||||
|     dnf install -y 'dnf-command(copr)' && \ | ||||
|     dnf copr enable -y fmuellner/gnome-shell-ci && \ | ||||
|     dnf copr enable -y jadahl/mutter-ci && \ | ||||
|     dnf -y update && dnf -y upgrade && \ | ||||
|  | ||||
|     dnf builddep -y mutter && \ | ||||
|  | ||||
|     # Until Fedora catches up with new build-deps | ||||
|     dnf install -y 'pkgconfig(graphene-gobject-1.0)' 'pkgconfig(sysprof-capture-3)' && \ | ||||
|     dnf builddep -y mutter --setopt=install_weak_deps=False && \ | ||||
|  | ||||
|     # For running unit tests | ||||
|     dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 '*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center && \ | ||||
|     dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 \ | ||||
|         '*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center \ | ||||
|         --setopt=install_weak_deps=False && \ | ||||
|  | ||||
|     # GNOME Shell | ||||
|     dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \ | ||||
|     dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel upower-devel python3-devel && \ | ||||
|     dnf remove -y gnome-bluetooth-libs-devel && \ | ||||
|     dnf remove -y --noautoremove mutter mutter-devel && \ | ||||
|  | ||||
|     dnf upgrade -y 'pkgconfig(libpipewire-0.3)' && \ | ||||
|  | ||||
|     dnf clean all | ||||
|   | ||||
							
								
								
									
										43
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,46 +1,3 @@ | ||||
| 3.36.1 | ||||
| ====== | ||||
| * Fix hardware cursor on GPU hotplpug [Pekka; !1097] | ||||
| * Fix black areas around XWayland windows when resizing [Robert, Olivier; !1091] | ||||
| * Fix applying wrong scale to monitors on X11 [Jonas; !1118] | ||||
| * Fix moving/resizing windows via keyboard on wayland [Alynx; !997] | ||||
| * Fix locate-pointer feature interfering with keybindings [Carlos; !1014] | ||||
| * Add support for middle-click emulation [Andrew; !256] | ||||
| * Fix freeze when moving cursor between scaled monitors [Robert; !1125] | ||||
| * Fix popup misplacement with focus-follows-mouse [Jonas Å.; !1122] | ||||
| * Fix misplaced cursor in preedit strings [Carlos; !1132] | ||||
| * Support mirroring with proprietary Nvidia driver [Jonas Å.; !1098] | ||||
| * Support tablets with multiple mode switch buttons in a group [Carlos; !970] | ||||
| * Ignore foreground color for color glyphs (emojis) [Carlos; !1148] | ||||
| * Allow pad mode switches while showing OSD [Carlos; !975] | ||||
| * Fix positioning of OSD for display-attached tablets [Carlos; !971] | ||||
| * Respect configured RANDR panning on X11 [Jonas Å.; !1085] | ||||
| * Use correct texture filtering with scaled displays [Jonas; !1124] | ||||
| * Fix cursor hotspots in virtual machines [Jonas Å.; !1136] | ||||
| * Fix build with GLES and no GL [Georges; !1151] | ||||
| * Work around Firefox bug when copying images on wayland [Robert; !1141] | ||||
| * Fix wrong cursor rotation on rotated displays [Hans; !1153] | ||||
| * Fix glitches in window screencasts [Georges; !1129] | ||||
| * Fix IM support for deleting surrounding text [Takao, Carlos; #539] | ||||
| * Fix map animation of maximized windows [Robert; !1164] | ||||
| * Fixed crashes [Jonas Å., Carlos, Florian, Robert; !1120, !1121, | ||||
|   #917, #1132, #1083, !1147, #1147] | ||||
| * Misc. bug fixes and cleanups [Jonas Å., Olivier, Mart, Sebastian, Corentin, | ||||
|   Andre, Daniel, Robert, Carlos, Peter, Georges, Jonas D., Florian, Christian; | ||||
|   !1115, !1102, !1104, !1106, !1117, !1119, !1101, !1123, #1124, !1130, !1131, | ||||
|   !1133, #1065, !1108, !1144, !1145, !1109, !1059, !1107, !999, !1152, #1128, | ||||
|   !1155, !1156, !1158, !1157, #1146, !1161, !1163] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Dreßler, Olivier Fourdan, Takao Fujiwara, Carlos Garnacho, Andrew Gaul, | ||||
|   Hans de Goede, Peter Hutterer, Sebastian Keller, Robert Mader, | ||||
|   Andre Moreira Magalhaes, Florian Müllner, Georges Basile Stavracas Neto, | ||||
|   Corentin Noël, Pekka Paalanen, Christian Rauch, Mart Raudsepp, | ||||
|   Daniel van Vugt, Alynx Zhou, Jonas Ådahl | ||||
|  | ||||
| Translators: | ||||
|   Марко Костић [sr], Daniel Șerbănescu [ro] | ||||
|  | ||||
| 3.36.0 | ||||
| ====== | ||||
| * Fix placement of popup windows in multi-monitor setups [Jonas; !1110] | ||||
|   | ||||
| @@ -88,6 +88,10 @@ static void | ||||
| clutter_actor_meta_real_set_actor (ClutterActorMeta *meta, | ||||
|                                    ClutterActor     *actor) | ||||
| { | ||||
|   g_warn_if_fail (!meta->priv->actor || | ||||
|                   !CLUTTER_ACTOR_IN_PAINT (meta->priv->actor)); | ||||
|   g_warn_if_fail (!actor || !CLUTTER_ACTOR_IN_PAINT (actor)); | ||||
|  | ||||
|   if (meta->priv->actor == actor) | ||||
|     return; | ||||
|  | ||||
| @@ -101,6 +105,18 @@ clutter_actor_meta_real_set_actor (ClutterActorMeta *meta, | ||||
|                                                meta); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_actor_meta_real_set_enabled (ClutterActorMeta *meta, | ||||
|                                      gboolean          is_enabled) | ||||
| { | ||||
|   g_warn_if_fail (!meta->priv->actor || | ||||
|                   !CLUTTER_ACTOR_IN_PAINT (meta->priv->actor)); | ||||
|  | ||||
|   meta->priv->is_enabled = is_enabled; | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_actor_meta_set_property (GObject      *gobject, | ||||
|                                  guint         prop_id, | ||||
| @@ -172,6 +188,7 @@ clutter_actor_meta_class_init (ClutterActorMetaClass *klass) | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   klass->set_actor = clutter_actor_meta_real_set_actor; | ||||
|   klass->set_enabled = clutter_actor_meta_real_set_enabled; | ||||
|  | ||||
|   /** | ||||
|    * ClutterActorMeta:actor: | ||||
| @@ -298,9 +315,7 @@ clutter_actor_meta_set_enabled (ClutterActorMeta *meta, | ||||
|   if (meta->priv->is_enabled == is_enabled) | ||||
|     return; | ||||
|  | ||||
|   meta->priv->is_enabled = is_enabled; | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]); | ||||
|   CLUTTER_ACTOR_META_GET_CLASS (meta)->set_enabled (meta, is_enabled); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -87,6 +87,9 @@ struct _ClutterActorMetaClass | ||||
|   void (* set_actor) (ClutterActorMeta *meta, | ||||
|                       ClutterActor     *actor); | ||||
|  | ||||
|   void (* set_enabled) (ClutterActorMeta *meta, | ||||
|                         gboolean          is_enabled); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   void (* _clutter_meta1) (void); | ||||
|   void (* _clutter_meta2) (void); | ||||
| @@ -94,7 +97,6 @@ struct _ClutterActorMetaClass | ||||
|   void (* _clutter_meta4) (void); | ||||
|   void (* _clutter_meta5) (void); | ||||
|   void (* _clutter_meta6) (void); | ||||
|   void (* _clutter_meta7) (void); | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
|   | ||||
| @@ -2410,6 +2410,7 @@ clutter_actor_should_pick_paint (ClutterActor *self) | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); | ||||
|  | ||||
|   if (CLUTTER_ACTOR_IS_MAPPED (self) && | ||||
|       clutter_actor_has_allocation (self) && | ||||
|       (_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL || | ||||
|        CLUTTER_ACTOR_IS_REACTIVE (self))) | ||||
|     return TRUE; | ||||
| @@ -3865,14 +3866,7 @@ clutter_actor_paint_node (ClutterActor        *actor, | ||||
|  | ||||
|       fb = clutter_paint_context_get_base_framebuffer (paint_context); | ||||
|  | ||||
|       if (clutter_stage_get_use_alpha (CLUTTER_STAGE (actor))) | ||||
|         { | ||||
|           bg_color.alpha = priv->opacity | ||||
|                          * priv->bg_color.alpha | ||||
|                          / 255; | ||||
|         } | ||||
|       else | ||||
|         bg_color.alpha = 255; | ||||
|       bg_color.alpha = 255; | ||||
|  | ||||
|       CLUTTER_NOTE (PAINT, "Stage clear color: (%d, %d, %d, %d)", | ||||
|                     bg_color.red, | ||||
| @@ -19966,6 +19960,23 @@ clutter_actor_get_transition (ClutterActor *self, | ||||
|   return clos->transition; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_actor_has_transitions: (skip) | ||||
|  */ | ||||
| gboolean | ||||
| clutter_actor_has_transitions (ClutterActor *self) | ||||
| { | ||||
|   const ClutterAnimationInfo *info; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); | ||||
|  | ||||
|   info = _clutter_actor_get_animation_info_or_defaults (self); | ||||
|   if (info->transitions == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   return g_hash_table_size (info->transitions) > 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_actor_save_easing_state: | ||||
|  * @self: a #ClutterActor | ||||
|   | ||||
| @@ -50,8 +50,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterConstraint, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeformEffect, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDesaturateEffect, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDragAction, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDropAction, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterEffect, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFixedLayout, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFlowLayout, g_object_unref) | ||||
|   | ||||
| @@ -238,6 +238,7 @@ click_action_query_long_press (ClutterClickAction *action) | ||||
|  | ||||
|   if (result) | ||||
|     { | ||||
|       g_clear_handle_id (&priv->long_press_id, g_source_remove); | ||||
|       priv->long_press_id = | ||||
|         clutter_threads_add_timeout (timeout, | ||||
|                                      click_action_emit_long_press, | ||||
| @@ -467,6 +468,20 @@ clutter_click_action_set_actor (ClutterActorMeta *meta, | ||||
|   CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_click_action_set_enabled (ClutterActorMeta *meta, | ||||
|                                   gboolean          is_enabled) | ||||
| { | ||||
|   ClutterClickAction *click_action = CLUTTER_CLICK_ACTION (meta); | ||||
|   ClutterActorMetaClass *parent_class = | ||||
|     CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class); | ||||
|  | ||||
|   if (!is_enabled) | ||||
|     clutter_click_action_release (click_action); | ||||
|  | ||||
|   parent_class->set_enabled (meta, is_enabled); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_click_action_set_property (GObject      *gobject, | ||||
|                                    guint         prop_id, | ||||
| @@ -546,6 +561,7 @@ clutter_click_action_class_init (ClutterClickActionClass *klass) | ||||
|   ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); | ||||
|  | ||||
|   meta_class->set_actor = clutter_click_action_set_actor; | ||||
|   meta_class->set_enabled = clutter_click_action_set_enabled; | ||||
|  | ||||
|   gobject_class->dispose = clutter_click_action_dispose; | ||||
|   gobject_class->set_property = clutter_click_action_set_property; | ||||
|   | ||||
| @@ -9,7 +9,13 @@ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| @CLUTTER_CONFIG_DEFINES@ | ||||
| #mesondefine CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT | ||||
| #mesondefine CLUTTER_WINDOWING_X11 | ||||
| #mesondefine CLUTTER_INPUT_X11 | ||||
| #mesondefine CLUTTER_WINDOWING_GLX | ||||
| #mesondefine CLUTTER_WINDOWING_EGL | ||||
| #mesondefine CLUTTER_INPUT_EVDEV | ||||
| #mesondefine CLUTTER_INPUT_NULL | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
|   | ||||
| @@ -160,28 +160,26 @@ constraint_update_preferred_size (ClutterConstraint  *constraint, | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_constraint_notify (GObject    *gobject, | ||||
|                            GParamSpec *pspec) | ||||
| clutter_constraint_set_enabled (ClutterActorMeta *meta, | ||||
|                                 gboolean          is_enabled) | ||||
| { | ||||
|   if (strcmp (pspec->name, "enabled") == 0) | ||||
|     { | ||||
|       ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); | ||||
|       ClutterActor *actor = clutter_actor_meta_get_actor (meta); | ||||
|   ClutterActorMetaClass *parent_class = | ||||
|     CLUTTER_ACTOR_META_CLASS (clutter_constraint_parent_class); | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|       if (actor != NULL) | ||||
|         clutter_actor_queue_relayout (actor); | ||||
|     } | ||||
|   actor = clutter_actor_meta_get_actor (meta); | ||||
|   if (actor) | ||||
|     clutter_actor_queue_relayout (actor); | ||||
|  | ||||
|   if (G_OBJECT_CLASS (clutter_constraint_parent_class)->notify != NULL) | ||||
|     G_OBJECT_CLASS (clutter_constraint_parent_class)->notify (gobject, pspec); | ||||
|   parent_class->set_enabled (meta, is_enabled); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_constraint_class_init (ClutterConstraintClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass); | ||||
|  | ||||
|   gobject_class->notify = clutter_constraint_notify; | ||||
|   actor_meta_class->set_enabled = clutter_constraint_set_enabled; | ||||
|  | ||||
|   klass->update_allocation = constraint_update_allocation; | ||||
|   klass->update_preferred_size = constraint_update_preferred_size; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,152 +0,0 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2010  Intel Corporation. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: | ||||
|  *   Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_DRAG_ACTION_H__ | ||||
| #define __CLUTTER_DRAG_ACTION_H__ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <clutter/clutter-action.h> | ||||
| #include <clutter/clutter-event.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_DRAG_ACTION                (clutter_drag_action_get_type ()) | ||||
| #define CLUTTER_DRAG_ACTION(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragAction)) | ||||
| #define CLUTTER_IS_DRAG_ACTION(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DRAG_ACTION)) | ||||
| #define CLUTTER_DRAG_ACTION_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass)) | ||||
| #define CLUTTER_IS_DRAG_ACTION_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DRAG_ACTION)) | ||||
| #define CLUTTER_DRAG_ACTION_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass)) | ||||
|  | ||||
| typedef struct _ClutterDragAction               ClutterDragAction; | ||||
| typedef struct _ClutterDragActionPrivate        ClutterDragActionPrivate; | ||||
| typedef struct _ClutterDragActionClass          ClutterDragActionClass; | ||||
|  | ||||
| /** | ||||
|  * ClutterDragAction: | ||||
|  * | ||||
|  * The #ClutterDragAction structure contains only | ||||
|  * private data and should be accessed using the provided API | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| struct _ClutterDragAction | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterAction parent_instance; | ||||
|  | ||||
|   ClutterDragActionPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * ClutterDragActionClass: | ||||
|  * @drag_begin: class handler of the #ClutterDragAction::drag-begin signal | ||||
|  * @drag_motion: class handler of the #ClutterDragAction::drag-motion signal | ||||
|  * @drag_end: class handler of the #ClutterDragAction::drag-end signal | ||||
|  * @drag_progress: class handler of the #ClutterDragAction::drag-progress signal | ||||
|  * | ||||
|  * The #ClutterDragActionClass structure contains | ||||
|  * only private data | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| struct _ClutterDragActionClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActionClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   void          (* drag_begin)          (ClutterDragAction   *action, | ||||
|                                          ClutterActor        *actor, | ||||
|                                          gfloat               event_x, | ||||
|                                          gfloat               event_y, | ||||
|                                          ClutterModifierType  modifiers); | ||||
|   void          (* drag_motion)         (ClutterDragAction   *action, | ||||
|                                          ClutterActor        *actor, | ||||
|                                          gfloat               delta_x, | ||||
|                                          gfloat               delta_y); | ||||
|   void          (* drag_end)            (ClutterDragAction   *action, | ||||
|                                          ClutterActor        *actor, | ||||
|                                          gfloat               event_x, | ||||
|                                          gfloat               event_y, | ||||
|                                          ClutterModifierType  modifiers); | ||||
|   gboolean      (* drag_progress)       (ClutterDragAction   *action, | ||||
|                                          ClutterActor        *actor, | ||||
|                                          gfloat               delta_x, | ||||
|                                          gfloat               delta_y); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   void (* _clutter_drag_action1) (void); | ||||
|   void (* _clutter_drag_action2) (void); | ||||
|   void (* _clutter_drag_action3) (void); | ||||
|   void (* _clutter_drag_action4) (void); | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_drag_action_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterAction * clutter_drag_action_new                   (void); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_set_drag_threshold (ClutterDragAction *action, | ||||
|                                                         gint               x_threshold, | ||||
|                                                         gint               y_threshold); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_get_drag_threshold (ClutterDragAction *action, | ||||
|                                                         guint             *x_threshold, | ||||
|                                                         guint             *y_threshold); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_set_drag_handle    (ClutterDragAction *action, | ||||
|                                                         ClutterActor      *handle); | ||||
| CLUTTER_EXPORT | ||||
| ClutterActor *  clutter_drag_action_get_drag_handle    (ClutterDragAction *action); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_set_drag_axis      (ClutterDragAction *action, | ||||
|                                                         ClutterDragAxis    axis); | ||||
| CLUTTER_EXPORT | ||||
| ClutterDragAxis clutter_drag_action_get_drag_axis      (ClutterDragAction *action); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_get_press_coords   (ClutterDragAction *action, | ||||
|                                                         gfloat            *press_x, | ||||
|                                                         gfloat            *press_y); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_get_motion_coords  (ClutterDragAction *action, | ||||
|                                                         gfloat            *motion_x, | ||||
|                                                         gfloat            *motion_y); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_drag_action_get_drag_area      (ClutterDragAction *action, | ||||
|                                                         graphene_rect_t   *drag_area); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_drag_action_set_drag_area      (ClutterDragAction     *action, | ||||
|                                                         const graphene_rect_t *drag_area); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_DRAG_ACTION_H__ */ | ||||
| @@ -1,527 +0,0 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright © 2011  Intel Corporation. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: | ||||
|  *   Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:clutter-drop-action | ||||
|  * @Title: ClutterDropAction | ||||
|  * @short_description: An action for drop targets | ||||
|  * | ||||
|  * #ClutterDropAction is a #ClutterAction that allows a #ClutterActor | ||||
|  * implementation to control what happens when an actor dragged using | ||||
|  * a #ClutterDragAction crosses the target area or when a dragged actor | ||||
|  * is released (or "dropped") on the target area. | ||||
|  * | ||||
|  * A trivial use of #ClutterDropAction consists in connecting to the | ||||
|  * #ClutterDropAction::drop signal and handling the drop from there, | ||||
|  * for instance: | ||||
|  * | ||||
|  * |[<!-- language="C" --> | ||||
|  *   ClutterAction *action = clutter_drop_action (); | ||||
|  * | ||||
|  *   g_signal_connect (action, "drop", G_CALLBACK (on_drop), NULL); | ||||
|  *   clutter_actor_add_action (an_actor, action); | ||||
|  * ]| | ||||
|  * | ||||
|  * The #ClutterDropAction::can-drop can be used to control whether the | ||||
|  * #ClutterDropAction::drop signal is going to be emitted; returning %FALSE | ||||
|  * from a handler connected to the #ClutterDropAction::can-drop signal will | ||||
|  * cause the #ClutterDropAction::drop signal to be skipped when the input | ||||
|  * device button is released. | ||||
|  * | ||||
|  * It's important to note that #ClutterDropAction will only work with | ||||
|  * actors dragged using #ClutterDragAction. | ||||
|  * | ||||
|  * See [drop-action.c](https://git.gnome.org/browse/clutter/tree/examples/drop-action.c?h=clutter-1.18) | ||||
|  * for an example of how to use #ClutterDropAction. | ||||
|  * | ||||
|  * #ClutterDropAction is available since Clutter 1.8 | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter-drop-action.h" | ||||
|  | ||||
| #include "clutter-actor-meta-private.h" | ||||
| #include "clutter-actor-private.h" | ||||
| #include "clutter-drag-action.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-stage-private.h" | ||||
|  | ||||
| struct _ClutterDropActionPrivate | ||||
| { | ||||
|   ClutterActor *actor; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   gulong mapped_id; | ||||
| }; | ||||
|  | ||||
| typedef struct _DropTarget { | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   gulong capture_id; | ||||
|  | ||||
|   GHashTable *actions; | ||||
|  | ||||
|   ClutterDropAction *last_action; | ||||
| } DropTarget; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CAN_DROP, | ||||
|   OVER_IN, | ||||
|   OVER_OUT, | ||||
|   DROP, | ||||
|   DROP_CANCEL, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint drop_signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterDropAction, clutter_drop_action, CLUTTER_TYPE_ACTION) | ||||
|  | ||||
| static void | ||||
| drop_target_free (gpointer _data) | ||||
| { | ||||
|   DropTarget *data = _data; | ||||
|  | ||||
|   g_clear_signal_handler (&data->capture_id, data->stage); | ||||
|   g_hash_table_destroy (data->actions); | ||||
|   g_free (data); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| on_stage_capture (ClutterStage *stage, | ||||
|                   ClutterEvent *event, | ||||
|                   gpointer      user_data) | ||||
| { | ||||
|   DropTarget *data = user_data; | ||||
|   gfloat event_x, event_y; | ||||
|   ClutterActor *actor, *drag_actor; | ||||
|   ClutterDropAction *drop_action; | ||||
|   ClutterInputDevice *device; | ||||
|   gboolean was_reactive; | ||||
|  | ||||
|   switch (clutter_event_type (event)) | ||||
|     { | ||||
|     case CLUTTER_MOTION: | ||||
|     case CLUTTER_BUTTON_RELEASE: | ||||
|       if (clutter_event_type (event) == CLUTTER_MOTION && | ||||
|           !(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK)) | ||||
|         return CLUTTER_EVENT_PROPAGATE; | ||||
|  | ||||
|       if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE && | ||||
|           clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY) | ||||
|         return CLUTTER_EVENT_PROPAGATE; | ||||
|  | ||||
|       device = clutter_event_get_device (event); | ||||
|       drag_actor = _clutter_stage_get_pointer_drag_actor (stage, device); | ||||
|       if (drag_actor == NULL) | ||||
|         return CLUTTER_EVENT_PROPAGATE; | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_TOUCH_UPDATE: | ||||
|     case CLUTTER_TOUCH_END: | ||||
|       drag_actor = _clutter_stage_get_touch_drag_actor (stage, | ||||
|                                                         clutter_event_get_event_sequence (event)); | ||||
|       if (drag_actor == NULL) | ||||
|         return CLUTTER_EVENT_PROPAGATE; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       return CLUTTER_EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|   clutter_event_get_coords (event, &event_x, &event_y); | ||||
|  | ||||
|   /* get the actor under the cursor, excluding the dragged actor; we | ||||
|    * use reactivity because it won't cause any scene invalidation | ||||
|    */ | ||||
|   was_reactive = clutter_actor_get_reactive (drag_actor); | ||||
|   clutter_actor_set_reactive (drag_actor, FALSE); | ||||
|  | ||||
|   actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_REACTIVE, | ||||
|                                           event_x, | ||||
|                                           event_y); | ||||
|   if (actor == NULL || actor == CLUTTER_ACTOR (stage)) | ||||
|     { | ||||
|       if (data->last_action != NULL) | ||||
|         { | ||||
|           ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action); | ||||
|  | ||||
|           g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0, | ||||
|                          clutter_actor_meta_get_actor (meta)); | ||||
|  | ||||
|           data->last_action = NULL; | ||||
|         } | ||||
|  | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   drop_action = g_hash_table_lookup (data->actions, actor); | ||||
|  | ||||
|   if (drop_action == NULL) | ||||
|     { | ||||
|       if (data->last_action != NULL) | ||||
|         { | ||||
|           ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action); | ||||
|  | ||||
|           g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0, | ||||
|                          clutter_actor_meta_get_actor (meta)); | ||||
|  | ||||
|           data->last_action = NULL; | ||||
|         } | ||||
|  | ||||
|       goto out; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (data->last_action != drop_action) | ||||
|         { | ||||
|           ClutterActorMeta *meta; | ||||
|  | ||||
|           if (data->last_action != NULL) | ||||
|             { | ||||
|               meta = CLUTTER_ACTOR_META (data->last_action); | ||||
|  | ||||
|               g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0, | ||||
|                              clutter_actor_meta_get_actor (meta)); | ||||
|             } | ||||
|  | ||||
|           meta = CLUTTER_ACTOR_META (drop_action); | ||||
|  | ||||
|           g_signal_emit (drop_action, drop_signals[OVER_IN], 0, | ||||
|                          clutter_actor_meta_get_actor (meta)); | ||||
|         } | ||||
|  | ||||
|       data->last_action = drop_action; | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE || | ||||
|       clutter_event_type (event) == CLUTTER_TOUCH_END) | ||||
|     { | ||||
|       if (data->last_action != NULL) | ||||
|         { | ||||
|           ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action); | ||||
|           gboolean can_drop = FALSE; | ||||
|  | ||||
|           g_signal_emit (data->last_action, drop_signals[CAN_DROP], 0, | ||||
|                          clutter_actor_meta_get_actor (meta), | ||||
|                          event_x, event_y, | ||||
|                          &can_drop); | ||||
|  | ||||
|           if (can_drop) | ||||
|             { | ||||
|               g_signal_emit (data->last_action, drop_signals[DROP], 0, | ||||
|                              clutter_actor_meta_get_actor (meta), | ||||
|                              event_x, event_y); | ||||
|             } | ||||
| 	  else | ||||
|             { | ||||
|               g_signal_emit (data->last_action, drop_signals[DROP_CANCEL], 0, | ||||
|                              clutter_actor_meta_get_actor (meta), | ||||
|                              event_x, event_y); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|       data->last_action = NULL; | ||||
|     } | ||||
|  | ||||
|   if (drag_actor != NULL) | ||||
|     clutter_actor_set_reactive (drag_actor, was_reactive); | ||||
|  | ||||
|   return CLUTTER_EVENT_PROPAGATE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| drop_action_register (ClutterDropAction *self) | ||||
| { | ||||
|   ClutterDropActionPrivate *priv = self->priv; | ||||
|   DropTarget *data; | ||||
|  | ||||
|   g_assert (priv->stage != NULL); | ||||
|  | ||||
|   data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets"); | ||||
|   if (data == NULL) | ||||
|     { | ||||
|       data = g_new0 (DropTarget, 1); | ||||
|  | ||||
|       data->stage = priv->stage; | ||||
|       data->actions = g_hash_table_new (NULL, NULL); | ||||
|       data->capture_id = g_signal_connect (priv->stage, "captured-event", | ||||
|                                            G_CALLBACK (on_stage_capture), | ||||
|                                            data); | ||||
|       g_object_set_data_full (G_OBJECT (priv->stage), "__clutter_drop_targets", | ||||
|                               data, | ||||
|                               drop_target_free); | ||||
|     } | ||||
|  | ||||
|   g_hash_table_replace (data->actions, priv->actor, self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| drop_action_unregister (ClutterDropAction *self) | ||||
| { | ||||
|   ClutterDropActionPrivate *priv = self->priv; | ||||
|   DropTarget *data = NULL; | ||||
|  | ||||
|   if (priv->stage != NULL) | ||||
|     data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets"); | ||||
|  | ||||
|   if (data == NULL) | ||||
|     return; | ||||
|  | ||||
|   g_hash_table_remove (data->actions, priv->actor); | ||||
|   if (g_hash_table_size (data->actions) == 0) | ||||
|     g_object_set_data (G_OBJECT (data->stage), "__clutter_drop_targets", NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_actor_mapped (ClutterActor      *actor, | ||||
|                  GParamSpec        *pspec, | ||||
|                  ClutterDropAction *self) | ||||
| { | ||||
|   if (clutter_actor_is_mapped (actor)) | ||||
|     { | ||||
|       if (self->priv->stage == NULL) | ||||
|         self->priv->stage = clutter_actor_get_stage (actor); | ||||
|  | ||||
|       drop_action_register (self); | ||||
|     } | ||||
|   else | ||||
|     drop_action_unregister (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_drop_action_set_actor (ClutterActorMeta *meta, | ||||
|                                ClutterActor     *actor) | ||||
| { | ||||
|   ClutterDropActionPrivate *priv = CLUTTER_DROP_ACTION (meta)->priv; | ||||
|  | ||||
|   if (priv->actor != NULL) | ||||
|     { | ||||
|       drop_action_unregister (CLUTTER_DROP_ACTION (meta)); | ||||
|  | ||||
|       g_clear_signal_handler (&priv->mapped_id, priv->actor); | ||||
|  | ||||
|       priv->stage = NULL; | ||||
|       priv->actor = NULL; | ||||
|     } | ||||
|  | ||||
|   priv->actor = actor; | ||||
|  | ||||
|   if (priv->actor != NULL) | ||||
|     { | ||||
|       priv->stage = clutter_actor_get_stage (actor); | ||||
|       priv->mapped_id = g_signal_connect (actor, "notify::mapped", | ||||
|                                           G_CALLBACK (on_actor_mapped), | ||||
|                                           meta); | ||||
|  | ||||
|       if (priv->stage != NULL) | ||||
|         drop_action_register (CLUTTER_DROP_ACTION (meta)); | ||||
|     } | ||||
|  | ||||
|   CLUTTER_ACTOR_META_CLASS (clutter_drop_action_parent_class)->set_actor (meta, actor); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| signal_accumulator (GSignalInvocationHint *ihint, | ||||
|                     GValue                *return_accu, | ||||
|                     const GValue          *handler_return, | ||||
|                     gpointer               user_data) | ||||
| { | ||||
|   gboolean continue_emission; | ||||
|  | ||||
|   continue_emission = g_value_get_boolean (handler_return); | ||||
|   g_value_set_boolean (return_accu, continue_emission); | ||||
|  | ||||
|   return continue_emission; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_drop_action_real_can_drop (ClutterDropAction *action, | ||||
|                                    ClutterActor      *actor, | ||||
|                                    gfloat             event_x, | ||||
|                                    gfloat             event_y) | ||||
| { | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_drop_action_class_init (ClutterDropActionClass *klass) | ||||
| { | ||||
|   ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); | ||||
|  | ||||
|   meta_class->set_actor = clutter_drop_action_set_actor; | ||||
|  | ||||
|   klass->can_drop = clutter_drop_action_real_can_drop; | ||||
|  | ||||
|   /** | ||||
|    * ClutterDropAction::can-drop: | ||||
|    * @action: the #ClutterDropAction that emitted the signal | ||||
|    * @actor: the #ClutterActor attached to the @action | ||||
|    * @event_x: the X coordinate (in stage space) of the drop event | ||||
|    * @event_y: the Y coordinate (in stage space) of the drop event | ||||
|    * | ||||
|    * The ::can-drop signal is emitted when the dragged actor is dropped | ||||
|    * on @actor. The return value of the ::can-drop signal will determine | ||||
|    * whether or not the #ClutterDropAction::drop signal is going to be | ||||
|    * emitted on @action. | ||||
|    * | ||||
|    * The default implementation of #ClutterDropAction returns %TRUE for | ||||
|    * this signal. | ||||
|    * | ||||
|    * Return value: %TRUE if the drop is accepted, and %FALSE otherwise | ||||
|    * | ||||
|    * Since: 1.8 | ||||
|    */ | ||||
|   drop_signals[CAN_DROP] = | ||||
|     g_signal_new (I_("can-drop"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (ClutterDropActionClass, can_drop), | ||||
|                   signal_accumulator, NULL, | ||||
|                   _clutter_marshal_BOOLEAN__OBJECT_FLOAT_FLOAT, | ||||
|                   G_TYPE_BOOLEAN, 3, | ||||
|                   CLUTTER_TYPE_ACTOR, | ||||
|                   G_TYPE_FLOAT, | ||||
|                   G_TYPE_FLOAT); | ||||
|  | ||||
|   /** | ||||
|    * ClutterDropAction::over-in: | ||||
|    * @action: the #ClutterDropAction that emitted the signal | ||||
|    * @actor: the #ClutterActor attached to the @action | ||||
|    * | ||||
|    * The ::over-in signal is emitted when the dragged actor crosses | ||||
|    * into @actor. | ||||
|    * | ||||
|    * Since: 1.8 | ||||
|    */ | ||||
|   drop_signals[OVER_IN] = | ||||
|     g_signal_new (I_("over-in"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (ClutterDropActionClass, over_in), | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 1, | ||||
|                   CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
|   /** | ||||
|    * ClutterDropAction::over-out: | ||||
|    * @action: the #ClutterDropAction that emitted the signal | ||||
|    * @actor: the #ClutterActor attached to the @action | ||||
|    * | ||||
|    * The ::over-out signal is emitted when the dragged actor crosses | ||||
|    * outside @actor. | ||||
|    * | ||||
|    * Since: 1.8 | ||||
|    */ | ||||
|   drop_signals[OVER_OUT] = | ||||
|     g_signal_new (I_("over-out"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (ClutterDropActionClass, over_out), | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 1, | ||||
|                   CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
|   /** | ||||
|    * ClutterDropAction::drop: | ||||
|    * @action: the #ClutterDropAction that emitted the signal | ||||
|    * @actor: the #ClutterActor attached to the @action | ||||
|    * @event_x: the X coordinate (in stage space) of the drop event | ||||
|    * @event_y: the Y coordinate (in stage space) of the drop event | ||||
|    * | ||||
|    * The ::drop signal is emitted when the dragged actor is dropped | ||||
|    * on @actor. This signal is only emitted if at least an handler of | ||||
|    * #ClutterDropAction::can-drop returns %TRUE. | ||||
|    * | ||||
|    * Since: 1.8 | ||||
|    */ | ||||
|   drop_signals[DROP] = | ||||
|     g_signal_new (I_("drop"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (ClutterDropActionClass, drop), | ||||
|                   NULL, NULL, | ||||
|                   _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT, | ||||
|                   G_TYPE_NONE, 3, | ||||
|                   CLUTTER_TYPE_ACTOR, | ||||
|                   G_TYPE_FLOAT, | ||||
|                   G_TYPE_FLOAT); | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * ClutterDropAction::drop-cancel: | ||||
|    * @action: the #ClutterDropAction that emitted the signal | ||||
|    * @actor: the #ClutterActor attached to the @action | ||||
|    * @event_x: the X coordinate (in stage space) of the drop event | ||||
|    * @event_y: the Y coordinate (in stage space) of the drop event | ||||
|    * | ||||
|    * The ::drop-cancel signal is emitted when the drop is refused | ||||
|    * by an emission of the #ClutterDropAction::can-drop signal. | ||||
|    * | ||||
|    * After the ::drop-cancel signal is fired the active drag is | ||||
|    * terminated. | ||||
|    * | ||||
|    * Since: 1.12 | ||||
|    */ | ||||
|   drop_signals[DROP_CANCEL] = | ||||
|     g_signal_new (I_("drop-cancel"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (ClutterDropActionClass, drop), | ||||
|                   NULL, NULL, | ||||
|                   _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT, | ||||
|                   G_TYPE_NONE, 3, | ||||
|                   CLUTTER_TYPE_ACTOR, | ||||
|                   G_TYPE_FLOAT, | ||||
|                   G_TYPE_FLOAT); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_drop_action_init (ClutterDropAction *self) | ||||
| { | ||||
|   self->priv = clutter_drop_action_get_instance_private (self); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_drop_action_new: | ||||
|  * | ||||
|  * Creates a new #ClutterDropAction. | ||||
|  * | ||||
|  * Use clutter_actor_add_action() to add the action to a #ClutterActor. | ||||
|  * | ||||
|  * Return value: the newly created #ClutterDropAction | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  */ | ||||
| ClutterAction * | ||||
| clutter_drop_action_new (void) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_DROP_ACTION, NULL); | ||||
| } | ||||
| @@ -1,115 +0,0 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright © 2011  Intel Corporation. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: | ||||
|  *   Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_DROP_ACTION_H__ | ||||
| #define __CLUTTER_DROP_ACTION_H__ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be directly included." | ||||
| #endif | ||||
|  | ||||
| #include <clutter/clutter-action.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_DROP_ACTION                (clutter_drop_action_get_type ()) | ||||
| #define CLUTTER_DROP_ACTION(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropAction)) | ||||
| #define CLUTTER_IS_DROP_ACTION(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DROP_ACTION)) | ||||
| #define CLUTTER_DROP_ACTION_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass)) | ||||
| #define CLUTTER_IS_DROP_ACTION_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DROP_ACTION)) | ||||
| #define CLUTTER_DROP_ACTION_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass)) | ||||
|  | ||||
| typedef struct _ClutterDropAction               ClutterDropAction; | ||||
| typedef struct _ClutterDropActionPrivate        ClutterDropActionPrivate; | ||||
| typedef struct _ClutterDropActionClass          ClutterDropActionClass; | ||||
|  | ||||
| /** | ||||
|  * ClutterDropAction: | ||||
|  * | ||||
|  * The #ClutterDropAction structure contains only | ||||
|  * private data and should be accessed using the provided API. | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  */ | ||||
| struct _ClutterDropAction | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterAction parent_instance; | ||||
|  | ||||
|   ClutterDropActionPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * ClutterDropActionClass: | ||||
|  * @can_drop: class handler for the #ClutterDropAction::can-drop signal | ||||
|  * @over_in: class handler for the #ClutterDropAction::over-in signal | ||||
|  * @over_out: class handler for the #ClutterDropAction::over-out signal | ||||
|  * @drop: class handler for the #ClutterDropAction::drop signal | ||||
|  * | ||||
|  * The #ClutterDropActionClass structure contains | ||||
|  * only private data. | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  */ | ||||
| struct _ClutterDropActionClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActionClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   gboolean (* can_drop) (ClutterDropAction *action, | ||||
|                          ClutterActor      *actor, | ||||
|                          gfloat             event_x, | ||||
|                          gfloat             event_y); | ||||
|  | ||||
|   void     (* over_in)  (ClutterDropAction *action, | ||||
|                          ClutterActor      *actor); | ||||
|   void     (* over_out) (ClutterDropAction *action, | ||||
|                          ClutterActor      *actor); | ||||
|  | ||||
|   void     (* drop)     (ClutterDropAction *action, | ||||
|                          ClutterActor      *actor, | ||||
|                          gfloat             event_x, | ||||
|                          gfloat             event_y); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   void (*_clutter_drop_action1) (void); | ||||
|   void (*_clutter_drop_action2) (void); | ||||
|   void (*_clutter_drop_action3) (void); | ||||
|   void (*_clutter_drop_action4) (void); | ||||
|   void (*_clutter_drop_action5) (void); | ||||
|   void (*_clutter_drop_action6) (void); | ||||
|   void (*_clutter_drop_action7) (void); | ||||
|   void (*_clutter_drop_action8) (void); | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_drop_action_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterAction *         clutter_drop_action_new         (void); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_DROP_ACTION_H__ */ | ||||
| @@ -230,28 +230,26 @@ clutter_effect_real_pick (ClutterEffect      *effect, | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_effect_notify (GObject    *gobject, | ||||
|                        GParamSpec *pspec) | ||||
| clutter_effect_set_enabled (ClutterActorMeta *meta, | ||||
|                             gboolean          is_enabled) | ||||
| { | ||||
|   if (strcmp (pspec->name, "enabled") == 0) | ||||
|     { | ||||
|       ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); | ||||
|       ClutterActor *actor = clutter_actor_meta_get_actor (meta); | ||||
|   ClutterActorMetaClass *parent_class = | ||||
|     CLUTTER_ACTOR_META_CLASS (clutter_effect_parent_class); | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|       if (actor != NULL) | ||||
|         clutter_actor_queue_redraw (actor); | ||||
|     } | ||||
|   actor = clutter_actor_meta_get_actor (meta); | ||||
|   if (actor) | ||||
|     clutter_actor_queue_redraw (actor); | ||||
|  | ||||
|   if (G_OBJECT_CLASS (clutter_effect_parent_class)->notify != NULL) | ||||
|     G_OBJECT_CLASS (clutter_effect_parent_class)->notify (gobject, pspec); | ||||
|   parent_class->set_enabled (meta, is_enabled); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_effect_class_init (ClutterEffectClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass); | ||||
|  | ||||
|   gobject_class->notify = clutter_effect_notify; | ||||
|   actor_meta_class->set_enabled = clutter_effect_set_enabled; | ||||
|  | ||||
|   klass->pre_paint = clutter_effect_real_pre_paint; | ||||
|   klass->post_paint = clutter_effect_real_post_paint; | ||||
|   | ||||
| @@ -556,6 +556,21 @@ clutter_gesture_action_set_actor (ClutterActorMeta *meta, | ||||
|   meta_class->set_actor (meta, actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_gesture_action_set_enabled (ClutterActorMeta *meta, | ||||
|                                     gboolean          is_enabled) | ||||
| { | ||||
|   ClutterActorMetaClass *meta_class = | ||||
|     CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class); | ||||
|   ClutterGestureAction *gesture_action = CLUTTER_GESTURE_ACTION (meta); | ||||
|   ClutterGestureActionPrivate *priv = gesture_action->priv; | ||||
|  | ||||
|   if (!is_enabled && priv->in_gesture) | ||||
|     cancel_gesture (gesture_action); | ||||
|  | ||||
|   meta_class->set_enabled (meta, is_enabled); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| default_event_handler (ClutterGestureAction *action, | ||||
|                        ClutterActor *actor) | ||||
| @@ -654,6 +669,7 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass) | ||||
|   gobject_class->get_property = clutter_gesture_action_get_property; | ||||
|  | ||||
|   meta_class->set_actor = clutter_gesture_action_set_actor; | ||||
|   meta_class->set_enabled = clutter_gesture_action_set_enabled; | ||||
|  | ||||
|   klass->gesture_begin = default_event_handler; | ||||
|   klass->gesture_progress = default_event_handler; | ||||
|   | ||||
| @@ -57,9 +57,16 @@ void clutter_stage_thaw_updates (ClutterStage *stage); | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_update_resource_scales (ClutterStage *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_view_assign_next_scanout (ClutterStageView *stage_view, | ||||
|                                              CoglScanout      *scanout); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean clutter_actor_has_damage (ClutterActor *actor); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean clutter_actor_has_transitions (ClutterActor *actor); | ||||
|  | ||||
| #undef __CLUTTER_H_INSIDE__ | ||||
|  | ||||
| #endif /* __CLUTTER_MUTTER_H__ */ | ||||
|   | ||||
| @@ -81,7 +81,7 @@ | ||||
| struct _ClutterOffscreenEffectPrivate | ||||
| { | ||||
|   CoglHandle offscreen; | ||||
|   CoglPipeline *target; | ||||
|   CoglPipeline *pipeline; | ||||
|   CoglHandle texture; | ||||
|  | ||||
|   ClutterActor *actor; | ||||
| @@ -140,7 +140,7 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self, | ||||
| { | ||||
|   CoglPipelineFilter filter; | ||||
|  | ||||
|   if (!self->priv->target) | ||||
|   if (!self->priv->pipeline) | ||||
|     return; | ||||
|  | ||||
|   /* If no fractional scaling is set, we're always going to render the texture | ||||
| @@ -154,7 +154,7 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self, | ||||
|   else | ||||
|     filter = COGL_PIPELINE_FILTER_LINEAR; | ||||
|  | ||||
|   cogl_pipeline_set_layer_filters (self->priv->target, 0 /* layer_index */, | ||||
|   cogl_pipeline_set_layer_filters (self->priv->pipeline, 0 /* layer_index */, | ||||
|                                    filter, filter); | ||||
| } | ||||
|  | ||||
| @@ -185,12 +185,12 @@ update_fbo (ClutterEffect *effect, | ||||
|     return TRUE; | ||||
|   } | ||||
|  | ||||
|   if (priv->target == NULL) | ||||
|   if (priv->pipeline == NULL) | ||||
|     { | ||||
|       CoglContext *ctx = | ||||
|         clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|  | ||||
|       priv->target = cogl_pipeline_new (ctx); | ||||
|       priv->pipeline = cogl_pipeline_new (ctx); | ||||
|       ensure_pipeline_filter_for_scale (self, resource_scale); | ||||
|     } | ||||
|  | ||||
| @@ -202,7 +202,7 @@ update_fbo (ClutterEffect *effect, | ||||
|   if (priv->texture == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture); | ||||
|   cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->texture); | ||||
|  | ||||
|   priv->target_width = target_width; | ||||
|   priv->target_height = target_height; | ||||
| @@ -212,8 +212,8 @@ update_fbo (ClutterEffect *effect, | ||||
|     { | ||||
|       g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC); | ||||
|  | ||||
|       cogl_object_unref (priv->target); | ||||
|       priv->target = NULL; | ||||
|       cogl_object_unref (priv->pipeline); | ||||
|       priv->pipeline = NULL; | ||||
|  | ||||
|       priv->target_width = 0; | ||||
|       priv->target_height = 0; | ||||
| @@ -380,7 +380,7 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect, | ||||
|  | ||||
|   paint_opacity = clutter_actor_get_paint_opacity (priv->actor); | ||||
|  | ||||
|   cogl_pipeline_set_color4ub (priv->target, | ||||
|   cogl_pipeline_set_color4ub (priv->pipeline, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
| @@ -392,7 +392,7 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect, | ||||
|    * hadn't been redirected offscreen. | ||||
|    */ | ||||
|   cogl_framebuffer_draw_textured_rectangle (framebuffer, | ||||
|                                             priv->target, | ||||
|                                             priv->pipeline, | ||||
|                                             0, 0, | ||||
|                                             cogl_texture_get_width (priv->texture), | ||||
|                                             cogl_texture_get_height (priv->texture), | ||||
| @@ -446,13 +446,16 @@ clutter_offscreen_effect_post_paint (ClutterEffect       *effect, | ||||
|   ClutterOffscreenEffectPrivate *priv = self->priv; | ||||
|   CoglFramebuffer *framebuffer; | ||||
|  | ||||
|   if (priv->offscreen == NULL || | ||||
|       priv->target == NULL || | ||||
|       priv->actor == NULL) | ||||
|     return; | ||||
|   g_warn_if_fail (priv->offscreen); | ||||
|   g_warn_if_fail (priv->pipeline); | ||||
|   g_warn_if_fail (priv->actor); | ||||
|  | ||||
|   /* Restore the previous opacity override */ | ||||
|   clutter_actor_set_opacity_override (priv->actor, priv->old_opacity_override); | ||||
|   if (priv->actor) | ||||
|     { | ||||
|       clutter_actor_set_opacity_override (priv->actor, | ||||
|                                           priv->old_opacity_override); | ||||
|     } | ||||
|  | ||||
|   framebuffer = clutter_paint_context_get_framebuffer (paint_context); | ||||
|   cogl_framebuffer_pop_matrix (framebuffer); | ||||
| @@ -498,16 +501,17 @@ clutter_offscreen_effect_paint (ClutterEffect           *effect, | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_offscreen_effect_notify (GObject    *gobject, | ||||
|                                  GParamSpec *pspec) | ||||
| clutter_offscreen_effect_set_enabled (ClutterActorMeta *meta, | ||||
|                                       gboolean          is_enabled) | ||||
| { | ||||
|   ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (gobject); | ||||
|   ClutterActorMetaClass *parent_class = | ||||
|     CLUTTER_ACTOR_META_CLASS (clutter_offscreen_effect_parent_class); | ||||
|   ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (meta); | ||||
|   ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv; | ||||
|  | ||||
|   if (strcmp (pspec->name, "enabled") == 0) | ||||
|     g_clear_pointer (&priv->offscreen, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->offscreen, cogl_object_unref); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->notify (gobject, pspec); | ||||
|   parent_class->set_enabled (meta, is_enabled); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -518,7 +522,7 @@ clutter_offscreen_effect_finalize (GObject *gobject) | ||||
|  | ||||
|   g_clear_pointer (&priv->offscreen, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->texture, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->target, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->pipeline, cogl_object_unref); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject); | ||||
| } | ||||
| @@ -534,13 +538,13 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass) | ||||
|   klass->paint_target = clutter_offscreen_effect_real_paint_target; | ||||
|  | ||||
|   meta_class->set_actor = clutter_offscreen_effect_set_actor; | ||||
|   meta_class->set_enabled = clutter_offscreen_effect_set_enabled; | ||||
|  | ||||
|   effect_class->pre_paint = clutter_offscreen_effect_pre_paint; | ||||
|   effect_class->post_paint = clutter_offscreen_effect_post_paint; | ||||
|   effect_class->paint = clutter_offscreen_effect_paint; | ||||
|  | ||||
|   gobject_class->finalize = clutter_offscreen_effect_finalize; | ||||
|   gobject_class->notify = clutter_offscreen_effect_notify; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -600,7 +604,7 @@ clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect) | ||||
|   g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), | ||||
|                         NULL); | ||||
|  | ||||
|   return (CoglMaterial *)effect->priv->target; | ||||
|   return (CoglMaterial *)effect->priv->pipeline; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -83,7 +83,6 @@ typedef enum | ||||
|   PAINT_OP_INVALID = 0, | ||||
|   PAINT_OP_TEX_RECT, | ||||
|   PAINT_OP_MULTITEX_RECT, | ||||
|   PAINT_OP_PATH, | ||||
|   PAINT_OP_PRIMITIVE | ||||
| } PaintOpCode; | ||||
|  | ||||
| @@ -96,8 +95,6 @@ struct _ClutterPaintOperation | ||||
|   union { | ||||
|     float texrect[8]; | ||||
|  | ||||
|     CoglPath *path; | ||||
|  | ||||
|     CoglPrimitive *primitive; | ||||
|   } op; | ||||
| }; | ||||
|   | ||||
| @@ -782,11 +782,6 @@ clutter_paint_operation_clear (ClutterPaintOperation *op) | ||||
|         g_array_unref (op->multitex_coords); | ||||
|       break; | ||||
|  | ||||
|     case PAINT_OP_PATH: | ||||
|       if (op->op.path != NULL) | ||||
|         cogl_object_unref (op->op.path); | ||||
|       break; | ||||
|  | ||||
|     case PAINT_OP_PRIMITIVE: | ||||
|       if (op->op.primitive != NULL) | ||||
|         cogl_object_unref (op->op.primitive); | ||||
| @@ -836,16 +831,6 @@ clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op, | ||||
|   op->op.texrect[3] = rect->y2; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| clutter_paint_op_init_path (ClutterPaintOperation *op, | ||||
|                             CoglPath              *path) | ||||
| { | ||||
|   clutter_paint_operation_clear (op); | ||||
|  | ||||
|   op->opcode = PAINT_OP_PATH; | ||||
|   op->op.path = cogl_object_ref (path); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| clutter_paint_op_init_primitive (ClutterPaintOperation *op, | ||||
|                                  CoglPrimitive         *primitive) | ||||
| @@ -950,34 +935,6 @@ clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode      *node, | ||||
|   g_array_append_val (node->operations, operation); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_paint_node_add_path: (skip) | ||||
|  * @node: a #ClutterPaintNode | ||||
|  * @path: a Cogl path | ||||
|  * | ||||
|  * Adds a region described as a path to the @node. | ||||
|  * | ||||
|  * This function acquires a reference on the passed @path, so it | ||||
|  * is safe to call cogl_object_unref() when it returns. | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| void | ||||
| clutter_paint_node_add_path (ClutterPaintNode *node, | ||||
|                              CoglPath         *path) | ||||
| { | ||||
|   ClutterPaintOperation operation = PAINT_OP_INIT; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); | ||||
|   g_return_if_fail (cogl_is_path (path)); | ||||
|  | ||||
|   clutter_paint_node_maybe_init_operations (node); | ||||
|  | ||||
|   clutter_paint_op_init_path (&operation, path); | ||||
|   g_array_append_val (node->operations, operation); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_paint_node_add_primitive: (skip) | ||||
|  * @node: a #ClutterPaintNode | ||||
| @@ -1114,11 +1071,6 @@ clutter_paint_node_to_json (ClutterPaintNode *node) | ||||
|               json_builder_end_array (builder); | ||||
|               break; | ||||
|  | ||||
|             case PAINT_OP_PATH: | ||||
|               json_builder_set_member_name (builder, "path"); | ||||
|               json_builder_add_int_value (builder, (intptr_t) op->op.path); | ||||
|               break; | ||||
|  | ||||
|             case PAINT_OP_PRIMITIVE: | ||||
|               json_builder_set_member_name (builder, "primitive"); | ||||
|               json_builder_add_int_value (builder, (intptr_t) op->op.primitive); | ||||
|   | ||||
| @@ -84,9 +84,6 @@ void                   clutter_paint_node_add_multitexture_rectangle   (ClutterP | ||||
|                                                                         unsigned int            text_coords_len); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                    clutter_paint_node_add_path                     (ClutterPaintNode      *node, | ||||
|                                                                          CoglPath              *path); | ||||
| CLUTTER_EXPORT | ||||
| void                    clutter_paint_node_add_primitive                (ClutterPaintNode      *node, | ||||
|                                                                          CoglPrimitive         *primitive); | ||||
|  | ||||
|   | ||||
| @@ -477,10 +477,6 @@ clutter_pipeline_node_draw (ClutterPaintNode    *node, | ||||
|                                                          op->multitex_coords->len); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PATH: | ||||
|           cogl_framebuffer_fill_path (fb, pnode->pipeline, op->op.path); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|           cogl_framebuffer_draw_primitive (fb, | ||||
|                                            pnode->pipeline, | ||||
| @@ -876,7 +872,6 @@ clutter_text_node_draw (ClutterPaintNode    *node, | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|         case PAINT_OP_PATH: | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|         case PAINT_OP_INVALID: | ||||
|           break; | ||||
| @@ -1037,11 +1032,6 @@ clutter_clip_node_pre_draw (ClutterPaintNode    *node, | ||||
|           retval = TRUE; | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PATH: | ||||
|           cogl_framebuffer_push_path_clip (fb, op->op.path); | ||||
|           retval = TRUE; | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|         case PAINT_OP_INVALID: | ||||
| @@ -1072,7 +1062,6 @@ clutter_clip_node_post_draw (ClutterPaintNode    *node, | ||||
|  | ||||
|       switch (op->opcode) | ||||
|         { | ||||
|         case PAINT_OP_PATH: | ||||
|         case PAINT_OP_TEX_RECT: | ||||
|           cogl_framebuffer_pop_clip (fb); | ||||
|           break; | ||||
| @@ -1242,9 +1231,8 @@ struct _ClutterLayerNode | ||||
|   float fbo_width; | ||||
|   float fbo_height; | ||||
|  | ||||
|   CoglPipeline *state; | ||||
|   CoglPipeline *pipeline; | ||||
|   CoglFramebuffer *offscreen; | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   guint8 opacity; | ||||
| }; | ||||
| @@ -1334,7 +1322,7 @@ clutter_layer_node_post_draw (ClutterPaintNode    *node, | ||||
|         case PAINT_OP_TEX_RECT: | ||||
|           /* now we need to paint the texture */ | ||||
|           cogl_framebuffer_draw_textured_rectangle (fb, | ||||
|                                                     lnode->state, | ||||
|                                                     lnode->pipeline, | ||||
|                                                     op->op.texrect[0], | ||||
|                                                     op->op.texrect[1], | ||||
|                                                     op->op.texrect[2], | ||||
| @@ -1347,7 +1335,7 @@ clutter_layer_node_post_draw (ClutterPaintNode    *node, | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|           cogl_framebuffer_draw_multitextured_rectangle (fb, | ||||
|                                                          lnode->state, | ||||
|                                                          lnode->pipeline, | ||||
|                                                          op->op.texrect[0], | ||||
|                                                          op->op.texrect[1], | ||||
|                                                          op->op.texrect[2], | ||||
| @@ -1356,12 +1344,10 @@ clutter_layer_node_post_draw (ClutterPaintNode    *node, | ||||
|                                                          op->multitex_coords->len); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PATH: | ||||
|           cogl_framebuffer_fill_path (fb, lnode->state, op->op.path); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|           cogl_framebuffer_draw_primitive (fb, lnode->state, op->op.primitive); | ||||
|           cogl_framebuffer_draw_primitive (fb, | ||||
|                                            lnode->pipeline, | ||||
|                                            op->op.primitive); | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
| @@ -1372,8 +1358,8 @@ clutter_layer_node_finalize (ClutterPaintNode *node) | ||||
| { | ||||
|   ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node); | ||||
|  | ||||
|   if (lnode->state != NULL) | ||||
|     cogl_object_unref (lnode->state); | ||||
|   if (lnode->pipeline != NULL) | ||||
|     cogl_object_unref (lnode->pipeline); | ||||
|  | ||||
|   if (lnode->offscreen != NULL) | ||||
|     cogl_object_unref (lnode->offscreen); | ||||
| @@ -1425,6 +1411,8 @@ clutter_layer_node_new (const CoglMatrix        *projection, | ||||
|                         guint8                   opacity) | ||||
| { | ||||
|   ClutterLayerNode *res; | ||||
|   CoglContext *context; | ||||
|   CoglTexture *texture; | ||||
|   CoglColor color; | ||||
|  | ||||
|   res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); | ||||
| @@ -1436,19 +1424,17 @@ clutter_layer_node_new (const CoglMatrix        *projection, | ||||
|   res->opacity = opacity; | ||||
|  | ||||
|   /* the texture backing the FBO */ | ||||
|   res->texture = cogl_texture_new_with_size (MAX (res->fbo_width, 1), | ||||
|                                              MAX (res->fbo_height, 1), | ||||
|                                              COGL_TEXTURE_NO_SLICING, | ||||
|                                              COGL_PIXEL_FORMAT_RGBA_8888_PRE); | ||||
|   context = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|  | ||||
|   res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (res->texture)); | ||||
|   texture = cogl_texture_2d_new_with_size (context, | ||||
|                                            MAX (res->fbo_width, 1), | ||||
|                                            MAX (res->fbo_height, 1)); | ||||
|   cogl_texture_set_premultiplied (texture, TRUE); | ||||
|  | ||||
|   res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture)); | ||||
|   if (res->offscreen == NULL) | ||||
|     { | ||||
|       g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC); | ||||
|  | ||||
|       cogl_object_unref (res->texture); | ||||
|       res->texture = NULL; | ||||
|  | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
| @@ -1458,14 +1444,15 @@ clutter_layer_node_new (const CoglMatrix        *projection, | ||||
|    * interpolation filters because the texture is always | ||||
|    * going to be painted at a 1:1 texel:pixel ratio | ||||
|    */ | ||||
|   res->state = cogl_pipeline_copy (default_texture_pipeline); | ||||
|   cogl_pipeline_set_layer_filters (res->state, 0, | ||||
|   res->pipeline = cogl_pipeline_copy (default_texture_pipeline); | ||||
|   cogl_pipeline_set_layer_filters (res->pipeline, 0, | ||||
|                                    COGL_PIPELINE_FILTER_NEAREST, | ||||
|                                    COGL_PIPELINE_FILTER_NEAREST); | ||||
|   cogl_pipeline_set_layer_texture (res->state, 0, res->texture); | ||||
|   cogl_pipeline_set_color (res->state, &color); | ||||
|   cogl_object_unref (res->texture); | ||||
|   cogl_pipeline_set_layer_texture (res->pipeline, 0, texture); | ||||
|   cogl_pipeline_set_color (res->pipeline, &color); | ||||
|  | ||||
| out: | ||||
|   cogl_object_unref (texture); | ||||
|  | ||||
|   return (ClutterPaintNode *) res; | ||||
| } | ||||
|   | ||||
| @@ -43,4 +43,6 @@ const cairo_region_t * clutter_stage_view_peek_redraw_clip (ClutterStageView *vi | ||||
|  | ||||
| cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view); | ||||
|  | ||||
| CoglScanout * clutter_stage_view_take_scanout (ClutterStageView *view); | ||||
|  | ||||
| #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
| #include <math.h> | ||||
|  | ||||
| #include "clutter/clutter-private.h" | ||||
| #include "clutter/clutter-mutter.h" | ||||
| #include "cogl/cogl.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
| @@ -52,6 +54,8 @@ typedef struct _ClutterStageViewPrivate | ||||
|   CoglOffscreen *shadowfb; | ||||
|   CoglPipeline *shadowfb_pipeline; | ||||
|  | ||||
|   CoglScanout *next_scanout; | ||||
|  | ||||
|   gboolean has_redraw_clip; | ||||
|   cairo_region_t *redraw_clip; | ||||
|  | ||||
| @@ -407,6 +411,25 @@ clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *vie | ||||
|   cogl_matrix_init_identity (matrix); | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_stage_view_assign_next_scanout (ClutterStageView *view, | ||||
|                                         CoglScanout      *scanout) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   g_set_object (&priv->next_scanout, scanout); | ||||
| } | ||||
|  | ||||
| CoglScanout * | ||||
| clutter_stage_view_take_scanout (ClutterStageView *view) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   return g_steal_pointer (&priv->next_scanout); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_view_get_property (GObject    *object, | ||||
|                                  guint       prop_id, | ||||
|   | ||||
| @@ -62,16 +62,6 @@ _clutter_stage_window_set_title (ClutterStageWindow *window, | ||||
|     iface->set_title (window, title); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, | ||||
|                                           gboolean            is_visible) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|  | ||||
|   if (iface->set_cursor_visible) | ||||
|     iface->set_cursor_visible (window, is_visible); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _clutter_stage_window_realize (ClutterStageWindow *window) | ||||
| { | ||||
| @@ -178,19 +168,6 @@ _clutter_stage_window_clear_update_time (ClutterStageWindow *window) | ||||
|   iface->clear_update_time (window); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, | ||||
|                                         gboolean            accept_focus) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); | ||||
|  | ||||
|   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|   if (iface->set_accept_focus) | ||||
|     iface->set_accept_focus (window, accept_focus); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_redraw (ClutterStageWindow *window) | ||||
| { | ||||
|   | ||||
| @@ -30,8 +30,6 @@ struct _ClutterStageWindowInterface | ||||
|  | ||||
|   void              (* set_title)               (ClutterStageWindow *stage_window, | ||||
|                                                  const gchar        *title); | ||||
|   void              (* set_cursor_visible)      (ClutterStageWindow *stage_window, | ||||
|                                                  gboolean            cursor_visible); | ||||
|  | ||||
|   gboolean          (* realize)                 (ClutterStageWindow *stage_window); | ||||
|   void              (* unrealize)               (ClutterStageWindow *stage_window); | ||||
| @@ -51,9 +49,6 @@ struct _ClutterStageWindowInterface | ||||
|   gint64            (* get_update_time)         (ClutterStageWindow *stage_window); | ||||
|   void              (* clear_update_time)       (ClutterStageWindow *stage_window); | ||||
|  | ||||
|   void              (* set_accept_focus)        (ClutterStageWindow *stage_window, | ||||
|                                                  gboolean            accept_focus); | ||||
|  | ||||
|   void              (* redraw)                  (ClutterStageWindow *stage_window); | ||||
|  | ||||
|   gboolean          (* can_clip_redraws)        (ClutterStageWindow *stage_window); | ||||
|   | ||||
| @@ -140,19 +140,12 @@ struct _ClutterStagePrivate | ||||
|  | ||||
|   ClutterStageState current_state; | ||||
|  | ||||
|   gpointer paint_data; | ||||
|   GDestroyNotify paint_notify; | ||||
|  | ||||
|   int update_freeze_count; | ||||
|  | ||||
|   guint redraw_pending         : 1; | ||||
|   guint is_cursor_visible      : 1; | ||||
|   guint throttle_motion_events : 1; | ||||
|   guint use_alpha              : 1; | ||||
|   guint min_size_changed       : 1; | ||||
|   guint accept_focus           : 1; | ||||
|   guint motion_events_enabled  : 1; | ||||
|   guint has_custom_perspective : 1; | ||||
|   guint stage_was_relayout     : 1; | ||||
| }; | ||||
|  | ||||
| @@ -161,12 +154,9 @@ enum | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_COLOR, | ||||
|   PROP_CURSOR_VISIBLE, | ||||
|   PROP_PERSPECTIVE, | ||||
|   PROP_TITLE, | ||||
|   PROP_USE_ALPHA, | ||||
|   PROP_KEY_FOCUS, | ||||
|   PROP_ACCEPT_FOCUS, | ||||
|   PROP_LAST | ||||
| }; | ||||
|  | ||||
| @@ -1320,15 +1310,9 @@ clutter_stage_queue_actor_relayout (ClutterStage *stage, | ||||
| { | ||||
|   ClutterStagePrivate *priv = stage->priv; | ||||
|  | ||||
|   if (g_hash_table_contains (priv->pending_relayouts, stage)) | ||||
|     return; | ||||
|  | ||||
|   if (g_hash_table_size (priv->pending_relayouts) == 0) | ||||
|     _clutter_stage_schedule_update (stage); | ||||
|  | ||||
|   if (actor == (ClutterActor *) stage) | ||||
|     g_hash_table_remove_all (priv->pending_relayouts); | ||||
|  | ||||
|   g_hash_table_add (priv->pending_relayouts, g_object_ref (actor)); | ||||
|   priv->pending_relayouts_version++; | ||||
| } | ||||
| @@ -1852,33 +1836,14 @@ clutter_stage_set_property (GObject      *object, | ||||
|                                           clutter_value_get_color (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_CURSOR_VISIBLE: | ||||
|       if (g_value_get_boolean (value)) | ||||
|         clutter_stage_show_cursor (stage); | ||||
|       else | ||||
|         clutter_stage_hide_cursor (stage); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PERSPECTIVE: | ||||
|       clutter_stage_set_perspective (stage, g_value_get_boxed (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TITLE: | ||||
|       clutter_stage_set_title (stage, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_USE_ALPHA: | ||||
|       clutter_stage_set_use_alpha (stage, g_value_get_boolean (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_KEY_FOCUS: | ||||
|       clutter_stage_set_key_focus (stage, g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_ACCEPT_FOCUS: | ||||
|       clutter_stage_set_accept_focus (stage, g_value_get_boolean (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
| @@ -1905,10 +1870,6 @@ clutter_stage_get_property (GObject    *gobject, | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case PROP_CURSOR_VISIBLE: | ||||
|       g_value_set_boolean (value, priv->is_cursor_visible); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PERSPECTIVE: | ||||
|       g_value_set_boxed (value, &priv->perspective); | ||||
|       break; | ||||
| @@ -1917,18 +1878,10 @@ clutter_stage_get_property (GObject    *gobject, | ||||
|       g_value_set_string (value, priv->title); | ||||
|       break; | ||||
|  | ||||
|     case PROP_USE_ALPHA: | ||||
|       g_value_set_boolean (value, priv->use_alpha); | ||||
|       break; | ||||
|  | ||||
|     case PROP_KEY_FOCUS: | ||||
|       g_value_set_object (value, priv->key_focused_actor); | ||||
|       break; | ||||
|  | ||||
|     case PROP_ACCEPT_FOCUS: | ||||
|       g_value_set_boolean (value, priv->accept_focus); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
| @@ -1992,9 +1945,6 @@ clutter_stage_finalize (GObject *object) | ||||
|   if (priv->fps_timer != NULL) | ||||
|     g_timer_destroy (priv->fps_timer); | ||||
|  | ||||
|   if (priv->paint_notify != NULL) | ||||
|     priv->paint_notify (priv->paint_data); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| @@ -2036,18 +1986,6 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|  | ||||
|   klass->paint_view = clutter_stage_real_paint_view; | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:cursor-visible: | ||||
|    * | ||||
|    * Whether the mouse pointer should be visible | ||||
|    */ | ||||
|   obj_props[PROP_CURSOR_VISIBLE] = | ||||
|       g_param_spec_boolean ("cursor-visible", | ||||
|                             P_("Cursor Visible"), | ||||
|                             P_("Whether the mouse pointer is visible on the main stage"), | ||||
|                             TRUE, | ||||
|                             CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:color: | ||||
|    * | ||||
| @@ -2077,7 +2015,7 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|                           P_("Perspective"), | ||||
|                           P_("Perspective projection parameters"), | ||||
|                           CLUTTER_TYPE_PERSPECTIVE, | ||||
|                           CLUTTER_PARAM_READWRITE); | ||||
|                           CLUTTER_PARAM_READABLE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:title: | ||||
| @@ -2093,23 +2031,6 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|                            NULL, | ||||
|                            CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:use-alpha: | ||||
|    * | ||||
|    * Whether the #ClutterStage should honour the alpha component of the | ||||
|    * #ClutterStage:color property when painting. If Clutter is run under | ||||
|    * a compositing manager this will result in the stage being blended | ||||
|    * with the underlying window(s) | ||||
|    * | ||||
|    * Since: 1.2 | ||||
|    */ | ||||
|   obj_props[PROP_USE_ALPHA] = | ||||
|       g_param_spec_boolean ("use-alpha", | ||||
|                             P_("Use Alpha"), | ||||
|                             P_("Whether to honour the alpha component of the stage color"), | ||||
|                             FALSE, | ||||
|                             CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:key-focus: | ||||
|    * | ||||
| @@ -2127,20 +2048,6 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|                            CLUTTER_TYPE_ACTOR, | ||||
|                            CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:accept-focus: | ||||
|    * | ||||
|    * Whether the #ClutterStage should accept key focus when shown. | ||||
|    * | ||||
|    * Since: 1.6 | ||||
|    */ | ||||
|   obj_props[PROP_ACCEPT_FOCUS] = | ||||
|       g_param_spec_boolean ("accept-focus", | ||||
|                             P_("Accept Focus"), | ||||
|                             P_("Whether the stage should accept focus on show"), | ||||
|                             TRUE, | ||||
|                             CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); | ||||
|  | ||||
|   /** | ||||
| @@ -2315,7 +2222,6 @@ clutter_stage_init (ClutterStage *self) | ||||
|  | ||||
|   priv->event_queue = g_queue_new (); | ||||
|  | ||||
|   priv->is_cursor_visible = TRUE; | ||||
|   priv->throttle_motion_events = TRUE; | ||||
|   priv->min_size_changed = FALSE; | ||||
|   priv->sync_delay = -1; | ||||
| @@ -2438,8 +2344,8 @@ clutter_stage_get_color (ClutterStage *stage, | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_set_perspective_internal (ClutterStage       *stage, | ||||
|                                         ClutterPerspective *perspective) | ||||
| clutter_stage_set_perspective (ClutterStage       *stage, | ||||
|                                ClutterPerspective *perspective) | ||||
| { | ||||
|   ClutterStagePrivate *priv = stage->priv; | ||||
|  | ||||
| @@ -2464,36 +2370,6 @@ clutter_stage_set_perspective_internal (ClutterStage       *stage, | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_perspective: | ||||
|  * @stage: A #ClutterStage | ||||
|  * @perspective: A #ClutterPerspective | ||||
|  * | ||||
|  * Sets the stage perspective. Using this function is not recommended | ||||
|  * because it will disable Clutter's attempts to generate an | ||||
|  * appropriate perspective based on the size of the stage. | ||||
|  */ | ||||
| void | ||||
| clutter_stage_set_perspective (ClutterStage       *stage, | ||||
|                                ClutterPerspective *perspective) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|   g_return_if_fail (perspective != NULL); | ||||
|   g_return_if_fail (perspective->z_far - perspective->z_near != 0); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|  | ||||
|   /* If the application ever calls this function then we'll stop | ||||
|      automatically updating the perspective when the stage changes | ||||
|      size */ | ||||
|   priv->has_custom_perspective = TRUE; | ||||
|  | ||||
|   clutter_stage_set_perspective_internal (stage, perspective); | ||||
|   clutter_stage_update_view_perspective (stage); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_get_perspective: | ||||
|  * @stage: A #ClutterStage | ||||
| @@ -2520,7 +2396,7 @@ clutter_stage_get_perspective (ClutterStage       *stage, | ||||
|  *              @stage. | ||||
|  * | ||||
|  * Retrieves the @stage's projection matrix. This is derived from the | ||||
|  * current perspective set using clutter_stage_set_perspective(). | ||||
|  * current perspective. | ||||
|  * | ||||
|  * Since: 1.6 | ||||
|  */ | ||||
| @@ -2684,72 +2560,6 @@ _clutter_stage_get_viewport (ClutterStage *stage, | ||||
|   *height = priv->viewport[3]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_show_cursor: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Shows the cursor on the stage window | ||||
|  */ | ||||
| void | ||||
| clutter_stage_show_cursor (ClutterStage *stage) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|   if (!priv->is_cursor_visible) | ||||
|     { | ||||
|       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); | ||||
|       ClutterStageWindowInterface *iface; | ||||
|  | ||||
|       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); | ||||
|       if (iface->set_cursor_visible) | ||||
|         { | ||||
|           priv->is_cursor_visible = TRUE; | ||||
|  | ||||
|           iface->set_cursor_visible (impl, TRUE); | ||||
|  | ||||
|           g_object_notify_by_pspec (G_OBJECT (stage), | ||||
|                                     obj_props[PROP_CURSOR_VISIBLE]); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_hide_cursor: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Makes the cursor invisible on the stage window | ||||
|  * | ||||
|  * Since: 0.4 | ||||
|  */ | ||||
| void | ||||
| clutter_stage_hide_cursor (ClutterStage *stage) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|   if (priv->is_cursor_visible) | ||||
|     { | ||||
|       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); | ||||
|       ClutterStageWindowInterface *iface; | ||||
|  | ||||
|       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); | ||||
|       if (iface->set_cursor_visible) | ||||
|         { | ||||
|           priv->is_cursor_visible = FALSE; | ||||
|  | ||||
|           iface->set_cursor_visible (impl, FALSE); | ||||
|  | ||||
|           g_object_notify_by_pspec (G_OBJECT (stage), | ||||
|                                     obj_props[PROP_CURSOR_VISIBLE]); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_read_pixels: | ||||
|  * @stage: A #ClutterStage | ||||
| @@ -3301,30 +3111,20 @@ clutter_stage_update_view_perspective (ClutterStage *stage) | ||||
|  | ||||
|   perspective = priv->perspective; | ||||
|  | ||||
|   /* Ideally we want to regenerate the perspective matrix whenever | ||||
|    * the size changes but if the user has provided a custom matrix | ||||
|    * then we don't want to override it */ | ||||
|   if (!priv->has_custom_perspective) | ||||
|     { | ||||
|       perspective.fovy = 60.0; /* 60 Degrees */ | ||||
|       perspective.z_near = 0.1; | ||||
|       perspective.aspect = priv->viewport[2] / priv->viewport[3]; | ||||
|       z_2d = calculate_z_translation (perspective.z_near); | ||||
|   perspective.fovy = 60.0; /* 60 Degrees */ | ||||
|   perspective.z_near = 0.1; | ||||
|   perspective.aspect = priv->viewport[2] / priv->viewport[3]; | ||||
|   z_2d = calculate_z_translation (perspective.z_near); | ||||
|  | ||||
|       /* NB: z_2d is only enough room for 85% of the stage_height between | ||||
|        * the stage and the z_near plane. For behind the stage plane we | ||||
|        * want a more consistent gap of 10 times the stage_height before | ||||
|        * hitting the far plane so we calculate that relative to the final | ||||
|        * height of the stage plane at the z_2d_distance we got... */ | ||||
|       perspective.z_far = z_2d + | ||||
|         tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f; | ||||
|   /* NB: z_2d is only enough room for 85% of the stage_height between | ||||
|    * the stage and the z_near plane. For behind the stage plane we | ||||
|    * want a more consistent gap of 10 times the stage_height before | ||||
|    * hitting the far plane so we calculate that relative to the final | ||||
|    * height of the stage plane at the z_2d_distance we got... */ | ||||
|   perspective.z_far = z_2d + | ||||
|     tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f; | ||||
|  | ||||
|       clutter_stage_set_perspective_internal (stage, &perspective); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       z_2d = calculate_z_translation (perspective.z_near); | ||||
|     } | ||||
|   clutter_stage_set_perspective (stage, &perspective); | ||||
|  | ||||
|   cogl_matrix_init_identity (&priv->view); | ||||
|   cogl_matrix_view_2d_in_perspective (&priv->view, | ||||
| @@ -3554,56 +3354,6 @@ clutter_stage_get_throttle_motion_events (ClutterStage *stage) | ||||
|   return stage->priv->throttle_motion_events; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_use_alpha: | ||||
|  * @stage: a #ClutterStage | ||||
|  * @use_alpha: whether the stage should honour the opacity or the | ||||
|  *   alpha channel of the stage color | ||||
|  * | ||||
|  * Sets whether the @stage should honour the #ClutterActor:opacity and | ||||
|  * the alpha channel of the #ClutterStage:color | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  */ | ||||
| void | ||||
| clutter_stage_set_use_alpha (ClutterStage *stage, | ||||
|                              gboolean      use_alpha) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|  | ||||
|   if (priv->use_alpha != use_alpha) | ||||
|     { | ||||
|       priv->use_alpha = use_alpha; | ||||
|  | ||||
|       clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); | ||||
|  | ||||
|       g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_USE_ALPHA]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_get_use_alpha: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Retrieves the value set using clutter_stage_set_use_alpha() | ||||
|  * | ||||
|  * Return value: %TRUE if the stage should honour the opacity and the | ||||
|  *   alpha channel of the stage color | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  */ | ||||
| gboolean | ||||
| clutter_stage_get_use_alpha (ClutterStage *stage) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); | ||||
|  | ||||
|   return stage->priv->use_alpha; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_minimum_size: | ||||
|  * @stage: a #ClutterStage | ||||
| @@ -3950,56 +3700,6 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_accept_focus: | ||||
|  * @stage: a #ClutterStage | ||||
|  * @accept_focus: %TRUE to accept focus on show | ||||
|  * | ||||
|  * Sets whether the @stage should accept the key focus when shown. | ||||
|  * | ||||
|  * This function should be called before showing @stage using | ||||
|  * clutter_actor_show(). | ||||
|  * | ||||
|  * Since: 1.6 | ||||
|  */ | ||||
| void | ||||
| clutter_stage_set_accept_focus (ClutterStage *stage, | ||||
|                                 gboolean      accept_focus) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|  | ||||
|   accept_focus = !!accept_focus; | ||||
|  | ||||
|   priv = stage->priv; | ||||
|  | ||||
|   if (priv->accept_focus != accept_focus) | ||||
|     { | ||||
|       _clutter_stage_window_set_accept_focus (priv->impl, accept_focus); | ||||
|       g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_ACCEPT_FOCUS]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_get_accept_focus: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Retrieves the value set with clutter_stage_set_accept_focus(). | ||||
|  * | ||||
|  * Return value: %TRUE if the #ClutterStage should accept focus, and %FALSE | ||||
|  *   otherwise | ||||
|  * | ||||
|  * Since: 1.6 | ||||
|  */ | ||||
| gboolean | ||||
| clutter_stage_get_accept_focus (ClutterStage *stage) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), TRUE); | ||||
|  | ||||
|   return stage->priv->accept_focus; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_motion_events_enabled: | ||||
|  * @stage: a #ClutterStage | ||||
|   | ||||
| @@ -103,8 +103,7 @@ struct _ClutterStageClass | ||||
|  * @z_far: the distance from the viewer to the far clipping | ||||
|  *   plane (always positive) | ||||
|  * | ||||
|  * Stage perspective definition. #ClutterPerspective is only used by | ||||
|  * the fixed point version of clutter_stage_set_perspective(). | ||||
|  * Stage perspective definition. | ||||
|  * | ||||
|  * Since: 0.4 | ||||
|  */ | ||||
| @@ -140,17 +139,10 @@ GType clutter_stage_get_type (void) G_GNUC_CONST; | ||||
| CLUTTER_EXPORT | ||||
| ClutterActor *  clutter_stage_new                               (void); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_set_perspective                   (ClutterStage          *stage, | ||||
| 			                                         ClutterPerspective    *perspective); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_get_perspective                   (ClutterStage          *stage, | ||||
| 			                                         ClutterPerspective    *perspective); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_show_cursor                       (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_hide_cursor                       (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_set_title                         (ClutterStage          *stage, | ||||
|                                                                  const gchar           *title); | ||||
| CLUTTER_EXPORT | ||||
| @@ -186,11 +178,6 @@ void            clutter_stage_set_motion_events_enabled         (ClutterStage | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_stage_get_motion_events_enabled         (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_set_accept_focus                  (ClutterStage          *stage, | ||||
|                                                                  gboolean               accept_focus); | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_stage_get_accept_focus                  (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_stage_event                             (ClutterStage          *stage, | ||||
|                                                                  ClutterEvent          *event); | ||||
|  | ||||
|   | ||||
| @@ -1907,14 +1907,6 @@ clutter_text_foreach_selection_rectangle (ClutterText              *self, | ||||
|   g_free (utf8); | ||||
| } | ||||
|  | ||||
| static void | ||||
| add_selection_rectangle_to_path (ClutterText           *text, | ||||
|                                  const ClutterActorBox *box, | ||||
|                                  gpointer               user_data) | ||||
| { | ||||
|   cogl_path_rectangle (user_data, box->x1, box->y1, box->x2, box->y2); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_foreach_selection_rectangle_prescaled (ClutterText              *self, | ||||
|                                                     ClutterTextSelectionFunc  func, | ||||
| @@ -1923,6 +1915,60 @@ clutter_text_foreach_selection_rectangle_prescaled (ClutterText              *se | ||||
|   clutter_text_foreach_selection_rectangle (self, 1.0f, func, user_data); | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint_selection_rectangle (ClutterText           *self, | ||||
|                            const ClutterActorBox *box, | ||||
|                            gpointer               user_data) | ||||
| { | ||||
|   CoglFramebuffer *fb = user_data; | ||||
|   ClutterTextPrivate *priv = self->priv; | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (self); | ||||
|   guint8 paint_opacity = clutter_actor_get_paint_opacity (actor); | ||||
|   CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline); | ||||
|   PangoLayout *layout = clutter_text_get_layout (self); | ||||
|   CoglColor cogl_color = { 0, }; | ||||
|   const ClutterColor *color; | ||||
|  | ||||
|   /* Paint selection background */ | ||||
|   if (priv->selection_color_set) | ||||
|     color = &priv->selection_color; | ||||
|   else if (priv->cursor_color_set) | ||||
|     color = &priv->cursor_color; | ||||
|   else | ||||
|     color = &priv->text_color; | ||||
|  | ||||
|   cogl_color_init_from_4ub (&cogl_color, | ||||
|                             color->red, | ||||
|                             color->green, | ||||
|                             color->blue, | ||||
|                             paint_opacity * color->alpha / 255); | ||||
|   cogl_color_premultiply (&cogl_color); | ||||
|   cogl_pipeline_set_color (color_pipeline, &cogl_color); | ||||
|  | ||||
|   cogl_framebuffer_push_rectangle_clip (fb, | ||||
|                                         box->x1, box->y1, | ||||
|                                         box->x2, box->y2); | ||||
|   cogl_framebuffer_draw_rectangle (fb, color_pipeline, | ||||
|                                    box->x1, box->y1, | ||||
|                                    box->x2, box->y2); | ||||
|  | ||||
|   if (priv->selected_text_color_set) | ||||
|     color = &priv->selected_text_color; | ||||
|   else | ||||
|     color = &priv->text_color; | ||||
|  | ||||
|   cogl_color_init_from_4ub (&cogl_color, | ||||
|                             color->red, | ||||
|                             color->green, | ||||
|                             color->blue, | ||||
|                             paint_opacity * color->alpha / 255); | ||||
|  | ||||
|   cogl_pango_show_layout (fb, layout, priv->text_x, 0, &cogl_color); | ||||
|  | ||||
|   cogl_framebuffer_pop_clip (fb); | ||||
|   cogl_object_unref (color_pipeline); | ||||
| } | ||||
|  | ||||
| /* Draws the selected text, its background, and the cursor */ | ||||
| static void | ||||
| selection_paint (ClutterText     *self, | ||||
| @@ -1965,52 +2011,9 @@ selection_paint (ClutterText     *self, | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Paint selection background first */ | ||||
|       CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline); | ||||
|       PangoLayout *layout = clutter_text_get_layout (self); | ||||
|       CoglPath *selection_path = cogl_path_new (); | ||||
|       CoglColor cogl_color = { 0, }; | ||||
|  | ||||
|       /* Paint selection background */ | ||||
|       if (priv->selection_color_set) | ||||
|         color = &priv->selection_color; | ||||
|       else if (priv->cursor_color_set) | ||||
|         color = &priv->cursor_color; | ||||
|       else | ||||
|         color = &priv->text_color; | ||||
|  | ||||
|       cogl_color_init_from_4ub (&cogl_color, | ||||
|                                 color->red, | ||||
|                                 color->green, | ||||
|                                 color->blue, | ||||
|                                 paint_opacity * color->alpha / 255); | ||||
|       cogl_color_premultiply (&cogl_color); | ||||
|       cogl_pipeline_set_color (color_pipeline, &cogl_color); | ||||
|  | ||||
|       clutter_text_foreach_selection_rectangle_prescaled (self, | ||||
|                                                           add_selection_rectangle_to_path, | ||||
|                                                           selection_path); | ||||
|  | ||||
|       cogl_framebuffer_fill_path (fb, color_pipeline, selection_path); | ||||
|  | ||||
|       /* Paint selected text */ | ||||
|       cogl_framebuffer_push_path_clip (fb, selection_path); | ||||
|       cogl_object_unref (selection_path); | ||||
|  | ||||
|       if (priv->selected_text_color_set) | ||||
|         color = &priv->selected_text_color; | ||||
|       else | ||||
|         color = &priv->text_color; | ||||
|  | ||||
|       cogl_color_init_from_4ub (&cogl_color, | ||||
|                                 color->red, | ||||
|                                 color->green, | ||||
|                                 color->blue, | ||||
|                                 paint_opacity * color->alpha / 255); | ||||
|  | ||||
|       cogl_pango_show_layout (fb, layout, priv->text_x, 0, &cogl_color); | ||||
|  | ||||
|       cogl_framebuffer_pop_clip (fb); | ||||
|                                                           paint_selection_rectangle, | ||||
|                                                           fb); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -56,8 +56,6 @@ | ||||
| #include "clutter-content.h" | ||||
| #include "clutter-deform-effect.h" | ||||
| #include "clutter-desaturate-effect.h" | ||||
| #include "clutter-drag-action.h" | ||||
| #include "clutter-drop-action.h" | ||||
| #include "clutter-effect.h" | ||||
| #include "clutter-enums.h" | ||||
| #include "clutter-enum-types.h" | ||||
|   | ||||
| @@ -959,6 +959,20 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl, | ||||
|                                  ClutterStageView *view, | ||||
|                                  CoglScanout      *scanout) | ||||
| { | ||||
|   CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view); | ||||
|   CoglOnscreen *onscreen; | ||||
|  | ||||
|   g_return_if_fail (cogl_is_onscreen (framebuffer)); | ||||
|  | ||||
|   onscreen = COGL_ONSCREEN (framebuffer); | ||||
|   cogl_onscreen_direct_scanout (onscreen, scanout); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) | ||||
| { | ||||
| @@ -971,11 +985,23 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) | ||||
|   for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next) | ||||
|     { | ||||
|       ClutterStageView *view = l->data; | ||||
|       g_autoptr (CoglScanout) scanout = NULL; | ||||
|  | ||||
|       if (!clutter_stage_view_has_redraw_clip (view)) | ||||
|         continue; | ||||
|  | ||||
|       swap_event |= clutter_stage_cogl_redraw_view (stage_window, view); | ||||
|       scanout = clutter_stage_view_take_scanout (view); | ||||
|       if (scanout) | ||||
|         { | ||||
|           clutter_stage_cogl_scanout_view (stage_cogl, | ||||
|                                            view, | ||||
|                                            scanout); | ||||
|           swap_event = TRUE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           swap_event |= clutter_stage_cogl_redraw_view (stage_window, view); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   _clutter_stage_emit_after_paint (stage_cogl->wrapper); | ||||
|   | ||||
| @@ -30,8 +30,6 @@ clutter_headers = [ | ||||
|   'clutter-deform-effect.h', | ||||
|   'clutter-deprecated.h', | ||||
|   'clutter-desaturate-effect.h', | ||||
|   'clutter-drag-action.h', | ||||
|   'clutter-drop-action.h', | ||||
|   'clutter-effect.h', | ||||
|   'clutter-enums.h', | ||||
|   'clutter-event.h', | ||||
| @@ -118,8 +116,6 @@ clutter_sources = [ | ||||
|   'clutter-content.c', | ||||
|   'clutter-deform-effect.c', | ||||
|   'clutter-desaturate-effect.c', | ||||
|   'clutter-drag-action.c', | ||||
|   'clutter-drop-action.c', | ||||
|   'clutter-effect.c', | ||||
|   'clutter-event.c', | ||||
|   'clutter-feature.c', | ||||
| @@ -341,35 +337,20 @@ clutter_build_config_h = configure_file( | ||||
| ) | ||||
| clutter_built_private_headers += clutter_build_config_h | ||||
|  | ||||
| clutter_config_defines = [] | ||||
| cdata = configuration_data() | ||||
| if have_wayland | ||||
|   clutter_config_defines += [ | ||||
|     '#define CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT 1', | ||||
|   ] | ||||
|   cdata.set10('CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT', true) | ||||
| endif | ||||
| if have_x11 | ||||
|   clutter_config_defines += [ | ||||
|     '#define CLUTTER_WINDOWING_X11 "x11"', | ||||
|     '#define CLUTTER_INPUT_X11 "x11"', | ||||
|     '#define CLUTTER_WINDOWING_GLX "glx"', | ||||
|   ] | ||||
|   cdata.set_quoted('CLUTTER_WINDOWING_X11', 'x11') | ||||
|   cdata.set_quoted('CLUTTER_INPUT_X11', 'x11') | ||||
|   cdata.set_quoted('CLUTTER_WINDOWING_GLX', 'glx') | ||||
| endif | ||||
| if have_native_backend | ||||
|   clutter_config_defines += [ | ||||
|     '#define CLUTTER_WINDOWING_EGL "eglnative"', | ||||
|     '#define CLUTTER_INPUT_EVDEV "evdev"', | ||||
|   ] | ||||
|   cdata.set_quoted('CLUTTER_WINDOWING_EGL', 'eglnative') | ||||
|   cdata.set_quoted('CLUTTER_INPUT_EVDEV', 'evdev') | ||||
| endif | ||||
| clutter_config_defines += [ | ||||
|   '#define CLUTTER_INPUT_NULL "null"', | ||||
| ] | ||||
| clutter_config_defines_string = '' | ||||
| foreach clutter_config_define : clutter_config_defines | ||||
|   clutter_config_defines_string += clutter_config_define + '\n' | ||||
| endforeach | ||||
|  | ||||
| cdata = configuration_data() | ||||
| cdata.set('CLUTTER_CONFIG_DEFINES', clutter_config_defines_string) | ||||
| cdata.set_quoted('CLUTTER_INPUT_NULL', 'null') | ||||
|  | ||||
| clutter_config_h = configure_file( | ||||
|   input: 'clutter-config.h.in', | ||||
| @@ -429,7 +410,6 @@ libmutter_clutter = shared_library(libmutter_clutter_name, | ||||
|   link_with: [ | ||||
|     libmutter_cogl, | ||||
|     libmutter_cogl_pango, | ||||
|     libmutter_cogl_path, | ||||
|   ], | ||||
|   install_rpath: pkglibdir, | ||||
|   install_dir: pkglibdir, | ||||
|   | ||||
							
								
								
									
										2
									
								
								cogl/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								cogl/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -36,8 +36,6 @@ cogl-egl-defines.h | ||||
| cogl-enum-types.c | ||||
| cogl-enum-types.h | ||||
| cogl-gl-header.h | ||||
| cogl-path-enum-types.c | ||||
| cogl-path-enum-types.h | ||||
| cogl-config.h | ||||
| cogl-config.h.in | ||||
| cogl-mutter-config.h | ||||
|   | ||||
| @@ -74,7 +74,7 @@ PangoFontMap * | ||||
| cogl_pango_font_map_new (void) | ||||
| { | ||||
|   PangoFontMap *fm = pango_cairo_font_map_new (); | ||||
|   CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1); | ||||
|   g_autofree CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1); | ||||
|  | ||||
|   _COGL_GET_CONTEXT (context, NULL); | ||||
|  | ||||
| @@ -85,7 +85,7 @@ cogl_pango_font_map_new (void) | ||||
|    * for now. */ | ||||
|   g_object_set_qdata_full (G_OBJECT (fm), | ||||
|                            cogl_pango_font_map_get_priv_key (), | ||||
|                            priv, | ||||
|                            g_steal_pointer (&priv), | ||||
|                            free_priv); | ||||
|  | ||||
|   return fm; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ libmutter_cogl_pango = shared_library('mutter-cogl-pango-' + libmutter_api_versi | ||||
|   version: '0.0.0', | ||||
|   soversion: 0, | ||||
|   c_args: cogl_c_args, | ||||
|   include_directories: [cogl_includepath, cogl_path_includepath], | ||||
|   include_directories: [cogl_includepath], | ||||
|   gnu_symbol_visibility: 'hidden', | ||||
|   dependencies: [cogl_pango_deps], | ||||
|   install_rpath: pkglibdir, | ||||
|   | ||||
| @@ -1,48 +0,0 @@ | ||||
| /*** BEGIN file-header ***/ | ||||
| #include "cogl-config.h" | ||||
|  | ||||
| /* We need to undefine this so that we will be sure to include | ||||
|  * cogl-path.h instead of cogl2-path.h when we include the framebuffer | ||||
|  * header. Otherwise it will include both headers and it won't | ||||
|  * compile. */ | ||||
| #undef COGL_ENABLE_EXPERIMENTAL_2_0_API | ||||
|  | ||||
| #include "cogl-path-enum-types.h" | ||||
| /*** END file-header ***/ | ||||
|  | ||||
| /*** BEGIN file-production ***/ | ||||
|  | ||||
| /* enumerations from "@filename@" */ | ||||
| #include "@filename@" | ||||
|  | ||||
| /*** END file-production ***/ | ||||
|  | ||||
| /*** BEGIN value-header ***/ | ||||
| GType | ||||
| @enum_name@_get_type (void) | ||||
| { | ||||
|   static volatile gsize g_enum_type_id__volatile = 0; | ||||
|  | ||||
|   if (g_once_init_enter (&g_enum_type_id__volatile)) | ||||
|     { | ||||
|       static const G@Type@Value values[] = { | ||||
| /*** END value-header ***/ | ||||
|  | ||||
| /*** BEGIN value-production ***/ | ||||
|         { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, | ||||
| /*** END value-production ***/ | ||||
|  | ||||
| /*** BEGIN value-tail ***/ | ||||
|         { 0, NULL, NULL } | ||||
|       }; | ||||
|       GType g_enum_type_id; | ||||
|  | ||||
|       g_enum_type_id = | ||||
|         g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); | ||||
|  | ||||
|       g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id); | ||||
|     } | ||||
|  | ||||
|   return g_enum_type_id__volatile; | ||||
| } | ||||
| /*** END value-tail ***/ | ||||
| @@ -1,25 +0,0 @@ | ||||
| /*** BEGIN file-header ***/ | ||||
| #ifndef __COGL_PATH_ENUM_TYPES_H__ | ||||
| #define __COGL_PATH_ENUM_TYPES_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /*** END file-header ***/ | ||||
|  | ||||
| /*** BEGIN file-production ***/ | ||||
| /* enumerations from "@basename@" */ | ||||
| /*** END file-production ***/ | ||||
|  | ||||
| /*** BEGIN file-tail ***/ | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __COGL_PATH_ENUM_TYPES_H__ */ | ||||
| /*** END file-tail ***/ | ||||
|  | ||||
| /*** BEGIN value-header ***/ | ||||
| GType @enum_name@_get_type (void) G_GNUC_CONST; | ||||
| #define COGL_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) | ||||
|  | ||||
| /*** END value-header ***/ | ||||
| @@ -1,487 +0,0 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2008,2009,2013 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) | ||||
| #error "Only <cogl/cogl.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __COGL_PATH_FUNCTIONS_H__ | ||||
| #define __COGL_PATH_FUNCTIONS_H__ | ||||
|  | ||||
| #include <cogl/cogl-types.h> | ||||
| #ifdef COGL_COMPILATION | ||||
| #include "cogl-context.h" | ||||
| #else | ||||
| #include <cogl/cogl.h> | ||||
| #endif | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /** | ||||
|  * cogl_path_get_gtype: | ||||
|  * | ||||
|  * Returns: a #GType that can be used with the GLib type system. | ||||
|  */ | ||||
| COGL_EXPORT | ||||
| GType cogl_path_get_gtype (void); | ||||
|  | ||||
| #define cogl_path_new cogl2_path_new | ||||
| /** | ||||
|  * cogl_path_new: | ||||
|  * | ||||
|  * Creates a new, empty path object. The default fill rule is | ||||
|  * %COGL_PATH_FILL_RULE_EVEN_ODD. | ||||
|  * | ||||
|  * Return value: A pointer to a newly allocated #CoglPath, which can | ||||
|  * be freed using cogl_object_unref(). | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT CoglPath * | ||||
| cogl_path_new (void); | ||||
|  | ||||
| /** | ||||
|  * cogl_path_copy: | ||||
|  * @path: A #CoglPath object | ||||
|  * | ||||
|  * Returns a new copy of the path in @path. The new path has a | ||||
|  * reference count of 1 so you should unref it with | ||||
|  * cogl_object_unref() if you no longer need it. | ||||
|  * | ||||
|  * Internally the path will share the data until one of the paths is | ||||
|  * modified so copying paths should be relatively cheap. | ||||
|  * | ||||
|  * Return value: (transfer full): a copy of the path in @path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT CoglPath * | ||||
| cogl_path_copy (CoglPath *path); | ||||
|  | ||||
| /** | ||||
|  * cogl_is_path: | ||||
|  * @object: A #CoglObject | ||||
|  * | ||||
|  * Gets whether the given object references an existing path object. | ||||
|  * | ||||
|  * Return value: %TRUE if the object references a #CoglPath, | ||||
|  *   %FALSE otherwise. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT gboolean | ||||
| cogl_is_path (void *object); | ||||
|  | ||||
| #define cogl_path_move_to cogl2_path_move_to | ||||
| /** | ||||
|  * cogl_path_move_to: | ||||
|  * @x: X coordinate of the pen location to move to. | ||||
|  * @y: Y coordinate of the pen location to move to. | ||||
|  * | ||||
|  * Moves the pen to the given location. If there is an existing path | ||||
|  * this will start a new disjoint subpath. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_move_to (CoglPath *path, | ||||
|                    float x, | ||||
|                    float y); | ||||
|  | ||||
| #define cogl_path_rel_move_to cogl2_path_rel_move_to | ||||
| /** | ||||
|  * cogl_path_rel_move_to: | ||||
|  * @x: X offset from the current pen location to move the pen to. | ||||
|  * @y: Y offset from the current pen location to move the pen to. | ||||
|  * | ||||
|  * Moves the pen to the given offset relative to the current pen | ||||
|  * location. If there is an existing path this will start a new | ||||
|  * disjoint subpath. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_rel_move_to (CoglPath *path, | ||||
|                        float x, | ||||
|                        float y); | ||||
|  | ||||
| #define cogl_path_line_to cogl2_path_line_to | ||||
| /** | ||||
|  * cogl_path_line_to: | ||||
|  * @x: X coordinate of the end line vertex | ||||
|  * @y: Y coordinate of the end line vertex | ||||
|  * | ||||
|  * Adds a straight line segment to the current path that ends at the | ||||
|  * given coordinates. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_line_to (CoglPath *path, | ||||
|                    float x, | ||||
|                    float y); | ||||
|  | ||||
| #define cogl_path_rel_line_to cogl2_path_rel_line_to | ||||
| /** | ||||
|  * cogl_path_rel_line_to: | ||||
|  * @x: X offset from the current pen location of the end line vertex | ||||
|  * @y: Y offset from the current pen location of the end line vertex | ||||
|  * | ||||
|  * Adds a straight line segment to the current path that ends at the | ||||
|  * given coordinates relative to the current pen location. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_rel_line_to (CoglPath *path, | ||||
|                        float x, | ||||
|                        float y); | ||||
|  | ||||
| #define cogl_path_arc cogl2_path_arc | ||||
| /** | ||||
|  * cogl_path_arc: | ||||
|  * @center_x: X coordinate of the elliptical arc center | ||||
|  * @center_y: Y coordinate of the elliptical arc center | ||||
|  * @radius_x: X radius of the elliptical arc | ||||
|  * @radius_y: Y radius of the elliptical arc | ||||
|  * @angle_1: Angle in degrees at which the arc begin | ||||
|  * @angle_2: Angle in degrees at which the arc ends | ||||
|  * | ||||
|  * Adds an elliptical arc segment to the current path. A straight line | ||||
|  * segment will link the current pen location with the first vertex | ||||
|  * of the arc. If you perform a move_to to the arcs start just before | ||||
|  * drawing it you create a free standing arc. | ||||
|  * | ||||
|  * The angles are measured in degrees where 0° is in the direction of | ||||
|  * the positive X axis and 90° is in the direction of the positive Y | ||||
|  * axis. The angle of the arc begins at @angle_1 and heads towards | ||||
|  * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease, | ||||
|  * otherwise it will increase). | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_arc (CoglPath *path, | ||||
|                float center_x, | ||||
|                float center_y, | ||||
|                float radius_x, | ||||
|                float radius_y, | ||||
|                float angle_1, | ||||
|                float angle_2); | ||||
|  | ||||
| #define cogl_path_curve_to cogl2_path_curve_to | ||||
| /** | ||||
|  * cogl_path_curve_to: | ||||
|  * @x_1: X coordinate of the second bezier control point | ||||
|  * @y_1: Y coordinate of the second bezier control point | ||||
|  * @x_2: X coordinate of the third bezier control point | ||||
|  * @y_2: Y coordinate of the third bezier control point | ||||
|  * @x_3: X coordinate of the fourth bezier control point | ||||
|  * @y_3: Y coordinate of the fourth bezier control point | ||||
|  * | ||||
|  * Adds a cubic bezier curve segment to the current path with the given | ||||
|  * second, third and fourth control points and using current pen location | ||||
|  * as the first control point. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_curve_to (CoglPath *path, | ||||
|                     float x_1, | ||||
|                     float y_1, | ||||
|                     float x_2, | ||||
|                     float y_2, | ||||
|                     float x_3, | ||||
|                     float y_3); | ||||
|  | ||||
| #define cogl_path_rel_curve_to cogl2_path_rel_curve_to | ||||
| /** | ||||
|  * cogl_path_rel_curve_to: | ||||
|  * @x_1: X coordinate of the second bezier control point | ||||
|  * @y_1: Y coordinate of the second bezier control point | ||||
|  * @x_2: X coordinate of the third bezier control point | ||||
|  * @y_2: Y coordinate of the third bezier control point | ||||
|  * @x_3: X coordinate of the fourth bezier control point | ||||
|  * @y_3: Y coordinate of the fourth bezier control point | ||||
|  * | ||||
|  * Adds a cubic bezier curve segment to the current path with the given | ||||
|  * second, third and fourth control points and using current pen location | ||||
|  * as the first control point. The given coordinates are relative to the | ||||
|  * current pen location. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_rel_curve_to (CoglPath *path, | ||||
|                         float x_1, | ||||
|                         float y_1, | ||||
|                         float x_2, | ||||
|                         float y_2, | ||||
|                         float x_3, | ||||
|                         float y_3); | ||||
|  | ||||
| #define cogl_path_close cogl2_path_close | ||||
| /** | ||||
|  * cogl_path_close: | ||||
|  * | ||||
|  * Closes the path being constructed by adding a straight line segment | ||||
|  * to it that ends at the first vertex of the path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_close (CoglPath *path); | ||||
|  | ||||
| #define cogl_path_line cogl2_path_line | ||||
| /** | ||||
|  * cogl_path_line: | ||||
|  * @x_1: X coordinate of the start line vertex | ||||
|  * @y_1: Y coordinate of the start line vertex | ||||
|  * @x_2: X coordinate of the end line vertex | ||||
|  * @y_2: Y coordinate of the end line vertex | ||||
|  * | ||||
|  * Constructs a straight line shape starting and ending at the given | ||||
|  * coordinates. If there is an existing path this will start a new | ||||
|  * disjoint sub-path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_line (CoglPath *path, | ||||
|                 float x_1, | ||||
|                 float y_1, | ||||
|                 float x_2, | ||||
|                 float y_2); | ||||
|  | ||||
| #define cogl_path_polyline cogl2_path_polyline | ||||
| /** | ||||
|  * cogl_path_polyline: | ||||
|  * @coords: (in) (array) (transfer none): A pointer to the first element of an | ||||
|  * array of fixed-point values that specify the vertex coordinates. | ||||
|  * @num_points: The total number of vertices. | ||||
|  * | ||||
|  * Constructs a series of straight line segments, starting from the | ||||
|  * first given vertex coordinate. If there is an existing path this | ||||
|  * will start a new disjoint sub-path. Each subsequent segment starts | ||||
|  * where the previous one ended and ends at the next given vertex | ||||
|  * coordinate. | ||||
|  * | ||||
|  * The coords array must contain 2 * num_points values. The first value | ||||
|  * represents the X coordinate of the first vertex, the second value | ||||
|  * represents the Y coordinate of the first vertex, continuing in the same | ||||
|  * fashion for the rest of the vertices. (num_points - 1) segments will | ||||
|  * be constructed. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_polyline (CoglPath *path, | ||||
|                     const float *coords, | ||||
|                     int num_points); | ||||
|  | ||||
| #define cogl_path_polygon cogl2_path_polygon | ||||
| /** | ||||
|  * cogl_path_polygon: | ||||
|  * @coords: (in) (array) (transfer none): A pointer to the first element of | ||||
|  * an array of fixed-point values that specify the vertex coordinates. | ||||
|  * @num_points: The total number of vertices. | ||||
|  * | ||||
|  * Constructs a polygonal shape of the given number of vertices. If | ||||
|  * there is an existing path this will start a new disjoint sub-path. | ||||
|  * | ||||
|  * The coords array must contain 2 * num_points values. The first value | ||||
|  * represents the X coordinate of the first vertex, the second value | ||||
|  * represents the Y coordinate of the first vertex, continuing in the same | ||||
|  * fashion for the rest of the vertices. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_polygon (CoglPath *path, | ||||
|                    const float *coords, | ||||
|                    int num_points); | ||||
|  | ||||
| #define cogl_path_rectangle cogl2_path_rectangle | ||||
| /** | ||||
|  * cogl_path_rectangle: | ||||
|  * @x_1: X coordinate of the top-left corner. | ||||
|  * @y_1: Y coordinate of the top-left corner. | ||||
|  * @x_2: X coordinate of the bottom-right corner. | ||||
|  * @y_2: Y coordinate of the bottom-right corner. | ||||
|  * | ||||
|  * Constructs a rectangular shape at the given coordinates. If there | ||||
|  * is an existing path this will start a new disjoint sub-path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_rectangle (CoglPath *path, | ||||
|                      float x_1, | ||||
|                      float y_1, | ||||
|                      float x_2, | ||||
|                      float y_2); | ||||
|  | ||||
| #define cogl_path_ellipse cogl2_path_ellipse | ||||
| /** | ||||
|  * cogl_path_ellipse: | ||||
|  * @center_x: X coordinate of the ellipse center | ||||
|  * @center_y: Y coordinate of the ellipse center | ||||
|  * @radius_x: X radius of the ellipse | ||||
|  * @radius_y: Y radius of the ellipse | ||||
|  * | ||||
|  * Constructs an ellipse shape. If there is an existing path this will | ||||
|  * start a new disjoint sub-path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_ellipse (CoglPath *path, | ||||
|                    float center_x, | ||||
|                    float center_y, | ||||
|                    float radius_x, | ||||
|                    float radius_y); | ||||
|  | ||||
| #define cogl_path_round_rectangle cogl2_path_round_rectangle | ||||
| /** | ||||
|  * cogl_path_round_rectangle: | ||||
|  * @x_1: X coordinate of the top-left corner. | ||||
|  * @y_1: Y coordinate of the top-left corner. | ||||
|  * @x_2: X coordinate of the bottom-right corner. | ||||
|  * @y_2: Y coordinate of the bottom-right corner. | ||||
|  * @radius: Radius of the corner arcs. | ||||
|  * @arc_step: Angle increment resolution for subdivision of | ||||
|  * the corner arcs. | ||||
|  * | ||||
|  * Constructs a rectangular shape with rounded corners. If there is an | ||||
|  * existing path this will start a new disjoint sub-path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_round_rectangle (CoglPath *path, | ||||
|                            float x_1, | ||||
|                            float y_1, | ||||
|                            float x_2, | ||||
|                            float y_2, | ||||
|                            float radius, | ||||
|                            float arc_step); | ||||
|  | ||||
| #define cogl_path_set_fill_rule cogl2_path_set_fill_rule | ||||
| /** | ||||
|  * cogl_path_set_fill_rule: | ||||
|  * @fill_rule: The new fill rule. | ||||
|  * | ||||
|  * Sets the fill rule of the current path to @fill_rule. This will | ||||
|  * affect how the path is filled when cogl_path_fill() is later | ||||
|  * called. Note that the fill rule state is attached to the path so | ||||
|  * calling cogl_get_path() will preserve the fill rule and calling | ||||
|  * cogl_path_new() will reset the fill rule back to the default. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_path_set_fill_rule (CoglPath *path, CoglPathFillRule fill_rule); | ||||
|  | ||||
| #define cogl_path_get_fill_rule cogl2_path_get_fill_rule | ||||
| /** | ||||
|  * cogl_path_get_fill_rule: | ||||
|  * | ||||
|  * Retrieves the fill rule set using cogl_path_set_fill_rule(). | ||||
|  * | ||||
|  * Return value: the fill rule that is used for the current path. | ||||
|  * | ||||
|  * Since: 2.0 | ||||
|  */ | ||||
| COGL_EXPORT CoglPathFillRule | ||||
| cogl_path_get_fill_rule (CoglPath *path); | ||||
|  | ||||
| /** | ||||
|  * cogl_framebuffer_fill_path: | ||||
|  * @framebuffer: A #CoglFramebuffer | ||||
|  * @pipeline: A #CoglPipeline to render with | ||||
|  * @path: The #CoglPath to fill | ||||
|  * | ||||
|  * Fills the interior of the path using the fragment operations | ||||
|  * defined by the pipeline. | ||||
|  * | ||||
|  * The interior of the shape is determined using the fill rule of the | ||||
|  * path. See %CoglPathFillRule for details. | ||||
|  * | ||||
|  * <note>The result of referencing sliced textures in your current | ||||
|  * pipeline when filling a path are undefined. You should pass | ||||
|  * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will | ||||
|  * use while filling a path.</note> | ||||
|  * | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer, | ||||
|                             CoglPipeline *pipeline, | ||||
|                             CoglPath *path); | ||||
|  | ||||
| /** | ||||
|  * cogl_framebuffer_stroke_path: | ||||
|  * @framebuffer: A #CoglFramebuffer | ||||
|  * @pipeline: A #CoglPipeline to render with | ||||
|  * @path: The #CoglPath to stroke | ||||
|  * | ||||
|  * Strokes the edge of the path using the fragment operations defined | ||||
|  * by the pipeline. The stroke line will have a width of 1 pixel | ||||
|  * regardless of the current transformation matrix. | ||||
|  * | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer, | ||||
|                               CoglPipeline *pipeline, | ||||
|                               CoglPath *path); | ||||
|  | ||||
| /** | ||||
|  * cogl_framebuffer_push_path_clip: | ||||
|  * @framebuffer: A #CoglFramebuffer pointer | ||||
|  * @path: The path to clip with. | ||||
|  * | ||||
|  * Sets a new clipping area using the silhouette of the specified, | ||||
|  * filled @path.  The clipping area is intersected with the previous | ||||
|  * clipping area. To restore the previous clipping area, call | ||||
|  * cogl_framebuffer_pop_clip(). | ||||
|  * | ||||
|  * Since: 1.0 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer, | ||||
|                                  CoglPath *path); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __COGL_PATH_FUNCTIONS_H__ */ | ||||
|  | ||||
| @@ -1,126 +0,0 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2010 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef __COGL_PATH_PRIVATE_H | ||||
| #define __COGL_PATH_PRIVATE_H | ||||
|  | ||||
| #include "cogl-object.h" | ||||
| #include "cogl-attribute-private.h" | ||||
|  | ||||
| typedef struct _floatVec2 | ||||
| { | ||||
|   float x; | ||||
|   float y; | ||||
| } floatVec2; | ||||
|  | ||||
| typedef struct _CoglPathNode | ||||
| { | ||||
|   float x; | ||||
|   float y; | ||||
|   unsigned int path_size; | ||||
| } CoglPathNode; | ||||
|  | ||||
| typedef struct _CoglBezQuad | ||||
| { | ||||
|   floatVec2 p1; | ||||
|   floatVec2 p2; | ||||
|   floatVec2 p3; | ||||
| } CoglBezQuad; | ||||
|  | ||||
| typedef struct _CoglBezCubic | ||||
| { | ||||
|   floatVec2 p1; | ||||
|   floatVec2 p2; | ||||
|   floatVec2 p3; | ||||
|   floatVec2 p4; | ||||
| } CoglBezCubic; | ||||
|  | ||||
| typedef struct _CoglPathData CoglPathData; | ||||
|  | ||||
| struct _CoglPath | ||||
| { | ||||
|   CoglObject _parent; | ||||
|  | ||||
|   CoglPathData *data; | ||||
| }; | ||||
|  | ||||
| #define COGL_PATH_N_ATTRIBUTES 2 | ||||
|  | ||||
| struct _CoglPathData | ||||
| { | ||||
|   unsigned int         ref_count; | ||||
|  | ||||
|   CoglContext         *context; | ||||
|  | ||||
|   CoglPathFillRule     fill_rule; | ||||
|  | ||||
|   GArray              *path_nodes; | ||||
|  | ||||
|   floatVec2            path_start; | ||||
|   floatVec2            path_pen; | ||||
|   unsigned int         last_path; | ||||
|   floatVec2            path_nodes_min; | ||||
|   floatVec2            path_nodes_max; | ||||
|  | ||||
|   CoglAttributeBuffer *fill_attribute_buffer; | ||||
|   CoglIndices         *fill_vbo_indices; | ||||
|   unsigned int         fill_vbo_n_indices; | ||||
|   CoglAttribute       *fill_attributes[COGL_PATH_N_ATTRIBUTES + 1]; | ||||
|   CoglPrimitive       *fill_primitive; | ||||
|  | ||||
|   CoglAttributeBuffer *stroke_attribute_buffer; | ||||
|   CoglAttribute      **stroke_attributes; | ||||
|   unsigned int         stroke_n_attributes; | ||||
|  | ||||
|   /* This is used as an optimisation for when the path contains a | ||||
|      single contour specified using cogl2_path_rectangle. Cogl is more | ||||
|      optimised to handle rectangles than paths so we can detect this | ||||
|      case and divert to the journal or a rectangle clip. If it is TRUE | ||||
|      then the entire path can be described by calling | ||||
|      _cogl_path_get_bounds */ | ||||
|   gboolean             is_rectangle; | ||||
| }; | ||||
|  | ||||
| void | ||||
| _cogl_add_path_to_stencil_buffer (CoglPath  *path, | ||||
|                                   gboolean   merge, | ||||
|                                   gboolean   need_clear); | ||||
|  | ||||
| void | ||||
| _cogl_path_get_bounds (CoglPath *path, | ||||
|                        float *min_x, | ||||
|                        float *min_y, | ||||
|                        float *max_x, | ||||
|                        float *max_y); | ||||
|  | ||||
| gboolean | ||||
| _cogl_path_is_rectangle (CoglPath *path); | ||||
|  | ||||
| #endif /* __COGL_PATH_PRIVATE_H */ | ||||
| @@ -1,86 +0,0 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2008,2009,2013 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) | ||||
| #error "Only <cogl/cogl.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __COGL_PATH_TYPES_H__ | ||||
| #define __COGL_PATH_TYPES_H__ | ||||
|  | ||||
| #include <cogl/cogl-types.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _CoglPath CoglPath; | ||||
|  | ||||
| /** | ||||
|  * CoglPathFillRule: | ||||
|  * @COGL_PATH_FILL_RULE_NON_ZERO: Each time the line crosses an edge of | ||||
|  * the path from left to right one is added to a counter and each time | ||||
|  * it crosses from right to left the counter is decremented. If the | ||||
|  * counter is non-zero then the point will be filled. See <xref | ||||
|  * linkend="fill-rule-non-zero"/>. | ||||
|  * @COGL_PATH_FILL_RULE_EVEN_ODD: If the line crosses an edge of the | ||||
|  * path an odd number of times then the point will filled, otherwise | ||||
|  * it won't. See <xref linkend="fill-rule-even-odd"/>. | ||||
|  * | ||||
|  * #CoglPathFillRule is used to determine how a path is filled. There | ||||
|  * are two options - 'non-zero' and 'even-odd'. To work out whether any | ||||
|  * point will be filled imagine drawing an infinetely long line in any | ||||
|  * direction from that point. The number of times and the direction | ||||
|  * that the edges of the path crosses this line determines whether the | ||||
|  * line is filled as described below. Any open sub paths are treated | ||||
|  * as if there was an extra line joining the first point and the last | ||||
|  * point. | ||||
|  * | ||||
|  * The default fill rule when creating a path is %COGL_PATH_FILL_RULE_EVEN_ODD. | ||||
|  * | ||||
|  * <figure id="fill-rule-non-zero"> | ||||
|  *   <title>Example of filling various paths using the non-zero rule</title> | ||||
|  *   <graphic fileref="fill-rule-non-zero.png" format="PNG"/> | ||||
|  * </figure> | ||||
|  * | ||||
|  * <figure id="fill-rule-even-odd"> | ||||
|  *   <title>Example of filling various paths using the even-odd rule</title> | ||||
|  *   <graphic fileref="fill-rule-even-odd.png" format="PNG"/> | ||||
|  * </figure> | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| typedef enum | ||||
| { | ||||
|   COGL_PATH_FILL_RULE_NON_ZERO, | ||||
|   COGL_PATH_FILL_RULE_EVEN_ODD | ||||
| } CoglPathFillRule; | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __COGL_PATH_TYPES_H__ */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,60 +0,0 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2008,2009,2013 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef __COGL_PATH_H__ | ||||
| #define __COGL_PATH_H__ | ||||
|  | ||||
| /** | ||||
|  * SECTION:cogl-paths | ||||
|  * @short_description: Functions for constructing and drawing 2D paths. | ||||
|  * | ||||
|  * There are two levels on which drawing with cogl-paths can be used. | ||||
|  * The highest level functions construct various simple primitive | ||||
|  * shapes to be either filled or stroked. Using a lower-level set of | ||||
|  * functions more complex and arbitrary paths can be constructed by | ||||
|  * concatenating straight line, bezier curve and arc segments. | ||||
|  * | ||||
|  * When constructing arbitrary paths, the current pen location is | ||||
|  * initialized using the move_to command. The subsequent path segments | ||||
|  * implicitly use the last pen location as their first vertex and move | ||||
|  * the pen location to the last vertex they produce at the end. Also | ||||
|  * there are special versions of functions that allow specifying the | ||||
|  * vertices of the path segments relative to the last pen location | ||||
|  * rather then in the absolute coordinates. | ||||
|  */ | ||||
|  | ||||
| #include <cogl/cogl-defines.h> | ||||
|  | ||||
| #include <cogl-path/cogl-path-enum-types.h> | ||||
| #include <cogl-path/cogl-path-types.h> | ||||
| #include <cogl-path/cogl-path-functions.h> | ||||
|  | ||||
| #endif /* __COGL_PATH_H__ */ | ||||
|  | ||||
| @@ -1,59 +0,0 @@ | ||||
| /* cogl1-path-functions.h */ | ||||
| cogl_clip_push_from_path | ||||
| cogl_clip_push_from_path_preserve | ||||
| cogl_get_path | ||||
| cogl_is_path | ||||
| cogl_path_arc | ||||
| cogl_path_close | ||||
| cogl_path_copy | ||||
| cogl_path_curve_to | ||||
| cogl_path_ellipse | ||||
| cogl_path_fill | ||||
| cogl_path_fill_preserve | ||||
| cogl_path_get_fill_rule | ||||
| #ifdef COGL_HAS_GTYPE_SUPPORT | ||||
| cogl_path_get_gtype | ||||
| #endif | ||||
| cogl_path_line | ||||
| cogl_path_line_to | ||||
| cogl_path_move_to | ||||
| cogl_path_new | ||||
| cogl_path_polygon | ||||
| cogl_path_polyline | ||||
| cogl_path_rectangle | ||||
| cogl_path_rel_curve_to | ||||
| cogl_path_rel_line_to | ||||
| cogl_path_rel_move_to | ||||
| cogl_path_round_rectangle | ||||
| cogl_path_set_fill_rule | ||||
| cogl_path_stroke | ||||
| cogl_path_stroke_preserve | ||||
| cogl_set_path | ||||
|  | ||||
| /* cogl2-path-functions.h */ | ||||
| cogl_framebuffer_fill_path | ||||
| cogl_framebuffer_push_path_clip | ||||
| cogl_framebuffer_stroke_path | ||||
| cogl2_clip_push_from_path | ||||
| cogl2_path_arc | ||||
| cogl2_path_close | ||||
| cogl2_path_curve_to | ||||
| cogl2_path_ellipse | ||||
| cogl2_path_fill | ||||
| cogl2_path_get_fill_rule | ||||
| cogl2_path_line | ||||
| cogl2_path_line_to | ||||
| cogl2_path_move_to | ||||
| cogl2_path_new | ||||
| cogl2_path_polygon | ||||
| cogl2_path_polyline | ||||
| cogl2_path_rectangle | ||||
| cogl2_path_rel_curve_to | ||||
| cogl2_path_rel_line_to | ||||
| cogl2_path_rel_move_to | ||||
| cogl2_path_round_rectangle | ||||
| cogl2_path_set_fill_rule | ||||
| cogl2_path_stroke | ||||
|  | ||||
| /* cogl-path-enums.h-contents may change as header is generated */ | ||||
| cogl_path_fill_rule_get_type | ||||
| @@ -1,87 +0,0 @@ | ||||
| cogl_path_includesubdir = join_paths(cogl_includesubdir, 'cogl-path') | ||||
| cogl_path_includedir = join_paths(cogl_includedir, 'cogl-path') | ||||
|  | ||||
| cogl_path_public_headers = [ | ||||
|   'cogl-path.h', | ||||
|   'cogl-path-functions.h', | ||||
|   'cogl-path-types.h', | ||||
| ] | ||||
|  | ||||
| cogl_path_sources = [ | ||||
|   'cogl-path.c', | ||||
|   'cogl-path-private.h', | ||||
|   'tesselator/dict-list.h', | ||||
|   'tesselator/dict.c', | ||||
|   'tesselator/dict.h', | ||||
|   'tesselator/geom.c', | ||||
|   'tesselator/geom.h', | ||||
|   'tesselator/gluos.h', | ||||
|   'tesselator/memalloc.h', | ||||
|   'tesselator/mesh.c', | ||||
|   'tesselator/mesh.h', | ||||
|   'tesselator/normal.c', | ||||
|   'tesselator/normal.h', | ||||
|   'tesselator/priorityq-heap.h', | ||||
|   'tesselator/priorityq-sort.h', | ||||
|   'tesselator/priorityq.c', | ||||
|   'tesselator/priorityq.h', | ||||
|   'tesselator/render.c', | ||||
|   'tesselator/render.h', | ||||
|   'tesselator/sweep.c', | ||||
|   'tesselator/sweep.h', | ||||
|   'tesselator/tess.c', | ||||
|   'tesselator/tess.h', | ||||
|   'tesselator/tesselator.h', | ||||
|   'tesselator/tessmono.c', | ||||
|   'tesselator/tessmono.h', | ||||
| ] | ||||
|  | ||||
| cogl_path_includepath = include_directories('.') | ||||
|  | ||||
| libmutter_cogl_path_enum_types = gnome.mkenums('cogl-path-enum-types', | ||||
|   sources: 'cogl-path-types.h', | ||||
|   c_template: 'cogl-path-enum-types.c.in', | ||||
|   h_template: 'cogl-path-enum-types.h.in', | ||||
|   install_dir: cogl_path_includedir, | ||||
|   install_header: true, | ||||
| ) | ||||
| libmutter_cogl_path_enum_types_h = libmutter_cogl_path_enum_types[1] | ||||
|  | ||||
| cogl_path_sources += libmutter_cogl_path_enum_types | ||||
|  | ||||
| cogl_path_c_args = [ | ||||
|   cogl_c_args, | ||||
| ] | ||||
|  | ||||
| libmutter_cogl_path = shared_library('mutter-cogl-path-' + libmutter_api_version, | ||||
|   sources: [cogl_path_sources, cogl_path_public_headers], | ||||
|   version: '0.0.0', | ||||
|   soversion: 0, | ||||
|   c_args: cogl_path_c_args, | ||||
|   include_directories: [cogl_includepath, cogl_path_includepath], | ||||
|   gnu_symbol_visibility: 'hidden', | ||||
|   dependencies: libmutter_cogl_dep, | ||||
|   install_rpath: pkglibdir, | ||||
|   install_dir: pkglibdir, | ||||
|   install: true, | ||||
| ) | ||||
| libmutter_cogl_path_dep = declare_dependency( | ||||
|   sources: [libmutter_cogl_path_enum_types_h], | ||||
|   link_with: libmutter_cogl_path | ||||
| ) | ||||
|  | ||||
| install_headers(cogl_path_public_headers, | ||||
|   subdir: cogl_path_includesubdir) | ||||
|  | ||||
| pkg.generate(libmutter_cogl_path, | ||||
|   name: 'CoglPath', | ||||
|   filebase: 'mutter-cogl-path-' + libmutter_api_version, | ||||
|   description: 'A 2D path drawing library for Cogl in mutter', | ||||
|   subdirs: join_paths(pkgname, 'cogl'), | ||||
|   requires: [cogl_pkg_deps, libmutter_cogl_name], | ||||
|   version: meson.project_version(), | ||||
|   variables: [ | ||||
|     'apiversion=' + libmutter_api_version, | ||||
|   ], | ||||
|   install_dir: pcdir, | ||||
| ) | ||||
| @@ -1,13 +0,0 @@ | ||||
| prefix=@prefix@ | ||||
| exec_prefix=@exec_prefix@ | ||||
| apiversion=@LIBMUTTER_API_VERSION@ | ||||
| libdir=@libdir@/mutter-${apiversion} | ||||
| includedir=@includedir@/mutter-${apiversion} | ||||
| requires=@COGL_PKG_REQUIRES@ mutter-cogl-${apiversion} | ||||
|  | ||||
| Name: Cogl | ||||
| Description: A 2D path drawing library for Cogl | ||||
| Version: @MUTTER_VERSION@ | ||||
| Libs: -L${libdir} -lmutter-cogl-path-${apiversion} | ||||
| Cflags: -I${includedir}/cogl | ||||
| Requires: ${requires} | ||||
| @@ -1,446 +0,0 @@ | ||||
| /* | ||||
| */ | ||||
|  | ||||
| General Polygon Tesselation | ||||
| --------------------------- | ||||
|  | ||||
|   This note describes a tesselator for polygons consisting of one or | ||||
|   more closed contours.  It is backward-compatible with the current | ||||
|   OpenGL Utilities tesselator, and is intended to replace it.  Here is | ||||
|   a summary of the major differences: | ||||
|  | ||||
|    - input contours can be intersecting, self-intersecting, or degenerate. | ||||
|    | ||||
|    - supports a choice of several winding rules for determining which parts | ||||
|      of the polygon are on the "interior".  This makes it possible to do | ||||
|      CSG operations on polygons. | ||||
|    | ||||
|    - boundary extraction: instead of tesselating the polygon, returns a | ||||
|      set of closed contours which separate the interior from the exterior. | ||||
|    | ||||
|    - returns the output as a small number of triangle fans and strips, | ||||
|      rather than a list of independent triangles (when possible). | ||||
|    | ||||
|    - output is available as an explicit mesh (a quad-edge structure), | ||||
|      in addition to the normal callback interface. | ||||
|    | ||||
|    - the algorithm used is extremely robust. | ||||
|  | ||||
|  | ||||
| The interface | ||||
| ------------- | ||||
|  | ||||
|   The tesselator state is maintained in a "tesselator object". | ||||
|   These are allocated and destroyed using | ||||
|  | ||||
|      GLUtesselator *gluNewTess( void ); | ||||
|      void gluDeleteTess( GLUtesselator *tess ); | ||||
|  | ||||
|   Several tesselator objects may be used simultaneously. | ||||
|  | ||||
|   Inputs | ||||
|   ------ | ||||
|    | ||||
|   The input contours are specified with the following routines: | ||||
|  | ||||
|      void gluTessBeginPolygon( GLUtesselator *tess ); | ||||
|      void gluTessBeginContour( GLUtesselator *tess ); | ||||
|      void gluTessVertex( GLUtesselator *tess, GLUcoord coords[3], void *data ); | ||||
|      void gluTessEndContour( GLUtesselator *tess ); | ||||
|      void gluTessEndPolygon( GLUtesselator *tess ); | ||||
|  | ||||
|   Within each BeginPolygon/EndPolygon pair, there can be zero or more | ||||
|   calls to BeginContour/EndContour.  Within each contour, there are zero | ||||
|   or more calls to gluTessVertex().  The vertices specify a closed | ||||
|   contour (the last vertex of each contour is automatically linked to | ||||
|   the first). | ||||
|  | ||||
|   "coords" give the coordinates of the vertex in 3-space.  For useful | ||||
|   results, all vertices should lie in some plane, since the vertices | ||||
|   are projected onto a plane before tesselation.  "data" is a pointer | ||||
|   to a user-defined vertex structure, which typically contains other | ||||
|   information such as color, texture coordinates, normal, etc.  It is | ||||
|   used to refer to the vertex during rendering. | ||||
|  | ||||
|   The library can be compiled in single- or double-precision; the type | ||||
|   GLUcoord represents either "float" or "double" accordingly.  The GLU | ||||
|   version will be available in double-precision only.  Compile with | ||||
|   GLU_TESS_API_FLOAT defined to get the single-precision version. | ||||
|  | ||||
|   When EndPolygon is called, the tesselation algorithm determines | ||||
|   which regions are interior to the given contours, according to one | ||||
|   of several "winding rules" described below.  The interior regions | ||||
|   are then tesselated, and the output is provided as callbacks. | ||||
|  | ||||
|  | ||||
|   Rendering Callbacks | ||||
|   ------------------- | ||||
|  | ||||
|   Callbacks are specified by the client using | ||||
|  | ||||
|      void gluTessCallback( GLUtesselator *tess, GLenum which, void (*fn)()); | ||||
|  | ||||
|   If "fn" is NULL, any previously defined callback is discarded. | ||||
|    | ||||
|   The callbacks used to provide output are:	/* which == */ | ||||
|  | ||||
|      void begin( GLenum type );			/* GLU_TESS_BEGIN */ | ||||
|      void edgeFlag( GLboolean flag );		/* GLU_TESS_EDGE_FLAG */ | ||||
|      void vertex( void *data );			/* GLU_TESS_VERTEX */ | ||||
|      void end( void );				/* GLU_TESS_END */ | ||||
|  | ||||
|   Any of the callbacks may be left undefined; if so, the corresponding | ||||
|   information will not be supplied during rendering. | ||||
|  | ||||
|   The "begin" callback indicates the start of a primitive; type is one | ||||
|   of GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES (but see the | ||||
|   notes on "boundary extraction" below). | ||||
|    | ||||
|   It is followed by any number of "vertex" callbacks, which supply the | ||||
|   vertices in the same order as expected by the corresponding glBegin() | ||||
|   call.  After the last vertex of a given primitive, there is a callback | ||||
|   to "end". | ||||
|  | ||||
|   If the "edgeFlag" callback is provided, no triangle fans or strips | ||||
|   will be used.  When edgeFlag is called, if "flag" is GL_TRUE then each | ||||
|   vertex which follows begins an edge which lies on the polygon boundary | ||||
|   (ie. an edge which separates an interior region from an exterior one). | ||||
|   If "flag" is GL_FALSE, each vertex which follows begins an edge which lies | ||||
|   in the polygon interior.  "edgeFlag" will be called before the first | ||||
|   call to "vertex". | ||||
|  | ||||
|   Other Callbacks | ||||
|   --------------- | ||||
|  | ||||
|    void mesh( GLUmesh *mesh );			/* GLU_TESS_MESH */ | ||||
|  | ||||
|    - Returns an explicit mesh, represented using the quad-edge structure | ||||
|      (Guibas/Stolfi '85).  Other implementations of this interface might | ||||
|      use a different mesh structure, so this is available only only as an | ||||
|      SGI extension.  When the mesh is no longer needed, it should be freed | ||||
|      using | ||||
|  | ||||
| 	void gluDeleteMesh( GLUmesh *mesh ); | ||||
|  | ||||
|      There is a brief description of this data structure in the include | ||||
|      file "mesh.h".  For the full details, see L. Guibas and J. Stolfi, | ||||
|      Primitives for the manipulation of general subdivisions and the | ||||
|      computation of Voronoi diagrams, ACM Transactions on Graphics, | ||||
|      4(2):74-123, April 1985.  For an introduction, see the course notes | ||||
|      for CS348a, "Mathematical Foundations of Computer Graphics", | ||||
|      available at the Stanford bookstore (and taught during the fall | ||||
|      quarter). | ||||
|  | ||||
|    void error( GLenum errno );			/* GLU_TESS_ERROR */ | ||||
|  | ||||
|    - errno is one of	GLU_TESS_MISSING_BEGIN_POLYGON, | ||||
| 			GLU_TESS_MISSING_END_POLYGON, | ||||
| 			GLU_TESS_MISSING_BEGIN_CONTOUR, | ||||
| 			GLU_TESS_MISSING_END_CONTOUR, | ||||
| 			GLU_TESS_COORD_TOO_LARGE, | ||||
| 			GLU_TESS_NEED_COMBINE_CALLBACK | ||||
|  | ||||
|      The first four are obvious.  The interface recovers from these | ||||
|      errors by inserting the missing call(s). | ||||
|    | ||||
|      GLU_TESS_COORD_TOO_LARGE says that some vertex coordinate exceeded | ||||
|      the predefined constant GLU_TESS_MAX_COORD in absolute value, and | ||||
|      that the value has been clamped.  (Coordinate values must be small | ||||
|      enough so that two can be multiplied together without overflow.) | ||||
|  | ||||
|      GLU_TESS_NEED_COMBINE_CALLBACK says that the algorithm detected an | ||||
|      intersection between two edges in the input data, and the "combine" | ||||
|      callback (below) was not provided.  No output will be generated. | ||||
|  | ||||
|  | ||||
|    void combine( GLUcoord coords[3], void *data[4],	/* GLU_TESS_COMBINE */ | ||||
| 		 GLUcoord weight[4], void **outData ); | ||||
|  | ||||
|    - When the algorithm detects an intersection, or wishes to merge | ||||
|      features, it needs to create a new vertex.  The vertex is defined | ||||
|      as a linear combination of up to 4 existing vertices, referenced | ||||
|      by data[0..3].  The coefficients of the linear combination are | ||||
|      given by weight[0..3]; these weights always sum to 1.0.  All vertex | ||||
|      pointers are valid even when some of the weights are zero. | ||||
|      "coords" gives the location of the new vertex. | ||||
|  | ||||
|      The user must allocate another vertex, interpolate parameters | ||||
|      using "data" and "weights", and return the new vertex pointer in | ||||
|      "outData".  This handle is supplied during rendering callbacks. | ||||
|      For example, if the polygon lies in an arbitrary plane in 3-space, | ||||
|      and we associate a color with each vertex, the combine callback might | ||||
|      look like this: | ||||
|      | ||||
|      void myCombine( GLUcoord coords[3], VERTEX *d[4], | ||||
|                      GLUcoord w[4], VERTEX **dataOut ) | ||||
|      { | ||||
|         VERTEX *new = new_vertex(); | ||||
|         | ||||
|         new->x = coords[0]; | ||||
|         new->y = coords[1]; | ||||
|         new->z = coords[2]; | ||||
|         new->r = w[0]*d[0]->r + w[1]*d[1]->r + w[2]*d[2]->r + w[3]*d[3]->r; | ||||
|         new->g = w[0]*d[0]->g + w[1]*d[1]->g + w[2]*d[2]->g + w[3]*d[3]->g; | ||||
|         new->b = w[0]*d[0]->b + w[1]*d[1]->b + w[2]*d[2]->b + w[3]*d[3]->b; | ||||
|         new->a = w[0]*d[0]->a + w[1]*d[1]->a + w[2]*d[2]->a + w[3]*d[3]->a; | ||||
|         *dataOut = new; | ||||
|      } | ||||
|  | ||||
|      If the algorithm detects an intersection, then the "combine" callback | ||||
|      must be defined, and must write a non-NULL pointer into "dataOut". | ||||
|      Otherwise the GLU_TESS_NEED_COMBINE_CALLBACK error occurs, and no | ||||
|      output is generated.  This is the only error that can occur during | ||||
|      tesselation and rendering. | ||||
|  | ||||
|  | ||||
|   Control over Tesselation | ||||
|   ------------------------ | ||||
|    | ||||
|    void gluTessProperty( GLUtesselator *tess, GLenum which, GLUcoord value ); | ||||
|  | ||||
|    Properties defined: | ||||
|  | ||||
|     - GLU_TESS_WINDING_RULE.  Possible values: | ||||
|  | ||||
| 	  GLU_TESS_WINDING_ODD | ||||
| 	  GLU_TESS_WINDING_NONZERO | ||||
| 	  GLU_TESS_WINDING_POSITIVE | ||||
| 	  GLU_TESS_WINDING_NEGATIVE | ||||
| 	  GLU_TESS_WINDING_ABS_GEQ_TWO | ||||
|  | ||||
|       The input contours parition the plane into regions.  A winding | ||||
|       rule determines which of these regions are inside the polygon. | ||||
|        | ||||
|       For a single contour C, the winding number of a point x is simply | ||||
|       the signed number of revolutions we make around x as we travel | ||||
|       once around C (where CCW is positive).  When there are several | ||||
|       contours, the individual winding numbers are summed.  This | ||||
|       procedure associates a signed integer value with each point x in | ||||
|       the plane.  Note that the winding number is the same for all | ||||
|       points in a single region. | ||||
|  | ||||
|       The winding rule classifies a region as "inside" if its winding | ||||
|       number belongs to the chosen category (odd, nonzero, positive, | ||||
|       negative, or absolute value of at least two).  The current GLU | ||||
|       tesselator implements the "odd" rule.  The "nonzero" rule is another | ||||
|       common way to define the interior.  The other three rules are | ||||
|       useful for polygon CSG operations (see below). | ||||
|  | ||||
|     - GLU_TESS_BOUNDARY_ONLY.  Values: TRUE (non-zero) or FALSE (zero). | ||||
|  | ||||
|       If TRUE, returns a set of closed contours which separate the | ||||
|       polygon interior and exterior (rather than a tesselation). | ||||
|       Exterior contours are oriented CCW with respect to the normal, | ||||
|       interior contours are oriented CW.  The GLU_TESS_BEGIN callback | ||||
|       uses the type GL_LINE_LOOP for each contour. | ||||
|        | ||||
|     - GLU_TESS_TOLERANCE.  Value: a real number between 0.0 and 1.0. | ||||
|  | ||||
|       This specifies a tolerance for merging features to reduce the size | ||||
|       of the output.  For example, two vertices which are very close to | ||||
|       each other might be replaced by a single vertex.  The tolerance | ||||
|       is multiplied by the largest coordinate magnitude of any input vertex; | ||||
|       this specifies the maximum distance that any feature can move as the | ||||
|       result of a single merge operation.  If a single feature takes part | ||||
|       in several merge operations, the total distance moved could be larger. | ||||
|  | ||||
|       Feature merging is completely optional; the tolerance is only a hint. | ||||
|       The implementation is free to merge in some cases and not in others, | ||||
|       or to never merge features at all.  The default tolerance is zero. | ||||
|        | ||||
|       The current implementation merges vertices only if they are exactly | ||||
|       coincident, regardless of the current tolerance.  A vertex is | ||||
|       spliced into an edge only if the implementation is unable to | ||||
|       distinguish which side of the edge the vertex lies on. | ||||
|       Two edges are merged only when both endpoints are identical. | ||||
|  | ||||
|  | ||||
|    void gluTessNormal( GLUtesselator *tess, | ||||
| 		      GLUcoord x, GLUcoord y, GLUcoord z ) | ||||
|  | ||||
|     - Lets the user supply the polygon normal, if known.  All input data | ||||
|       is projected into a plane perpendicular to the normal before | ||||
|       tesselation.  All output triangles are oriented CCW with | ||||
|       respect to the normal (CW orientation can be obtained by | ||||
|       reversing the sign of the supplied normal).  For example, if | ||||
|       you know that all polygons lie in the x-y plane, call | ||||
|       "gluTessNormal(tess, 0.0, 0.0, 1.0)" before rendering any polygons. | ||||
|        | ||||
|     - If the supplied normal is (0,0,0) (the default value), the | ||||
|       normal is determined as follows.  The direction of the normal, | ||||
|       up to its sign, is found by fitting a plane to the vertices, | ||||
|       without regard to how the vertices are connected.  It is | ||||
|       expected that the input data lies approximately in plane; | ||||
|       otherwise projection perpendicular to the computed normal may | ||||
|       substantially change the geometry.  The sign of the normal is | ||||
|       chosen so that the sum of the signed areas of all input contours | ||||
|       is non-negative (where a CCW contour has positive area). | ||||
|      | ||||
|     - The supplied normal persists until it is changed by another | ||||
|       call to gluTessNormal. | ||||
|  | ||||
|  | ||||
|   Backward compatibility with the GLU tesselator | ||||
|   ---------------------------------------------- | ||||
|  | ||||
|   The preferred interface is the one described above.  The following | ||||
|   routines are obsolete, and are provided only for backward compatibility: | ||||
|  | ||||
|     typedef GLUtesselator GLUtriangulatorObj;	/* obsolete name */ | ||||
|  | ||||
|     void gluBeginPolygon( GLUtesselator *tess ); | ||||
|     void gluNextContour( GLUtesselator *tess, GLenum type ); | ||||
|     void gluEndPolygon( GLUtesselator *tess ); | ||||
|    | ||||
|   "type" is one of GLU_EXTERIOR, GLU_INTERIOR, GLU_CCW, GLU_CW, or | ||||
|   GLU_UNKNOWN.  It is ignored by the current GLU tesselator. | ||||
|    | ||||
|   GLU_BEGIN, GLU_VERTEX, GLU_END, GLU_ERROR, and GLU_EDGE_FLAG are defined | ||||
|   as synonyms for GLU_TESS_BEGIN, GLU_TESS_VERTEX, GLU_TESS_END, | ||||
|   GLU_TESS_ERROR, and GLU_TESS_EDGE_FLAG. | ||||
|  | ||||
|  | ||||
| Polygon CSG operations | ||||
| ---------------------- | ||||
|  | ||||
|   The features of the tesselator make it easy to find the union, difference, | ||||
|   or intersection of several polygons. | ||||
|  | ||||
|   First, assume that each polygon is defined so that the winding number | ||||
|   is 0 for each exterior region, and 1 for each interior region.  Under | ||||
|   this model, CCW contours define the outer boundary of the polygon, and | ||||
|   CW contours define holes.  Contours may be nested, but a nested | ||||
|   contour must be oriented oppositely from the contour that contains it. | ||||
|  | ||||
|   If the original polygons do not satisfy this description, they can be | ||||
|   converted to this form by first running the tesselator with the | ||||
|   GLU_TESS_BOUNDARY_ONLY property turned on.  This returns a list of | ||||
|   contours satisfying the restriction above.  By allocating two | ||||
|   tesselator objects, the callbacks from one tesselator can be fed | ||||
|   directly to the input of another. | ||||
|  | ||||
|   Given two or more polygons of the form above, CSG operations can be | ||||
|   implemented as follows: | ||||
|  | ||||
|   Union | ||||
|      Draw all the input contours as a single polygon.  The winding number | ||||
|      of each resulting region is the number of original polygons | ||||
|      which cover it.  The union can be extracted using the | ||||
|      GLU_TESS_WINDING_NONZERO or GLU_TESS_WINDING_POSITIVE winding rules. | ||||
|      Note that with the nonzero rule, we would get the same result if | ||||
|      all contour orientations were reversed. | ||||
|  | ||||
|   Intersection (two polygons at a time only) | ||||
|      Draw a single polygon using the contours from both input polygons. | ||||
|      Extract the result using GLU_TESS_WINDING_ABS_GEQ_TWO.  (Since this | ||||
|      winding rule looks at the absolute value, reversing all contour | ||||
|      orientations does not change the result.) | ||||
|  | ||||
|   Difference | ||||
|    | ||||
|      Suppose we want to compute A \ (B union C union D).  Draw a single | ||||
|      polygon consisting of the unmodified contours from A, followed by | ||||
|      the contours of B,C,D with the vertex order reversed (this changes | ||||
|      the winding number of the interior regions to -1).  To extract the | ||||
|      result, use the GLU_TESS_WINDING_POSITIVE rule. | ||||
|     | ||||
|      If B,C,D are the result of a GLU_TESS_BOUNDARY_ONLY call, an | ||||
|      alternative to reversing the vertex order is to reverse the sign of | ||||
|      the supplied normal.  For example in the x-y plane, call | ||||
|      gluTessNormal( tess, 0.0, 0.0, -1.0 ). | ||||
|   | ||||
|  | ||||
| Performance | ||||
| ----------- | ||||
|  | ||||
|   The tesselator is not intended for immediate-mode rendering; when | ||||
|   possible the output should be cached in a user structure or display | ||||
|   list.  General polygon tesselation is an inherently difficult problem, | ||||
|   especially given the goal of extreme robustness. | ||||
|  | ||||
|   The implementation makes an effort to output a small number of fans | ||||
|   and strips; this should improve the rendering performance when the | ||||
|   output is used in a display list. | ||||
|  | ||||
|   Single-contour input polygons are first tested to see whether they can | ||||
|   be rendered as a triangle fan with respect to the first vertex (to | ||||
|   avoid running the full decomposition algorithm on convex polygons). | ||||
|   Non-convex polygons may be rendered by this "fast path" as well, if | ||||
|   the algorithm gets lucky in its choice of a starting vertex. | ||||
|  | ||||
|   For best performance follow these guidelines: | ||||
|  | ||||
|    - supply the polygon normal, if available, using gluTessNormal(). | ||||
|      This represents about 10% of the computation time.  For example, | ||||
|      if all polygons lie in the x-y plane, use gluTessNormal(tess,0,0,1). | ||||
|  | ||||
|    - render many polygons using the same tesselator object, rather than | ||||
|      allocating a new tesselator for each one.  (In a multi-threaded, | ||||
|      multi-processor environment you may get better performance using | ||||
|      several tesselators.) | ||||
|  | ||||
|  | ||||
| Comparison with the GLU tesselator | ||||
| ---------------------------------- | ||||
|  | ||||
|   On polygons which make it through the "fast path", the tesselator is | ||||
|   3 to 5 times faster than the GLU tesselator. | ||||
|  | ||||
|   On polygons which don't make it through the fast path (but which don't | ||||
|   have self-intersections or degeneracies), it is about 2 times slower. | ||||
|  | ||||
|   On polygons with self-intersections or degeneraces, there is nothing | ||||
|   to compare against. | ||||
|  | ||||
|   The new tesselator generates many more fans and strips, reducing the | ||||
|   number of vertices that need to be sent to the hardware. | ||||
|  | ||||
|   Key to the statistics: | ||||
|  | ||||
| 	vert		number of input vertices on all contours | ||||
| 	cntr		number of input contours | ||||
| 	tri		number of triangles in all output primitives | ||||
| 	strip		number of triangle strips | ||||
| 	fan		number of triangle fans | ||||
| 	ind		number of independent triangles | ||||
| 	ms		number of milliseconds for tesselation | ||||
| 			(on a 150MHz R4400 Indy) | ||||
|  | ||||
|   Convex polygon examples: | ||||
|  | ||||
| New:     3 vert,   1 cntr,     1 tri,   0 strip,   0 fan,     1 ind,  0.0459 ms | ||||
| Old:     3 vert,   1 cntr,     1 tri,   0 strip,   0 fan,     1 ind,   0.149 ms | ||||
| New:     4 vert,   1 cntr,     2 tri,   0 strip,   1 fan,     0 ind,  0.0459 ms | ||||
| Old:     4 vert,   1 cntr,     2 tri,   0 strip,   0 fan,     2 ind,   0.161 ms | ||||
| New:    36 vert,   1 cntr,    34 tri,   0 strip,   1 fan,     0 ind,   0.153 ms | ||||
| Old:    36 vert,   1 cntr,    34 tri,   0 strip,   0 fan,    34 ind,   0.621 ms | ||||
|  | ||||
|   Concave single-contour polygons: | ||||
|  | ||||
| New:     5 vert,   1 cntr,     3 tri,   0 strip,   1 fan,     0 ind,   0.052 ms | ||||
| Old:     5 vert,   1 cntr,     3 tri,   0 strip,   0 fan,     3 ind,   0.252 ms | ||||
| New:    19 vert,   1 cntr,    17 tri,   2 strip,   2 fan,     1 ind,   0.911 ms | ||||
| Old:    19 vert,   1 cntr,    17 tri,   0 strip,   0 fan,    17 ind,   0.529 ms | ||||
| New:   151 vert,   1 cntr,   149 tri,  13 strip,  18 fan,     3 ind,    6.82 ms | ||||
| Old:   151 vert,   1 cntr,   149 tri,   0 strip,   3 fan,   143 ind,     2.7 ms | ||||
| New:   574 vert,   1 cntr,   572 tri,  59 strip,  54 fan,    11 ind,    26.6 ms | ||||
| Old:   574 vert,   1 cntr,   572 tri,   0 strip,  31 fan,   499 ind,    12.4 ms | ||||
|  | ||||
|   Multiple contours, but no intersections: | ||||
|  | ||||
| New:     7 vert,   2 cntr,     7 tri,   1 strip,   0 fan,     0 ind,   0.527 ms | ||||
| Old:     7 vert,   2 cntr,     7 tri,   0 strip,   0 fan,     7 ind,   0.274 ms | ||||
| New:    81 vert,   6 cntr,    89 tri,   9 strip,   7 fan,     6 ind,    3.88 ms | ||||
| Old:    81 vert,   6 cntr,    89 tri,   0 strip,  13 fan,    61 ind,     2.2 ms | ||||
| New:   391 vert,  19 cntr,   413 tri,  37 strip,  32 fan,    26 ind,    20.2 ms | ||||
| Old:   391 vert,  19 cntr,   413 tri,   0 strip,  25 fan,   363 ind,    8.68 ms | ||||
|  | ||||
|   Self-intersecting and degenerate examples: | ||||
|  | ||||
| Bowtie:  4 vert,   1 cntr,     2 tri,   0 strip,   0 fan,     2 ind,   0.483 ms | ||||
| Star:    5 vert,   1 cntr,     5 tri,   0 strip,   0 fan,     5 ind,    0.91 ms | ||||
| Random: 24 vert,   7 cntr,    46 tri,   2 strip,  12 fan,     7 ind,    5.32 ms | ||||
| Font:  333 vert,   2 cntr,   331 tri,  32 strip,  16 fan,     3 ind,    14.1 ms | ||||
| :      167 vert,  35 cntr,   254 tri,   8 strip,  56 fan,    52 ind,    46.3 ms | ||||
| :       78 vert,   1 cntr,  2675 tri, 148 strip, 207 fan,   180 ind,     243 ms | ||||
| :    12480 vert,   2 cntr, 12478 tri, 736 strip,1275 fan,     5 ind,    1010 ms | ||||
| @@ -1,100 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __dict_list_h_ | ||||
| #define __dict_list_h_ | ||||
|  | ||||
| /* Use #define's so that another heap implementation can use this one */ | ||||
|  | ||||
| #define DictKey		DictListKey | ||||
| #define Dict		DictList | ||||
| #define DictNode	DictListNode | ||||
|  | ||||
| #define dictNewDict(frame,leq)		__gl_dictListNewDict(frame,leq) | ||||
| #define dictDeleteDict(dict)		__gl_dictListDeleteDict(dict) | ||||
|  | ||||
| #define dictSearch(dict,key)		__gl_dictListSearch(dict,key) | ||||
| #define dictInsert(dict,key)		__gl_dictListInsert(dict,key) | ||||
| #define dictInsertBefore(dict,node,key)	__gl_dictListInsertBefore(dict,node,key) | ||||
| #define dictDelete(dict,node)		__gl_dictListDelete(dict,node) | ||||
|  | ||||
| #define dictKey(n)			__gl_dictListKey(n) | ||||
| #define dictSucc(n)			__gl_dictListSucc(n) | ||||
| #define dictPred(n)			__gl_dictListPred(n) | ||||
| #define dictMin(d)			__gl_dictListMin(d) | ||||
| #define dictMax(d)			__gl_dictListMax(d) | ||||
|  | ||||
|  | ||||
|  | ||||
| typedef void *DictKey; | ||||
| typedef struct Dict Dict; | ||||
| typedef struct DictNode DictNode; | ||||
|  | ||||
| Dict		*dictNewDict( | ||||
| 			void *frame, | ||||
| 			int (*leq)(void *frame, DictKey key1, DictKey key2) ); | ||||
| 			 | ||||
| void		dictDeleteDict( Dict *dict ); | ||||
|  | ||||
| /* Search returns the node with the smallest key greater than or equal | ||||
|  * to the given key.  If there is no such key, returns a node whose | ||||
|  * key is NULL.  Similarly, Succ(Max(d)) has a NULL key, etc. | ||||
|  */ | ||||
| DictNode	*dictSearch( Dict *dict, DictKey key ); | ||||
| DictNode	*dictInsertBefore( Dict *dict, DictNode *node, DictKey key ); | ||||
| void		dictDelete( Dict *dict, DictNode *node ); | ||||
|  | ||||
| #define		__gl_dictListKey(n)	((n)->key) | ||||
| #define		__gl_dictListSucc(n)	((n)->next) | ||||
| #define		__gl_dictListPred(n)	((n)->prev) | ||||
| #define		__gl_dictListMin(d)	((d)->head.next) | ||||
| #define		__gl_dictListMax(d)	((d)->head.prev) | ||||
| #define	       __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k))) | ||||
|  | ||||
|  | ||||
| /*** Private data structures ***/ | ||||
|  | ||||
| struct DictNode { | ||||
|   DictKey	key; | ||||
|   DictNode	*next; | ||||
|   DictNode	*prev; | ||||
| }; | ||||
|  | ||||
| struct Dict { | ||||
|   DictNode	head; | ||||
|   void		*frame; | ||||
|   int		(*leq)(void *frame, DictKey key1, DictKey key2); | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -1,111 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include "dict-list.h" | ||||
| #include "memalloc.h" | ||||
|  | ||||
| /* really __gl_dictListNewDict */ | ||||
| Dict *dictNewDict( void *frame, | ||||
| 		   int (*leq)(void *frame, DictKey key1, DictKey key2) ) | ||||
| { | ||||
|   Dict *dict = (Dict *) memAlloc( sizeof( Dict )); | ||||
|   DictNode *head; | ||||
|  | ||||
|   if (dict == NULL) return NULL; | ||||
|  | ||||
|   head = &dict->head; | ||||
|  | ||||
|   head->key = NULL; | ||||
|   head->next = head; | ||||
|   head->prev = head; | ||||
|  | ||||
|   dict->frame = frame; | ||||
|   dict->leq = leq; | ||||
|  | ||||
|   return dict; | ||||
| } | ||||
|  | ||||
| /* really __gl_dictListDeleteDict */ | ||||
| void dictDeleteDict( Dict *dict ) | ||||
| { | ||||
|   DictNode *node, *next; | ||||
|  | ||||
|   for( node = dict->head.next; node != &dict->head; node = next ) { | ||||
|     next = node->next; | ||||
|     memFree( node ); | ||||
|   } | ||||
|   memFree( dict ); | ||||
| } | ||||
|  | ||||
| /* really __gl_dictListInsertBefore */ | ||||
| DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ) | ||||
| { | ||||
|   DictNode *newNode; | ||||
|  | ||||
|   do { | ||||
|     node = node->prev; | ||||
|   } while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key)); | ||||
|  | ||||
|   newNode = (DictNode *) memAlloc( sizeof( DictNode )); | ||||
|   if (newNode == NULL) return NULL; | ||||
|  | ||||
|   newNode->key = key; | ||||
|   newNode->next = node->next; | ||||
|   node->next->prev = newNode; | ||||
|   newNode->prev = node; | ||||
|   node->next = newNode; | ||||
|  | ||||
|   return newNode; | ||||
| } | ||||
|  | ||||
| /* really __gl_dictListDelete */ | ||||
| void dictDelete( Dict *dict, DictNode *node ) /*ARGSUSED*/ | ||||
| { | ||||
|   node->next->prev = node->prev; | ||||
|   node->prev->next = node->next; | ||||
|   memFree( node ); | ||||
| } | ||||
|  | ||||
| /* really __gl_dictListSearch */ | ||||
| DictNode *dictSearch( Dict *dict, DictKey key ) | ||||
| { | ||||
|   DictNode *node = &dict->head; | ||||
|  | ||||
|   do { | ||||
|     node = node->next; | ||||
|   } while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key)); | ||||
|  | ||||
|   return node; | ||||
| } | ||||
| @@ -1,100 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __dict_list_h_ | ||||
| #define __dict_list_h_ | ||||
|  | ||||
| /* Use #define's so that another heap implementation can use this one */ | ||||
|  | ||||
| #define DictKey		DictListKey | ||||
| #define Dict		DictList | ||||
| #define DictNode	DictListNode | ||||
|  | ||||
| #define dictNewDict(frame,leq)		__gl_dictListNewDict(frame,leq) | ||||
| #define dictDeleteDict(dict)		__gl_dictListDeleteDict(dict) | ||||
|  | ||||
| #define dictSearch(dict,key)		__gl_dictListSearch(dict,key) | ||||
| #define dictInsert(dict,key)		__gl_dictListInsert(dict,key) | ||||
| #define dictInsertBefore(dict,node,key)	__gl_dictListInsertBefore(dict,node,key) | ||||
| #define dictDelete(dict,node)		__gl_dictListDelete(dict,node) | ||||
|  | ||||
| #define dictKey(n)			__gl_dictListKey(n) | ||||
| #define dictSucc(n)			__gl_dictListSucc(n) | ||||
| #define dictPred(n)			__gl_dictListPred(n) | ||||
| #define dictMin(d)			__gl_dictListMin(d) | ||||
| #define dictMax(d)			__gl_dictListMax(d) | ||||
|  | ||||
|  | ||||
|  | ||||
| typedef void *DictKey; | ||||
| typedef struct Dict Dict; | ||||
| typedef struct DictNode DictNode; | ||||
|  | ||||
| Dict		*dictNewDict( | ||||
| 			void *frame, | ||||
| 			int (*leq)(void *frame, DictKey key1, DictKey key2) ); | ||||
| 			 | ||||
| void		dictDeleteDict( Dict *dict ); | ||||
|  | ||||
| /* Search returns the node with the smallest key greater than or equal | ||||
|  * to the given key.  If there is no such key, returns a node whose | ||||
|  * key is NULL.  Similarly, Succ(Max(d)) has a NULL key, etc. | ||||
|  */ | ||||
| DictNode	*dictSearch( Dict *dict, DictKey key ); | ||||
| DictNode	*dictInsertBefore( Dict *dict, DictNode *node, DictKey key ); | ||||
| void		dictDelete( Dict *dict, DictNode *node ); | ||||
|  | ||||
| #define		__gl_dictListKey(n)	((n)->key) | ||||
| #define		__gl_dictListSucc(n)	((n)->next) | ||||
| #define		__gl_dictListPred(n)	((n)->prev) | ||||
| #define		__gl_dictListMin(d)	((d)->head.next) | ||||
| #define		__gl_dictListMax(d)	((d)->head.prev) | ||||
| #define	       __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k))) | ||||
|  | ||||
|  | ||||
| /*** Private data structures ***/ | ||||
|  | ||||
| struct DictNode { | ||||
|   DictKey	key; | ||||
|   DictNode	*next; | ||||
|   DictNode	*prev; | ||||
| }; | ||||
|  | ||||
| struct Dict { | ||||
|   DictNode	head; | ||||
|   void		*frame; | ||||
|   int		(*leq)(void *frame, DictKey key1, DictKey key2); | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -1,264 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include <assert.h> | ||||
| #include "mesh.h" | ||||
| #include "geom.h" | ||||
|  | ||||
| int __gl_vertLeq( GLUvertex *u, GLUvertex *v ) | ||||
| { | ||||
|   /* Returns TRUE if u is lexicographically <= v. */ | ||||
|  | ||||
|   return VertLeq( u, v ); | ||||
| } | ||||
|  | ||||
| GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ) | ||||
| { | ||||
|   /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), | ||||
|    * evaluates the t-coord of the edge uw at the s-coord of the vertex v. | ||||
|    * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. | ||||
|    * If uw is vertical (and thus passes thru v), the result is zero. | ||||
|    * | ||||
|    * The calculation is extremely accurate and stable, even when v | ||||
|    * is very close to u or w.  In particular if we set v->t = 0 and | ||||
|    * let r be the negated result (this evaluates (uw)(v->s)), then | ||||
|    * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). | ||||
|    */ | ||||
|   GLdouble gapL, gapR; | ||||
|  | ||||
|   assert( VertLeq( u, v ) && VertLeq( v, w )); | ||||
|    | ||||
|   gapL = v->s - u->s; | ||||
|   gapR = w->s - v->s; | ||||
|  | ||||
|   if( gapL + gapR > 0 ) { | ||||
|     if( gapL < gapR ) { | ||||
|       return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR)); | ||||
|     } else { | ||||
|       return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR)); | ||||
|     } | ||||
|   } | ||||
|   /* vertical line */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ) | ||||
| { | ||||
|   /* Returns a number whose sign matches EdgeEval(u,v,w) but which | ||||
|    * is cheaper to evaluate.  Returns > 0, == 0 , or < 0 | ||||
|    * as v is above, on, or below the edge uw. | ||||
|    */ | ||||
|   GLdouble gapL, gapR; | ||||
|  | ||||
|   assert( VertLeq( u, v ) && VertLeq( v, w )); | ||||
|    | ||||
|   gapL = v->s - u->s; | ||||
|   gapR = w->s - v->s; | ||||
|  | ||||
|   if( gapL + gapR > 0 ) { | ||||
|     return (v->t - w->t) * gapL + (v->t - u->t) * gapR; | ||||
|   } | ||||
|   /* vertical line */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*********************************************************************** | ||||
|  * Define versions of EdgeSign, EdgeEval with s and t transposed. | ||||
|  */ | ||||
|  | ||||
| GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ) | ||||
| { | ||||
|   /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), | ||||
|    * evaluates the t-coord of the edge uw at the s-coord of the vertex v. | ||||
|    * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. | ||||
|    * If uw is vertical (and thus passes thru v), the result is zero. | ||||
|    * | ||||
|    * The calculation is extremely accurate and stable, even when v | ||||
|    * is very close to u or w.  In particular if we set v->s = 0 and | ||||
|    * let r be the negated result (this evaluates (uw)(v->t)), then | ||||
|    * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). | ||||
|    */ | ||||
|   GLdouble gapL, gapR; | ||||
|  | ||||
|   assert( TransLeq( u, v ) && TransLeq( v, w )); | ||||
|    | ||||
|   gapL = v->t - u->t; | ||||
|   gapR = w->t - v->t; | ||||
|  | ||||
|   if( gapL + gapR > 0 ) { | ||||
|     if( gapL < gapR ) { | ||||
|       return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR)); | ||||
|     } else { | ||||
|       return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR)); | ||||
|     } | ||||
|   } | ||||
|   /* vertical line */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ) | ||||
| { | ||||
|   /* Returns a number whose sign matches TransEval(u,v,w) but which | ||||
|    * is cheaper to evaluate.  Returns > 0, == 0 , or < 0 | ||||
|    * as v is above, on, or below the edge uw. | ||||
|    */ | ||||
|   GLdouble gapL, gapR; | ||||
|  | ||||
|   assert( TransLeq( u, v ) && TransLeq( v, w )); | ||||
|    | ||||
|   gapL = v->t - u->t; | ||||
|   gapR = w->t - v->t; | ||||
|  | ||||
|   if( gapL + gapR > 0 ) { | ||||
|     return (v->s - w->s) * gapL + (v->s - u->s) * gapR; | ||||
|   } | ||||
|   /* vertical line */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w ) | ||||
| { | ||||
|   /* For almost-degenerate situations, the results are not reliable. | ||||
|    * Unless the floating-point arithmetic can be performed without | ||||
|    * rounding errors, *any* implementation will give incorrect results | ||||
|    * on some degenerate inputs, so the client must have some way to | ||||
|    * handle this situation. | ||||
|    */ | ||||
|   return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0; | ||||
| } | ||||
|  | ||||
| /* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), | ||||
|  * or (x+y)/2 if a==b==0.  It requires that a,b >= 0, and enforces | ||||
|  * this in the rare case that one argument is slightly negative. | ||||
|  * The implementation is extremely stable numerically. | ||||
|  * In particular it guarantees that the result r satisfies | ||||
|  * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate | ||||
|  * even when a and b differ greatly in magnitude. | ||||
|  */ | ||||
| #define RealInterpolate(a,x,b,y)			\ | ||||
|   (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b,		\ | ||||
|   ((a <= b) ? ((b == 0) ? ((x+y) / 2)			\ | ||||
|                         : (x + (y-x) * (a/(a+b))))	\ | ||||
|             : (y + (x-y) * (b/(a+b))))) | ||||
|  | ||||
| #ifndef FOR_TRITE_TEST_PROGRAM | ||||
| #define Interpolate(a,x,b,y)	RealInterpolate(a,x,b,y) | ||||
| #else | ||||
|  | ||||
| /* Claim: the ONLY property the sweep algorithm relies on is that | ||||
|  * MIN(x,y) <= r <= MAX(x,y).  This is a nasty way to test that. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| extern int RandomInterpolate; | ||||
|  | ||||
| GLdouble Interpolate( GLdouble a, GLdouble x, GLdouble b, GLdouble y) | ||||
| { | ||||
| printf("*********************%d\n",RandomInterpolate); | ||||
|   if( RandomInterpolate ) { | ||||
|     a = 1.2 * drand48() - 0.1; | ||||
|     a = (a < 0) ? 0 : ((a > 1) ? 1 : a); | ||||
|     b = 1.0 - a; | ||||
|   } | ||||
|   return RealInterpolate(a,x,b,y); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #define Swap(a,b)	do { GLUvertex *t = a; a = b; b = t; } while (0) | ||||
|  | ||||
| void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1, | ||||
| 			 GLUvertex *o2, GLUvertex *d2, | ||||
| 			 GLUvertex *v ) | ||||
| /* Given edges (o1,d1) and (o2,d2), compute their point of intersection. | ||||
|  * The computed point is guaranteed to lie in the intersection of the | ||||
|  * bounding rectangles defined by each edge. | ||||
|  */ | ||||
| { | ||||
|   GLdouble z1, z2; | ||||
|  | ||||
|   /* This is certainly not the most efficient way to find the intersection | ||||
|    * of two line segments, but it is very numerically stable. | ||||
|    * | ||||
|    * Strategy: find the two middle vertices in the VertLeq ordering, | ||||
|    * and interpolate the intersection s-value from these.  Then repeat | ||||
|    * using the TransLeq ordering to find the intersection t-value. | ||||
|    */ | ||||
|  | ||||
|   if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); } | ||||
|   if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); } | ||||
|   if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } | ||||
|  | ||||
|   if( ! VertLeq( o2, d1 )) { | ||||
|     /* Technically, no intersection -- do our best */ | ||||
|     v->s = (o2->s + d1->s) / 2; | ||||
|   } else if( VertLeq( d1, d2 )) { | ||||
|     /* Interpolate between o2 and d1 */ | ||||
|     z1 = EdgeEval( o1, o2, d1 ); | ||||
|     z2 = EdgeEval( o2, d1, d2 ); | ||||
|     if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } | ||||
|     v->s = Interpolate( z1, o2->s, z2, d1->s ); | ||||
|   } else { | ||||
|     /* Interpolate between o2 and d2 */ | ||||
|     z1 = EdgeSign( o1, o2, d1 ); | ||||
|     z2 = -EdgeSign( o1, d2, d1 ); | ||||
|     if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } | ||||
|     v->s = Interpolate( z1, o2->s, z2, d2->s ); | ||||
|   } | ||||
|  | ||||
|   /* Now repeat the process for t */ | ||||
|  | ||||
|   if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); } | ||||
|   if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); } | ||||
|   if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } | ||||
|  | ||||
|   if( ! TransLeq( o2, d1 )) { | ||||
|     /* Technically, no intersection -- do our best */ | ||||
|     v->t = (o2->t + d1->t) / 2; | ||||
|   } else if( TransLeq( d1, d2 )) { | ||||
|     /* Interpolate between o2 and d1 */ | ||||
|     z1 = TransEval( o1, o2, d1 ); | ||||
|     z2 = TransEval( o2, d1, d2 ); | ||||
|     if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } | ||||
|     v->t = Interpolate( z1, o2->t, z2, d1->t ); | ||||
|   } else { | ||||
|     /* Interpolate between o2 and d2 */ | ||||
|     z1 = TransSign( o1, o2, d1 ); | ||||
|     z2 = -TransSign( o1, d2, d1 ); | ||||
|     if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } | ||||
|     v->t = Interpolate( z1, o2->t, z2, d2->t ); | ||||
|   } | ||||
| } | ||||
| @@ -1,84 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __geom_h_ | ||||
| #define __geom_h_ | ||||
|  | ||||
| #include "mesh.h" | ||||
|  | ||||
| #ifdef NO_BRANCH_CONDITIONS | ||||
| /* MIPS architecture has special instructions to evaluate boolean | ||||
|  * conditions -- more efficient than branching, IF you can get the | ||||
|  * compiler to generate the right instructions (SGI compiler doesn't) | ||||
|  */ | ||||
| #define VertEq(u,v)	(((u)->s == (v)->s) & ((u)->t == (v)->t)) | ||||
| #define VertLeq(u,v)	(((u)->s < (v)->s) | \ | ||||
|                          ((u)->s == (v)->s & (u)->t <= (v)->t)) | ||||
| #else | ||||
| #define VertEq(u,v)	((u)->s == (v)->s && (u)->t == (v)->t) | ||||
| #define VertLeq(u,v)	(((u)->s < (v)->s) || \ | ||||
|                          ((u)->s == (v)->s && (u)->t <= (v)->t)) | ||||
| #endif | ||||
|  | ||||
| #define EdgeEval(u,v,w) __gl_edgeEval(u,v,w) | ||||
| #define EdgeSign(u,v,w) __gl_edgeSign(u,v,w) | ||||
|  | ||||
| /* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ | ||||
|  | ||||
| #define TransLeq(u,v)	(((u)->t < (v)->t) || \ | ||||
|                          ((u)->t == (v)->t && (u)->s <= (v)->s)) | ||||
| #define TransEval(u,v,w)	__gl_transEval(u,v,w) | ||||
| #define TransSign(u,v,w)	__gl_transSign(u,v,w) | ||||
|  | ||||
|  | ||||
| #define EdgeGoesLeft(e) 	VertLeq( (e)->Dst, (e)->Org ) | ||||
| #define EdgeGoesRight(e)	VertLeq( (e)->Org, (e)->Dst ) | ||||
|  | ||||
| #undef	ABS | ||||
| #define ABS(x)	((x) < 0 ? -(x) : (x)) | ||||
| #define VertL1dist(u,v) (ABS(u->s - v->s) + ABS(u->t - v->t)) | ||||
|  | ||||
| #define VertCCW(u,v,w)	__gl_vertCCW(u,v,w) | ||||
|  | ||||
| int		__gl_vertLeq( GLUvertex *u, GLUvertex *v ); | ||||
| GLdouble	__gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); | ||||
| GLdouble	__gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); | ||||
| GLdouble	__gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); | ||||
| GLdouble	__gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); | ||||
| int		__gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w ); | ||||
| void		__gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1, | ||||
| 				    GLUvertex *o2, GLUvertex *d2, | ||||
| 				    GLUvertex *v ); | ||||
|  | ||||
| #endif | ||||
| @@ -1 +0,0 @@ | ||||
| /* This is a stub header to avoid having to change tess.c */ | ||||
| @@ -1,49 +0,0 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2010 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /* This is a simple replacement for memalloc from the SGI tesselator | ||||
|    code to force it to use glib's allocation instead */ | ||||
|  | ||||
| #ifndef __MEMALLOC_H__ | ||||
| #define __MEMALLOC_H__ | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #define memRealloc g_realloc | ||||
| #define memAlloc   g_malloc | ||||
| #define memFree    g_free | ||||
| #define memInit(x) 1 | ||||
|  | ||||
| /* tess.c defines TRUE and FALSE itself unconditionally so we need to | ||||
|    undefine it from the glib headers */ | ||||
| #undef TRUE | ||||
| #undef FALSE | ||||
|  | ||||
| #endif /* __MEMALLOC_H__ */ | ||||
| @@ -1,798 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include <stddef.h> | ||||
| #include <assert.h> | ||||
| #include "mesh.h" | ||||
| #include "memalloc.h" | ||||
|  | ||||
| #ifndef TRUE | ||||
| #define TRUE 1 | ||||
| #endif | ||||
| #ifndef FALSE | ||||
| #define FALSE 0 | ||||
| #endif | ||||
|  | ||||
| static GLUvertex *allocVertex(void) | ||||
| { | ||||
|    return (GLUvertex *)memAlloc( sizeof( GLUvertex )); | ||||
| } | ||||
|  | ||||
| static GLUface *allocFace(void) | ||||
| { | ||||
|    return (GLUface *)memAlloc( sizeof( GLUface )); | ||||
| } | ||||
|  | ||||
| /************************ Utility Routines ************************/ | ||||
|  | ||||
| /* Allocate and free half-edges in pairs for efficiency. | ||||
|  * The *only* place that should use this fact is allocation/free. | ||||
|  */ | ||||
| typedef struct { GLUhalfEdge e, eSym; } EdgePair; | ||||
|  | ||||
| /* MakeEdge creates a new pair of half-edges which form their own loop. | ||||
|  * No vertex or face structures are allocated, but these must be assigned | ||||
|  * before the current edge operation is completed. | ||||
|  */ | ||||
| static GLUhalfEdge *MakeEdge( GLUhalfEdge *eNext ) | ||||
| { | ||||
|   GLUhalfEdge *e; | ||||
|   GLUhalfEdge *eSym; | ||||
|   GLUhalfEdge *ePrev; | ||||
|   EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair )); | ||||
|   if (pair == NULL) return NULL; | ||||
|  | ||||
|   e = &pair->e; | ||||
|   eSym = &pair->eSym; | ||||
|  | ||||
|   /* Make sure eNext points to the first edge of the edge pair */ | ||||
|   if( eNext->Sym < eNext ) { eNext = eNext->Sym; } | ||||
|  | ||||
|   /* Insert in circular doubly-linked list before eNext. | ||||
|    * Note that the prev pointer is stored in Sym->next. | ||||
|    */ | ||||
|   ePrev = eNext->Sym->next; | ||||
|   eSym->next = ePrev; | ||||
|   ePrev->Sym->next = e; | ||||
|   e->next = eNext; | ||||
|   eNext->Sym->next = eSym; | ||||
|  | ||||
|   e->Sym = eSym; | ||||
|   e->Onext = e; | ||||
|   e->Lnext = eSym; | ||||
|   e->Org = NULL; | ||||
|   e->Lface = NULL; | ||||
|   e->winding = 0; | ||||
|   e->activeRegion = NULL; | ||||
|  | ||||
|   eSym->Sym = e; | ||||
|   eSym->Onext = eSym; | ||||
|   eSym->Lnext = e; | ||||
|   eSym->Org = NULL; | ||||
|   eSym->Lface = NULL; | ||||
|   eSym->winding = 0; | ||||
|   eSym->activeRegion = NULL; | ||||
|  | ||||
|   return e; | ||||
| } | ||||
|  | ||||
| /* Splice( a, b ) is best described by the Guibas/Stolfi paper or the | ||||
|  * CS348a notes (see mesh.h).  Basically it modifies the mesh so that | ||||
|  * a->Onext and b->Onext are exchanged.  This can have various effects | ||||
|  * depending on whether a and b belong to different face or vertex rings. | ||||
|  * For more explanation see __gl_meshSplice() below. | ||||
|  */ | ||||
| static void Splice( GLUhalfEdge *a, GLUhalfEdge *b ) | ||||
| { | ||||
|   GLUhalfEdge *aOnext = a->Onext; | ||||
|   GLUhalfEdge *bOnext = b->Onext; | ||||
|  | ||||
|   aOnext->Sym->Lnext = b; | ||||
|   bOnext->Sym->Lnext = a; | ||||
|   a->Onext = bOnext; | ||||
|   b->Onext = aOnext; | ||||
| } | ||||
|  | ||||
| /* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the | ||||
|  * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives | ||||
|  * a place to insert the new vertex in the global vertex list.  We insert | ||||
|  * the new vertex *before* vNext so that algorithms which walk the vertex | ||||
|  * list will not see the newly created vertices. | ||||
|  */ | ||||
| static void MakeVertex( GLUvertex *newVertex,  | ||||
| 			GLUhalfEdge *eOrig, GLUvertex *vNext ) | ||||
| { | ||||
|   GLUhalfEdge *e; | ||||
|   GLUvertex *vPrev; | ||||
|   GLUvertex *vNew = newVertex; | ||||
|  | ||||
|   assert(vNew != NULL); | ||||
|  | ||||
|   /* insert in circular doubly-linked list before vNext */ | ||||
|   vPrev = vNext->prev; | ||||
|   vNew->prev = vPrev; | ||||
|   vPrev->next = vNew; | ||||
|   vNew->next = vNext; | ||||
|   vNext->prev = vNew; | ||||
|  | ||||
|   vNew->anEdge = eOrig; | ||||
|   vNew->data = NULL; | ||||
|   /* leave coords, s, t undefined */ | ||||
|  | ||||
|   /* fix other edges on this vertex loop */ | ||||
|   e = eOrig; | ||||
|   do { | ||||
|     e->Org = vNew; | ||||
|     e = e->Onext; | ||||
|   } while( e != eOrig ); | ||||
| } | ||||
|  | ||||
| /* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left | ||||
|  * face of all edges in the face loop to which eOrig belongs.  "fNext" gives | ||||
|  * a place to insert the new face in the global face list.  We insert | ||||
|  * the new face *before* fNext so that algorithms which walk the face | ||||
|  * list will not see the newly created faces. | ||||
|  */ | ||||
| static void MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext ) | ||||
| { | ||||
|   GLUhalfEdge *e; | ||||
|   GLUface *fPrev; | ||||
|   GLUface *fNew = newFace; | ||||
|  | ||||
|   assert(fNew != NULL);  | ||||
|  | ||||
|   /* insert in circular doubly-linked list before fNext */ | ||||
|   fPrev = fNext->prev; | ||||
|   fNew->prev = fPrev; | ||||
|   fPrev->next = fNew; | ||||
|   fNew->next = fNext; | ||||
|   fNext->prev = fNew; | ||||
|  | ||||
|   fNew->anEdge = eOrig; | ||||
|   fNew->data = NULL; | ||||
|   fNew->trail = NULL; | ||||
|   fNew->marked = FALSE; | ||||
|  | ||||
|   /* The new face is marked "inside" if the old one was.  This is a | ||||
|    * convenience for the common case where a face has been split in two. | ||||
|    */ | ||||
|   fNew->inside = fNext->inside; | ||||
|  | ||||
|   /* fix other edges on this face loop */ | ||||
|   e = eOrig; | ||||
|   do { | ||||
|     e->Lface = fNew; | ||||
|     e = e->Lnext; | ||||
|   } while( e != eOrig ); | ||||
| } | ||||
|  | ||||
| /* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), | ||||
|  * and removes from the global edge list. | ||||
|  */ | ||||
| static void KillEdge( GLUhalfEdge *eDel ) | ||||
| { | ||||
|   GLUhalfEdge *ePrev, *eNext; | ||||
|  | ||||
|   /* Half-edges are allocated in pairs, see EdgePair above */ | ||||
|   if( eDel->Sym < eDel ) { eDel = eDel->Sym; } | ||||
|  | ||||
|   /* delete from circular doubly-linked list */ | ||||
|   eNext = eDel->next; | ||||
|   ePrev = eDel->Sym->next; | ||||
|   eNext->Sym->next = ePrev; | ||||
|   ePrev->Sym->next = eNext; | ||||
|  | ||||
|   memFree( eDel ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* KillVertex( vDel ) destroys a vertex and removes it from the global | ||||
|  * vertex list.  It updates the vertex loop to point to a given new vertex. | ||||
|  */ | ||||
| static void KillVertex( GLUvertex *vDel, GLUvertex *newOrg ) | ||||
| { | ||||
|   GLUhalfEdge *e, *eStart = vDel->anEdge; | ||||
|   GLUvertex *vPrev, *vNext; | ||||
|  | ||||
|   /* change the origin of all affected edges */ | ||||
|   e = eStart; | ||||
|   do { | ||||
|     e->Org = newOrg; | ||||
|     e = e->Onext; | ||||
|   } while( e != eStart ); | ||||
|  | ||||
|   /* delete from circular doubly-linked list */ | ||||
|   vPrev = vDel->prev; | ||||
|   vNext = vDel->next; | ||||
|   vNext->prev = vPrev; | ||||
|   vPrev->next = vNext; | ||||
|  | ||||
|   memFree( vDel ); | ||||
| } | ||||
|  | ||||
| /* KillFace( fDel ) destroys a face and removes it from the global face | ||||
|  * list.  It updates the face loop to point to a given new face. | ||||
|  */ | ||||
| static void KillFace( GLUface *fDel, GLUface *newLface ) | ||||
| { | ||||
|   GLUhalfEdge *e, *eStart = fDel->anEdge; | ||||
|   GLUface *fPrev, *fNext; | ||||
|  | ||||
|   /* change the left face of all affected edges */ | ||||
|   e = eStart; | ||||
|   do { | ||||
|     e->Lface = newLface; | ||||
|     e = e->Lnext; | ||||
|   } while( e != eStart ); | ||||
|  | ||||
|   /* delete from circular doubly-linked list */ | ||||
|   fPrev = fDel->prev; | ||||
|   fNext = fDel->next; | ||||
|   fNext->prev = fPrev; | ||||
|   fPrev->next = fNext; | ||||
|  | ||||
|   memFree( fDel ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /****************** Basic Edge Operations **********************/ | ||||
|  | ||||
| /* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). | ||||
|  * The loop consists of the two new half-edges. | ||||
|  */ | ||||
| GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh ) | ||||
| { | ||||
|   GLUvertex *newVertex1= allocVertex(); | ||||
|   GLUvertex *newVertex2= allocVertex(); | ||||
|   GLUface *newFace= allocFace(); | ||||
|   GLUhalfEdge *e; | ||||
|  | ||||
|   /* if any one is null then all get freed */ | ||||
|   if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) { | ||||
|      if (newVertex1 != NULL) memFree(newVertex1); | ||||
|      if (newVertex2 != NULL) memFree(newVertex2); | ||||
|      if (newFace != NULL) memFree(newFace);      | ||||
|      return NULL; | ||||
|   }  | ||||
|  | ||||
|   e = MakeEdge( &mesh->eHead ); | ||||
|   if (e == NULL) { | ||||
|      memFree(newVertex1); | ||||
|      memFree(newVertex2); | ||||
|      memFree(newFace); | ||||
|      return NULL; | ||||
|   } | ||||
|  | ||||
|   MakeVertex( newVertex1, e, &mesh->vHead ); | ||||
|   MakeVertex( newVertex2, e->Sym, &mesh->vHead ); | ||||
|   MakeFace( newFace, e, &mesh->fHead ); | ||||
|   return e; | ||||
| } | ||||
|    | ||||
|  | ||||
| /* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the | ||||
|  * mesh connectivity and topology.  It changes the mesh so that | ||||
|  *	eOrg->Onext <- OLD( eDst->Onext ) | ||||
|  *	eDst->Onext <- OLD( eOrg->Onext ) | ||||
|  * where OLD(...) means the value before the meshSplice operation. | ||||
|  * | ||||
|  * This can have two effects on the vertex structure: | ||||
|  *  - if eOrg->Org != eDst->Org, the two vertices are merged together | ||||
|  *  - if eOrg->Org == eDst->Org, the origin is split into two vertices | ||||
|  * In both cases, eDst->Org is changed and eOrg->Org is untouched. | ||||
|  * | ||||
|  * Similarly (and independently) for the face structure, | ||||
|  *  - if eOrg->Lface == eDst->Lface, one loop is split into two | ||||
|  *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one | ||||
|  * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. | ||||
|  * | ||||
|  * Some special cases: | ||||
|  * If eDst == eOrg, the operation has no effect. | ||||
|  * If eDst == eOrg->Lnext, the new face will have a single edge. | ||||
|  * If eDst == eOrg->Lprev, the old face will have a single edge. | ||||
|  * If eDst == eOrg->Onext, the new vertex will have a single edge. | ||||
|  * If eDst == eOrg->Oprev, the old vertex will have a single edge. | ||||
|  */ | ||||
| int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ) | ||||
| { | ||||
|   int joiningLoops = FALSE; | ||||
|   int joiningVertices = FALSE; | ||||
|  | ||||
|   if( eOrg == eDst ) return 1; | ||||
|  | ||||
|   if( eDst->Org != eOrg->Org ) { | ||||
|     /* We are merging two disjoint vertices -- destroy eDst->Org */ | ||||
|     joiningVertices = TRUE; | ||||
|     KillVertex( eDst->Org, eOrg->Org ); | ||||
|   } | ||||
|   if( eDst->Lface != eOrg->Lface ) { | ||||
|     /* We are connecting two disjoint loops -- destroy eDst->Lface */ | ||||
|     joiningLoops = TRUE; | ||||
|     KillFace( eDst->Lface, eOrg->Lface ); | ||||
|   } | ||||
|  | ||||
|   /* Change the edge structure */ | ||||
|   Splice( eDst, eOrg ); | ||||
|  | ||||
|   if( ! joiningVertices ) { | ||||
|     GLUvertex *newVertex= allocVertex(); | ||||
|     if (newVertex == NULL) return 0; | ||||
|  | ||||
|     /* We split one vertex into two -- the new vertex is eDst->Org. | ||||
|      * Make sure the old vertex points to a valid half-edge. | ||||
|      */ | ||||
|     MakeVertex( newVertex, eDst, eOrg->Org ); | ||||
|     eOrg->Org->anEdge = eOrg; | ||||
|   } | ||||
|   if( ! joiningLoops ) { | ||||
|     GLUface *newFace= allocFace();   | ||||
|     if (newFace == NULL) return 0; | ||||
|  | ||||
|     /* We split one loop into two -- the new loop is eDst->Lface. | ||||
|      * Make sure the old face points to a valid half-edge. | ||||
|      */ | ||||
|     MakeFace( newFace, eDst, eOrg->Lface ); | ||||
|     eOrg->Lface->anEdge = eOrg; | ||||
|   } | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases: | ||||
|  * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop | ||||
|  * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two; | ||||
|  * the newly created loop will contain eDel->Dst.  If the deletion of eDel | ||||
|  * would create isolated vertices, those are deleted as well. | ||||
|  * | ||||
|  * This function could be implemented as two calls to __gl_meshSplice | ||||
|  * plus a few calls to memFree, but this would allocate and delete | ||||
|  * unnecessary vertices and faces. | ||||
|  */ | ||||
| int __gl_meshDelete( GLUhalfEdge *eDel ) | ||||
| { | ||||
|   GLUhalfEdge *eDelSym = eDel->Sym; | ||||
|   int joiningLoops = FALSE; | ||||
|  | ||||
|   /* First step: disconnect the origin vertex eDel->Org.  We make all | ||||
|    * changes to get a consistent mesh in this "intermediate" state. | ||||
|    */ | ||||
|   if( eDel->Lface != eDel->Rface ) { | ||||
|     /* We are joining two loops into one -- remove the left face */ | ||||
|     joiningLoops = TRUE; | ||||
|     KillFace( eDel->Lface, eDel->Rface ); | ||||
|   } | ||||
|  | ||||
|   if( eDel->Onext == eDel ) { | ||||
|     KillVertex( eDel->Org, NULL ); | ||||
|   } else { | ||||
|     /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */ | ||||
|     eDel->Rface->anEdge = eDel->Oprev; | ||||
|     eDel->Org->anEdge = eDel->Onext; | ||||
|  | ||||
|     Splice( eDel, eDel->Oprev ); | ||||
|     if( ! joiningLoops ) { | ||||
|       GLUface *newFace= allocFace(); | ||||
|       if (newFace == NULL) return 0;  | ||||
|  | ||||
|       /* We are splitting one loop into two -- create a new loop for eDel. */ | ||||
|       MakeFace( newFace, eDel, eDel->Lface ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* Claim: the mesh is now in a consistent state, except that eDel->Org | ||||
|    * may have been deleted.  Now we disconnect eDel->Dst. | ||||
|    */ | ||||
|   if( eDelSym->Onext == eDelSym ) { | ||||
|     KillVertex( eDelSym->Org, NULL ); | ||||
|     KillFace( eDelSym->Lface, NULL ); | ||||
|   } else { | ||||
|     /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */ | ||||
|     eDel->Lface->anEdge = eDelSym->Oprev; | ||||
|     eDelSym->Org->anEdge = eDelSym->Onext; | ||||
|     Splice( eDelSym, eDelSym->Oprev ); | ||||
|   } | ||||
|  | ||||
|   /* Any isolated vertices or faces have already been freed. */ | ||||
|   KillEdge( eDel ); | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /******************** Other Edge Operations **********************/ | ||||
|  | ||||
| /* All these routines can be implemented with the basic edge | ||||
|  * operations above.  They are provided for convenience and efficiency. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that | ||||
|  * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. | ||||
|  * eOrg and eNew will have the same left face. | ||||
|  */ | ||||
| GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg ) | ||||
| { | ||||
|   GLUhalfEdge *eNewSym; | ||||
|   GLUhalfEdge *eNew = MakeEdge( eOrg ); | ||||
|   if (eNew == NULL) return NULL; | ||||
|  | ||||
|   eNewSym = eNew->Sym; | ||||
|  | ||||
|   /* Connect the new edge appropriately */ | ||||
|   Splice( eNew, eOrg->Lnext ); | ||||
|  | ||||
|   /* Set the vertex and face information */ | ||||
|   eNew->Org = eOrg->Dst; | ||||
|   { | ||||
|     GLUvertex *newVertex= allocVertex(); | ||||
|     if (newVertex == NULL) return NULL; | ||||
|  | ||||
|     MakeVertex( newVertex, eNewSym, eNew->Org ); | ||||
|   } | ||||
|   eNew->Lface = eNewSym->Lface = eOrg->Lface; | ||||
|  | ||||
|   return eNew; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, | ||||
|  * such that eNew == eOrg->Lnext.  The new vertex is eOrg->Dst == eNew->Org. | ||||
|  * eOrg and eNew will have the same left face. | ||||
|  */ | ||||
| GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg ) | ||||
| { | ||||
|   GLUhalfEdge *eNew; | ||||
|   GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg ); | ||||
|   if (tempHalfEdge == NULL) return NULL; | ||||
|  | ||||
|   eNew = tempHalfEdge->Sym; | ||||
|  | ||||
|   /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */ | ||||
|   Splice( eOrg->Sym, eOrg->Sym->Oprev ); | ||||
|   Splice( eOrg->Sym, eNew ); | ||||
|  | ||||
|   /* Set the vertex and face information */ | ||||
|   eOrg->Dst = eNew->Org; | ||||
|   eNew->Dst->anEdge = eNew->Sym;	/* may have pointed to eOrg->Sym */ | ||||
|   eNew->Rface = eOrg->Rface; | ||||
|   eNew->winding = eOrg->winding;	/* copy old winding information */ | ||||
|   eNew->Sym->winding = eOrg->Sym->winding; | ||||
|  | ||||
|   return eNew; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst | ||||
|  * to eDst->Org, and returns the corresponding half-edge eNew. | ||||
|  * If eOrg->Lface == eDst->Lface, this splits one loop into two, | ||||
|  * and the newly created loop is eNew->Lface.  Otherwise, two disjoint | ||||
|  * loops are merged into one, and the loop eDst->Lface is destroyed. | ||||
|  * | ||||
|  * If (eOrg == eDst), the new face will have only two edges. | ||||
|  * If (eOrg->Lnext == eDst), the old face is reduced to a single edge. | ||||
|  * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges. | ||||
|  */ | ||||
| GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ) | ||||
| { | ||||
|   GLUhalfEdge *eNewSym; | ||||
|   int joiningLoops = FALSE;   | ||||
|   GLUhalfEdge *eNew = MakeEdge( eOrg ); | ||||
|   if (eNew == NULL) return NULL; | ||||
|  | ||||
|   eNewSym = eNew->Sym; | ||||
|  | ||||
|   if( eDst->Lface != eOrg->Lface ) { | ||||
|     /* We are connecting two disjoint loops -- destroy eDst->Lface */ | ||||
|     joiningLoops = TRUE; | ||||
|     KillFace( eDst->Lface, eOrg->Lface ); | ||||
|   } | ||||
|  | ||||
|   /* Connect the new edge appropriately */ | ||||
|   Splice( eNew, eOrg->Lnext ); | ||||
|   Splice( eNewSym, eDst ); | ||||
|  | ||||
|   /* Set the vertex and face information */ | ||||
|   eNew->Org = eOrg->Dst; | ||||
|   eNewSym->Org = eDst->Org; | ||||
|   eNew->Lface = eNewSym->Lface = eOrg->Lface; | ||||
|  | ||||
|   /* Make sure the old face points to a valid half-edge */ | ||||
|   eOrg->Lface->anEdge = eNewSym; | ||||
|  | ||||
|   if( ! joiningLoops ) { | ||||
|     GLUface *newFace= allocFace(); | ||||
|     if (newFace == NULL) return NULL; | ||||
|  | ||||
|     /* We split one loop into two -- the new loop is eNew->Lface */ | ||||
|     MakeFace( newFace, eNew, eOrg->Lface ); | ||||
|   } | ||||
|   return eNew; | ||||
| } | ||||
|  | ||||
|  | ||||
| /******************** Other Operations **********************/ | ||||
|  | ||||
| /* __gl_meshZapFace( fZap ) destroys a face and removes it from the | ||||
|  * global face list.  All edges of fZap will have a NULL pointer as their | ||||
|  * left face.  Any edges which also have a NULL pointer as their right face | ||||
|  * are deleted entirely (along with any isolated vertices this produces). | ||||
|  * An entire mesh can be deleted by zapping its faces, one at a time, | ||||
|  * in any order.  Zapped faces cannot be used in further mesh operations! | ||||
|  */ | ||||
| void __gl_meshZapFace( GLUface *fZap ) | ||||
| { | ||||
|   GLUhalfEdge *eStart = fZap->anEdge; | ||||
|   GLUhalfEdge *e, *eNext, *eSym; | ||||
|   GLUface *fPrev, *fNext; | ||||
|  | ||||
|   /* walk around face, deleting edges whose right face is also NULL */ | ||||
|   eNext = eStart->Lnext; | ||||
|   do { | ||||
|     e = eNext; | ||||
|     eNext = e->Lnext; | ||||
|  | ||||
|     e->Lface = NULL; | ||||
|     if( e->Rface == NULL ) { | ||||
|       /* delete the edge -- see __gl_MeshDelete above */ | ||||
|  | ||||
|       if( e->Onext == e ) { | ||||
| 	KillVertex( e->Org, NULL ); | ||||
|       } else { | ||||
| 	/* Make sure that e->Org points to a valid half-edge */ | ||||
| 	e->Org->anEdge = e->Onext; | ||||
| 	Splice( e, e->Oprev ); | ||||
|       } | ||||
|       eSym = e->Sym; | ||||
|       if( eSym->Onext == eSym ) { | ||||
| 	KillVertex( eSym->Org, NULL ); | ||||
|       } else { | ||||
| 	/* Make sure that eSym->Org points to a valid half-edge */ | ||||
| 	eSym->Org->anEdge = eSym->Onext; | ||||
| 	Splice( eSym, eSym->Oprev ); | ||||
|       } | ||||
|       KillEdge( e ); | ||||
|     } | ||||
|   } while( e != eStart ); | ||||
|  | ||||
|   /* delete from circular doubly-linked list */ | ||||
|   fPrev = fZap->prev; | ||||
|   fNext = fZap->next; | ||||
|   fNext->prev = fPrev; | ||||
|   fPrev->next = fNext; | ||||
|  | ||||
|   memFree( fZap ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, | ||||
|  * and no loops (what we usually call a "face"). | ||||
|  */ | ||||
| GLUmesh *__gl_meshNewMesh( void ) | ||||
| { | ||||
|   GLUvertex *v; | ||||
|   GLUface *f; | ||||
|   GLUhalfEdge *e; | ||||
|   GLUhalfEdge *eSym; | ||||
|   GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh )); | ||||
|   if (mesh == NULL) { | ||||
|      return NULL; | ||||
|   } | ||||
|    | ||||
|   v = &mesh->vHead; | ||||
|   f = &mesh->fHead; | ||||
|   e = &mesh->eHead; | ||||
|   eSym = &mesh->eHeadSym; | ||||
|  | ||||
|   v->next = v->prev = v; | ||||
|   v->anEdge = NULL; | ||||
|   v->data = NULL; | ||||
|  | ||||
|   f->next = f->prev = f; | ||||
|   f->anEdge = NULL; | ||||
|   f->data = NULL; | ||||
|   f->trail = NULL; | ||||
|   f->marked = FALSE; | ||||
|   f->inside = FALSE; | ||||
|  | ||||
|   e->next = e; | ||||
|   e->Sym = eSym; | ||||
|   e->Onext = NULL; | ||||
|   e->Lnext = NULL; | ||||
|   e->Org = NULL; | ||||
|   e->Lface = NULL; | ||||
|   e->winding = 0; | ||||
|   e->activeRegion = NULL; | ||||
|  | ||||
|   eSym->next = eSym; | ||||
|   eSym->Sym = e; | ||||
|   eSym->Onext = NULL; | ||||
|   eSym->Lnext = NULL; | ||||
|   eSym->Org = NULL; | ||||
|   eSym->Lface = NULL; | ||||
|   eSym->winding = 0; | ||||
|   eSym->activeRegion = NULL; | ||||
|  | ||||
|   return mesh; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in | ||||
|  * both meshes, and returns the new mesh (the old meshes are destroyed). | ||||
|  */ | ||||
| GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 ) | ||||
| { | ||||
|   GLUface *f1 = &mesh1->fHead; | ||||
|   GLUvertex *v1 = &mesh1->vHead; | ||||
|   GLUhalfEdge *e1 = &mesh1->eHead; | ||||
|   GLUface *f2 = &mesh2->fHead; | ||||
|   GLUvertex *v2 = &mesh2->vHead; | ||||
|   GLUhalfEdge *e2 = &mesh2->eHead; | ||||
|  | ||||
|   /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ | ||||
|   if( f2->next != f2 ) { | ||||
|     f1->prev->next = f2->next; | ||||
|     f2->next->prev = f1->prev; | ||||
|     f2->prev->next = f1; | ||||
|     f1->prev = f2->prev; | ||||
|   } | ||||
|  | ||||
|   if( v2->next != v2 ) { | ||||
|     v1->prev->next = v2->next; | ||||
|     v2->next->prev = v1->prev; | ||||
|     v2->prev->next = v1; | ||||
|     v1->prev = v2->prev; | ||||
|   } | ||||
|  | ||||
|   if( e2->next != e2 ) { | ||||
|     e1->Sym->next->Sym->next = e2->next; | ||||
|     e2->next->Sym->next = e1->Sym->next; | ||||
|     e2->Sym->next->Sym->next = e1; | ||||
|     e1->Sym->next = e2->Sym->next; | ||||
|   } | ||||
|  | ||||
|   memFree( mesh2 ); | ||||
|   return mesh1; | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef DELETE_BY_ZAPPING | ||||
|  | ||||
| /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. | ||||
|  */ | ||||
| void __gl_meshDeleteMesh( GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *fHead = &mesh->fHead; | ||||
|  | ||||
|   while( fHead->next != fHead ) { | ||||
|     __gl_meshZapFace( fHead->next ); | ||||
|   } | ||||
|   assert( mesh->vHead.next == &mesh->vHead ); | ||||
|  | ||||
|   memFree( mesh ); | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. | ||||
|  */ | ||||
| void __gl_meshDeleteMesh( GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *f, *fNext; | ||||
|   GLUvertex *v, *vNext; | ||||
|   GLUhalfEdge *e, *eNext; | ||||
|  | ||||
|   for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) { | ||||
|     fNext = f->next; | ||||
|     memFree( f ); | ||||
|   } | ||||
|  | ||||
|   for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) { | ||||
|     vNext = v->next; | ||||
|     memFree( v ); | ||||
|   } | ||||
|  | ||||
|   for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { | ||||
|     /* One call frees both e and e->Sym (see EdgePair above) */ | ||||
|     eNext = e->next; | ||||
|     memFree( e ); | ||||
|   } | ||||
|  | ||||
|   memFree( mesh ); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifndef NDEBUG | ||||
|  | ||||
| /* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. | ||||
|  */ | ||||
| void __gl_meshCheckMesh( GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *fHead = &mesh->fHead; | ||||
|   GLUvertex *vHead = &mesh->vHead; | ||||
|   GLUhalfEdge *eHead = &mesh->eHead; | ||||
|   GLUface *f, *fPrev; | ||||
|   GLUvertex *v, *vPrev; | ||||
|   GLUhalfEdge *e, *ePrev; | ||||
|  | ||||
|   fPrev = fHead; | ||||
|   for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) { | ||||
|     assert( f->prev == fPrev ); | ||||
|     e = f->anEdge; | ||||
|     do { | ||||
|       assert( e->Sym != e ); | ||||
|       assert( e->Sym->Sym == e ); | ||||
|       assert( e->Lnext->Onext->Sym == e ); | ||||
|       assert( e->Onext->Sym->Lnext == e ); | ||||
|       assert( e->Lface == f ); | ||||
|       e = e->Lnext; | ||||
|     } while( e != f->anEdge ); | ||||
|   } | ||||
|   assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL ); | ||||
|  | ||||
|   vPrev = vHead; | ||||
|   for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) { | ||||
|     assert( v->prev == vPrev ); | ||||
|     e = v->anEdge; | ||||
|     do { | ||||
|       assert( e->Sym != e ); | ||||
|       assert( e->Sym->Sym == e ); | ||||
|       assert( e->Lnext->Onext->Sym == e ); | ||||
|       assert( e->Onext->Sym->Lnext == e ); | ||||
|       assert( e->Org == v ); | ||||
|       e = e->Onext; | ||||
|     } while( e != v->anEdge ); | ||||
|   } | ||||
|   assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL ); | ||||
|  | ||||
|   ePrev = eHead; | ||||
|   for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) { | ||||
|     assert( e->Sym->next == ePrev->Sym ); | ||||
|     assert( e->Sym != e ); | ||||
|     assert( e->Sym->Sym == e ); | ||||
|     assert( e->Org != NULL ); | ||||
|     assert( e->Dst != NULL ); | ||||
|     assert( e->Lnext->Onext->Sym == e ); | ||||
|     assert( e->Onext->Sym->Lnext == e ); | ||||
|   } | ||||
|   assert( e->Sym->next == ePrev->Sym | ||||
|        && e->Sym == &mesh->eHeadSym | ||||
|        && e->Sym->Sym == e | ||||
|        && e->Org == NULL && e->Dst == NULL | ||||
|        && e->Lface == NULL && e->Rface == NULL ); | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -1,266 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __mesh_h_ | ||||
| #define __mesh_h_ | ||||
|  | ||||
| #include <GL/gl.h> | ||||
|  | ||||
| typedef struct GLUmesh GLUmesh;  | ||||
|  | ||||
| typedef struct GLUvertex GLUvertex; | ||||
| typedef struct GLUface GLUface; | ||||
| typedef struct GLUhalfEdge GLUhalfEdge; | ||||
|  | ||||
| typedef struct ActiveRegion ActiveRegion;	/* Internal data */ | ||||
|  | ||||
| /* The mesh structure is similar in spirit, notation, and operations | ||||
|  * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives | ||||
|  * for the manipulation of general subdivisions and the computation of | ||||
|  * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985). | ||||
|  * For a simplified description, see the course notes for CS348a, | ||||
|  * "Mathematical Foundations of Computer Graphics", available at the | ||||
|  * Stanford bookstore (and taught during the fall quarter). | ||||
|  * The implementation also borrows a tiny subset of the graph-based approach | ||||
|  * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction | ||||
|  * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988). | ||||
|  * | ||||
|  * The fundamental data structure is the "half-edge".  Two half-edges | ||||
|  * go together to make an edge, but they point in opposite directions. | ||||
|  * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym), | ||||
|  * its origin vertex (Org), the face on its left side (Lface), and the | ||||
|  * adjacent half-edges in the CCW direction around the origin vertex | ||||
|  * (Onext) and around the left face (Lnext).  There is also a "next" | ||||
|  * pointer for the global edge list (see below). | ||||
|  * | ||||
|  * The notation used for mesh navigation: | ||||
|  *	Sym   = the mate of a half-edge (same edge, but opposite direction) | ||||
|  *	Onext = edge CCW around origin vertex (keep same origin) | ||||
|  *	Dnext = edge CCW around destination vertex (keep same dest) | ||||
|  *	Lnext = edge CCW around left face (dest becomes new origin) | ||||
|  *	Rnext = edge CCW around right face (origin becomes new dest) | ||||
|  * | ||||
|  * "prev" means to substitute CW for CCW in the definitions above. | ||||
|  * | ||||
|  * The mesh keeps global lists of all vertices, faces, and edges, | ||||
|  * stored as doubly-linked circular lists with a dummy header node. | ||||
|  * The mesh stores pointers to these dummy headers (vHead, fHead, eHead). | ||||
|  * | ||||
|  * The circular edge list is special; since half-edges always occur | ||||
|  * in pairs (e and e->Sym), each half-edge stores a pointer in only | ||||
|  * one direction.  Starting at eHead and following the e->next pointers | ||||
|  * will visit each *edge* once (ie. e or e->Sym, but not both). | ||||
|  * e->Sym stores a pointer in the opposite direction, thus it is | ||||
|  * always true that e->Sym->next->Sym->next == e. | ||||
|  * | ||||
|  * Each vertex has a pointer to next and previous vertices in the | ||||
|  * circular list, and a pointer to a half-edge with this vertex as | ||||
|  * the origin (NULL if this is the dummy header).  There is also a | ||||
|  * field "data" for client data. | ||||
|  * | ||||
|  * Each face has a pointer to the next and previous faces in the | ||||
|  * circular list, and a pointer to a half-edge with this face as | ||||
|  * the left face (NULL if this is the dummy header).  There is also | ||||
|  * a field "data" for client data. | ||||
|  * | ||||
|  * Note that what we call a "face" is really a loop; faces may consist | ||||
|  * of more than one loop (ie. not simply connected), but there is no | ||||
|  * record of this in the data structure.  The mesh may consist of | ||||
|  * several disconnected regions, so it may not be possible to visit | ||||
|  * the entire mesh by starting at a half-edge and traversing the edge | ||||
|  * structure. | ||||
|  * | ||||
|  * The mesh does NOT support isolated vertices; a vertex is deleted along | ||||
|  * with its last edge.  Similarly when two faces are merged, one of the | ||||
|  * faces is deleted (see __gl_meshDelete below).  For mesh operations, | ||||
|  * all face (loop) and vertex pointers must not be NULL.  However, once | ||||
|  * mesh manipulation is finished, __gl_MeshZapFace can be used to delete | ||||
|  * faces of the mesh, one at a time.  All external faces can be "zapped" | ||||
|  * before the mesh is returned to the client; then a NULL face indicates | ||||
|  * a region which is not part of the output polygon. | ||||
|  */ | ||||
|  | ||||
| struct GLUvertex { | ||||
|   GLUvertex	*next;		/* next vertex (never NULL) */ | ||||
|   GLUvertex	*prev;		/* previous vertex (never NULL) */ | ||||
|   GLUhalfEdge	*anEdge;	/* a half-edge with this origin */ | ||||
|   void		*data;		/* client's data */ | ||||
|  | ||||
|   /* Internal data (keep hidden) */ | ||||
|   GLdouble	coords[3];	/* vertex location in 3D */ | ||||
|   GLdouble	s, t;		/* projection onto the sweep plane */ | ||||
|   long		pqHandle;	/* to allow deletion from priority queue */ | ||||
| }; | ||||
|  | ||||
| struct GLUface { | ||||
|   GLUface	*next;		/* next face (never NULL) */ | ||||
|   GLUface	*prev;		/* previous face (never NULL) */ | ||||
|   GLUhalfEdge	*anEdge;	/* a half edge with this left face */ | ||||
|   void		*data;		/* room for client's data */ | ||||
|  | ||||
|   /* Internal data (keep hidden) */ | ||||
|   GLUface	*trail;		/* "stack" for conversion to strips */ | ||||
|   GLboolean	marked;		/* flag for conversion to strips */ | ||||
|   GLboolean	inside;		/* this face is in the polygon interior */ | ||||
| }; | ||||
|  | ||||
| struct GLUhalfEdge { | ||||
|   GLUhalfEdge	*next;		/* doubly-linked list (prev==Sym->next) */ | ||||
|   GLUhalfEdge	*Sym;		/* same edge, opposite direction */ | ||||
|   GLUhalfEdge	*Onext;		/* next edge CCW around origin */ | ||||
|   GLUhalfEdge	*Lnext;		/* next edge CCW around left face */ | ||||
|   GLUvertex	*Org;		/* origin vertex (Overtex too long) */ | ||||
|   GLUface	*Lface;		/* left face */ | ||||
|  | ||||
|   /* Internal data (keep hidden) */ | ||||
|   ActiveRegion	*activeRegion;	/* a region with this upper edge (sweep.c) */ | ||||
|   int		winding;	/* change in winding number when crossing | ||||
|                                    from the right face to the left face */ | ||||
| }; | ||||
|  | ||||
| #define	Rface	Sym->Lface | ||||
| #define Dst	Sym->Org | ||||
|  | ||||
| #define Oprev	Sym->Lnext | ||||
| #define Lprev   Onext->Sym | ||||
| #define Dprev	Lnext->Sym | ||||
| #define Rprev	Sym->Onext | ||||
| #define Dnext	Rprev->Sym	/* 3 pointers */ | ||||
| #define Rnext	Oprev->Sym	/* 3 pointers */ | ||||
|  | ||||
|  | ||||
| struct GLUmesh { | ||||
|   GLUvertex	vHead;		/* dummy header for vertex list */ | ||||
|   GLUface	fHead;		/* dummy header for face list */ | ||||
|   GLUhalfEdge	eHead;		/* dummy header for edge list */ | ||||
|   GLUhalfEdge	eHeadSym;	/* and its symmetric counterpart */ | ||||
| }; | ||||
|  | ||||
| /* The mesh operations below have three motivations: completeness, | ||||
|  * convenience, and efficiency.  The basic mesh operations are MakeEdge, | ||||
|  * Splice, and Delete.  All the other edge operations can be implemented | ||||
|  * in terms of these.  The other operations are provided for convenience | ||||
|  * and/or efficiency. | ||||
|  * | ||||
|  * When a face is split or a vertex is added, they are inserted into the | ||||
|  * global list *before* the existing vertex or face (ie. e->Org or e->Lface). | ||||
|  * This makes it easier to process all vertices or faces in the global lists | ||||
|  * without worrying about processing the same data twice.  As a convenience, | ||||
|  * when a face is split, the "inside" flag is copied from the old face. | ||||
|  * Other internal data (v->data, v->activeRegion, f->data, f->marked, | ||||
|  * f->trail, e->winding) is set to zero. | ||||
|  * | ||||
|  * ********************** Basic Edge Operations ************************** | ||||
|  * | ||||
|  * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop. | ||||
|  * The loop (face) consists of the two new half-edges. | ||||
|  * | ||||
|  * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the | ||||
|  * mesh connectivity and topology.  It changes the mesh so that | ||||
|  *	eOrg->Onext <- OLD( eDst->Onext ) | ||||
|  *	eDst->Onext <- OLD( eOrg->Onext ) | ||||
|  * where OLD(...) means the value before the meshSplice operation. | ||||
|  * | ||||
|  * This can have two effects on the vertex structure: | ||||
|  *  - if eOrg->Org != eDst->Org, the two vertices are merged together | ||||
|  *  - if eOrg->Org == eDst->Org, the origin is split into two vertices | ||||
|  * In both cases, eDst->Org is changed and eOrg->Org is untouched. | ||||
|  * | ||||
|  * Similarly (and independently) for the face structure, | ||||
|  *  - if eOrg->Lface == eDst->Lface, one loop is split into two | ||||
|  *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one | ||||
|  * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. | ||||
|  * | ||||
|  * __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases: | ||||
|  * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop | ||||
|  * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two; | ||||
|  * the newly created loop will contain eDel->Dst.  If the deletion of eDel | ||||
|  * would create isolated vertices, those are deleted as well. | ||||
|  * | ||||
|  * ********************** Other Edge Operations ************************** | ||||
|  * | ||||
|  * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that | ||||
|  * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. | ||||
|  * eOrg and eNew will have the same left face. | ||||
|  * | ||||
|  * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, | ||||
|  * such that eNew == eOrg->Lnext.  The new vertex is eOrg->Dst == eNew->Org. | ||||
|  * eOrg and eNew will have the same left face. | ||||
|  * | ||||
|  * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst | ||||
|  * to eDst->Org, and returns the corresponding half-edge eNew. | ||||
|  * If eOrg->Lface == eDst->Lface, this splits one loop into two, | ||||
|  * and the newly created loop is eNew->Lface.  Otherwise, two disjoint | ||||
|  * loops are merged into one, and the loop eDst->Lface is destroyed. | ||||
|  * | ||||
|  * ************************ Other Operations ***************************** | ||||
|  * | ||||
|  * __gl_meshNewMesh() creates a new mesh with no edges, no vertices, | ||||
|  * and no loops (what we usually call a "face"). | ||||
|  * | ||||
|  * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in | ||||
|  * both meshes, and returns the new mesh (the old meshes are destroyed). | ||||
|  * | ||||
|  * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. | ||||
|  * | ||||
|  * __gl_meshZapFace( fZap ) destroys a face and removes it from the | ||||
|  * global face list.  All edges of fZap will have a NULL pointer as their | ||||
|  * left face.  Any edges which also have a NULL pointer as their right face | ||||
|  * are deleted entirely (along with any isolated vertices this produces). | ||||
|  * An entire mesh can be deleted by zapping its faces, one at a time, | ||||
|  * in any order.  Zapped faces cannot be used in further mesh operations! | ||||
|  * | ||||
|  * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. | ||||
|  */ | ||||
|  | ||||
| GLUhalfEdge	*__gl_meshMakeEdge( GLUmesh *mesh ); | ||||
| int		__gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ); | ||||
| int		__gl_meshDelete( GLUhalfEdge *eDel ); | ||||
|  | ||||
| GLUhalfEdge	*__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg ); | ||||
| GLUhalfEdge	*__gl_meshSplitEdge( GLUhalfEdge *eOrg ); | ||||
| GLUhalfEdge	*__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ); | ||||
|  | ||||
| GLUmesh		*__gl_meshNewMesh( void ); | ||||
| GLUmesh		*__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 ); | ||||
| void		__gl_meshDeleteMesh( GLUmesh *mesh ); | ||||
| void		__gl_meshZapFace( GLUface *fZap ); | ||||
|  | ||||
| #ifdef NDEBUG | ||||
| #define		__gl_meshCheckMesh( mesh ) | ||||
| #else | ||||
| void		__gl_meshCheckMesh( GLUmesh *mesh ); | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
| @@ -1,257 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include "mesh.h" | ||||
| #include "tess.h" | ||||
| #include "normal.h" | ||||
| #include <math.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| #ifndef TRUE | ||||
| #define TRUE 1 | ||||
| #endif | ||||
| #ifndef FALSE | ||||
| #define FALSE 0 | ||||
| #endif | ||||
|  | ||||
| #define Dot(u,v)	(u[0]*v[0] + u[1]*v[1] + u[2]*v[2]) | ||||
|  | ||||
| #if 0 | ||||
| static void Normalize( GLdouble v[3] ) | ||||
| { | ||||
|   GLdouble len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; | ||||
|  | ||||
|   assert( len > 0 ); | ||||
|   len = sqrt( len ); | ||||
|   v[0] /= len; | ||||
|   v[1] /= len; | ||||
|   v[2] /= len; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #undef	ABS | ||||
| #define ABS(x)	((x) < 0 ? -(x) : (x)) | ||||
|  | ||||
| static int LongAxis( GLdouble v[3] ) | ||||
| { | ||||
|   int i = 0; | ||||
|  | ||||
|   if( ABS(v[1]) > ABS(v[0]) ) { i = 1; } | ||||
|   if( ABS(v[2]) > ABS(v[i]) ) { i = 2; } | ||||
|   return i; | ||||
| } | ||||
|  | ||||
| static void ComputeNormal( GLUtesselator *tess, GLdouble norm[3] ) | ||||
| { | ||||
|   GLUvertex *v, *v1, *v2; | ||||
|   GLdouble c, tLen2, maxLen2; | ||||
|   GLdouble maxVal[3], minVal[3], d1[3], d2[3], tNorm[3]; | ||||
|   GLUvertex *maxVert[3], *minVert[3]; | ||||
|   GLUvertex *vHead = &tess->mesh->vHead; | ||||
|   int i; | ||||
|  | ||||
|   maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU_TESS_MAX_COORD; | ||||
|   minVal[0] = minVal[1] = minVal[2] = 2 * GLU_TESS_MAX_COORD; | ||||
|  | ||||
|   for( v = vHead->next; v != vHead; v = v->next ) { | ||||
|     for( i = 0; i < 3; ++i ) { | ||||
|       c = v->coords[i]; | ||||
|       if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; } | ||||
|       if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* Find two vertices separated by at least 1/sqrt(3) of the maximum | ||||
|    * distance between any two vertices | ||||
|    */ | ||||
|   i = 0; | ||||
|   if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; } | ||||
|   if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; } | ||||
|   if( minVal[i] >= maxVal[i] ) { | ||||
|     /* All vertices are the same -- normal doesn't matter */ | ||||
|     norm[0] = 0; norm[1] = 0; norm[2] = 1; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   /* Look for a third vertex which forms the triangle with maximum area | ||||
|    * (Length of normal == twice the triangle area) | ||||
|    */ | ||||
|   maxLen2 = 0; | ||||
|   v1 = minVert[i]; | ||||
|   v2 = maxVert[i]; | ||||
|   d1[0] = v1->coords[0] - v2->coords[0]; | ||||
|   d1[1] = v1->coords[1] - v2->coords[1]; | ||||
|   d1[2] = v1->coords[2] - v2->coords[2]; | ||||
|   for( v = vHead->next; v != vHead; v = v->next ) { | ||||
|     d2[0] = v->coords[0] - v2->coords[0]; | ||||
|     d2[1] = v->coords[1] - v2->coords[1]; | ||||
|     d2[2] = v->coords[2] - v2->coords[2]; | ||||
|     tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1]; | ||||
|     tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2]; | ||||
|     tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0]; | ||||
|     tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2]; | ||||
|     if( tLen2 > maxLen2 ) { | ||||
|       maxLen2 = tLen2; | ||||
|       norm[0] = tNorm[0]; | ||||
|       norm[1] = tNorm[1]; | ||||
|       norm[2] = tNorm[2]; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if( maxLen2 <= 0 ) { | ||||
|     /* All points lie on a single line -- any decent normal will do */ | ||||
|     norm[0] = norm[1] = norm[2] = 0; | ||||
|     norm[LongAxis(d1)] = 1; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void CheckOrientation( GLUtesselator *tess ) | ||||
| { | ||||
|   GLdouble area; | ||||
|   GLUface *f, *fHead = &tess->mesh->fHead; | ||||
|   GLUvertex *v, *vHead = &tess->mesh->vHead; | ||||
|   GLUhalfEdge *e; | ||||
|  | ||||
|   /* When we compute the normal automatically, we choose the orientation | ||||
|    * so that the sum of the signed areas of all contours is non-negative. | ||||
|    */ | ||||
|   area = 0; | ||||
|   for( f = fHead->next; f != fHead; f = f->next ) { | ||||
|     e = f->anEdge; | ||||
|     if( e->winding <= 0 ) continue; | ||||
|     do { | ||||
|       area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t); | ||||
|       e = e->Lnext; | ||||
|     } while( e != f->anEdge ); | ||||
|   } | ||||
|   if( area < 0 ) { | ||||
|     /* Reverse the orientation by flipping all the t-coordinates */ | ||||
|     for( v = vHead->next; v != vHead; v = v->next ) { | ||||
|       v->t = - v->t; | ||||
|     } | ||||
|     tess->tUnit[0] = - tess->tUnit[0]; | ||||
|     tess->tUnit[1] = - tess->tUnit[1]; | ||||
|     tess->tUnit[2] = - tess->tUnit[2]; | ||||
|   } | ||||
| } | ||||
|  | ||||
| #ifdef FOR_TRITE_TEST_PROGRAM | ||||
| #include <stdlib.h> | ||||
| extern int RandomSweep; | ||||
| #define S_UNIT_X	(RandomSweep ? (2*drand48()-1) : 1.0) | ||||
| #define S_UNIT_Y	(RandomSweep ? (2*drand48()-1) : 0.0) | ||||
| #else | ||||
| #if defined(SLANTED_SWEEP) | ||||
| /* The "feature merging" is not intended to be complete.  There are | ||||
|  * special cases where edges are nearly parallel to the sweep line | ||||
|  * which are not implemented.  The algorithm should still behave | ||||
|  * robustly (ie. produce a reasonable tesselation) in the presence | ||||
|  * of such edges, however it may miss features which could have been | ||||
|  * merged.  We could minimize this effect by choosing the sweep line | ||||
|  * direction to be something unusual (ie. not parallel to one of the | ||||
|  * coordinate axes). | ||||
|  */ | ||||
| #define S_UNIT_X	0.50941539564955385	/* Pre-normalized */ | ||||
| #define S_UNIT_Y	0.86052074622010633 | ||||
| #else | ||||
| #define S_UNIT_X	1.0 | ||||
| #define S_UNIT_Y	0.0 | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| /* Determine the polygon normal and project vertices onto the plane | ||||
|  * of the polygon. | ||||
|  */ | ||||
| void __gl_projectPolygon( GLUtesselator *tess ) | ||||
| { | ||||
|   GLUvertex *v, *vHead = &tess->mesh->vHead; | ||||
|   GLdouble norm[3]; | ||||
|   GLdouble *sUnit, *tUnit; | ||||
|   int i, computedNormal = FALSE; | ||||
|  | ||||
|   norm[0] = tess->normal[0]; | ||||
|   norm[1] = tess->normal[1]; | ||||
|   norm[2] = tess->normal[2]; | ||||
|   if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) { | ||||
|     ComputeNormal( tess, norm ); | ||||
|     computedNormal = TRUE; | ||||
|   } | ||||
|   sUnit = tess->sUnit; | ||||
|   tUnit = tess->tUnit; | ||||
|   i = LongAxis( norm ); | ||||
|  | ||||
| #if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT) | ||||
|   /* Choose the initial sUnit vector to be approximately perpendicular | ||||
|    * to the normal. | ||||
|    */ | ||||
|   Normalize( norm ); | ||||
|  | ||||
|   sUnit[i] = 0; | ||||
|   sUnit[(i+1)%3] = S_UNIT_X; | ||||
|   sUnit[(i+2)%3] = S_UNIT_Y; | ||||
|  | ||||
|   /* Now make it exactly perpendicular */ | ||||
|   w = Dot( sUnit, norm ); | ||||
|   sUnit[0] -= w * norm[0]; | ||||
|   sUnit[1] -= w * norm[1]; | ||||
|   sUnit[2] -= w * norm[2]; | ||||
|   Normalize( sUnit ); | ||||
|  | ||||
|   /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ | ||||
|   tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1]; | ||||
|   tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2]; | ||||
|   tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0]; | ||||
|   Normalize( tUnit ); | ||||
| #else | ||||
|   /* Project perpendicular to a coordinate axis -- better numerically */ | ||||
|   sUnit[i] = 0; | ||||
|   sUnit[(i+1)%3] = S_UNIT_X; | ||||
|   sUnit[(i+2)%3] = S_UNIT_Y; | ||||
|  | ||||
|   tUnit[i] = 0; | ||||
|   tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; | ||||
|   tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; | ||||
| #endif | ||||
|  | ||||
|   /* Project the vertices onto the sweep plane */ | ||||
|   for( v = vHead->next; v != vHead; v = v->next ) { | ||||
|     v->s = Dot( v->coords, sUnit ); | ||||
|     v->t = Dot( v->coords, tUnit ); | ||||
|   } | ||||
|   if( computedNormal ) { | ||||
|     CheckOrientation( tess ); | ||||
|   } | ||||
| } | ||||
| @@ -1,46 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __normal_h_ | ||||
| #define __normal_h_ | ||||
|  | ||||
| #include "tess.h" | ||||
| #include "tesselator.h" | ||||
|  | ||||
| /* __gl_projectPolygon( tess ) determines the polygon normal | ||||
|  * and project vertices onto the plane of the polygon. | ||||
|  */ | ||||
| void __gl_projectPolygon( GLUtesselator *tess ); | ||||
|  | ||||
| #endif | ||||
| @@ -1,256 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include <assert.h> | ||||
| #include "priorityq-heap.h" | ||||
| #include "memalloc.h" | ||||
|  | ||||
| #define INIT_SIZE	32 | ||||
|  | ||||
| #ifndef TRUE | ||||
| #define TRUE 1 | ||||
| #endif | ||||
| #ifndef FALSE | ||||
| #define FALSE 0 | ||||
| #endif | ||||
|  | ||||
| #ifdef FOR_TRITE_TEST_PROGRAM | ||||
| #define LEQ(x,y)	(*pq->leq)(x,y) | ||||
| #else | ||||
| /* Violates modularity, but a little faster */ | ||||
| #include "geom.h" | ||||
| #define LEQ(x,y)	VertLeq((GLUvertex *)x, (GLUvertex *)y) | ||||
| #endif | ||||
|  | ||||
| /* really __gl_pqHeapNewPriorityQ */ | ||||
| PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ) | ||||
| { | ||||
|   PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ )); | ||||
|   if (pq == NULL) return NULL; | ||||
|  | ||||
|   pq->size = 0; | ||||
|   pq->max = INIT_SIZE; | ||||
|   pq->nodes = (PQnode *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->nodes[0]) ); | ||||
|   if (pq->nodes == NULL) { | ||||
|      memFree(pq); | ||||
|      return NULL; | ||||
|   } | ||||
|  | ||||
|   pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->handles[0]) ); | ||||
|   if (pq->handles == NULL) { | ||||
|      memFree(pq->nodes); | ||||
|      memFree(pq); | ||||
|      return NULL; | ||||
|   } | ||||
|  | ||||
|   pq->initialized = FALSE; | ||||
|   pq->freeList = 0; | ||||
|   pq->leq = leq; | ||||
|  | ||||
|   pq->nodes[1].handle = 1;	/* so that Minimum() returns NULL */ | ||||
|   pq->handles[1].key = NULL; | ||||
|   return pq; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqHeapDeletePriorityQ */ | ||||
| void pqDeletePriorityQ( PriorityQ *pq ) | ||||
| { | ||||
|   memFree( pq->handles ); | ||||
|   memFree( pq->nodes ); | ||||
|   memFree( pq ); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void FloatDown( PriorityQ *pq, long curr ) | ||||
| { | ||||
|   PQnode *n = pq->nodes; | ||||
|   PQhandleElem *h = pq->handles; | ||||
|   PQhandle hCurr, hChild; | ||||
|   long child; | ||||
|  | ||||
|   hCurr = n[curr].handle; | ||||
|   for( ;; ) { | ||||
|     child = curr << 1; | ||||
|     if( child < pq->size && LEQ( h[n[child+1].handle].key, | ||||
| 				 h[n[child].handle].key )) { | ||||
|       ++child; | ||||
|     } | ||||
|  | ||||
|     assert(child <= pq->max); | ||||
|  | ||||
|     hChild = n[child].handle; | ||||
|     if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) { | ||||
|       n[curr].handle = hCurr; | ||||
|       h[hCurr].node = curr; | ||||
|       break; | ||||
|     } | ||||
|     n[curr].handle = hChild; | ||||
|     h[hChild].node = curr; | ||||
|     curr = child; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void FloatUp( PriorityQ *pq, long curr ) | ||||
| { | ||||
|   PQnode *n = pq->nodes; | ||||
|   PQhandleElem *h = pq->handles; | ||||
|   PQhandle hCurr, hParent; | ||||
|   long parent; | ||||
|  | ||||
|   hCurr = n[curr].handle; | ||||
|   for( ;; ) { | ||||
|     parent = curr >> 1; | ||||
|     hParent = n[parent].handle; | ||||
|     if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) { | ||||
|       n[curr].handle = hCurr; | ||||
|       h[hCurr].node = curr; | ||||
|       break; | ||||
|     } | ||||
|     n[curr].handle = hParent; | ||||
|     h[hParent].node = curr; | ||||
|     curr = parent; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /* really __gl_pqHeapInit */ | ||||
| void pqInit( PriorityQ *pq ) | ||||
| { | ||||
|   long i; | ||||
|  | ||||
|   /* This method of building a heap is O(n), rather than O(n lg n). */ | ||||
|  | ||||
|   for( i = pq->size; i >= 1; --i ) { | ||||
|     FloatDown( pq, i ); | ||||
|   } | ||||
|   pq->initialized = TRUE; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqHeapInsert */ | ||||
| /* returns LONG_MAX iff out of memory */ | ||||
| PQhandle pqInsert( PriorityQ *pq, PQkey keyNew ) | ||||
| { | ||||
|   long curr; | ||||
|   PQhandle free_handle; | ||||
|  | ||||
|   curr = ++ pq->size; | ||||
|   if( (curr*2) > pq->max ) { | ||||
|     PQnode *saveNodes= pq->nodes; | ||||
|     PQhandleElem *saveHandles= pq->handles; | ||||
|  | ||||
|     /* If the heap overflows, double its size. */ | ||||
|     pq->max <<= 1; | ||||
|     pq->nodes = (PQnode *)memRealloc( pq->nodes,  | ||||
| 				     (size_t)  | ||||
| 				     ((pq->max + 1) * sizeof( pq->nodes[0] ))); | ||||
|     if (pq->nodes == NULL) { | ||||
|        pq->nodes = saveNodes;	/* restore ptr to free upon return */ | ||||
|        return LONG_MAX; | ||||
|     } | ||||
|     pq->handles = (PQhandleElem *)memRealloc( pq->handles, | ||||
| 			                     (size_t) | ||||
| 			                      ((pq->max + 1) *  | ||||
| 					       sizeof( pq->handles[0] ))); | ||||
|     if (pq->handles == NULL) { | ||||
|        pq->handles = saveHandles; /* restore ptr to free upon return */ | ||||
|        return LONG_MAX; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if( pq->freeList == 0 ) { | ||||
|     free_handle = curr; | ||||
|   } else { | ||||
|     free_handle = pq->freeList; | ||||
|     pq->freeList = pq->handles[free_handle].node; | ||||
|   } | ||||
|  | ||||
|   pq->nodes[curr].handle = free_handle; | ||||
|   pq->handles[free_handle].node = curr; | ||||
|   pq->handles[free_handle].key = keyNew; | ||||
|  | ||||
|   if( pq->initialized ) { | ||||
|     FloatUp( pq, curr ); | ||||
|   } | ||||
|   assert(free_handle != LONG_MAX); | ||||
|   return free_handle; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqHeapExtractMin */ | ||||
| PQkey pqExtractMin( PriorityQ *pq ) | ||||
| { | ||||
|   PQnode *n = pq->nodes; | ||||
|   PQhandleElem *h = pq->handles; | ||||
|   PQhandle hMin = n[1].handle; | ||||
|   PQkey min = h[hMin].key; | ||||
|  | ||||
|   if( pq->size > 0 ) { | ||||
|     n[1].handle = n[pq->size].handle; | ||||
|     h[n[1].handle].node = 1; | ||||
|  | ||||
|     h[hMin].key = NULL; | ||||
|     h[hMin].node = pq->freeList; | ||||
|     pq->freeList = hMin; | ||||
|  | ||||
|     if( -- pq->size > 0 ) { | ||||
|       FloatDown( pq, 1 ); | ||||
|     } | ||||
|   } | ||||
|   return min; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqHeapDelete */ | ||||
| void pqDelete( PriorityQ *pq, PQhandle hCurr ) | ||||
| { | ||||
|   PQnode *n = pq->nodes; | ||||
|   PQhandleElem *h = pq->handles; | ||||
|   long curr; | ||||
|  | ||||
|   assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL ); | ||||
|  | ||||
|   curr = h[hCurr].node; | ||||
|   n[curr].handle = n[pq->size].handle; | ||||
|   h[n[curr].handle].node = curr; | ||||
|  | ||||
|   if( curr <= -- pq->size ) { | ||||
|     if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) { | ||||
|       FloatDown( pq, curr ); | ||||
|     } else { | ||||
|       FloatUp( pq, curr ); | ||||
|     } | ||||
|   } | ||||
|   h[hCurr].key = NULL; | ||||
|   h[hCurr].node = pq->freeList; | ||||
|   pq->freeList = hCurr; | ||||
| } | ||||
| @@ -1,107 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __priorityq_heap_h_ | ||||
| #define __priorityq_heap_h_ | ||||
|  | ||||
| /* Use #define's so that another heap implementation can use this one */ | ||||
|  | ||||
| #define PQkey			PQHeapKey | ||||
| #define PQhandle		PQHeapHandle | ||||
| #define PriorityQ		PriorityQHeap | ||||
|  | ||||
| #define pqNewPriorityQ(leq)	__gl_pqHeapNewPriorityQ(leq) | ||||
| #define pqDeletePriorityQ(pq)	__gl_pqHeapDeletePriorityQ(pq) | ||||
|  | ||||
| /* The basic operations are insertion of a new key (pqInsert), | ||||
|  * and examination/extraction of a key whose value is minimum | ||||
|  * (pqMinimum/pqExtractMin).  Deletion is also allowed (pqDelete); | ||||
|  * for this purpose pqInsert returns a "handle" which is supplied | ||||
|  * as the argument. | ||||
|  * | ||||
|  * An initial heap may be created efficiently by calling pqInsert | ||||
|  * repeatedly, then calling pqInit.  In any case pqInit must be called | ||||
|  * before any operations other than pqInsert are used. | ||||
|  * | ||||
|  * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. | ||||
|  * This may also be tested with pqIsEmpty. | ||||
|  */ | ||||
| #define pqInit(pq)		__gl_pqHeapInit(pq) | ||||
| #define pqInsert(pq,key)	__gl_pqHeapInsert(pq,key) | ||||
| #define pqMinimum(pq)		__gl_pqHeapMinimum(pq) | ||||
| #define pqExtractMin(pq)	__gl_pqHeapExtractMin(pq) | ||||
| #define pqDelete(pq,handle)	__gl_pqHeapDelete(pq,handle) | ||||
| #define pqIsEmpty(pq)		__gl_pqHeapIsEmpty(pq) | ||||
|  | ||||
|  | ||||
| /* Since we support deletion the data structure is a little more | ||||
|  * complicated than an ordinary heap.  "nodes" is the heap itself; | ||||
|  * active nodes are stored in the range 1..pq->size.  When the | ||||
|  * heap exceeds its allocated size (pq->max), its size doubles. | ||||
|  * The children of node i are nodes 2i and 2i+1. | ||||
|  * | ||||
|  * Each node stores an index into an array "handles".  Each handle | ||||
|  * stores a key, plus a pointer back to the node which currently | ||||
|  * represents that key (ie. nodes[handles[i].node].handle == i). | ||||
|  */ | ||||
|  | ||||
| typedef void *PQkey; | ||||
| typedef long PQhandle; | ||||
| typedef struct PriorityQ PriorityQ; | ||||
|  | ||||
| typedef struct { PQhandle handle; } PQnode; | ||||
| typedef struct { PQkey key; PQhandle node; } PQhandleElem; | ||||
|  | ||||
| struct PriorityQ { | ||||
|   PQnode	*nodes; | ||||
|   PQhandleElem	*handles; | ||||
|   long		size, max; | ||||
|   PQhandle	freeList; | ||||
|   int		initialized; | ||||
|   int		(*leq)(PQkey key1, PQkey key2); | ||||
| }; | ||||
|    | ||||
| PriorityQ	*pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ); | ||||
| void		pqDeletePriorityQ( PriorityQ *pq ); | ||||
|  | ||||
| void		pqInit( PriorityQ *pq ); | ||||
| PQhandle	pqInsert( PriorityQ *pq, PQkey key ); | ||||
| PQkey		pqExtractMin( PriorityQ *pq ); | ||||
| void		pqDelete( PriorityQ *pq, PQhandle handle ); | ||||
|  | ||||
|  | ||||
| #define __gl_pqHeapMinimum(pq)	((pq)->handles[(pq)->nodes[1].handle].key) | ||||
| #define __gl_pqHeapIsEmpty(pq)	((pq)->size == 0) | ||||
|  | ||||
| #endif | ||||
| @@ -1,117 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __priorityq_sort_h_ | ||||
| #define __priorityq_sort_h_ | ||||
|  | ||||
| #include "priorityq-heap.h" | ||||
|  | ||||
| #undef PQkey | ||||
| #undef PQhandle | ||||
| #undef PriorityQ | ||||
| #undef pqNewPriorityQ | ||||
| #undef pqDeletePriorityQ | ||||
| #undef pqInit | ||||
| #undef pqInsert | ||||
| #undef pqMinimum | ||||
| #undef pqExtractMin | ||||
| #undef pqDelete | ||||
| #undef pqIsEmpty | ||||
|  | ||||
| /* Use #define's so that another heap implementation can use this one */ | ||||
|  | ||||
| #define PQkey			PQSortKey | ||||
| #define PQhandle		PQSortHandle | ||||
| #define PriorityQ		PriorityQSort | ||||
|  | ||||
| #define pqNewPriorityQ(leq)	__gl_pqSortNewPriorityQ(leq) | ||||
| #define pqDeletePriorityQ(pq)	__gl_pqSortDeletePriorityQ(pq) | ||||
|  | ||||
| /* The basic operations are insertion of a new key (pqInsert), | ||||
|  * and examination/extraction of a key whose value is minimum | ||||
|  * (pqMinimum/pqExtractMin).  Deletion is also allowed (pqDelete); | ||||
|  * for this purpose pqInsert returns a "handle" which is supplied | ||||
|  * as the argument. | ||||
|  * | ||||
|  * An initial heap may be created efficiently by calling pqInsert | ||||
|  * repeatedly, then calling pqInit.  In any case pqInit must be called | ||||
|  * before any operations other than pqInsert are used. | ||||
|  * | ||||
|  * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. | ||||
|  * This may also be tested with pqIsEmpty. | ||||
|  */ | ||||
| #define pqInit(pq)		__gl_pqSortInit(pq) | ||||
| #define pqInsert(pq,key)	__gl_pqSortInsert(pq,key) | ||||
| #define pqMinimum(pq)		__gl_pqSortMinimum(pq) | ||||
| #define pqExtractMin(pq)	__gl_pqSortExtractMin(pq) | ||||
| #define pqDelete(pq,handle)	__gl_pqSortDelete(pq,handle) | ||||
| #define pqIsEmpty(pq)		__gl_pqSortIsEmpty(pq) | ||||
|  | ||||
|  | ||||
| /* Since we support deletion the data structure is a little more | ||||
|  * complicated than an ordinary heap.  "nodes" is the heap itself; | ||||
|  * active nodes are stored in the range 1..pq->size.  When the | ||||
|  * heap exceeds its allocated size (pq->max), its size doubles. | ||||
|  * The children of node i are nodes 2i and 2i+1. | ||||
|  * | ||||
|  * Each node stores an index into an array "handles".  Each handle | ||||
|  * stores a key, plus a pointer back to the node which currently | ||||
|  * represents that key (ie. nodes[handles[i].node].handle == i). | ||||
|  */ | ||||
|  | ||||
| typedef PQHeapKey PQkey; | ||||
| typedef PQHeapHandle PQhandle; | ||||
| typedef struct PriorityQ PriorityQ; | ||||
|  | ||||
| struct PriorityQ { | ||||
|   PriorityQHeap	*heap; | ||||
|   PQkey		*keys; | ||||
|   PQkey		**order; | ||||
|   PQhandle	size, max; | ||||
|   int		initialized; | ||||
|   int		(*leq)(PQkey key1, PQkey key2); | ||||
| }; | ||||
|    | ||||
| PriorityQ	*pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ); | ||||
| void		pqDeletePriorityQ( PriorityQ *pq ); | ||||
|  | ||||
| int		pqInit( PriorityQ *pq ); | ||||
| PQhandle	pqInsert( PriorityQ *pq, PQkey key ); | ||||
| PQkey		pqExtractMin( PriorityQ *pq ); | ||||
| void		pqDelete( PriorityQ *pq, PQhandle handle ); | ||||
|  | ||||
| PQkey		pqMinimum( PriorityQ *pq ); | ||||
| int		pqIsEmpty( PriorityQ *pq ); | ||||
|  | ||||
| #endif | ||||
| @@ -1,261 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include <stddef.h> | ||||
| #include <assert.h> | ||||
| #include <limits.h>		/* LONG_MAX */ | ||||
| #include "memalloc.h" | ||||
|  | ||||
| /* Include all the code for the regular heap-based queue here. */ | ||||
|  | ||||
| #include "priorityq-heap.c" | ||||
|  | ||||
| /* Now redefine all the function names to map to their "Sort" versions. */ | ||||
|  | ||||
| #include "priorityq-sort.h" | ||||
|  | ||||
| /* really __gl_pqSortNewPriorityQ */ | ||||
| PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ) | ||||
| { | ||||
|   PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ )); | ||||
|   if (pq == NULL) return NULL; | ||||
|  | ||||
|   pq->heap = __gl_pqHeapNewPriorityQ( leq ); | ||||
|   if (pq->heap == NULL) { | ||||
|      memFree(pq); | ||||
|      return NULL; | ||||
|   } | ||||
|  | ||||
|   pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) ); | ||||
|   if (pq->keys == NULL) { | ||||
|      __gl_pqHeapDeletePriorityQ(pq->heap); | ||||
|      memFree(pq); | ||||
|      return NULL; | ||||
|   } | ||||
|  | ||||
|   pq->order = NULL; | ||||
|   pq->size = 0; | ||||
|   pq->max = INIT_SIZE; | ||||
|   pq->initialized = FALSE; | ||||
|   pq->leq = leq; | ||||
|   return pq; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqSortDeletePriorityQ */ | ||||
| void pqDeletePriorityQ( PriorityQ *pq ) | ||||
| { | ||||
|   assert(pq != NULL);  | ||||
|   if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap ); | ||||
|   if (pq->order != NULL) memFree( pq->order ); | ||||
|   if (pq->keys != NULL) memFree( pq->keys ); | ||||
|   memFree( pq ); | ||||
| } | ||||
|  | ||||
|  | ||||
| #define LT(x,y)		(! LEQ(y,x)) | ||||
| #define GT(x,y)		(! LEQ(x,y)) | ||||
| #define Swap(a,b)	do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0) | ||||
|  | ||||
| /* really __gl_pqSortInit */ | ||||
| int pqInit( PriorityQ *pq ) | ||||
| { | ||||
|   PQkey **p, **r, **i, **j, *piv; | ||||
|   struct { PQkey **p, **r; } Stack[50], *top = Stack; | ||||
|   unsigned long seed = 2016473283; | ||||
|  | ||||
|   /* Create an array of indirect pointers to the keys, so that we | ||||
|    * the handles we have returned are still valid. | ||||
|    */ | ||||
| /* | ||||
|   pq->order = (PQHeapKey **)memAlloc( (size_t) | ||||
|                                   (pq->size * sizeof(pq->order[0])) ); | ||||
| */ | ||||
|   pq->order = (PQHeapKey **)memAlloc( (size_t) | ||||
|                                   ((pq->size+1) * sizeof(pq->order[0])) ); | ||||
| /* the previous line is a patch to compensate for the fact that IBM */ | ||||
| /* machines return a null on a malloc of zero bytes (unlike SGI),   */ | ||||
| /* so we have to put in this defense to guard against a memory      */ | ||||
| /* fault four lines down. from fossum@austin.ibm.com.               */ | ||||
|   if (pq->order == NULL) return 0; | ||||
|  | ||||
|   p = pq->order; | ||||
|   r = p + pq->size - 1; | ||||
|   for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) { | ||||
|     *i = piv; | ||||
|   } | ||||
|  | ||||
|   /* Sort the indirect pointers in descending order, | ||||
|    * using randomized Quicksort | ||||
|    */ | ||||
|   top->p = p; top->r = r; ++top; | ||||
|   while( --top >= Stack ) { | ||||
|     p = top->p; | ||||
|     r = top->r; | ||||
|     while( r > p + 10 ) { | ||||
|       seed = seed * 1539415821 + 1; | ||||
|       i = p + seed % (r - p + 1); | ||||
|       piv = *i; | ||||
|       *i = *p; | ||||
|       *p = piv; | ||||
|       i = p - 1; | ||||
|       j = r + 1; | ||||
|       do { | ||||
| 	do { ++i; } while( GT( **i, *piv )); | ||||
| 	do { --j; } while( LT( **j, *piv )); | ||||
| 	Swap( i, j ); | ||||
|       } while( i < j ); | ||||
|       Swap( i, j );	/* Undo last swap */ | ||||
|       if( i - p < r - j ) { | ||||
| 	top->p = j+1; top->r = r; ++top; | ||||
| 	r = i-1; | ||||
|       } else { | ||||
| 	top->p = p; top->r = i-1; ++top; | ||||
| 	p = j+1; | ||||
|       } | ||||
|     } | ||||
|     /* Insertion sort small lists */ | ||||
|     for( i = p+1; i <= r; ++i ) { | ||||
|       piv = *i; | ||||
|       for( j = i; j > p && LT( **(j-1), *piv ); --j ) { | ||||
| 	*j = *(j-1); | ||||
|       } | ||||
|       *j = piv; | ||||
|     } | ||||
|   } | ||||
|   pq->max = pq->size; | ||||
|   pq->initialized = TRUE; | ||||
|   __gl_pqHeapInit( pq->heap );	/* always succeeds */ | ||||
|  | ||||
| #ifndef NDEBUG | ||||
|   p = pq->order; | ||||
|   r = p + pq->size - 1; | ||||
|   for( i = p; i < r; ++i ) { | ||||
|     assert( LEQ( **(i+1), **i )); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqSortInsert */ | ||||
| /* returns LONG_MAX iff out of memory */  | ||||
| PQhandle pqInsert( PriorityQ *pq, PQkey keyNew ) | ||||
| { | ||||
|   long curr; | ||||
|  | ||||
|   if( pq->initialized ) { | ||||
|     return __gl_pqHeapInsert( pq->heap, keyNew ); | ||||
|   } | ||||
|   curr = pq->size; | ||||
|   if( ++ pq->size >= pq->max ) { | ||||
|     PQkey *saveKey= pq->keys; | ||||
|  | ||||
|     /* If the heap overflows, double its size. */ | ||||
|     pq->max <<= 1; | ||||
|     pq->keys = (PQHeapKey *)memRealloc( pq->keys,  | ||||
| 	 	                        (size_t) | ||||
| 	                                 (pq->max * sizeof( pq->keys[0] ))); | ||||
|     if (pq->keys == NULL) {	 | ||||
|        pq->keys = saveKey;	/* restore ptr to free upon return */ | ||||
|        return LONG_MAX; | ||||
|     } | ||||
|   } | ||||
|   assert(curr != LONG_MAX);	 | ||||
|   pq->keys[curr] = keyNew; | ||||
|  | ||||
|   /* Negative handles index the sorted array. */ | ||||
|   return -(curr+1); | ||||
| } | ||||
|  | ||||
| /* really __gl_pqSortExtractMin */ | ||||
| PQkey pqExtractMin( PriorityQ *pq ) | ||||
| { | ||||
|   PQkey sortMin, heapMin; | ||||
|  | ||||
|   if( pq->size == 0 ) { | ||||
|     return __gl_pqHeapExtractMin( pq->heap ); | ||||
|   } | ||||
|   sortMin = *(pq->order[pq->size-1]); | ||||
|   if( ! __gl_pqHeapIsEmpty( pq->heap )) { | ||||
|     heapMin = __gl_pqHeapMinimum( pq->heap ); | ||||
|     if( LEQ( heapMin, sortMin )) { | ||||
|       return __gl_pqHeapExtractMin( pq->heap ); | ||||
|     } | ||||
|   } | ||||
|   do { | ||||
|     -- pq->size; | ||||
|   } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ); | ||||
|   return sortMin; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqSortMinimum */ | ||||
| PQkey pqMinimum( PriorityQ *pq ) | ||||
| { | ||||
|   PQkey sortMin, heapMin; | ||||
|  | ||||
|   if( pq->size == 0 ) { | ||||
|     return __gl_pqHeapMinimum( pq->heap ); | ||||
|   } | ||||
|   sortMin = *(pq->order[pq->size-1]); | ||||
|   if( ! __gl_pqHeapIsEmpty( pq->heap )) { | ||||
|     heapMin = __gl_pqHeapMinimum( pq->heap ); | ||||
|     if( LEQ( heapMin, sortMin )) { | ||||
|       return heapMin; | ||||
|     } | ||||
|   } | ||||
|   return sortMin; | ||||
| } | ||||
|  | ||||
| /* really __gl_pqSortIsEmpty */ | ||||
| int pqIsEmpty( PriorityQ *pq ) | ||||
| { | ||||
|   return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap ); | ||||
| } | ||||
|  | ||||
| /* really __gl_pqSortDelete */ | ||||
| void pqDelete( PriorityQ *pq, PQhandle curr ) | ||||
| { | ||||
|   if( curr >= 0 ) { | ||||
|     __gl_pqHeapDelete( pq->heap, curr ); | ||||
|     return; | ||||
|   } | ||||
|   curr = -(curr+1); | ||||
|   assert( curr < pq->max && pq->keys[curr] != NULL ); | ||||
|  | ||||
|   pq->keys[curr] = NULL; | ||||
|   while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) { | ||||
|     -- pq->size; | ||||
|   } | ||||
| } | ||||
| @@ -1,117 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __priorityq_sort_h_ | ||||
| #define __priorityq_sort_h_ | ||||
|  | ||||
| #include "priorityq-heap.h" | ||||
|  | ||||
| #undef PQkey | ||||
| #undef PQhandle | ||||
| #undef PriorityQ | ||||
| #undef pqNewPriorityQ | ||||
| #undef pqDeletePriorityQ | ||||
| #undef pqInit | ||||
| #undef pqInsert | ||||
| #undef pqMinimum | ||||
| #undef pqExtractMin | ||||
| #undef pqDelete | ||||
| #undef pqIsEmpty | ||||
|  | ||||
| /* Use #define's so that another heap implementation can use this one */ | ||||
|  | ||||
| #define PQkey			PQSortKey | ||||
| #define PQhandle		PQSortHandle | ||||
| #define PriorityQ		PriorityQSort | ||||
|  | ||||
| #define pqNewPriorityQ(leq)	__gl_pqSortNewPriorityQ(leq) | ||||
| #define pqDeletePriorityQ(pq)	__gl_pqSortDeletePriorityQ(pq) | ||||
|  | ||||
| /* The basic operations are insertion of a new key (pqInsert), | ||||
|  * and examination/extraction of a key whose value is minimum | ||||
|  * (pqMinimum/pqExtractMin).  Deletion is also allowed (pqDelete); | ||||
|  * for this purpose pqInsert returns a "handle" which is supplied | ||||
|  * as the argument. | ||||
|  * | ||||
|  * An initial heap may be created efficiently by calling pqInsert | ||||
|  * repeatedly, then calling pqInit.  In any case pqInit must be called | ||||
|  * before any operations other than pqInsert are used. | ||||
|  * | ||||
|  * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. | ||||
|  * This may also be tested with pqIsEmpty. | ||||
|  */ | ||||
| #define pqInit(pq)		__gl_pqSortInit(pq) | ||||
| #define pqInsert(pq,key)	__gl_pqSortInsert(pq,key) | ||||
| #define pqMinimum(pq)		__gl_pqSortMinimum(pq) | ||||
| #define pqExtractMin(pq)	__gl_pqSortExtractMin(pq) | ||||
| #define pqDelete(pq,handle)	__gl_pqSortDelete(pq,handle) | ||||
| #define pqIsEmpty(pq)		__gl_pqSortIsEmpty(pq) | ||||
|  | ||||
|  | ||||
| /* Since we support deletion the data structure is a little more | ||||
|  * complicated than an ordinary heap.  "nodes" is the heap itself; | ||||
|  * active nodes are stored in the range 1..pq->size.  When the | ||||
|  * heap exceeds its allocated size (pq->max), its size doubles. | ||||
|  * The children of node i are nodes 2i and 2i+1. | ||||
|  * | ||||
|  * Each node stores an index into an array "handles".  Each handle | ||||
|  * stores a key, plus a pointer back to the node which currently | ||||
|  * represents that key (ie. nodes[handles[i].node].handle == i). | ||||
|  */ | ||||
|  | ||||
| typedef PQHeapKey PQkey; | ||||
| typedef PQHeapHandle PQhandle; | ||||
| typedef struct PriorityQ PriorityQ; | ||||
|  | ||||
| struct PriorityQ { | ||||
|   PriorityQHeap	*heap; | ||||
|   PQkey		*keys; | ||||
|   PQkey		**order; | ||||
|   PQhandle	size, max; | ||||
|   int		initialized; | ||||
|   int		(*leq)(PQkey key1, PQkey key2); | ||||
| }; | ||||
|    | ||||
| PriorityQ	*pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ); | ||||
| void		pqDeletePriorityQ( PriorityQ *pq ); | ||||
|  | ||||
| int		pqInit( PriorityQ *pq ); | ||||
| PQhandle	pqInsert( PriorityQ *pq, PQkey key ); | ||||
| PQkey		pqExtractMin( PriorityQ *pq ); | ||||
| void		pqDelete( PriorityQ *pq, PQhandle handle ); | ||||
|  | ||||
| PQkey		pqMinimum( PriorityQ *pq ); | ||||
| int		pqIsEmpty( PriorityQ *pq ); | ||||
|  | ||||
| #endif | ||||
| @@ -1,502 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include <assert.h> | ||||
| #include <stddef.h> | ||||
| #include "mesh.h" | ||||
| #include "tess.h" | ||||
| #include "render.h" | ||||
|  | ||||
| #ifndef TRUE | ||||
| #define TRUE 1 | ||||
| #endif | ||||
| #ifndef FALSE | ||||
| #define FALSE 0 | ||||
| #endif | ||||
|  | ||||
| /* This structure remembers the information we need about a primitive | ||||
|  * to be able to render it later, once we have determined which | ||||
|  * primitive is able to use the most triangles. | ||||
|  */ | ||||
| struct FaceCount { | ||||
|   long		size;		/* number of triangles used */ | ||||
|   GLUhalfEdge	*eStart;	/* edge where this primitive starts */ | ||||
|   void		(*render)(GLUtesselator *, GLUhalfEdge *, long); | ||||
|                                 /* routine to render this primitive */ | ||||
| }; | ||||
|  | ||||
| static struct FaceCount MaximumFan( GLUhalfEdge *eOrig ); | ||||
| static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig ); | ||||
|  | ||||
| static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size ); | ||||
| static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size ); | ||||
| static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart, | ||||
| 			    long size ); | ||||
|  | ||||
| static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig ); | ||||
| static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head ); | ||||
|  | ||||
|  | ||||
|  | ||||
| /************************ Strips and Fans decomposition ******************/ | ||||
|  | ||||
| /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle | ||||
|  * fans, strips, and separate triangles.  A substantial effort is made | ||||
|  * to use as few rendering primitives as possible (ie. to make the fans | ||||
|  * and strips as large as possible). | ||||
|  * | ||||
|  * The rendering output is provided as callbacks (see the api). | ||||
|  */ | ||||
| void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *f; | ||||
|  | ||||
|   /* Make a list of separate triangles so we can render them all at once */ | ||||
|   tess->lonelyTriList = NULL; | ||||
|  | ||||
|   for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { | ||||
|     f->marked = FALSE; | ||||
|   } | ||||
|   for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { | ||||
|  | ||||
|     /* We examine all faces in an arbitrary order.  Whenever we find | ||||
|      * an unprocessed face F, we output a group of faces including F | ||||
|      * whose size is maximum. | ||||
|      */ | ||||
|     if( f->inside && ! f->marked ) { | ||||
|       RenderMaximumFaceGroup( tess, f ); | ||||
|       assert( f->marked ); | ||||
|     } | ||||
|   } | ||||
|   if( tess->lonelyTriList != NULL ) { | ||||
|     RenderLonelyTriangles( tess, tess->lonelyTriList ); | ||||
|     tess->lonelyTriList = NULL; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig ) | ||||
| { | ||||
|   /* We want to find the largest triangle fan or strip of unmarked faces | ||||
|    * which includes the given face fOrig.  There are 3 possible fans | ||||
|    * passing through fOrig (one centered at each vertex), and 3 possible | ||||
|    * strips (one for each CCW permutation of the vertices).  Our strategy | ||||
|    * is to try all of these, and take the primitive which uses the most | ||||
|    * triangles (a greedy approach). | ||||
|    */ | ||||
|   GLUhalfEdge *e = fOrig->anEdge; | ||||
|   struct FaceCount max, newFace; | ||||
|  | ||||
|   max.size = 1; | ||||
|   max.eStart = e; | ||||
|   max.render = &RenderTriangle; | ||||
|  | ||||
|   if( ! tess->flagBoundary ) { | ||||
|     newFace = MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; } | ||||
|     newFace = MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; } | ||||
|     newFace = MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; } | ||||
|  | ||||
|     newFace = MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; } | ||||
|     newFace = MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; } | ||||
|     newFace = MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; } | ||||
|   } | ||||
|   (*(max.render))( tess, max.eStart, max.size ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Macros which keep track of faces we have marked temporarily, and allow | ||||
|  * us to backtrack when necessary.  With triangle fans, this is not | ||||
|  * really necessary, since the only awkward case is a loop of triangles | ||||
|  * around a single origin vertex.  However with strips the situation is | ||||
|  * more complicated, and we need a general tracking method like the | ||||
|  * one here. | ||||
|  */ | ||||
| #define Marked(f)	(! (f)->inside || (f)->marked) | ||||
|  | ||||
| #define AddToTrail(f,t)	((f)->trail = (t), (t) = (f), (f)->marked = TRUE) | ||||
|  | ||||
| #define FreeTrail(t)	do { \ | ||||
| 			  while( (t) != NULL ) { \ | ||||
| 			    (t)->marked = FALSE; t = (t)->trail; \ | ||||
| 			  } \ | ||||
| 			} while(0) /* absorb trailing semicolon */ | ||||
|  | ||||
|  | ||||
|  | ||||
| static struct FaceCount MaximumFan( GLUhalfEdge *eOrig ) | ||||
| { | ||||
|   /* eOrig->Lface is the face we want to render.  We want to find the size | ||||
|    * of a maximal fan around eOrig->Org.  To do this we just walk around | ||||
|    * the origin vertex as far as possible in both directions. | ||||
|    */ | ||||
|   struct FaceCount newFace = { 0, NULL, &RenderFan }; | ||||
|   GLUface *trail = NULL; | ||||
|   GLUhalfEdge *e; | ||||
|  | ||||
|   for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) { | ||||
|     AddToTrail( e->Lface, trail ); | ||||
|     ++newFace.size; | ||||
|   } | ||||
|   for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) { | ||||
|     AddToTrail( e->Rface, trail ); | ||||
|     ++newFace.size; | ||||
|   } | ||||
|   newFace.eStart = e; | ||||
|   /*LINTED*/ | ||||
|   FreeTrail( trail ); | ||||
|   return newFace; | ||||
| } | ||||
|  | ||||
|  | ||||
| #define IsEven(n)	(((n) & 1) == 0) | ||||
|  | ||||
| static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig ) | ||||
| { | ||||
|   /* Here we are looking for a maximal strip that contains the vertices | ||||
|    * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the | ||||
|    * reverse, such that all triangles are oriented CCW). | ||||
|    * | ||||
|    * Again we walk forward and backward as far as possible.  However for | ||||
|    * strips there is a twist: to get CCW orientations, there must be | ||||
|    * an *even* number of triangles in the strip on one side of eOrig. | ||||
|    * We walk the strip starting on a side with an even number of triangles; | ||||
|    * if both side have an odd number, we are forced to shorten one side. | ||||
|    */ | ||||
|   struct FaceCount newFace = { 0, NULL, &RenderStrip }; | ||||
|   long headSize = 0, tailSize = 0; | ||||
|   GLUface *trail = NULL; | ||||
|   GLUhalfEdge *e, *eTail, *eHead; | ||||
|  | ||||
|   for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) { | ||||
|     AddToTrail( e->Lface, trail ); | ||||
|     ++tailSize; | ||||
|     e = e->Dprev; | ||||
|     if( Marked( e->Lface )) break; | ||||
|     AddToTrail( e->Lface, trail ); | ||||
|   } | ||||
|   eTail = e; | ||||
|  | ||||
|   for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) { | ||||
|     AddToTrail( e->Rface, trail ); | ||||
|     ++headSize; | ||||
|     e = e->Oprev; | ||||
|     if( Marked( e->Rface )) break; | ||||
|     AddToTrail( e->Rface, trail ); | ||||
|   } | ||||
|   eHead = e; | ||||
|  | ||||
|   newFace.size = tailSize + headSize; | ||||
|   if( IsEven( tailSize )) { | ||||
|     newFace.eStart = eTail->Sym; | ||||
|   } else if( IsEven( headSize )) { | ||||
|     newFace.eStart = eHead; | ||||
|   } else { | ||||
|     /* Both sides have odd length, we must shorten one of them.  In fact, | ||||
|      * we must start from eHead to guarantee inclusion of eOrig->Lface. | ||||
|      */ | ||||
|     --newFace.size; | ||||
|     newFace.eStart = eHead->Onext; | ||||
|   } | ||||
|   /*LINTED*/ | ||||
|   FreeTrail( trail ); | ||||
|   return newFace; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size ) | ||||
| { | ||||
|   /* Just add the triangle to a triangle list, so we can render all | ||||
|    * the separate triangles at once. | ||||
|    */ | ||||
|   assert( size == 1 ); | ||||
|   AddToTrail( e->Lface, tess->lonelyTriList ); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f ) | ||||
| { | ||||
|   /* Now we render all the separate triangles which could not be | ||||
|    * grouped into a triangle fan or strip. | ||||
|    */ | ||||
|   GLUhalfEdge *e; | ||||
|   int newState; | ||||
|   int edgeState = -1;	/* force edge state output for first vertex */ | ||||
|  | ||||
|   CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES ); | ||||
|  | ||||
|   for( ; f != NULL; f = f->trail ) { | ||||
|     /* Loop once for each edge (there will always be 3 edges) */ | ||||
|  | ||||
|     e = f->anEdge; | ||||
|     do { | ||||
|       if( tess->flagBoundary ) { | ||||
| 	/* Set the "edge state" to TRUE just before we output the | ||||
| 	 * first vertex of each edge on the polygon boundary. | ||||
| 	 */ | ||||
| 	newState = ! e->Rface->inside; | ||||
| 	if( edgeState != newState ) { | ||||
| 	  edgeState = newState; | ||||
|           CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState ); | ||||
| 	} | ||||
|       } | ||||
|       CALL_VERTEX_OR_VERTEX_DATA( e->Org->data ); | ||||
|  | ||||
|       e = e->Lnext; | ||||
|     } while( e != f->anEdge ); | ||||
|   } | ||||
|   CALL_END_OR_END_DATA(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size ) | ||||
| { | ||||
|   /* Render as many CCW triangles as possible in a fan starting from | ||||
|    * edge "e".  The fan *should* contain exactly "size" triangles | ||||
|    * (otherwise we've goofed up somewhere). | ||||
|    */ | ||||
|   CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN );  | ||||
|   CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );  | ||||
|   CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );  | ||||
|  | ||||
|   while( ! Marked( e->Lface )) { | ||||
|     e->Lface->marked = TRUE; | ||||
|     --size; | ||||
|     e = e->Onext; | ||||
|     CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );  | ||||
|   } | ||||
|  | ||||
|   assert( size == 0 ); | ||||
|   CALL_END_OR_END_DATA(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size ) | ||||
| { | ||||
|   /* Render as many CCW triangles as possible in a strip starting from | ||||
|    * edge "e".  The strip *should* contain exactly "size" triangles | ||||
|    * (otherwise we've goofed up somewhere). | ||||
|    */ | ||||
|   CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP ); | ||||
|   CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );  | ||||
|   CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );  | ||||
|  | ||||
|   while( ! Marked( e->Lface )) { | ||||
|     e->Lface->marked = TRUE; | ||||
|     --size; | ||||
|     e = e->Dprev; | ||||
|     CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );  | ||||
|     if( Marked( e->Lface )) break; | ||||
|  | ||||
|     e->Lface->marked = TRUE; | ||||
|     --size; | ||||
|     e = e->Onext; | ||||
|     CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );  | ||||
|   } | ||||
|  | ||||
|   assert( size == 0 ); | ||||
|   CALL_END_OR_END_DATA(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /************************ Boundary contour decomposition ******************/ | ||||
|  | ||||
| /* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one | ||||
|  * contour for each face marked "inside".  The rendering output is | ||||
|  * provided as callbacks (see the api). | ||||
|  */ | ||||
| void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *f; | ||||
|   GLUhalfEdge *e; | ||||
|  | ||||
|   for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { | ||||
|     if( f->inside ) { | ||||
|       CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP ); | ||||
|       e = f->anEdge; | ||||
|       do { | ||||
|         CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );  | ||||
| 	e = e->Lnext; | ||||
|       } while( e != f->anEdge ); | ||||
|       CALL_END_OR_END_DATA(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| /************************ Quick-and-dirty decomposition ******************/ | ||||
|  | ||||
| #define SIGN_INCONSISTENT 2 | ||||
|  | ||||
| static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3], int check ) | ||||
| /* | ||||
|  * If check==FALSE, we compute the polygon normal and place it in norm[]. | ||||
|  * If check==TRUE, we check that each triangle in the fan from v0 has a | ||||
|  * consistent orientation with respect to norm[].  If triangles are | ||||
|  * consistently oriented CCW, return 1; if CW, return -1; if all triangles | ||||
|  * are degenerate return 0; otherwise (no consistent orientation) return | ||||
|  * SIGN_INCONSISTENT. | ||||
|  */ | ||||
| { | ||||
|   CachedVertex *v0 = tess->cache; | ||||
|   CachedVertex *vn = v0 + tess->cacheCount; | ||||
|   CachedVertex *vc; | ||||
|   GLdouble dot, xc, yc, zc, xp, yp, zp, n[3]; | ||||
|   int sign = 0; | ||||
|  | ||||
|   /* Find the polygon normal.  It is important to get a reasonable | ||||
|    * normal even when the polygon is self-intersecting (eg. a bowtie). | ||||
|    * Otherwise, the computed normal could be very tiny, but perpendicular | ||||
|    * to the true plane of the polygon due to numerical noise.  Then all | ||||
|    * the triangles would appear to be degenerate and we would incorrectly | ||||
|    * decompose the polygon as a fan (or simply not render it at all). | ||||
|    * | ||||
|    * We use a sum-of-triangles normal algorithm rather than the more | ||||
|    * efficient sum-of-trapezoids method (used in CheckOrientation() | ||||
|    * in normal.c).  This lets us explicitly reverse the signed area | ||||
|    * of some triangles to get a reasonable normal in the self-intersecting | ||||
|    * case. | ||||
|    */ | ||||
|   if( ! check ) { | ||||
|     norm[0] = norm[1] = norm[2] = 0.0; | ||||
|   } | ||||
|  | ||||
|   vc = v0 + 1; | ||||
|   xc = vc->coords[0] - v0->coords[0]; | ||||
|   yc = vc->coords[1] - v0->coords[1]; | ||||
|   zc = vc->coords[2] - v0->coords[2]; | ||||
|   while( ++vc < vn ) { | ||||
|     xp = xc; yp = yc; zp = zc; | ||||
|     xc = vc->coords[0] - v0->coords[0]; | ||||
|     yc = vc->coords[1] - v0->coords[1]; | ||||
|     zc = vc->coords[2] - v0->coords[2]; | ||||
|  | ||||
|     /* Compute (vp - v0) cross (vc - v0) */ | ||||
|     n[0] = yp*zc - zp*yc; | ||||
|     n[1] = zp*xc - xp*zc; | ||||
|     n[2] = xp*yc - yp*xc; | ||||
|  | ||||
|     dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2]; | ||||
|     if( ! check ) { | ||||
|       /* Reverse the contribution of back-facing triangles to get | ||||
|        * a reasonable normal for self-intersecting polygons (see above) | ||||
|        */ | ||||
|       if( dot >= 0 ) { | ||||
| 	norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2]; | ||||
|       } else { | ||||
| 	norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2]; | ||||
|       } | ||||
|     } else if( dot != 0 ) { | ||||
|       /* Check the new orientation for consistency with previous triangles */ | ||||
|       if( dot > 0 ) { | ||||
| 	if( sign < 0 ) return SIGN_INCONSISTENT; | ||||
| 	sign = 1; | ||||
|       } else { | ||||
| 	if( sign > 0 ) return SIGN_INCONSISTENT; | ||||
| 	sign = -1; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return sign; | ||||
| } | ||||
|  | ||||
| /* __gl_renderCache( tess ) takes a single contour and tries to render it | ||||
|  * as a triangle fan.  This handles convex polygons, as well as some | ||||
|  * non-convex polygons if we get lucky. | ||||
|  * | ||||
|  * Returns TRUE if the polygon was successfully rendered.  The rendering | ||||
|  * output is provided as callbacks (see the api). | ||||
|  */ | ||||
| GLboolean __gl_renderCache( GLUtesselator *tess ) | ||||
| { | ||||
|   CachedVertex *v0 = tess->cache; | ||||
|   CachedVertex *vn = v0 + tess->cacheCount; | ||||
|   CachedVertex *vc; | ||||
|   GLdouble norm[3]; | ||||
|   int sign; | ||||
|  | ||||
|   if( tess->cacheCount < 3 ) { | ||||
|     /* Degenerate contour -- no output */ | ||||
|     return TRUE; | ||||
|   } | ||||
|  | ||||
|   norm[0] = tess->normal[0]; | ||||
|   norm[1] = tess->normal[1]; | ||||
|   norm[2] = tess->normal[2]; | ||||
|   if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) { | ||||
|     ComputeNormal( tess, norm, FALSE ); | ||||
|   } | ||||
|  | ||||
|   sign = ComputeNormal( tess, norm, TRUE ); | ||||
|   if( sign == SIGN_INCONSISTENT ) { | ||||
|     /* Fan triangles did not have a consistent orientation */ | ||||
|     return FALSE; | ||||
|   } | ||||
|   if( sign == 0 ) { | ||||
|     /* All triangles were degenerate */ | ||||
|     return TRUE; | ||||
|   } | ||||
|  | ||||
|   /* Make sure we do the right thing for each winding rule */ | ||||
|   switch( tess->windingRule ) { | ||||
|   case GLU_TESS_WINDING_ODD: | ||||
|   case GLU_TESS_WINDING_NONZERO: | ||||
|     break; | ||||
|   case GLU_TESS_WINDING_POSITIVE: | ||||
|     if( sign < 0 ) return TRUE; | ||||
|     break; | ||||
|   case GLU_TESS_WINDING_NEGATIVE: | ||||
|     if( sign > 0 ) return TRUE; | ||||
|     break; | ||||
|   case GLU_TESS_WINDING_ABS_GEQ_TWO: | ||||
|     return TRUE; | ||||
|   } | ||||
|  | ||||
|   CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP | ||||
| 			  : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN | ||||
| 			  : GL_TRIANGLES ); | ||||
|  | ||||
|   CALL_VERTEX_OR_VERTEX_DATA( v0->data );  | ||||
|   if( sign > 0 ) { | ||||
|     for( vc = v0+1; vc < vn; ++vc ) { | ||||
|       CALL_VERTEX_OR_VERTEX_DATA( vc->data );  | ||||
|     } | ||||
|   } else { | ||||
|     for( vc = vn-1; vc > v0; --vc ) { | ||||
|       CALL_VERTEX_OR_VERTEX_DATA( vc->data );  | ||||
|     } | ||||
|   } | ||||
|   CALL_END_OR_END_DATA(); | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __render_h_ | ||||
| #define __render_h_ | ||||
|  | ||||
| #include "mesh.h" | ||||
| #include "tesselator.h" | ||||
|  | ||||
| /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle | ||||
|  * fans, strips, and separate triangles.  A substantial effort is made | ||||
|  * to use as few rendering primitives as possible (ie. to make the fans | ||||
|  * and strips as large as possible). | ||||
|  * | ||||
|  * The rendering output is provided as callbacks (see the api). | ||||
|  */ | ||||
| void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh ); | ||||
| void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh ); | ||||
|  | ||||
| GLboolean __gl_renderCache( GLUtesselator *tess ); | ||||
|  | ||||
| #endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,78 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __sweep_h_ | ||||
| #define __sweep_h_ | ||||
|  | ||||
| #include "mesh.h" | ||||
| #include "tesselator.h" | ||||
|  | ||||
| /* __gl_computeInterior( tess ) computes the planar arrangement specified | ||||
|  * by the given contours, and further subdivides this arrangement | ||||
|  * into regions.  Each region is marked "inside" if it belongs | ||||
|  * to the polygon, according to the rule given by tess->windingRule. | ||||
|  * Each interior region is guaranteed be monotone. | ||||
|  */ | ||||
| int __gl_computeInterior( GLUtesselator *tess ); | ||||
|  | ||||
|  | ||||
| /* The following is here *only* for access by debugging routines */ | ||||
|  | ||||
| #include "dict.h" | ||||
|  | ||||
| /* For each pair of adjacent edges crossing the sweep line, there is | ||||
|  * an ActiveRegion to represent the region between them.  The active | ||||
|  * regions are kept in sorted order in a dynamic dictionary.  As the | ||||
|  * sweep line crosses each vertex, we update the affected regions. | ||||
|  */ | ||||
|  | ||||
| struct ActiveRegion { | ||||
|   GLUhalfEdge	*eUp;		/* upper edge, directed right to left */ | ||||
|   DictNode	*nodeUp;	/* dictionary node corresponding to eUp */ | ||||
|   int		windingNumber;	/* used to determine which regions are | ||||
|                                  * inside the polygon */ | ||||
|   GLboolean	inside;		/* is this region inside the polygon? */ | ||||
|   GLboolean	sentinel;	/* marks fake edges at t = +/-infinity */ | ||||
|   GLboolean	dirty;		/* marks regions where the upper or lower | ||||
|                                  * edge has changed, but we haven't checked | ||||
|                                  * whether they intersect yet */ | ||||
|   GLboolean	fixUpperEdge;	/* marks temporary edges introduced when | ||||
|                                  * we process a "right vertex" (one without | ||||
|                                  * any edges leaving to the right) */ | ||||
| }; | ||||
|  | ||||
| #define RegionBelow(r)	((ActiveRegion *) dictKey(dictPred((r)->nodeUp))) | ||||
| #define RegionAbove(r)	((ActiveRegion *) dictKey(dictSucc((r)->nodeUp))) | ||||
|  | ||||
| #endif | ||||
| @@ -1,632 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include <stddef.h> | ||||
| #include <assert.h> | ||||
| #include <setjmp.h> | ||||
| #include "memalloc.h" | ||||
| #include "tess.h" | ||||
| #include "mesh.h" | ||||
| #include "normal.h" | ||||
| #include "sweep.h" | ||||
| #include "tessmono.h" | ||||
| #include "render.h" | ||||
|  | ||||
| #define GLU_TESS_DEFAULT_TOLERANCE 0.0 | ||||
| #define GLU_TESS_MESH		100112	/* void (*)(GLUmesh *mesh)	    */ | ||||
|  | ||||
| #ifndef TRUE | ||||
| #define TRUE 1 | ||||
| #endif | ||||
| #ifndef FALSE | ||||
| #define FALSE 0 | ||||
| #endif | ||||
|  | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noBegin( GLenum type ) {} | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noEdgeFlag( GLboolean boundaryEdge ) {} | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noVertex( void *data ) {} | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noEnd( void ) {} | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noError( GLenum errnum ) {} | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noCombine( GLdouble coords[3], void *data[4], | ||||
| 				    GLfloat weight[4], void **dataOut ) {} | ||||
| /*ARGSUSED*/ static void GLAPIENTRY noMesh( GLUmesh *mesh ) {} | ||||
|  | ||||
|  | ||||
| /*ARGSUSED*/ void GLAPIENTRY __gl_noBeginData( GLenum type, | ||||
| 					     void *polygonData ) {} | ||||
| /*ARGSUSED*/ void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, | ||||
| 				       void *polygonData ) {} | ||||
| /*ARGSUSED*/ void GLAPIENTRY __gl_noVertexData( void *data, | ||||
| 					      void *polygonData ) {} | ||||
| /*ARGSUSED*/ void GLAPIENTRY __gl_noEndData( void *polygonData ) {} | ||||
| /*ARGSUSED*/ void GLAPIENTRY __gl_noErrorData( GLenum errnum, | ||||
| 					     void *polygonData ) {} | ||||
| /*ARGSUSED*/ void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], | ||||
| 					       void *data[4], | ||||
| 					       GLfloat weight[4], | ||||
| 					       void **outData, | ||||
| 					       void *polygonData ) {} | ||||
|  | ||||
| /* Half-edges are allocated in pairs (see mesh.c) */ | ||||
| typedef struct { GLUhalfEdge e, eSym; } EdgePair; | ||||
|  | ||||
| #undef	MAX | ||||
| #define MAX(a,b)	((a) > (b) ? (a) : (b)) | ||||
| #define MAX_FAST_ALLOC	(MAX(sizeof(EdgePair), \ | ||||
|                          MAX(sizeof(GLUvertex),sizeof(GLUface)))) | ||||
|  | ||||
|  | ||||
| GLUtesselator * GLAPIENTRY | ||||
| gluNewTess( void ) | ||||
| { | ||||
|   GLUtesselator *tess; | ||||
|  | ||||
|   /* Only initialize fields which can be changed by the api.  Other fields | ||||
|    * are initialized where they are used. | ||||
|    */ | ||||
|  | ||||
|   if (memInit( MAX_FAST_ALLOC ) == 0) { | ||||
|      return 0;			/* out of memory */ | ||||
|   } | ||||
|   tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator )); | ||||
|   if (tess == NULL) { | ||||
|      return 0;			/* out of memory */ | ||||
|   } | ||||
|  | ||||
|   tess->state = T_DORMANT; | ||||
|  | ||||
|   tess->normal[0] = 0; | ||||
|   tess->normal[1] = 0; | ||||
|   tess->normal[2] = 0; | ||||
|  | ||||
|   tess->relTolerance = GLU_TESS_DEFAULT_TOLERANCE; | ||||
|   tess->windingRule = GLU_TESS_WINDING_ODD; | ||||
|   tess->flagBoundary = FALSE; | ||||
|   tess->boundaryOnly = FALSE; | ||||
|  | ||||
|   tess->callBegin = &noBegin; | ||||
|   tess->callEdgeFlag = &noEdgeFlag; | ||||
|   tess->callVertex = &noVertex; | ||||
|   tess->callEnd = &noEnd; | ||||
|  | ||||
|   tess->callError = &noError; | ||||
|   tess->callCombine = &noCombine; | ||||
|   tess->callMesh = &noMesh; | ||||
|  | ||||
|   tess->callBeginData= &__gl_noBeginData; | ||||
|   tess->callEdgeFlagData= &__gl_noEdgeFlagData; | ||||
|   tess->callVertexData= &__gl_noVertexData; | ||||
|   tess->callEndData= &__gl_noEndData; | ||||
|   tess->callErrorData= &__gl_noErrorData; | ||||
|   tess->callCombineData= &__gl_noCombineData; | ||||
|  | ||||
|   tess->polygonData= NULL; | ||||
|  | ||||
|   return tess; | ||||
| } | ||||
|  | ||||
| static void MakeDormant( GLUtesselator *tess ) | ||||
| { | ||||
|   /* Return the tessellator to its original dormant state. */ | ||||
|  | ||||
|   if( tess->mesh != NULL ) { | ||||
|     __gl_meshDeleteMesh( tess->mesh ); | ||||
|   } | ||||
|   tess->state = T_DORMANT; | ||||
|   tess->lastEdge = NULL; | ||||
|   tess->mesh = NULL; | ||||
| } | ||||
|  | ||||
| #define RequireState( tess, s )   if( tess->state != s ) GotoState(tess,s) | ||||
|  | ||||
| static void GotoState( GLUtesselator *tess, enum TessState newState ) | ||||
| { | ||||
|   while( tess->state != newState ) { | ||||
|     /* We change the current state one level at a time, to get to | ||||
|      * the desired state. | ||||
|      */ | ||||
|     if( tess->state < newState ) { | ||||
|       switch( tess->state ) { | ||||
|       case T_DORMANT: | ||||
| 	CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON ); | ||||
| 	gluTessBeginPolygon( tess, NULL ); | ||||
| 	break; | ||||
|       case T_IN_POLYGON: | ||||
| 	CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR ); | ||||
| 	gluTessBeginContour( tess ); | ||||
| 	break; | ||||
|       default: | ||||
| 	 ; | ||||
|       } | ||||
|     } else { | ||||
|       switch( tess->state ) { | ||||
|       case T_IN_CONTOUR: | ||||
| 	CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR ); | ||||
| 	gluTessEndContour( tess ); | ||||
| 	break; | ||||
|       case T_IN_POLYGON: | ||||
| 	CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON ); | ||||
| 	/* gluTessEndPolygon( tess ) is too much work! */ | ||||
| 	MakeDormant( tess ); | ||||
| 	break; | ||||
|       default: | ||||
| 	 ; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluDeleteTess( GLUtesselator *tess ) | ||||
| { | ||||
|   RequireState( tess, T_DORMANT ); | ||||
|   memFree( tess ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessProperty( GLUtesselator *tess, GLenum which, GLdouble value ) | ||||
| { | ||||
|   GLenum windingRule; | ||||
|  | ||||
|   switch( which ) { | ||||
|   case GLU_TESS_TOLERANCE: | ||||
|     if( value < 0.0 || value > 1.0 ) break; | ||||
|     tess->relTolerance = value; | ||||
|     return; | ||||
|  | ||||
|   case GLU_TESS_WINDING_RULE: | ||||
|     windingRule = (GLenum) value; | ||||
|     if( windingRule != value ) break;	/* not an integer */ | ||||
|  | ||||
|     switch( windingRule ) { | ||||
|     case GLU_TESS_WINDING_ODD: | ||||
|     case GLU_TESS_WINDING_NONZERO: | ||||
|     case GLU_TESS_WINDING_POSITIVE: | ||||
|     case GLU_TESS_WINDING_NEGATIVE: | ||||
|     case GLU_TESS_WINDING_ABS_GEQ_TWO: | ||||
|       tess->windingRule = windingRule; | ||||
|       return; | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   case GLU_TESS_BOUNDARY_ONLY: | ||||
|     tess->boundaryOnly = (value != 0); | ||||
|     return; | ||||
|  | ||||
|   default: | ||||
|     CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); | ||||
|     return; | ||||
|   } | ||||
|   CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE ); | ||||
| } | ||||
|  | ||||
| /* Returns tessellator property */ | ||||
| void GLAPIENTRY | ||||
| gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value ) | ||||
| { | ||||
|    switch (which) { | ||||
|    case GLU_TESS_TOLERANCE: | ||||
|       /* tolerance should be in range [0..1] */ | ||||
|       assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0); | ||||
|       *value= tess->relTolerance; | ||||
|       break; | ||||
|    case GLU_TESS_WINDING_RULE: | ||||
|       assert(tess->windingRule == GLU_TESS_WINDING_ODD || | ||||
| 	     tess->windingRule == GLU_TESS_WINDING_NONZERO || | ||||
| 	     tess->windingRule == GLU_TESS_WINDING_POSITIVE || | ||||
| 	     tess->windingRule == GLU_TESS_WINDING_NEGATIVE || | ||||
| 	     tess->windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO); | ||||
|       *value= tess->windingRule; | ||||
|       break; | ||||
|    case GLU_TESS_BOUNDARY_ONLY: | ||||
|       assert(tess->boundaryOnly == TRUE || tess->boundaryOnly == FALSE); | ||||
|       *value= tess->boundaryOnly; | ||||
|       break; | ||||
|    default: | ||||
|       *value= 0.0; | ||||
|       CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); | ||||
|       break; | ||||
|    } | ||||
| } /* gluGetTessProperty() */ | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessNormal( GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z ) | ||||
| { | ||||
|   tess->normal[0] = x; | ||||
|   tess->normal[1] = y; | ||||
|   tess->normal[2] = z; | ||||
| } | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessCallback( GLUtesselator *tess, GLenum which, _GLUfuncptr fn) | ||||
| { | ||||
|   switch( which ) { | ||||
|   case GLU_TESS_BEGIN: | ||||
|     tess->callBegin = (fn == NULL) ? &noBegin : (void (GLAPIENTRY *)(GLenum)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_BEGIN_DATA: | ||||
|     tess->callBeginData = (fn == NULL) ? | ||||
| 	&__gl_noBeginData : (void (GLAPIENTRY *)(GLenum, void *)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_EDGE_FLAG: | ||||
|     tess->callEdgeFlag = (fn == NULL) ? &noEdgeFlag : | ||||
| 					(void (GLAPIENTRY *)(GLboolean)) fn; | ||||
|     /* If the client wants boundary edges to be flagged, | ||||
|      * we render everything as separate triangles (no strips or fans). | ||||
|      */ | ||||
|     tess->flagBoundary = (fn != NULL); | ||||
|     return; | ||||
|   case GLU_TESS_EDGE_FLAG_DATA: | ||||
|     tess->callEdgeFlagData= (fn == NULL) ? | ||||
| 	&__gl_noEdgeFlagData : (void (GLAPIENTRY *)(GLboolean, void *)) fn; | ||||
|     /* If the client wants boundary edges to be flagged, | ||||
|      * we render everything as separate triangles (no strips or fans). | ||||
|      */ | ||||
|     tess->flagBoundary = (fn != NULL); | ||||
|     return; | ||||
|   case GLU_TESS_VERTEX: | ||||
|     tess->callVertex = (fn == NULL) ? &noVertex : | ||||
| 				      (void (GLAPIENTRY *)(void *)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_VERTEX_DATA: | ||||
|     tess->callVertexData = (fn == NULL) ? | ||||
| 	&__gl_noVertexData : (void (GLAPIENTRY *)(void *, void *)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_END: | ||||
|     tess->callEnd = (fn == NULL) ? &noEnd : (void (GLAPIENTRY *)(void)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_END_DATA: | ||||
|     tess->callEndData = (fn == NULL) ? &__gl_noEndData : | ||||
| 				       (void (GLAPIENTRY *)(void *)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_ERROR: | ||||
|     tess->callError = (fn == NULL) ? &noError : (void (GLAPIENTRY *)(GLenum)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_ERROR_DATA: | ||||
|     tess->callErrorData = (fn == NULL) ? | ||||
| 	&__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_COMBINE: | ||||
|     tess->callCombine = (fn == NULL) ? &noCombine : | ||||
| 	(void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn; | ||||
|     return; | ||||
|   case GLU_TESS_COMBINE_DATA: | ||||
|     tess->callCombineData = (fn == NULL) ? &__gl_noCombineData : | ||||
| 					   (void (GLAPIENTRY *)(GLdouble [3], | ||||
| 						     void *[4], | ||||
| 						     GLfloat [4], | ||||
| 						     void **, | ||||
| 						     void *)) fn; | ||||
|     return; | ||||
|   case GLU_TESS_MESH: | ||||
|     tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn; | ||||
|     return; | ||||
|   default: | ||||
|     CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) | ||||
| { | ||||
|   GLUhalfEdge *e; | ||||
|  | ||||
|   e = tess->lastEdge; | ||||
|   if( e == NULL ) { | ||||
|     /* Make a self-loop (one vertex, one edge). */ | ||||
|  | ||||
|     e = __gl_meshMakeEdge( tess->mesh ); | ||||
|     if (e == NULL) return 0; | ||||
|     if ( !__gl_meshSplice( e, e->Sym ) ) return 0; | ||||
|   } else { | ||||
|     /* Create a new vertex and edge which immediately follow e | ||||
|      * in the ordering around the left face. | ||||
|      */ | ||||
|     if (__gl_meshSplitEdge( e ) == NULL) return 0; | ||||
|     e = e->Lnext; | ||||
|   } | ||||
|  | ||||
|   /* The new vertex is now e->Org. */ | ||||
|   e->Org->data = data; | ||||
|   e->Org->coords[0] = coords[0]; | ||||
|   e->Org->coords[1] = coords[1]; | ||||
|   e->Org->coords[2] = coords[2]; | ||||
|  | ||||
|   /* The winding of an edge says how the winding number changes as we | ||||
|    * cross from the edge''s right face to its left face.  We add the | ||||
|    * vertices in such an order that a CCW contour will add +1 to | ||||
|    * the winding number of the region inside the contour. | ||||
|    */ | ||||
|   e->winding = 1; | ||||
|   e->Sym->winding = -1; | ||||
|  | ||||
|   tess->lastEdge = e; | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) | ||||
| { | ||||
|   CachedVertex *v = &tess->cache[tess->cacheCount]; | ||||
|  | ||||
|   v->data = data; | ||||
|   v->coords[0] = coords[0]; | ||||
|   v->coords[1] = coords[1]; | ||||
|   v->coords[2] = coords[2]; | ||||
|   ++tess->cacheCount; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int EmptyCache( GLUtesselator *tess ) | ||||
| { | ||||
|   CachedVertex *v = tess->cache; | ||||
|   CachedVertex *vLast; | ||||
|  | ||||
|   tess->mesh = __gl_meshNewMesh(); | ||||
|   if (tess->mesh == NULL) return 0; | ||||
|  | ||||
|   for( vLast = v + tess->cacheCount; v < vLast; ++v ) { | ||||
|     if ( !AddVertex( tess, v->coords, v->data ) ) return 0; | ||||
|   } | ||||
|   tess->cacheCount = 0; | ||||
|   tess->emptyCache = FALSE; | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) | ||||
| { | ||||
|   int i, tooLarge = FALSE; | ||||
|   GLdouble x, clamped[3]; | ||||
|  | ||||
|   RequireState( tess, T_IN_CONTOUR ); | ||||
|  | ||||
|   if( tess->emptyCache ) { | ||||
|     if ( !EmptyCache( tess ) ) { | ||||
|        CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); | ||||
|        return; | ||||
|     } | ||||
|     tess->lastEdge = NULL; | ||||
|   } | ||||
|   for( i = 0; i < 3; ++i ) { | ||||
|     x = coords[i]; | ||||
|     if( x < - GLU_TESS_MAX_COORD ) { | ||||
|       x = - GLU_TESS_MAX_COORD; | ||||
|       tooLarge = TRUE; | ||||
|     } | ||||
|     if( x > GLU_TESS_MAX_COORD ) { | ||||
|       x = GLU_TESS_MAX_COORD; | ||||
|       tooLarge = TRUE; | ||||
|     } | ||||
|     clamped[i] = x; | ||||
|   } | ||||
|   if( tooLarge ) { | ||||
|     CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE ); | ||||
|   } | ||||
|  | ||||
|   if( tess->mesh == NULL ) { | ||||
|     if( tess->cacheCount < TESS_MAX_CACHE ) { | ||||
|       CacheVertex( tess, clamped, data ); | ||||
|       return; | ||||
|     } | ||||
|     if ( !EmptyCache( tess ) ) { | ||||
|        CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); | ||||
|        return; | ||||
|     } | ||||
|   } | ||||
|   if ( !AddVertex( tess, clamped, data ) ) { | ||||
|        CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessBeginPolygon( GLUtesselator *tess, void *data ) | ||||
| { | ||||
|   RequireState( tess, T_DORMANT ); | ||||
|  | ||||
|   tess->state = T_IN_POLYGON; | ||||
|   tess->cacheCount = 0; | ||||
|   tess->emptyCache = FALSE; | ||||
|   tess->mesh = NULL; | ||||
|  | ||||
|   tess->polygonData= data; | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessBeginContour( GLUtesselator *tess ) | ||||
| { | ||||
|   RequireState( tess, T_IN_POLYGON ); | ||||
|  | ||||
|   tess->state = T_IN_CONTOUR; | ||||
|   tess->lastEdge = NULL; | ||||
|   if( tess->cacheCount > 0 ) { | ||||
|     /* Just set a flag so we don't get confused by empty contours | ||||
|      * -- these can be generated accidentally with the obsolete | ||||
|      * NextContour() interface. | ||||
|      */ | ||||
|     tess->emptyCache = TRUE; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessEndContour( GLUtesselator *tess ) | ||||
| { | ||||
|   RequireState( tess, T_IN_CONTOUR ); | ||||
|   tess->state = T_IN_POLYGON; | ||||
| } | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluTessEndPolygon( GLUtesselator *tess ) | ||||
| { | ||||
|   GLUmesh *mesh; | ||||
|  | ||||
|   if (setjmp(tess->env) != 0) {  | ||||
|      /* come back here if out of memory */ | ||||
|      CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); | ||||
|      return; | ||||
|   } | ||||
|  | ||||
|   RequireState( tess, T_IN_POLYGON ); | ||||
|   tess->state = T_DORMANT; | ||||
|  | ||||
|   if( tess->mesh == NULL ) { | ||||
|     if( ! tess->flagBoundary && tess->callMesh == &noMesh ) { | ||||
|  | ||||
|       /* Try some special code to make the easy cases go quickly | ||||
|        * (eg. convex polygons).  This code does NOT handle multiple contours, | ||||
|        * intersections, edge flags, and of course it does not generate | ||||
|        * an explicit mesh either. | ||||
|        */ | ||||
|       if( __gl_renderCache( tess )) { | ||||
| 	tess->polygonData= NULL; | ||||
| 	return; | ||||
|       } | ||||
|     } | ||||
|     if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/ | ||||
|   } | ||||
|  | ||||
|   /* Determine the polygon normal and project vertices onto the plane | ||||
|    * of the polygon. | ||||
|    */ | ||||
|   __gl_projectPolygon( tess ); | ||||
|  | ||||
|   /* __gl_computeInterior( tess ) computes the planar arrangement specified | ||||
|    * by the given contours, and further subdivides this arrangement | ||||
|    * into regions.  Each region is marked "inside" if it belongs | ||||
|    * to the polygon, according to the rule given by tess->windingRule. | ||||
|    * Each interior region is guaranteed be monotone. | ||||
|    */ | ||||
|   if ( !__gl_computeInterior( tess ) ) { | ||||
|      longjmp(tess->env,1);	/* could've used a label */ | ||||
|   } | ||||
|  | ||||
|   mesh = tess->mesh; | ||||
|   if( ! tess->fatalError ) { | ||||
|     int rc = 1; | ||||
|  | ||||
|     /* If the user wants only the boundary contours, we throw away all edges | ||||
|      * except those which separate the interior from the exterior. | ||||
|      * Otherwise we tessellate all the regions marked "inside". | ||||
|      */ | ||||
|     if( tess->boundaryOnly ) { | ||||
|       rc = __gl_meshSetWindingNumber( mesh, 1, TRUE ); | ||||
|     } else { | ||||
|       rc = __gl_meshTessellateInterior( mesh ); | ||||
|     } | ||||
|     if (rc == 0) longjmp(tess->env,1);	/* could've used a label */ | ||||
|  | ||||
|     __gl_meshCheckMesh( mesh ); | ||||
|  | ||||
|     if( tess->callBegin != &noBegin || tess->callEnd != &noEnd | ||||
|        || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag | ||||
|        || tess->callBeginData != &__gl_noBeginData | ||||
|        || tess->callEndData != &__gl_noEndData | ||||
|        || tess->callVertexData != &__gl_noVertexData | ||||
|        || tess->callEdgeFlagData != &__gl_noEdgeFlagData ) | ||||
|     { | ||||
|       if( tess->boundaryOnly ) { | ||||
| 	__gl_renderBoundary( tess, mesh );  /* output boundary contours */ | ||||
|       } else { | ||||
| 	__gl_renderMesh( tess, mesh );	   /* output strips and fans */ | ||||
|       } | ||||
|     } | ||||
|     if( tess->callMesh != &noMesh ) { | ||||
|  | ||||
|       /* Throw away the exterior faces, so that all faces are interior. | ||||
|        * This way the user doesn't have to check the "inside" flag, | ||||
|        * and we don't need to even reveal its existence.  It also leaves | ||||
|        * the freedom for an implementation to not generate the exterior | ||||
|        * faces in the first place. | ||||
|        */ | ||||
|       __gl_meshDiscardExterior( mesh ); | ||||
|       (*tess->callMesh)( mesh );		/* user wants the mesh itself */ | ||||
|       tess->mesh = NULL; | ||||
|       tess->polygonData= NULL; | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|   __gl_meshDeleteMesh( mesh ); | ||||
|   tess->polygonData= NULL; | ||||
|   tess->mesh = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*XXXblythe unused function*/ | ||||
| #if 0 | ||||
| void GLAPIENTRY | ||||
| gluDeleteMesh( GLUmesh *mesh ) | ||||
| { | ||||
|   __gl_meshDeleteMesh( mesh ); | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| /*******************************************************/ | ||||
|  | ||||
| /* Obsolete calls -- for backward compatibility */ | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluBeginPolygon( GLUtesselator *tess ) | ||||
| { | ||||
|   gluTessBeginPolygon( tess, NULL ); | ||||
|   gluTessBeginContour( tess ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /*ARGSUSED*/ | ||||
| void GLAPIENTRY | ||||
| gluNextContour( GLUtesselator *tess, GLenum type ) | ||||
| { | ||||
|   gluTessEndContour( tess ); | ||||
|   gluTessBeginContour( tess ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void GLAPIENTRY | ||||
| gluEndPolygon( GLUtesselator *tess ) | ||||
| { | ||||
|   gluTessEndContour( tess ); | ||||
|   gluTessEndPolygon( tess ); | ||||
| } | ||||
| @@ -1,164 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __tess_h_ | ||||
| #define __tess_h_ | ||||
|  | ||||
| #include <setjmp.h> | ||||
| #include "mesh.h" | ||||
| #include "dict.h" | ||||
| #include "priorityq.h" | ||||
|  | ||||
| /* The begin/end calls must be properly nested.  We keep track of | ||||
|  * the current state to enforce the ordering. | ||||
|  */ | ||||
| enum TessState { T_DORMANT, T_IN_POLYGON, T_IN_CONTOUR }; | ||||
|  | ||||
| /* We cache vertex data for single-contour polygons so that we can | ||||
|  * try a quick-and-dirty decomposition first. | ||||
|  */ | ||||
| #define TESS_MAX_CACHE	100 | ||||
|  | ||||
| typedef struct CachedVertex { | ||||
|   GLdouble	coords[3]; | ||||
|   void		*data; | ||||
| } CachedVertex; | ||||
|  | ||||
| struct GLUtesselator { | ||||
|  | ||||
|   /*** state needed for collecting the input data ***/ | ||||
|  | ||||
|   enum TessState state;		/* what begin/end calls have we seen? */ | ||||
|  | ||||
|   GLUhalfEdge	*lastEdge;	/* lastEdge->Org is the most recent vertex */ | ||||
|   GLUmesh	*mesh;		/* stores the input contours, and eventually | ||||
|                                    the tessellation itself */ | ||||
|  | ||||
|   void		(GLAPIENTRY *callError)( GLenum errnum ); | ||||
|  | ||||
|   /*** state needed for projecting onto the sweep plane ***/ | ||||
|  | ||||
|   GLdouble	normal[3];	/* user-specified normal (if provided) */ | ||||
|   GLdouble	sUnit[3];	/* unit vector in s-direction (debugging) */ | ||||
|   GLdouble	tUnit[3];	/* unit vector in t-direction (debugging) */ | ||||
|  | ||||
|   /*** state needed for the line sweep ***/ | ||||
|  | ||||
|   GLdouble	relTolerance;	/* tolerance for merging features */ | ||||
|   GLenum	windingRule;	/* rule for determining polygon interior */ | ||||
|   GLboolean	fatalError;	/* fatal error: needed combine callback */ | ||||
|  | ||||
|   Dict		*dict;		/* edge dictionary for sweep line */ | ||||
|   PriorityQ	*pq;		/* priority queue of vertex events */ | ||||
|   GLUvertex	*event;		/* current sweep event being processed */ | ||||
|  | ||||
|   void		(GLAPIENTRY *callCombine)( GLdouble coords[3], void *data[4], | ||||
| 			        GLfloat weight[4], void **outData ); | ||||
|  | ||||
|   /*** state needed for rendering callbacks (see render.c) ***/ | ||||
|  | ||||
|   GLboolean	flagBoundary;	/* mark boundary edges (use EdgeFlag) */ | ||||
|   GLboolean	boundaryOnly;	/* Extract contours, not triangles */ | ||||
|   GLUface	*lonelyTriList; | ||||
|     /* list of triangles which could not be rendered as strips or fans */ | ||||
|  | ||||
|   void		(GLAPIENTRY *callBegin)( GLenum type ); | ||||
|   void		(GLAPIENTRY *callEdgeFlag)( GLboolean boundaryEdge ); | ||||
|   void		(GLAPIENTRY *callVertex)( void *data ); | ||||
|   void		(GLAPIENTRY *callEnd)( void ); | ||||
|   void		(GLAPIENTRY *callMesh)( GLUmesh *mesh ); | ||||
|  | ||||
|  | ||||
|   /*** state needed to cache single-contour polygons for renderCache() */ | ||||
|  | ||||
|   GLboolean	emptyCache;		/* empty cache on next vertex() call */ | ||||
|   int		cacheCount;		/* number of cached vertices */ | ||||
|   CachedVertex	cache[TESS_MAX_CACHE];	/* the vertex data */ | ||||
|  | ||||
|   /*** rendering callbacks that also pass polygon data  ***/  | ||||
|   void		(GLAPIENTRY *callBeginData)( GLenum type, void *polygonData ); | ||||
|   void		(GLAPIENTRY *callEdgeFlagData)( GLboolean boundaryEdge,  | ||||
| 				     void *polygonData ); | ||||
|   void		(GLAPIENTRY *callVertexData)( void *data, void *polygonData ); | ||||
|   void		(GLAPIENTRY *callEndData)( void *polygonData ); | ||||
|   void		(GLAPIENTRY *callErrorData)( GLenum errnum, void *polygonData ); | ||||
|   void		(GLAPIENTRY *callCombineData)( GLdouble coords[3], void *data[4], | ||||
| 				    GLfloat weight[4], void **outData, | ||||
| 				    void *polygonData ); | ||||
|  | ||||
|   jmp_buf env;			/* place to jump to when memAllocs fail */ | ||||
|  | ||||
|   void *polygonData;		/* client data for current polygon */ | ||||
| }; | ||||
|  | ||||
| void GLAPIENTRY __gl_noBeginData( GLenum type, void *polygonData ); | ||||
| void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, void *polygonData ); | ||||
| void GLAPIENTRY __gl_noVertexData( void *data, void *polygonData ); | ||||
| void GLAPIENTRY __gl_noEndData( void *polygonData ); | ||||
| void GLAPIENTRY __gl_noErrorData( GLenum errnum, void *polygonData ); | ||||
| void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], void *data[4], | ||||
| 			 GLfloat weight[4], void **outData, | ||||
| 			 void *polygonData ); | ||||
|  | ||||
| #define CALL_BEGIN_OR_BEGIN_DATA(a) \ | ||||
|    if (tess->callBeginData != &__gl_noBeginData) \ | ||||
|       (*tess->callBeginData)((a),tess->polygonData); \ | ||||
|    else (*tess->callBegin)((a)); | ||||
|  | ||||
| #define CALL_VERTEX_OR_VERTEX_DATA(a) \ | ||||
|    if (tess->callVertexData != &__gl_noVertexData) \ | ||||
|       (*tess->callVertexData)((a),tess->polygonData); \ | ||||
|    else (*tess->callVertex)((a)); | ||||
|  | ||||
| #define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a) \ | ||||
|    if (tess->callEdgeFlagData != &__gl_noEdgeFlagData) \ | ||||
|       (*tess->callEdgeFlagData)((a),tess->polygonData); \ | ||||
|    else (*tess->callEdgeFlag)((a)); | ||||
|  | ||||
| #define CALL_END_OR_END_DATA() \ | ||||
|    if (tess->callEndData != &__gl_noEndData) \ | ||||
|       (*tess->callEndData)(tess->polygonData); \ | ||||
|    else (*tess->callEnd)(); | ||||
|  | ||||
| #define CALL_COMBINE_OR_COMBINE_DATA(a,b,c,d) \ | ||||
|    if (tess->callCombineData != &__gl_noCombineData) \ | ||||
|       (*tess->callCombineData)((a),(b),(c),(d),tess->polygonData); \ | ||||
|    else (*tess->callCombine)((a),(b),(c),(d)); | ||||
|  | ||||
| #define CALL_ERROR_OR_ERROR_DATA(a) \ | ||||
|    if (tess->callErrorData != &__gl_noErrorData) \ | ||||
|       (*tess->callErrorData)((a),tess->polygonData); \ | ||||
|    else (*tess->callError)((a)); | ||||
|  | ||||
| #endif | ||||
| @@ -1,122 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * Copyright (C) 2010 Intel Corporation | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
|  | ||||
| #ifndef __TESSELATOR_H__ | ||||
| #define __TESSELATOR_H__ | ||||
|  | ||||
| /* This just includes the defines needed by the tesselator code */ | ||||
|  | ||||
| #include "cogl/cogl-defines.h" | ||||
| #include "cogl/cogl-gl-header.h" | ||||
|  | ||||
| typedef struct GLUtesselator GLUtesselator; | ||||
|  | ||||
| #define GLU_TESS_MAX_COORD 1.0e150 | ||||
|  | ||||
| void gluBeginPolygon (GLUtesselator* tess); | ||||
| void gluDeleteTess (GLUtesselator* tess); | ||||
| void gluEndPolygon (GLUtesselator* tess); | ||||
|  | ||||
| typedef void (_GLUfuncptr)(void); | ||||
|  | ||||
| void gluGetTessProperty (GLUtesselator* tess, GLenum which, double* data); | ||||
|  | ||||
| GLUtesselator *gluNewTess (void); | ||||
| void gluNextContour (GLUtesselator* tess, GLenum type); | ||||
|  | ||||
| void gluTessBeginContour (GLUtesselator* tess); | ||||
| void gluTessBeginPolygon (GLUtesselator* tess, GLvoid* data); | ||||
| void gluTessCallback (GLUtesselator* tess, GLenum which, _GLUfuncptr CallBackFunc); | ||||
| void gluTessEndContour (GLUtesselator* tess); | ||||
| void gluTessEndPolygon (GLUtesselator* tess); | ||||
| void gluTessNormal (GLUtesselator* tess, double valueX, double valueY, double valueZ); | ||||
| void gluTessProperty (GLUtesselator* tess, GLenum which, double data); | ||||
| void gluTessVertex (GLUtesselator* tess, double *location, GLvoid* data); | ||||
|  | ||||
| /* ErrorCode */ | ||||
| #define GLU_INVALID_ENUM                   100900 | ||||
| #define GLU_INVALID_VALUE                  100901 | ||||
| #define GLU_OUT_OF_MEMORY                  100902 | ||||
|  | ||||
| /* TessCallback */ | ||||
| #define GLU_TESS_BEGIN                     100100 | ||||
| #define GLU_BEGIN                          100100 | ||||
| #define GLU_TESS_VERTEX                    100101 | ||||
| #define GLU_VERTEX                         100101 | ||||
| #define GLU_TESS_END                       100102 | ||||
| #define GLU_END                            100102 | ||||
| #define GLU_TESS_ERROR                     100103 | ||||
| #define GLU_TESS_EDGE_FLAG                 100104 | ||||
| #define GLU_EDGE_FLAG                      100104 | ||||
| #define GLU_TESS_COMBINE                   100105 | ||||
| #define GLU_TESS_BEGIN_DATA                100106 | ||||
| #define GLU_TESS_VERTEX_DATA               100107 | ||||
| #define GLU_TESS_END_DATA                  100108 | ||||
| #define GLU_TESS_ERROR_DATA                100109 | ||||
| #define GLU_TESS_EDGE_FLAG_DATA            100110 | ||||
| #define GLU_TESS_COMBINE_DATA              100111 | ||||
|  | ||||
| /* TessContour */ | ||||
| #define GLU_CW                             100120 | ||||
| #define GLU_CCW                            100121 | ||||
| #define GLU_INTERIOR                       100122 | ||||
| #define GLU_EXTERIOR                       100123 | ||||
| #define GLU_UNKNOWN                        100124 | ||||
|  | ||||
| /* TessProperty */ | ||||
| #define GLU_TESS_WINDING_RULE              100140 | ||||
| #define GLU_TESS_BOUNDARY_ONLY             100141 | ||||
| #define GLU_TESS_TOLERANCE                 100142 | ||||
|  | ||||
| /* TessError */ | ||||
| #define GLU_TESS_ERROR1                    100151 | ||||
| #define GLU_TESS_ERROR2                    100152 | ||||
| #define GLU_TESS_ERROR3                    100153 | ||||
| #define GLU_TESS_ERROR4                    100154 | ||||
| #define GLU_TESS_ERROR5                    100155 | ||||
| #define GLU_TESS_ERROR6                    100156 | ||||
| #define GLU_TESS_ERROR7                    100157 | ||||
| #define GLU_TESS_ERROR8                    100158 | ||||
| #define GLU_TESS_MISSING_BEGIN_POLYGON     100151 | ||||
| #define GLU_TESS_MISSING_BEGIN_CONTOUR     100152 | ||||
| #define GLU_TESS_MISSING_END_POLYGON       100153 | ||||
| #define GLU_TESS_MISSING_END_CONTOUR       100154 | ||||
| #define GLU_TESS_COORD_TOO_LARGE           100155 | ||||
| #define GLU_TESS_NEED_COMBINE_CALLBACK     100156 | ||||
|  | ||||
| /* TessWinding */ | ||||
| #define GLU_TESS_WINDING_ODD               100130 | ||||
| #define GLU_TESS_WINDING_NONZERO           100131 | ||||
| #define GLU_TESS_WINDING_POSITIVE          100132 | ||||
| #define GLU_TESS_WINDING_NEGATIVE          100133 | ||||
| #define GLU_TESS_WINDING_ABS_GEQ_TWO       100134 | ||||
|  | ||||
| #endif /* __TESSELATOR_H__ */ | ||||
| @@ -1,201 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #include "gluos.h" | ||||
| #include <stdlib.h> | ||||
| #include "geom.h" | ||||
| #include "mesh.h" | ||||
| #include "tessmono.h" | ||||
| #include <assert.h> | ||||
|  | ||||
| #define AddWinding(eDst,eSrc)	(eDst->winding += eSrc->winding, \ | ||||
| 				 eDst->Sym->winding += eSrc->Sym->winding) | ||||
|  | ||||
| /* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region | ||||
|  * (what else would it do??)  The region must consist of a single | ||||
|  * loop of half-edges (see mesh.h) oriented CCW.  "Monotone" in this | ||||
|  * case means that any vertical line intersects the interior of the | ||||
|  * region in a single interval.   | ||||
|  * | ||||
|  * Tessellation consists of adding interior edges (actually pairs of | ||||
|  * half-edges), to split the region into non-overlapping triangles. | ||||
|  * | ||||
|  * The basic idea is explained in Preparata and Shamos (which I don''t | ||||
|  * have handy right now), although their implementation is more | ||||
|  * complicated than this one.  The are two edge chains, an upper chain | ||||
|  * and a lower chain.  We process all vertices from both chains in order, | ||||
|  * from right to left. | ||||
|  * | ||||
|  * The algorithm ensures that the following invariant holds after each | ||||
|  * vertex is processed: the untessellated region consists of two | ||||
|  * chains, where one chain (say the upper) is a single edge, and | ||||
|  * the other chain is concave.  The left vertex of the single edge | ||||
|  * is always to the left of all vertices in the concave chain. | ||||
|  * | ||||
|  * Each step consists of adding the rightmost unprocessed vertex to one | ||||
|  * of the two chains, and forming a fan of triangles from the rightmost | ||||
|  * of two chain endpoints.  Determining whether we can add each triangle | ||||
|  * to the fan is a simple orientation test.  By making the fan as large | ||||
|  * as possible, we restore the invariant (check it yourself). | ||||
|  */ | ||||
| int __gl_meshTessellateMonoRegion( GLUface *face ) | ||||
| { | ||||
|   GLUhalfEdge *up, *lo; | ||||
|  | ||||
|   /* All edges are oriented CCW around the boundary of the region. | ||||
|    * First, find the half-edge whose origin vertex is rightmost. | ||||
|    * Since the sweep goes from left to right, face->anEdge should | ||||
|    * be close to the edge we want. | ||||
|    */ | ||||
|   up = face->anEdge; | ||||
|   assert( up->Lnext != up && up->Lnext->Lnext != up ); | ||||
|  | ||||
|   for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev ) | ||||
|     ; | ||||
|   for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext ) | ||||
|     ; | ||||
|   lo = up->Lprev; | ||||
|  | ||||
|   while( up->Lnext != lo ) { | ||||
|     if( VertLeq( up->Dst, lo->Org )) { | ||||
|       /* up->Dst is on the left.  It is safe to form triangles from lo->Org. | ||||
|        * The EdgeGoesLeft test guarantees progress even when some triangles | ||||
|        * are CW, given that the upper and lower chains are truly monotone. | ||||
|        */ | ||||
|       while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext ) | ||||
| 	     || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) { | ||||
| 	GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo ); | ||||
| 	if (tempHalfEdge == NULL) return 0; | ||||
| 	lo = tempHalfEdge->Sym; | ||||
|       } | ||||
|       lo = lo->Lprev; | ||||
|     } else { | ||||
|       /* lo->Org is on the left.  We can make CCW triangles from up->Dst. */ | ||||
|       while( lo->Lnext != up && (EdgeGoesRight( up->Lprev ) | ||||
| 	     || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) { | ||||
| 	GLUhalfEdge *tempHalfEdge= __gl_meshConnect( up, up->Lprev ); | ||||
| 	if (tempHalfEdge == NULL) return 0; | ||||
| 	up = tempHalfEdge->Sym; | ||||
|       } | ||||
|       up = up->Lnext; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* Now lo->Org == up->Dst == the leftmost vertex.  The remaining region | ||||
|    * can be tessellated in a fan from this leftmost vertex. | ||||
|    */ | ||||
|   assert( lo->Lnext != up ); | ||||
|   while( lo->Lnext->Lnext != up ) { | ||||
|     GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo ); | ||||
|     if (tempHalfEdge == NULL) return 0; | ||||
|     lo = tempHalfEdge->Sym; | ||||
|   } | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshTessellateInterior( mesh ) tessellates each region of | ||||
|  * the mesh which is marked "inside" the polygon.  Each such region | ||||
|  * must be monotone. | ||||
|  */ | ||||
| int __gl_meshTessellateInterior( GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *f, *next; | ||||
|  | ||||
|   /*LINTED*/ | ||||
|   for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { | ||||
|     /* Make sure we don''t try to tessellate the new triangles. */ | ||||
|     next = f->next; | ||||
|     if( f->inside ) { | ||||
|       if ( !__gl_meshTessellateMonoRegion( f ) ) return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces | ||||
|  * which are not marked "inside" the polygon.  Since further mesh operations | ||||
|  * on NULL faces are not allowed, the main purpose is to clean up the | ||||
|  * mesh so that exterior loops are not represented in the data structure. | ||||
|  */ | ||||
| void __gl_meshDiscardExterior( GLUmesh *mesh ) | ||||
| { | ||||
|   GLUface *f, *next; | ||||
|  | ||||
|   /*LINTED*/ | ||||
|   for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { | ||||
|     /* Since f will be destroyed, save its next pointer. */ | ||||
|     next = f->next; | ||||
|     if( ! f->inside ) { | ||||
|       __gl_meshZapFace( f ); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| #define MARKED_FOR_DELETION	0x7fffffff | ||||
|  | ||||
| /* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the | ||||
|  * winding numbers on all edges so that regions marked "inside" the | ||||
|  * polygon have a winding number of "value", and regions outside | ||||
|  * have a winding number of 0. | ||||
|  * | ||||
|  * If keepOnlyBoundary is TRUE, it also deletes all edges which do not | ||||
|  * separate an interior region from an exterior one. | ||||
|  */ | ||||
| int __gl_meshSetWindingNumber( GLUmesh *mesh, int value, | ||||
| 			        GLboolean keepOnlyBoundary ) | ||||
| { | ||||
|   GLUhalfEdge *e, *eNext; | ||||
|  | ||||
|   for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { | ||||
|     eNext = e->next; | ||||
|     if( e->Rface->inside != e->Lface->inside ) { | ||||
|  | ||||
|       /* This is a boundary edge (one side is interior, one is exterior). */ | ||||
|       e->winding = (e->Lface->inside) ? value : -value; | ||||
|     } else { | ||||
|  | ||||
|       /* Both regions are interior, or both are exterior. */ | ||||
|       if( ! keepOnlyBoundary ) { | ||||
| 	e->winding = 0; | ||||
|       } else { | ||||
| 	if ( !__gl_meshDelete( e ) ) return 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return 1; | ||||
| } | ||||
| @@ -1,71 +0,0 @@ | ||||
| /* | ||||
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) | ||||
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice including the dates of first publication and | ||||
|  * either this permission notice or a reference to | ||||
|  * http://oss.sgi.com/projects/FreeB/ | ||||
|  * shall be included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||||
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * Except as contained in this notice, the name of Silicon Graphics, Inc. | ||||
|  * shall not be used in advertising or otherwise to promote the sale, use or | ||||
|  * other dealings in this Software without prior written authorization from | ||||
|  * Silicon Graphics, Inc. | ||||
|  */ | ||||
| /* | ||||
| ** Author: Eric Veach, July 1994. | ||||
| ** | ||||
| */ | ||||
|  | ||||
| #ifndef __tessmono_h_ | ||||
| #define __tessmono_h_ | ||||
|  | ||||
| /* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region | ||||
|  * (what else would it do??)  The region must consist of a single | ||||
|  * loop of half-edges (see mesh.h) oriented CCW.  "Monotone" in this | ||||
|  * case means that any vertical line intersects the interior of the | ||||
|  * region in a single interval.   | ||||
|  * | ||||
|  * Tessellation consists of adding interior edges (actually pairs of | ||||
|  * half-edges), to split the region into non-overlapping triangles. | ||||
|  * | ||||
|  * __gl_meshTessellateInterior( mesh ) tessellates each region of | ||||
|  * the mesh which is marked "inside" the polygon.  Each such region | ||||
|  * must be monotone. | ||||
|  * | ||||
|  * __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces | ||||
|  * which are not marked "inside" the polygon.  Since further mesh operations | ||||
|  * on NULL faces are not allowed, the main purpose is to clean up the | ||||
|  * mesh so that exterior loops are not represented in the data structure. | ||||
|  * | ||||
|  * __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the | ||||
|  * winding numbers on all edges so that regions marked "inside" the | ||||
|  * polygon have a winding number of "value", and regions outside | ||||
|  * have a winding number of 0. | ||||
|  * | ||||
|  * If keepOnlyBoundary is TRUE, it also deletes all edges which do not | ||||
|  * separate an interior region from an exterior one. | ||||
|  */ | ||||
|  | ||||
| int __gl_meshTessellateMonoRegion( GLUface *face ); | ||||
| int __gl_meshTessellateInterior( GLUmesh *mesh ); | ||||
| void __gl_meshDiscardExterior( GLUmesh *mesh ); | ||||
| int __gl_meshSetWindingNumber( GLUmesh *mesh, int value, | ||||
| 			        GLboolean keepOnlyBoundary ); | ||||
|  | ||||
| #endif | ||||
| @@ -52,7 +52,6 @@ | ||||
| #include "cogl-onscreen-private.h" | ||||
| #include "cogl-fence-private.h" | ||||
| #include "cogl-poll-private.h" | ||||
| #include "cogl-path/cogl-path-types.h" | ||||
| #include "cogl-private.h" | ||||
| #include "winsys/cogl-winsys-private.h" | ||||
|  | ||||
| @@ -125,11 +124,6 @@ struct _CoglContext | ||||
|  | ||||
|   CoglMatrixEntry identity_entry; | ||||
|  | ||||
|   /* A cache of the last (immutable) matrix stack entries that were | ||||
|    * flushed to the GL matrix builtins */ | ||||
|   CoglMatrixEntryCache builtin_flushed_projection; | ||||
|   CoglMatrixEntryCache builtin_flushed_modelview; | ||||
|  | ||||
|   GArray           *texture_units; | ||||
|   int               active_texture_unit; | ||||
|  | ||||
| @@ -153,8 +147,6 @@ struct _CoglContext | ||||
|   GArray           *journal_flush_attributes_array; | ||||
|   GArray           *journal_clip_bounds; | ||||
|  | ||||
|   GArray           *polygon_vertices; | ||||
|  | ||||
|   /* Some simple caching, to minimize state changes... */ | ||||
|   CoglPipeline     *current_pipeline; | ||||
|   unsigned long     current_pipeline_changes_since_flush; | ||||
| @@ -196,20 +188,12 @@ struct _CoglContext | ||||
|   gboolean was_bound_to_onscreen; | ||||
|  | ||||
|   /* Primitives */ | ||||
|   CoglPath         *current_path; | ||||
|   CoglPipeline     *stencil_pipeline; | ||||
|  | ||||
|   /* Pre-generated VBOs containing indices to generate GL_TRIANGLES | ||||
|      out of a vertex array of quads */ | ||||
|   CoglIndices      *quad_buffer_indices_byte; | ||||
|   unsigned int      quad_buffer_indices_len; | ||||
|   CoglIndices      *quad_buffer_indices; | ||||
|  | ||||
|   CoglIndices      *rectangle_byte_indices; | ||||
|   CoglIndices      *rectangle_short_indices; | ||||
|   int               rectangle_short_indices_len; | ||||
|  | ||||
|   CoglPipeline     *texture_download_pipeline; | ||||
|   CoglPipeline     *blit_texture_pipeline; | ||||
|  | ||||
|   GSList           *atlases; | ||||
|   | ||||
| @@ -276,8 +276,6 @@ cogl_context_new (CoglDisplay *display, | ||||
|     g_array_new (TRUE, FALSE, sizeof (CoglAttribute *)); | ||||
|   context->journal_clip_bounds = NULL; | ||||
|  | ||||
|   context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (float)); | ||||
|  | ||||
|   context->current_pipeline = NULL; | ||||
|   context->current_pipeline_changes_since_flush = 0; | ||||
|   context->current_pipeline_with_color_attrib = FALSE; | ||||
| @@ -308,25 +306,17 @@ cogl_context_new (CoglDisplay *display, | ||||
|   for (i = 0; i < COGL_BUFFER_BIND_TARGET_COUNT; i++) | ||||
|     context->current_buffer[i] = NULL; | ||||
|  | ||||
|   context->current_path = NULL; | ||||
|   context->stencil_pipeline = cogl_pipeline_new (context); | ||||
|  | ||||
|   context->quad_buffer_indices_byte = NULL; | ||||
|   context->quad_buffer_indices = NULL; | ||||
|   context->quad_buffer_indices_len = 0; | ||||
|  | ||||
|   context->rectangle_byte_indices = NULL; | ||||
|   context->rectangle_short_indices = NULL; | ||||
|   context->rectangle_short_indices_len = 0; | ||||
|  | ||||
|   context->texture_download_pipeline = NULL; | ||||
|   context->blit_texture_pipeline = NULL; | ||||
|  | ||||
|   context->current_modelview_entry = NULL; | ||||
|   context->current_projection_entry = NULL; | ||||
|   _cogl_matrix_entry_identity_init (&context->identity_entry); | ||||
|   _cogl_matrix_entry_cache_init (&context->builtin_flushed_projection); | ||||
|   _cogl_matrix_entry_cache_init (&context->builtin_flushed_modelview); | ||||
|  | ||||
|   /* Create default textures used for fall backs */ | ||||
|   context->default_gl_texture_2d_tex = | ||||
| @@ -356,9 +346,6 @@ _cogl_context_free (CoglContext *context) | ||||
|  | ||||
|   winsys->context_deinit (context); | ||||
|  | ||||
|   if (context->current_path) | ||||
|     cogl_object_unref (context->current_path); | ||||
|  | ||||
|   if (context->default_gl_texture_2d_tex) | ||||
|     cogl_object_unref (context->default_gl_texture_2d_tex); | ||||
|  | ||||
| @@ -376,14 +363,6 @@ _cogl_context_free (CoglContext *context) | ||||
|   if (context->journal_clip_bounds) | ||||
|     g_array_free (context->journal_clip_bounds, TRUE); | ||||
|  | ||||
|   if (context->polygon_vertices) | ||||
|     g_array_free (context->polygon_vertices, TRUE); | ||||
|  | ||||
|   if (context->quad_buffer_indices_byte) | ||||
|     cogl_object_unref (context->quad_buffer_indices_byte); | ||||
|   if (context->quad_buffer_indices) | ||||
|     cogl_object_unref (context->quad_buffer_indices); | ||||
|  | ||||
|   if (context->rectangle_byte_indices) | ||||
|     cogl_object_unref (context->rectangle_byte_indices); | ||||
|   if (context->rectangle_short_indices) | ||||
| @@ -413,8 +392,6 @@ _cogl_context_free (CoglContext *context) | ||||
|     cogl_matrix_entry_unref (context->current_modelview_entry); | ||||
|   if (context->current_projection_entry) | ||||
|     cogl_matrix_entry_unref (context->current_projection_entry); | ||||
|   _cogl_matrix_entry_cache_destroy (&context->builtin_flushed_projection); | ||||
|   _cogl_matrix_entry_cache_destroy (&context->builtin_flushed_modelview); | ||||
|  | ||||
|   _cogl_pipeline_cache_free (context->pipeline_cache); | ||||
|  | ||||
|   | ||||
| @@ -112,12 +112,12 @@ cogl_object_unref (void *object); | ||||
|  * } | ||||
|  * | ||||
|  * static void | ||||
|  * my_path_set_data (CoglPath *path, void *data) | ||||
|  * my_path_set_data (CoglPipeline *pipeline, void *data) | ||||
|  * { | ||||
|  *   cogl_object_set_user_data (COGL_OBJECT (path), | ||||
|  *   cogl_object_set_user_data (COGL_OBJECT (pipeline), | ||||
|  *                              &private_key, | ||||
|  *                              data, | ||||
|  *                              destroy_path_private_cb); | ||||
|  *                              destroy_pipeline_private_cb); | ||||
|  * } | ||||
|  * ]| | ||||
|  * | ||||
|   | ||||
| @@ -93,10 +93,12 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen, | ||||
| CoglOnscreen * | ||||
| _cogl_onscreen_new (void) | ||||
| { | ||||
|   CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1); | ||||
|   g_autofree CoglOnscreen *onscreen_ptr = g_new0 (CoglOnscreen, 1); | ||||
|   CoglOnscreen *onscreen; | ||||
|  | ||||
|   _COGL_GET_CONTEXT (ctx, NULL); | ||||
|  | ||||
|   onscreen = g_steal_pointer (&onscreen_ptr); | ||||
|   _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen), | ||||
|                           ctx, | ||||
|                           COGL_FRAMEBUFFER_TYPE_ONSCREEN, | ||||
| @@ -403,6 +405,27 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen) | ||||
|   return winsys->onscreen_get_buffer_age (onscreen); | ||||
| } | ||||
|  | ||||
| void | ||||
| cogl_onscreen_direct_scanout (CoglOnscreen *onscreen, | ||||
|                               CoglScanout  *scanout) | ||||
| { | ||||
|   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); | ||||
|   const CoglWinsysVtable *winsys; | ||||
|   CoglFrameInfo *info; | ||||
|  | ||||
|   g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN); | ||||
|   g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)); | ||||
|  | ||||
|   info = _cogl_frame_info_new (); | ||||
|   info->frame_counter = onscreen->frame_counter; | ||||
|   g_queue_push_tail (&onscreen->pending_frame_infos, info); | ||||
|  | ||||
|   winsys = _cogl_framebuffer_get_winsys (framebuffer); | ||||
|   winsys->onscreen_direct_scanout (onscreen, scanout); | ||||
|  | ||||
|   onscreen->frame_counter++; | ||||
| } | ||||
|  | ||||
| #ifdef COGL_HAS_X11_SUPPORT | ||||
| uint32_t | ||||
| cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen) | ||||
|   | ||||
| @@ -50,6 +50,8 @@ G_BEGIN_DECLS | ||||
| typedef struct _CoglOnscreen CoglOnscreen; | ||||
| #define COGL_ONSCREEN(X) ((CoglOnscreen *)(X)) | ||||
|  | ||||
| typedef struct _CoglScanout CoglScanout; | ||||
|  | ||||
| /** | ||||
|  * cogl_onscreen_get_gtype: | ||||
|  * | ||||
| @@ -284,6 +286,13 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, | ||||
|                                         const int *rectangles, | ||||
|                                         int n_rectangles); | ||||
|  | ||||
| /** | ||||
|  * cogl_onscreen_direct_scanout: (skip) | ||||
|  */ | ||||
| COGL_EXPORT void | ||||
| cogl_onscreen_direct_scanout (CoglOnscreen *onscreen, | ||||
|                               CoglScanout  *scanout); | ||||
|  | ||||
| /** | ||||
|  * cogl_onscreen_swap_region: | ||||
|  * @onscreen: A #CoglOnscreen framebuffer | ||||
|   | ||||
| @@ -50,7 +50,7 @@ struct _CoglPipelineCache | ||||
| CoglPipelineCache * | ||||
| _cogl_pipeline_cache_new (void) | ||||
| { | ||||
|   CoglPipelineCache *cache = g_new (CoglPipelineCache, 1); | ||||
|   g_autofree CoglPipelineCache *cache = g_new (CoglPipelineCache, 1); | ||||
|   unsigned long vertex_state; | ||||
|   unsigned long layer_vertex_state; | ||||
|   unsigned int fragment_state; | ||||
| @@ -80,7 +80,7 @@ _cogl_pipeline_cache_new (void) | ||||
|                                   layer_vertex_state | layer_fragment_state, | ||||
|                                   "programs"); | ||||
|  | ||||
|   return cache; | ||||
|   return g_steal_pointer (&cache); | ||||
| } | ||||
|  | ||||
| void | ||||
|   | ||||
							
								
								
									
										27
									
								
								cogl/cogl/cogl-scanout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								cogl/cogl/cogl-scanout.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat Inc. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "cogl-config.h" | ||||
|  | ||||
| #include "cogl-scanout.h" | ||||
|  | ||||
| G_DEFINE_INTERFACE (CoglScanout, cogl_scanout, G_TYPE_OBJECT) | ||||
|  | ||||
| static void | ||||
| cogl_scanout_default_init (CoglScanoutInterface *iface) | ||||
| { | ||||
| } | ||||
							
								
								
									
										35
									
								
								cogl/cogl/cogl-scanout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								cogl/cogl/cogl-scanout.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat Inc. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef COGL_SCANOUT_H | ||||
| #define COGL_SCANOUT_H | ||||
|  | ||||
| #include "cogl/cogl-types.h" | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #define COGL_TYPE_SCANOUT (cogl_scanout_get_type ()) | ||||
| COGL_EXPORT | ||||
| G_DECLARE_INTERFACE (CoglScanout, cogl_scanout, | ||||
|                      COGL, SCANOUT, GObject) | ||||
|  | ||||
| struct _CoglScanoutInterface | ||||
| { | ||||
|   GTypeInterface parent_iface; | ||||
| }; | ||||
|  | ||||
| #endif /* COGL_SCANOUT_H */ | ||||
| @@ -121,6 +121,9 @@ cogl_texture_2d_new_with_size (CoglContext *ctx, | ||||
| { | ||||
|   CoglTextureLoader *loader; | ||||
|  | ||||
|   g_return_val_if_fail (width >= 1, NULL); | ||||
|   g_return_val_if_fail (height >= 1, NULL); | ||||
|  | ||||
|   loader = _cogl_texture_create_loader (); | ||||
|   loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; | ||||
|   loader->src.sized.width = width; | ||||
|   | ||||
| @@ -122,26 +122,11 @@ | ||||
| #include <cogl/cogl-fence.h> | ||||
| #include <cogl/cogl-glib-source.h> | ||||
| #include <cogl/cogl-trace.h> | ||||
| #include <cogl/cogl-scanout.h> | ||||
| /* XXX: This will definitly go away once all the Clutter winsys | ||||
|  * code has been migrated down into Cogl! */ | ||||
| #include <cogl/deprecated/cogl-clutter.h> | ||||
|  | ||||
| /* | ||||
|  * Cogl Path api compatability | ||||
|  * | ||||
|  * The cogl_path_ api used to be part of the core Cogl api so for | ||||
|  * compatability we include cogl-path.h via cogl.h | ||||
|  * | ||||
|  * Note: we have to make sure not to include cogl-path.h while | ||||
|  * building core cogl or generating the Cogl .gir data because | ||||
|  * cogl-path now gets built after cogl and some cogl-path headers are | ||||
|  * only generated at build time... | ||||
|  */ | ||||
| #if !defined (COGL_COMPILATION) && \ | ||||
|   !defined (COGL_GIR_SCANNING) | ||||
| #include <cogl-path/cogl-path.h> | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * SECTION:cogl | ||||
|  * @short_description: General purpose API | ||||
|   | ||||
| @@ -132,8 +132,8 @@ _cogl_framebuffer_gl_flush_viewport_state (CoglFramebuffer *framebuffer) | ||||
| { | ||||
|   float gl_viewport_y; | ||||
|  | ||||
|   g_assert (framebuffer->viewport_width >=0 && | ||||
|             framebuffer->viewport_height >=0); | ||||
|   g_return_if_fail (framebuffer->viewport_width >= 0); | ||||
|   g_return_if_fail (framebuffer->viewport_height >= 0); | ||||
|  | ||||
|   /* Convert the Cogl viewport y offset to an OpenGL viewport y offset | ||||
|    * NB: OpenGL defines its window and viewport origins to be bottom | ||||
|   | ||||
| @@ -122,6 +122,7 @@ cogl_nonintrospected_headers = [ | ||||
|   'cogl-version.h', | ||||
|   'cogl-gtype-private.h', | ||||
|   'cogl-glib-source.h', | ||||
|   'cogl-scanout.h', | ||||
| ] | ||||
|  | ||||
| cogl_nodist_headers = [ | ||||
| @@ -347,6 +348,7 @@ cogl_sources = [ | ||||
|   'cogl-closure-list.c', | ||||
|   'cogl-fence.c', | ||||
|   'cogl-fence-private.h', | ||||
|   'cogl-scanout.c', | ||||
|   'deprecated/cogl-material-compat.c', | ||||
|   'deprecated/cogl-program.c', | ||||
|   'deprecated/cogl-program-private.h', | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
|  | ||||
| #include "cogl-renderer.h" | ||||
| #include "cogl-onscreen.h" | ||||
| #include "cogl-scanout.h" | ||||
|  | ||||
| #ifdef COGL_HAS_XLIB_SUPPORT | ||||
| #include "cogl-texture-pixmap-x11-private.h" | ||||
| @@ -117,6 +118,10 @@ typedef struct _CoglWinsysVtable | ||||
|                                         const int *rectangles, | ||||
|                                         int n_rectangles); | ||||
|  | ||||
|   void | ||||
|   (*onscreen_direct_scanout) (CoglOnscreen *onscreen, | ||||
|                               CoglScanout  *scanout); | ||||
|  | ||||
|   void | ||||
|   (*onscreen_set_visibility) (CoglOnscreen *onscreen, | ||||
|                               gboolean visibility); | ||||
|   | ||||
| @@ -116,7 +116,6 @@ if have_cogl_tests | ||||
|   subdir('test-fixtures') | ||||
| endif | ||||
| subdir('cogl') | ||||
| subdir('cogl-path') | ||||
| subdir('cogl-pango') | ||||
| if have_cogl_tests | ||||
|   subdir('tests') | ||||
|   | ||||
| @@ -40,8 +40,6 @@ cogl_test_conformance_sources = [ | ||||
|   'test-pipeline-shader-state.c', | ||||
|   'test-texture-rg.c', | ||||
|   'test-fence.c', | ||||
|   'test-path.c', | ||||
|   'test-path-clip.c', | ||||
| ] | ||||
|  | ||||
| #unported = [ | ||||
| @@ -84,7 +82,6 @@ libmutter_cogl_test_conformance = executable('test-conformance', | ||||
|   include_directories: cogl_test_conformance_includes, | ||||
|   dependencies: [ | ||||
|     libmutter_cogl_dep, | ||||
|     libmutter_cogl_path_dep, | ||||
|     libmutter_cogl_test_fixtures_dep, | ||||
|   ], | ||||
|   install: have_installed_tests, | ||||
|   | ||||
| @@ -57,8 +57,6 @@ main (int argc, char **argv) | ||||
|   ADD_TEST (test_blend, 0, 0); | ||||
|   ADD_TEST (test_premult, 0, TEST_KNOWN_FAILURE); | ||||
|   UNPORTED_TEST (test_readpixels); | ||||
|   ADD_TEST (test_path, 0, 0); | ||||
|   ADD_TEST (test_path_clip, 0, 0); | ||||
|   ADD_TEST (test_depth_test, 0, 0); | ||||
|   ADD_TEST (test_backface_culling, 0, TEST_REQUIREMENT_NPOT); | ||||
|   ADD_TEST (test_layer_remove, 0, 0); | ||||
|   | ||||
| @@ -42,39 +42,39 @@ void | ||||
| test_object (TestUtilsGTestFixture *fixture, | ||||
|                   void *data) | ||||
| { | ||||
|   CoglPath *path; | ||||
|   CoglPipeline *pipeline; | ||||
|  | ||||
|   /* Assuming that COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES == 2 | ||||
|    * test associating 2 pointers to private data with an object */ | ||||
|   cogl_path_new (); | ||||
|   path = cogl_get_path (); | ||||
|   cogl_pipeline_new (); | ||||
|   pipeline = cogl_pipeline_path (); | ||||
|  | ||||
|   cogl_object_set_user_data (COGL_OBJECT (path), | ||||
|   cogl_object_set_user_data (COGL_OBJECT (pipeline), | ||||
|                              &private_key0, | ||||
|                              &user_data0, | ||||
|                              destroy0_cb); | ||||
|  | ||||
|   cogl_object_set_user_data (COGL_OBJECT (path), | ||||
|   cogl_object_set_user_data (COGL_OBJECT (pipeline), | ||||
|                              &private_key1, | ||||
|                              &user_data1, | ||||
|                              destroy1_cb); | ||||
|  | ||||
|   cogl_object_set_user_data (COGL_OBJECT (path), | ||||
|   cogl_object_set_user_data (COGL_OBJECT (pipeline), | ||||
|                              &private_key2, | ||||
|                              &user_data2, | ||||
|                              destroy2_cb); | ||||
|  | ||||
|   cogl_object_set_user_data (COGL_OBJECT (path), | ||||
|   cogl_object_set_user_data (COGL_OBJECT (pipeline), | ||||
|                              &private_key1, | ||||
|                              NULL, | ||||
|                              destroy1_cb); | ||||
|  | ||||
|   cogl_object_set_user_data (COGL_OBJECT (path), | ||||
|   cogl_object_set_user_data (COGL_OBJECT (pipeline), | ||||
|                              &private_key1, | ||||
|                              &user_data1, | ||||
|                              destroy1_cb); | ||||
|  | ||||
|   cogl_object_unref (path); | ||||
|   cogl_object_unref (pipeline); | ||||
|  | ||||
|   g_assert_cmpint (destroy0_count, ==, 1); | ||||
|   g_assert_cmpint (destroy1_count, ==, 2); | ||||
|   | ||||
| @@ -1,68 +0,0 @@ | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl-path/cogl-path.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "test-declarations.h" | ||||
| #include "test-utils.h" | ||||
|  | ||||
| void | ||||
| test_path_clip (void) | ||||
| { | ||||
|   CoglPath *path; | ||||
|   CoglPipeline *pipeline; | ||||
|   int fb_width, fb_height; | ||||
|  | ||||
|   fb_width = cogl_framebuffer_get_width (test_fb); | ||||
|   fb_height = cogl_framebuffer_get_height (test_fb); | ||||
|  | ||||
|   cogl_framebuffer_orthographic (test_fb, | ||||
|                                  0, 0, fb_width, fb_height, -1, 100); | ||||
|  | ||||
|   path = cogl_path_new (); | ||||
|  | ||||
|   cogl_framebuffer_clear4f (test_fb, | ||||
|                             COGL_BUFFER_BIT_COLOR, | ||||
|                             1.0f, 0.0f, 0.0f, 1.0f); | ||||
|  | ||||
|   /* Make an L-shape with the top right corner left untouched */ | ||||
|   cogl_path_move_to (path, 0, fb_height); | ||||
|   cogl_path_line_to (path, fb_width, fb_height); | ||||
|   cogl_path_line_to (path, fb_width, fb_height / 2); | ||||
|   cogl_path_line_to (path, fb_width / 2, fb_height / 2); | ||||
|   cogl_path_line_to (path, fb_width / 2, 0); | ||||
|   cogl_path_line_to (path, 0, 0); | ||||
|   cogl_path_close (path); | ||||
|  | ||||
|   cogl_framebuffer_push_path_clip (test_fb, path); | ||||
|  | ||||
|   /* Try to fill the framebuffer with a blue rectangle. This should be | ||||
|    * clipped to leave the top right quadrant as is */ | ||||
|   pipeline = cogl_pipeline_new (test_ctx); | ||||
|   cogl_pipeline_set_color4ub (pipeline, 0, 0, 255, 255); | ||||
|   cogl_framebuffer_draw_rectangle (test_fb, | ||||
|                                    pipeline, | ||||
|                                    0, 0, fb_width, fb_height); | ||||
|  | ||||
|   cogl_framebuffer_pop_clip (test_fb); | ||||
|  | ||||
|   cogl_object_unref (pipeline); | ||||
|   cogl_object_unref (path); | ||||
|  | ||||
|   /* Check each of the four quadrants */ | ||||
|   test_utils_check_pixel (test_fb, | ||||
|                           fb_width / 4, fb_height / 4, | ||||
|                           0x0000ffff); | ||||
|   test_utils_check_pixel (test_fb, | ||||
|                           fb_width * 3 / 4, fb_height / 4, | ||||
|                           0xff0000ff); | ||||
|   test_utils_check_pixel (test_fb, | ||||
|                           fb_width / 4, fb_height * 3 / 4, | ||||
|                           0x0000ffff); | ||||
|   test_utils_check_pixel (test_fb, | ||||
|                           fb_width * 3 / 4, fb_height * 3 / 4, | ||||
|                           0x0000ffff); | ||||
|  | ||||
|   if (cogl_test_verbose ()) | ||||
|     g_print ("OK\n"); | ||||
| } | ||||
| @@ -1,213 +0,0 @@ | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl-path/cogl-path.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "test-declarations.h" | ||||
| #include "test-utils.h" | ||||
|  | ||||
| #define BLOCK_SIZE 16 | ||||
|  | ||||
| /* Number of pixels at the border of a block quadrant to skip when verifying */ | ||||
| #define TEST_INSET 1 | ||||
|  | ||||
| typedef struct _TestState | ||||
| { | ||||
|   int dummy; | ||||
| } TestState; | ||||
|  | ||||
| static void | ||||
| draw_path_at (CoglPath *path, CoglPipeline *pipeline, int x, int y) | ||||
| { | ||||
|   cogl_framebuffer_push_matrix (test_fb); | ||||
|   cogl_framebuffer_translate (test_fb, x * BLOCK_SIZE, y * BLOCK_SIZE, 0.0f); | ||||
|  | ||||
|   cogl_framebuffer_fill_path (test_fb, pipeline, path); | ||||
|  | ||||
|   cogl_framebuffer_pop_matrix (test_fb); | ||||
| } | ||||
|  | ||||
| static void | ||||
| check_block (int block_x, int block_y, int block_mask) | ||||
| { | ||||
|   uint32_t data[BLOCK_SIZE * BLOCK_SIZE]; | ||||
|   int qx, qy; | ||||
|  | ||||
|   /* Block mask represents which quarters of the block should be | ||||
|      filled. The bits from 0->3 represent the top left, top right, | ||||
|      bottom left and bottom right respectively */ | ||||
|  | ||||
|   cogl_framebuffer_read_pixels (test_fb, | ||||
|                                 block_x * BLOCK_SIZE, | ||||
|                                 block_y * BLOCK_SIZE, | ||||
|                                 BLOCK_SIZE, BLOCK_SIZE, | ||||
|                                 COGL_PIXEL_FORMAT_RGBA_8888_PRE, | ||||
|                                 (uint8_t *)data); | ||||
|  | ||||
|   for (qy = 0; qy < 2; qy++) | ||||
|     for (qx = 0; qx < 2; qx++) | ||||
|       { | ||||
|         int bit = qx | (qy << 1); | ||||
| 	const char *intended_pixel = ((block_mask & (1 << bit)) ? "#ffffff" : "#000000"); | ||||
|         int x, y; | ||||
|  | ||||
|         for (x = 0; x < BLOCK_SIZE / 2 - TEST_INSET * 2; x++) | ||||
|           for (y = 0; y < BLOCK_SIZE / 2 - TEST_INSET * 2; y++) | ||||
|             { | ||||
|               const uint32_t *p = data + (qx * BLOCK_SIZE / 2 + | ||||
|                                         qy * BLOCK_SIZE * BLOCK_SIZE / 2 + | ||||
|                                         (x + TEST_INSET) + | ||||
|                                         (y + TEST_INSET) * BLOCK_SIZE); | ||||
| 	      char *screen_pixel = g_strdup_printf ("#%06x", GUINT32_FROM_BE (*p) >> 8); | ||||
| 	      g_assert_cmpstr (screen_pixel, ==, intended_pixel); | ||||
| 	      g_free (screen_pixel); | ||||
|             } | ||||
|       } | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint (TestState *state) | ||||
| { | ||||
|   CoglPath *path_a, *path_b, *path_c; | ||||
|   CoglPipeline *white = cogl_pipeline_new (test_ctx); | ||||
|  | ||||
|   cogl_pipeline_set_color4f (white, 1, 1, 1, 1); | ||||
|  | ||||
|   /* Create a path filling just a quarter of a block. It will use two | ||||
|      rectangles so that we have a sub path in the path */ | ||||
|   path_a = cogl_path_new (); | ||||
|   cogl_path_rectangle (path_a, | ||||
|                        BLOCK_SIZE * 3 / 4, BLOCK_SIZE / 2, | ||||
|                        BLOCK_SIZE, BLOCK_SIZE); | ||||
|   cogl_path_rectangle (path_a, | ||||
|                        BLOCK_SIZE / 2, BLOCK_SIZE / 2, | ||||
|                        BLOCK_SIZE * 3 / 4, BLOCK_SIZE); | ||||
|   draw_path_at (path_a, white, 0, 0); | ||||
|  | ||||
|   /* Create another path filling the whole block */ | ||||
|   path_b = cogl_path_new (); | ||||
|   cogl_path_rectangle (path_b, 0, 0, BLOCK_SIZE, BLOCK_SIZE); | ||||
|   draw_path_at (path_b, white, 1, 0); | ||||
|  | ||||
|   /* Draw the first path again */ | ||||
|   draw_path_at (path_a, white, 2, 0); | ||||
|  | ||||
|   /* Draw a copy of path a */ | ||||
|   path_c = cogl_path_copy (path_a); | ||||
|   draw_path_at (path_c, white, 3, 0); | ||||
|  | ||||
|   /* Add another rectangle to path a. We'll use line_to's instead of | ||||
|      cogl_rectangle so that we don't create another sub-path because | ||||
|      that is more likely to break the copy */ | ||||
|   cogl_path_line_to (path_a, 0, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_a, 0, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); | ||||
|   draw_path_at (path_a, white, 4, 0); | ||||
|  | ||||
|   /* Draw the copy again. It should not have changed */ | ||||
|   draw_path_at (path_c, white, 5, 0); | ||||
|  | ||||
|   /* Add another rectangle to path c. It will be added in two halves, | ||||
|      one as an extension of the previous path and the other as a new | ||||
|      sub path */ | ||||
|   cogl_path_line_to (path_c, BLOCK_SIZE / 2, 0); | ||||
|   cogl_path_line_to (path_c, BLOCK_SIZE * 3 / 4, 0); | ||||
|   cogl_path_line_to (path_c, BLOCK_SIZE * 3 / 4, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_c, BLOCK_SIZE / 2, BLOCK_SIZE / 2); | ||||
|   cogl_path_rectangle (path_c, | ||||
|                        BLOCK_SIZE * 3 / 4, 0, BLOCK_SIZE, BLOCK_SIZE / 2); | ||||
|   draw_path_at (path_c, white, 6, 0); | ||||
|  | ||||
|   /* Draw the original path again. It should not have changed */ | ||||
|   draw_path_at (path_a, white, 7, 0); | ||||
|  | ||||
|   cogl_object_unref (path_a); | ||||
|   cogl_object_unref (path_b); | ||||
|   cogl_object_unref (path_c); | ||||
|  | ||||
|   /* Draw a self-intersecting path. The part that intersects should be | ||||
|      inverted */ | ||||
|   path_a = cogl_path_new (); | ||||
|   cogl_path_rectangle (path_a, 0, 0, BLOCK_SIZE, BLOCK_SIZE); | ||||
|   cogl_path_line_to (path_a, 0, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0); | ||||
|   cogl_path_close (path_a); | ||||
|   draw_path_at (path_a, white, 8, 0); | ||||
|   cogl_object_unref (path_a); | ||||
|  | ||||
|   /* Draw two sub paths. Where the paths intersect it should be | ||||
|      inverted */ | ||||
|   path_a = cogl_path_new (); | ||||
|   cogl_path_rectangle (path_a, 0, 0, BLOCK_SIZE, BLOCK_SIZE); | ||||
|   cogl_path_rectangle (path_a, | ||||
|                        BLOCK_SIZE / 2, BLOCK_SIZE / 2, BLOCK_SIZE, BLOCK_SIZE); | ||||
|   draw_path_at (path_a, white, 9, 0); | ||||
|   cogl_object_unref (path_a); | ||||
|  | ||||
|   /* Draw a clockwise outer path */ | ||||
|   path_a = cogl_path_new (); | ||||
|   cogl_path_move_to (path_a, 0, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE, BLOCK_SIZE); | ||||
|   cogl_path_line_to (path_a, 0, BLOCK_SIZE); | ||||
|   cogl_path_close (path_a); | ||||
|   /* Add a clockwise sub path in the upper left quadrant */ | ||||
|   cogl_path_move_to (path_a, 0, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_a, 0, BLOCK_SIZE / 2); | ||||
|   cogl_path_close (path_a); | ||||
|   /* Add a counter-clockwise sub path in the upper right quadrant */ | ||||
|   cogl_path_move_to (path_a, BLOCK_SIZE / 2, 0); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE, BLOCK_SIZE / 2); | ||||
|   cogl_path_line_to (path_a, BLOCK_SIZE, 0); | ||||
|   cogl_path_close (path_a); | ||||
|   /* Retain the path for the next test */ | ||||
|   draw_path_at (path_a, white, 10, 0); | ||||
|  | ||||
|   /* Draw the same path again with the other fill rule */ | ||||
|   cogl_path_set_fill_rule (path_a, COGL_PATH_FILL_RULE_NON_ZERO); | ||||
|   draw_path_at (path_a, white, 11, 0); | ||||
|  | ||||
|   cogl_object_unref (path_a); | ||||
| } | ||||
|  | ||||
| static void | ||||
| validate_result (void) | ||||
| { | ||||
|   check_block (0, 0, 0x8 /* bottom right */); | ||||
|   check_block (1, 0, 0xf /* all of them */); | ||||
|   check_block (2, 0, 0x8 /* bottom right */); | ||||
|   check_block (3, 0, 0x8 /* bottom right */); | ||||
|   check_block (4, 0, 0x9 /* top left and bottom right */); | ||||
|   check_block (5, 0, 0x8 /* bottom right */); | ||||
|   check_block (6, 0, 0xa /* bottom right and top right */); | ||||
|   check_block (7, 0, 0x9 /* top_left and bottom right */); | ||||
|   check_block (8, 0, 0xe /* all but top left */); | ||||
|   check_block (9, 0, 0x7 /* all but bottom right */); | ||||
|   check_block (10, 0, 0xc /* bottom two */); | ||||
|   check_block (11, 0, 0xd /* all but top right */); | ||||
| } | ||||
|  | ||||
| void | ||||
| test_path (void) | ||||
| { | ||||
|   TestState state; | ||||
|  | ||||
|   cogl_framebuffer_orthographic (test_fb, | ||||
|                                  0, 0, | ||||
|                                  cogl_framebuffer_get_width (test_fb), | ||||
|                                  cogl_framebuffer_get_height (test_fb), | ||||
|                                  -1, | ||||
|                                  100); | ||||
|  | ||||
|   paint (&state); | ||||
|   validate_result (); | ||||
|  | ||||
|   if (cogl_test_verbose ()) | ||||
|     g_print ("OK\n"); | ||||
| } | ||||
|  | ||||
| @@ -17,7 +17,6 @@ libmutter_cogl_test_unit = executable('test-unit', | ||||
|   include_directories: cogl_test_unit_includes, | ||||
|   dependencies: [ | ||||
|     libmutter_cogl_dep, | ||||
|     libmutter_cogl_path_dep, | ||||
|     libmutter_cogl_test_fixtures_dep, | ||||
|   ], | ||||
|   install: false, | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| project('mutter', 'c', | ||||
|   version: '3.36.1', | ||||
|   version: '3.37.0', | ||||
|   meson_version: '>= 0.50.0', | ||||
|   license: 'GPLv2+' | ||||
| ) | ||||
|   | ||||
							
								
								
									
										167
									
								
								po/sk.po
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								po/sk.po
									
									
									
									
									
								
							| @@ -13,8 +13,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter\n" | ||||
| "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" | ||||
| "POT-Creation-Date: 2018-02-06 04:14+0000\n" | ||||
| "PO-Revision-Date: 2018-03-17 21:52+0100\n" | ||||
| "POT-Creation-Date: 2020-03-30 20:11+0000\n" | ||||
| "PO-Revision-Date: 2020-04-05 22:21+0200\n" | ||||
| "Last-Translator: Dušan Kazik <prescott66@gmail.com>\n" | ||||
| "Language-Team: Slovak <gnome-sk-list@gnome.org>\n" | ||||
| "Language: sk\n" | ||||
| @@ -22,7 +22,7 @@ msgstr "" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" | ||||
| "X-Generator: Poedit 2.0.6\n" | ||||
| "X-Generator: Poedit 2.3\n" | ||||
|  | ||||
| #: data/50-mutter-navigation.xml:6 | ||||
| msgid "Navigation" | ||||
| @@ -468,29 +468,47 @@ msgid "" | ||||
| "proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " | ||||
| "mutter default to layout logical monitors in a logical pixel coordinate " | ||||
| "space, while scaling monitor framebuffers instead of window content, to " | ||||
| "manage HiDPI monitors. Does not require a restart. • “remote-desktop” — " | ||||
| "enables remote desktop support. To support remote desktop with screen " | ||||
| "sharing, “screen-cast” must also be enabled. • “screen-cast” — enables " | ||||
| "screen cast support." | ||||
| "manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes " | ||||
| "mutter request a low priority real-time scheduling. The executable or user " | ||||
| "must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — " | ||||
| "initializes Xwayland lazily if there are X11 clients. Requires restart." | ||||
| msgstr "" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:134 | ||||
| msgid "Modifier to use to locate the pointer" | ||||
| msgstr "Modifikátor použitý na lokalizovanie ukazovateľa" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:135 | ||||
| msgid "This key will initiate the “locate pointer” action." | ||||
| msgstr "" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:142 | ||||
| msgid "Timeout for check-alive ping" | ||||
| msgstr "" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:143 | ||||
| msgid "" | ||||
| "Number of milliseconds a client has to respond to a ping request in order to " | ||||
| "not be detected as frozen. Using 0 will disable the alive check completely." | ||||
| msgstr "" | ||||
|  | ||||
| # summary | ||||
| #: data/org.gnome.mutter.gschema.xml.in:145 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:165 | ||||
| msgid "Select window from tab popup" | ||||
| msgstr "Vybrať okno z rozbaľovacej ponuky tabulátora" | ||||
|  | ||||
| # summary | ||||
| #: data/org.gnome.mutter.gschema.xml.in:150 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:170 | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Zrušit rozbaľovaciu ponuku tabulátora" | ||||
|  | ||||
| # PK: predpokladam ze to prepisane medzi tlacidlami | ||||
| # description | ||||
| #: data/org.gnome.mutter.gschema.xml.in:155 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:175 | ||||
| msgid "Switch monitor configurations" | ||||
| msgstr "Prepnúť nastavenia monitorov" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:160 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:180 | ||||
| msgid "Rotates the built-in monitor configuration" | ||||
| msgstr "Otočí nastavenie vstavaného monitora" | ||||
|  | ||||
| @@ -554,23 +572,27 @@ msgid "Re-enable shortcuts" | ||||
| msgstr "Znovu povoliť klávesové skratky" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:64 | ||||
| msgid "Allow grabs with Xwayland" | ||||
| msgid "Allow X11 grabs to lock keyboard focus with Xwayland" | ||||
| msgstr "" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:65 | ||||
| msgid "" | ||||
| "Allow keyboard grabs issued by X11 applications running in Xwayland to be " | ||||
| "taken into account. For a X11 grab to be taken into account under Wayland, " | ||||
| "the client must also either send a specific X11 ClientMessage to the root " | ||||
| "window or be among the applications white-listed in key “xwayland-grab-" | ||||
| "access-rules”." | ||||
| "Allow all keyboard events to be routed to X11 “override redirect” windows " | ||||
| "with a grab when running in Xwayland. This option is to support X11 clients " | ||||
| "which map an “override redirect” window (which do not receive keyboard " | ||||
| "focus) and issue a keyboard grab to force all keyboard events to that " | ||||
| "window. This option is seldom used and has no effect on regular X11 windows " | ||||
| "which can receive keyboard focus under normal circumstances. For a X11 grab " | ||||
| "to be taken into account under Wayland, the client must also either send a " | ||||
| "specific X11 ClientMessage to the root window or be among the applications " | ||||
| "white-listed in key “xwayland-grab-access-rules”." | ||||
| msgstr "" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:77 | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:84 | ||||
| msgid "Xwayland applications allowed to issue keyboard grabs" | ||||
| msgstr "" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:78 | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:85 | ||||
| msgid "" | ||||
| "List the resource names or resource class of X11 windows either allowed or " | ||||
| "not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " | ||||
| @@ -587,7 +609,7 @@ msgstr "" | ||||
| #. TRANSLATORS: This string refers to a button that switches between | ||||
| #. * different modes. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2260 | ||||
| #: src/backends/meta-input-settings.c:2631 | ||||
| #, c-format | ||||
| msgid "Mode Switch (Group %d)" | ||||
| msgstr "Prepínač režimu (skupina č. %d)" | ||||
| @@ -597,53 +619,61 @@ msgstr "Prepínač režimu (skupina č. %d)" | ||||
| #. TRANSLATORS: This string refers to an action, cycles drawing tablets' | ||||
| #. * mapping through the available outputs. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2283 | ||||
| #: src/backends/meta-input-settings.c:2654 | ||||
| msgid "Switch monitor" | ||||
| msgstr "Prepnúť monitor" | ||||
|  | ||||
| #: src/backends/meta-input-settings.c:2285 | ||||
| #: src/backends/meta-input-settings.c:2656 | ||||
| msgid "Show on-screen help" | ||||
| msgstr "Zobraziť pomocníka na obrazovke" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:900 | ||||
| #: src/backends/meta-monitor.c:226 | ||||
| msgid "Built-in display" | ||||
| msgstr "Vstavaný displej" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:923 | ||||
| #: src/backends/meta-monitor.c:255 | ||||
| msgid "Unknown" | ||||
| msgstr "Neznámy" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:925 | ||||
| #: src/backends/meta-monitor.c:257 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Neznámy displej" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: src/backends/meta-monitor-manager.c:933 | ||||
| #: src/backends/meta-monitor.c:265 | ||||
| #, c-format | ||||
| #| msgid "%s %s" | ||||
| msgctxt "" | ||||
| "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: src/backends/meta-monitor.c:273 | ||||
| #, c-format | ||||
| #| msgid "%s %s" | ||||
| msgctxt "" | ||||
| "This is a monitor vendor name followed by product/model name where size in " | ||||
| "inches could not be calculated, e.g. Dell U2414H" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. Translators: this string will appear in Sysprof | ||||
| #: src/backends/meta-profiler.c:79 | ||||
| msgid "Compositor" | ||||
| msgstr "Kompozítor" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: src/compositor/compositor.c:481 | ||||
| #: src/compositor/compositor.c:533 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display “%s”." | ||||
| msgstr "" | ||||
| "Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia." | ||||
|  | ||||
| #: src/core/bell.c:194 | ||||
| #: src/core/bell.c:192 | ||||
| msgid "Bell event" | ||||
| msgstr "Udalosť zvončeka" | ||||
|  | ||||
| # X window system preloz, napr. system na spravu okien X | ||||
| #: src/core/display.c:608 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display “%s”\n" | ||||
| msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" | ||||
|  | ||||
| # cmd desc | ||||
| #: src/core/main.c:190 | ||||
| msgid "Disable connection to session manager" | ||||
| @@ -683,41 +713,45 @@ msgstr "Spustí ako kompozitor protokolu wayland" | ||||
| msgid "Run as a nested compositor" | ||||
| msgstr "Spustí ako kompozitor s vnoreným režimom" | ||||
|  | ||||
| #: src/core/main.c:240 | ||||
| #: src/core/main.c:238 | ||||
| msgid "Run wayland compositor without starting Xwayland" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/core/main.c:246 | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Spustí ako plnohodnotný zobrazovací server, namiesto vnoreného režimu" | ||||
|  | ||||
| #: src/core/main.c:246 | ||||
| #: src/core/main.c:252 | ||||
| msgid "Run with X11 backend" | ||||
| msgstr "Spustí s obslužným programom X11" | ||||
|  | ||||
| # %s is a window title | ||||
| #. Translators: %s is a window title | ||||
| #: src/core/meta-close-dialog-default.c:147 | ||||
| #: src/core/meta-close-dialog-default.c:151 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "„%s“ neodpovedá." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:149 | ||||
| #: src/core/meta-close-dialog-default.c:153 | ||||
| msgid "Application is not responding." | ||||
| msgstr "Aplikácia neodpovedá." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:154 | ||||
| #: src/core/meta-close-dialog-default.c:158 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| msgstr "" | ||||
| "Môžete chvíľu počkať na pokračovanie aplikácie, alebo ju môžete ukončiť." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:161 | ||||
| #: src/core/meta-close-dialog-default.c:165 | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Vynútiť ukončenie" | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:161 | ||||
| #: src/core/meta-close-dialog-default.c:165 | ||||
| msgid "_Wait" | ||||
| msgstr "_Počkať" | ||||
|  | ||||
| #: src/core/mutter.c:39 | ||||
| #: src/core/mutter.c:38 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "mutter %s\n" | ||||
| @@ -733,21 +767,30 @@ msgstr "" | ||||
| "Záruka sa NEPOSKYTUJE; ani na PREDAJNOSŤ alebo VHODNOSŤ PRE URČITÝ ÚČEL.\n" | ||||
|  | ||||
| # cmd desc | ||||
| #: src/core/mutter.c:53 | ||||
| #: src/core/mutter.c:52 | ||||
| msgid "Print version" | ||||
| msgstr "Zobrazí verziu" | ||||
|  | ||||
| # cmd desc | ||||
| #: src/core/mutter.c:59 | ||||
| #: src/core/mutter.c:58 | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Použije zásuvný modul Mutter" | ||||
|  | ||||
| #: src/core/prefs.c:1997 | ||||
| #: src/core/prefs.c:1911 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Pracovný priestor č. %d" | ||||
|  | ||||
| #: src/core/screen.c:583 | ||||
| #: src/core/util.c:122 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" | ||||
|  | ||||
| #: src/wayland/meta-wayland-tablet-pad.c:568 | ||||
| #, c-format | ||||
| msgid "Mode Switch: Mode %d" | ||||
| msgstr "Prepínač režimu: Režim č. %d" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:676 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display “%s” already has a window manager; try using the --replace option to " | ||||
| @@ -756,21 +799,27 @@ msgstr "" | ||||
| "Displej „%s“ už má správcu okien. Skúste použiť prepínač --replace, aby sa " | ||||
| "aktuálny správca nahradil." | ||||
|  | ||||
| #: src/core/screen.c:668 | ||||
| #: src/x11/meta-x11-display.c:1089 | ||||
| msgid "Failed to initialize GDK\n" | ||||
| msgstr "Zlyhala inicializácia GDK\n" | ||||
|  | ||||
| # X window system preloz, napr. system na spravu okien X | ||||
| #: src/x11/meta-x11-display.c:1113 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display “%s”\n" | ||||
| msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1196 | ||||
| #, c-format | ||||
| msgid "Screen %d on display “%s” is invalid\n" | ||||
| msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n" | ||||
|  | ||||
| #: src/core/util.c:120 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" | ||||
|  | ||||
| #: src/wayland/meta-wayland-tablet-pad.c:563 | ||||
| #: src/x11/meta-x11-selection-input-stream.c:460 | ||||
| #, c-format | ||||
| msgid "Mode Switch: Mode %d" | ||||
| msgstr "Prepínač režimu: Režim č. %d" | ||||
| msgid "Format %s not supported" | ||||
| msgstr "Formát %s nie je podporovaný" | ||||
|  | ||||
| #: src/x11/session.c:1818 | ||||
| #: src/x11/session.c:1821 | ||||
| msgid "" | ||||
| "These windows do not support “save current setup” and will have to be " | ||||
| "restarted manually next time you log in." | ||||
| @@ -779,7 +828,7 @@ msgstr "" | ||||
| "prihlásení ich budete musieť znovu spustiť ručne." | ||||
|  | ||||
| # window title; wm_client_machine | ||||
| #: src/x11/window-props.c:559 | ||||
| #: src/x11/window-props.c:569 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (na %s)" | ||||
|   | ||||
| @@ -818,7 +818,7 @@ update_trackball_scroll_button (MetaInputSettings  *input_settings, | ||||
|  | ||||
|       for (l = devices; l; l = l->next) | ||||
|         { | ||||
|           device = devices->data; | ||||
|           device = l->data; | ||||
|  | ||||
|           if (input_settings_class->is_trackball_device (input_settings, device)) | ||||
|             input_settings_class->set_scroll_button (input_settings, device, button); | ||||
|   | ||||
| @@ -172,6 +172,7 @@ assign_monitor_crtc (MetaMonitor         *monitor, | ||||
|   MetaCrtc *crtc; | ||||
|   MetaMonitorTransform transform; | ||||
|   MetaMonitorTransform crtc_transform; | ||||
|   MetaMonitorTransform crtc_hw_transform; | ||||
|   int crtc_x, crtc_y; | ||||
|   float x_offset, y_offset; | ||||
|   float scale = 0.0; | ||||
| @@ -200,10 +201,12 @@ assign_monitor_crtc (MetaMonitor         *monitor, | ||||
|  | ||||
|   transform = data->logical_monitor_config->transform; | ||||
|   crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform); | ||||
|   if (!meta_monitor_manager_is_transform_handled (data->monitor_manager, | ||||
|                                                   crtc, | ||||
|                                                   crtc_transform)) | ||||
|     crtc_transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|   if (meta_monitor_manager_is_transform_handled (data->monitor_manager, | ||||
|                                                  crtc, | ||||
|                                                  crtc_transform)) | ||||
|     crtc_hw_transform = crtc_transform; | ||||
|   else | ||||
|     crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|  | ||||
|   meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform, | ||||
|                                    &crtc_x, &crtc_y); | ||||
| @@ -244,7 +247,7 @@ assign_monitor_crtc (MetaMonitor         *monitor, | ||||
|     .crtc = crtc, | ||||
|     .mode = crtc_mode, | ||||
|     .layout = crtc_layout, | ||||
|     .transform = crtc_transform, | ||||
|     .transform = crtc_hw_transform, | ||||
|     .outputs = g_ptr_array_new () | ||||
|   }; | ||||
|   g_ptr_array_add (crtc_info->outputs, output); | ||||
| @@ -443,23 +446,35 @@ MetaMonitorsConfigKey * | ||||
| meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager) | ||||
| { | ||||
|   MetaMonitorsConfigKey *config_key; | ||||
|   MetaMonitorSpec *laptop_monitor_spec; | ||||
|   GList *l; | ||||
|   GList *monitor_specs; | ||||
|  | ||||
|   laptop_monitor_spec = NULL; | ||||
|   monitor_specs = NULL; | ||||
|   for (l = monitor_manager->monitors; l; l = l->next) | ||||
|     { | ||||
|       MetaMonitor *monitor = l->data; | ||||
|       MetaMonitorSpec *monitor_spec; | ||||
|  | ||||
|       if (meta_monitor_is_laptop_panel (monitor) && | ||||
|           is_lid_closed (monitor_manager)) | ||||
|         continue; | ||||
|       if (meta_monitor_is_laptop_panel (monitor)) | ||||
|         { | ||||
|           laptop_monitor_spec = meta_monitor_get_spec (monitor); | ||||
|  | ||||
|           if (is_lid_closed (monitor_manager)) | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|       monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor)); | ||||
|       monitor_specs = g_list_prepend (monitor_specs, monitor_spec); | ||||
|     } | ||||
|  | ||||
|   if (!monitor_specs && laptop_monitor_spec) | ||||
|     { | ||||
|       monitor_specs = | ||||
|         g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec)); | ||||
|     } | ||||
|  | ||||
|   if (!monitor_specs) | ||||
|     return NULL; | ||||
|  | ||||
|   | ||||
| @@ -817,19 +817,19 @@ calculate_tile_coordinate (MetaMonitor         *monitor, | ||||
|         case META_MONITOR_TRANSFORM_270: | ||||
|         case META_MONITOR_TRANSFORM_FLIPPED_270: | ||||
|           if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile && | ||||
|               other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile) | ||||
|               other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile) | ||||
|             y += other_output->tile_info.tile_w; | ||||
|           if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile && | ||||
|               other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile) | ||||
|               other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile) | ||||
|             x += other_output->tile_info.tile_h; | ||||
|           break; | ||||
|         case META_MONITOR_TRANSFORM_90: | ||||
|         case META_MONITOR_TRANSFORM_FLIPPED_90: | ||||
|           if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile && | ||||
|               other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile) | ||||
|               other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile) | ||||
|             y += other_output->tile_info.tile_w; | ||||
|           if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile && | ||||
|               other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile) | ||||
|               other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile) | ||||
|             x += other_output->tile_info.tile_h; | ||||
|           break; | ||||
|         } | ||||
|   | ||||
| @@ -291,9 +291,7 @@ meta_stage_new (MetaBackend *backend) | ||||
|   MetaStage *stage; | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|  | ||||
|   stage = g_object_new (META_TYPE_STAGE, | ||||
|                         "cursor-visible", FALSE, | ||||
|                         NULL); | ||||
|   stage = g_object_new (META_TYPE_STAGE, NULL); | ||||
|  | ||||
|   monitor_manager = meta_backend_get_monitor_manager (backend); | ||||
|   g_signal_connect (monitor_manager, "power-save-mode-changed", | ||||
|   | ||||
| @@ -407,13 +407,14 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor, | ||||
|   else | ||||
|     scale = 1.0; | ||||
|  | ||||
|   meta_monitor_calculate_crtc_pos (monitor, monitor_mode, | ||||
|                                    monitor_crtc_mode->output, | ||||
|                                    META_MONITOR_TRANSFORM_NORMAL, | ||||
|                                    &crtc_x, &crtc_y); | ||||
|  | ||||
|   transform = meta_logical_monitor_get_transform (data->in_logical_monitor); | ||||
|   transform = meta_monitor_logical_to_crtc_transform (monitor, transform); | ||||
|  | ||||
|   meta_monitor_calculate_crtc_pos (monitor, monitor_mode, | ||||
|                                    monitor_crtc_mode->output, | ||||
|                                    transform, | ||||
|                                    &crtc_x, &crtc_y); | ||||
|  | ||||
|   if (meta_monitor_transform_is_rotated (transform)) | ||||
|     { | ||||
|       crtc_width = monitor_crtc_mode->crtc_mode->height; | ||||
|   | ||||
| @@ -44,7 +44,12 @@ struct _MetaDrmBufferGbm | ||||
|   uint32_t fb_id; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER) | ||||
| static void | ||||
| cogl_scanout_iface_init (CoglScanoutInterface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER, | ||||
|                          G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT, | ||||
|                                                 cogl_scanout_iface_init)) | ||||
|  | ||||
| struct gbm_bo * | ||||
| meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm) | ||||
| @@ -53,22 +58,12 @@ meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm) | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| acquire_swapped_buffer (MetaDrmBufferGbm  *buffer_gbm, | ||||
|                         gboolean           use_modifiers, | ||||
|                         GError           **error) | ||||
| init_fb_id (MetaDrmBufferGbm  *buffer_gbm, | ||||
|             struct gbm_bo     *bo, | ||||
|             gboolean           use_modifiers, | ||||
|             GError           **error) | ||||
| { | ||||
|   MetaGpuKmsFBArgs fb_args = { 0, }; | ||||
|   struct gbm_bo *bo; | ||||
|  | ||||
|   bo = gbm_surface_lock_front_buffer (buffer_gbm->surface); | ||||
|   if (!bo) | ||||
|     { | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_FAILED, | ||||
|                    "gbm_surface_lock_front_buffer failed"); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1) | ||||
|     { | ||||
| @@ -99,21 +94,34 @@ acquire_swapped_buffer (MetaDrmBufferGbm  *buffer_gbm, | ||||
|                             use_modifiers, | ||||
|                             &fb_args, | ||||
|                             &buffer_gbm->fb_id, error)) | ||||
|     { | ||||
|       gbm_surface_release_buffer (buffer_gbm->surface, bo); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   buffer_gbm->bo = bo; | ||||
|     return FALSE; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| lock_front_buffer (MetaDrmBufferGbm  *buffer_gbm, | ||||
|                    gboolean           use_modifiers, | ||||
|                    GError           **error) | ||||
| { | ||||
|   buffer_gbm->bo = gbm_surface_lock_front_buffer (buffer_gbm->surface); | ||||
|   if (!buffer_gbm->bo) | ||||
|     { | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_FAILED, | ||||
|                    "gbm_surface_lock_front_buffer failed"); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   return init_fb_id (buffer_gbm, buffer_gbm->bo, use_modifiers, error); | ||||
| } | ||||
|  | ||||
| MetaDrmBufferGbm * | ||||
| meta_drm_buffer_gbm_new (MetaGpuKms          *gpu_kms, | ||||
|                          struct gbm_surface  *gbm_surface, | ||||
|                          gboolean             use_modifiers, | ||||
|                          GError             **error) | ||||
| meta_drm_buffer_gbm_new_lock_front (MetaGpuKms          *gpu_kms, | ||||
|                                     struct gbm_surface  *gbm_surface, | ||||
|                                     gboolean             use_modifiers, | ||||
|                                     GError             **error) | ||||
| { | ||||
|   MetaDrmBufferGbm *buffer_gbm; | ||||
|  | ||||
| @@ -121,7 +129,7 @@ meta_drm_buffer_gbm_new (MetaGpuKms          *gpu_kms, | ||||
|   buffer_gbm->gpu_kms = gpu_kms; | ||||
|   buffer_gbm->surface = gbm_surface; | ||||
|  | ||||
|   if (!acquire_swapped_buffer (buffer_gbm, use_modifiers, error)) | ||||
|   if (!lock_front_buffer (buffer_gbm, use_modifiers, error)) | ||||
|     { | ||||
|       g_object_unref (buffer_gbm); | ||||
|       return NULL; | ||||
| @@ -130,12 +138,39 @@ meta_drm_buffer_gbm_new (MetaGpuKms          *gpu_kms, | ||||
|   return buffer_gbm; | ||||
| } | ||||
|  | ||||
| MetaDrmBufferGbm * | ||||
| meta_drm_buffer_gbm_new_take (MetaGpuKms     *gpu_kms, | ||||
|                               struct gbm_bo  *bo, | ||||
|                               gboolean        use_modifiers, | ||||
|                               GError        **error) | ||||
| { | ||||
|   MetaDrmBufferGbm *buffer_gbm; | ||||
|  | ||||
|   buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, NULL); | ||||
|   buffer_gbm->gpu_kms = gpu_kms; | ||||
|  | ||||
|   if (!init_fb_id (buffer_gbm, bo, use_modifiers, error)) | ||||
|     { | ||||
|       g_object_unref (buffer_gbm); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   buffer_gbm->bo = bo; | ||||
|  | ||||
|   return buffer_gbm; | ||||
| } | ||||
|  | ||||
| static uint32_t | ||||
| meta_drm_buffer_gbm_get_fb_id (MetaDrmBuffer *buffer) | ||||
| { | ||||
|   return META_DRM_BUFFER_GBM (buffer)->fb_id; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cogl_scanout_iface_init (CoglScanoutInterface *iface) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_drm_buffer_gbm_finalize (GObject *object) | ||||
| { | ||||
| @@ -150,7 +185,12 @@ meta_drm_buffer_gbm_finalize (GObject *object) | ||||
|     } | ||||
|  | ||||
|   if (buffer_gbm->bo) | ||||
|     gbm_surface_release_buffer (buffer_gbm->surface, buffer_gbm->bo); | ||||
|     { | ||||
|       if (buffer_gbm->surface) | ||||
|         gbm_surface_release_buffer (buffer_gbm->surface, buffer_gbm->bo); | ||||
|       else | ||||
|         gbm_bo_destroy (buffer_gbm->bo); | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_drm_buffer_gbm_parent_class)->finalize (object); | ||||
| } | ||||
|   | ||||
| @@ -33,10 +33,16 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferGbm, | ||||
|                       META, DRM_BUFFER_GBM, | ||||
|                       MetaDrmBuffer) | ||||
|  | ||||
| MetaDrmBufferGbm * meta_drm_buffer_gbm_new (MetaGpuKms          *gpu_kms, | ||||
|                                             struct gbm_surface  *gbm_surface, | ||||
|                                             gboolean             use_modifiers, | ||||
|                                             GError             **error); | ||||
| MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaGpuKms          *gpu_kms, | ||||
|                                                        struct gbm_surface  *gbm_surface, | ||||
|                                                        gboolean             use_modifiers, | ||||
|                                                        GError             **error); | ||||
|  | ||||
|  | ||||
| MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaGpuKms     *gpu_kms, | ||||
|                                                  struct gbm_bo  *gbm_bo, | ||||
|                                                  gboolean        use_modifiers, | ||||
|                                                  GError        **error); | ||||
|  | ||||
| struct gbm_bo * meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm); | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user