Пример #1
0
		/// <summary>
		/// Helper function for the above methods. The IAddinLocalizer provides a generic way to
		/// get translated strings both for Pinta's effects and for effect add-ins.
		/// </summary>
		private static bool LaunchSimpleEffectDialog (BaseEffect effect, IAddinLocalizer localizer)
		{
			if (effect == null)
				throw new ArgumentNullException ("effect");
			
			if (effect.EffectData == null)
				throw new ArgumentException ("effect.EffectData is null.");
			
			var dialog = new SimpleEffectDialog (effect.Name,
			                                     PintaCore.Resources.GetIcon (effect.Icon),
			                                     effect.EffectData, localizer);
			
			// Hookup event handling for live preview.
			dialog.EffectDataChanged += (o, e) => {
				if (effect.EffectData != null)
					effect.EffectData.FirePropertyChanged (e.PropertyName);
			};
			
			int response = dialog.Run ();

			bool ret = false;
			if (response == (int)Gtk.ResponseType.Ok && effect.EffectData != null)
				ret = !effect.EffectData.IsDefault;

			dialog.Destroy ();

			return ret;
		}
Пример #2
0
        /// <summary>
        /// Register a new adjustment with Pinta, causing it to be added to the Adjustments menu.
        /// </summary>
        /// <param name="adjustment">The adjustment to register</param>
        /// <returns>The action created for this adjustment</returns>
        public Gtk.Action RegisterAdjustment(BaseEffect adjustment)
        {
            // Add icon to IconFactory
            Gtk.IconFactory fact = new Gtk.IconFactory ();
            fact.Add (adjustment.Icon, new Gtk.IconSet (PintaCore.Resources.GetIcon (adjustment.Icon)));
            fact.AddDefault ();

            // Create a gtk action for each adjustment
            Gtk.Action act = new Gtk.Action (adjustment.GetType ().Name, adjustment.Name + (adjustment.IsConfigurable ? Catalog.GetString ("...") : ""), string.Empty, adjustment.Icon);
            act.Activated += delegate (object sender, EventArgs e) { PintaCore.LivePreview.Start (adjustment); };

            PintaCore.Actions.Adjustments.Actions.Add (act);

            // Create a menu item for each adjustment
            MenuItem menu_item;

            // If no key is specified, don't use an accelerated menu item
            if (adjustment.AdjustmentMenuKey == (Gdk.Key)0)
                menu_item = (MenuItem)act.CreateMenuItem ();
            else
                menu_item = act.CreateAcceleratedMenuItem (adjustment.AdjustmentMenuKey, adjustment.AdjustmentMenuKeyModifiers);

            ((Menu)((ImageMenuItem)PintaCore.Chrome.MainMenu.Children[5]).Submenu).AppendMenuItemSorted (menu_item);

            adjustments.Add (adjustment, act);
            adjustment_menuitems.Add (adjustment, menu_item);

            return act;
        }
Пример #3
0
        /// <summary>
        /// Register a new effect with Pinta, causing it to be added to the Effects menu.
        /// </summary>
        /// <param name="effect">The effect to register</param>
        /// <returns>The action created for this effect</returns>
        public Gtk.Action RegisterEffect(BaseEffect effect)
        {
            // Add icon to IconFactory
            Gtk.IconFactory fact = new Gtk.IconFactory();
            fact.Add(effect.Icon, new Gtk.IconSet(PintaCore.Resources.GetIcon(effect.Icon)));
            fact.AddDefault();

            // Create a gtk action and menu item for each effect
            Gtk.Action act = new Gtk.Action(effect.GetType().Name, effect.Name + (effect.IsConfigurable ? Catalog.GetString("...") : ""), string.Empty, effect.Icon);
            act.Activated += delegate(object sender, EventArgs e) { PintaCore.LivePreview.Start(effect); };

            PintaCore.Actions.Effects.AddEffect(effect.EffectMenuCategory, act);

            effects.Add(effect, act);

            return(act);
        }
Пример #4
0
        internal void Start(BaseEffect effect,
                            Cairo.ImageSurface source,
                            Cairo.ImageSurface dest,
                            Gdk.Rectangle renderBounds)
        {
            Debug.WriteLine("AsyncEffectRenderer.Start ()");

            if (effect == null)
            {
                throw new ArgumentNullException("effect");
            }

            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (dest == null)
            {
                throw new ArgumentNullException("dest");
            }

            if (renderBounds.IsEmpty)
            {
                throw new ArgumentException("renderBounds.IsEmpty");
            }

            // It is important the effect's properties don't change during rendering.
            // So a copy is made for the render.
            this.effect = effect.Clone();

            this.source_surface = source;
            this.dest_surface   = dest;
            this.render_bounds  = renderBounds;

            // If a render is already in progress, then cancel it,
            // and start a new render.
            if (IsRendering)
            {
                cancel_render_flag  = true;
                restart_render_flag = true;
                return;
            }

            StartRender();
        }
Пример #5
0
        // Clean up resources when live preview is disabled.
        void CleanUp()
        {
            Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " LivePreviewManager.CleanUp()");

            live_preview_enabled = false;

            if (effect != null)
            {
                if (effect.EffectData != null)
                {
                    effect.EffectData.PropertyChanged -= EffectData_PropertyChanged;
                }
                effect = null !;
            }

            live_preview_surface?.Dispose();
            live_preview_surface = null !;

            if (renderer != null)
            {
                renderer.Dispose();
                renderer = null !;
            }

            if (history_item != null)
            {
                history_item.Dispose();
                history_item = null !;
            }

            // Hide progress dialog and clean up events.
            var dialog = PintaCore.Chrome.ProgressDialog;

            dialog.Hide();
            dialog.Canceled -= HandleProgressDialogCancel;

            PintaCore.Chrome.MainWindowBusy = false;
        }
Пример #6
0
        /// <summary>
        /// Unregister an effect with Pinta, causing it to be removed from the Effects menu.
        /// </summary>
        /// <param name="effect">The effect to unregister</param>
        public void UnregisterEffect(BaseEffect effect)
        {
            if (!effects.ContainsKey (effect))
                return;

            var action = effects[effect];

            effects.Remove (effect);
            PintaCore.Actions.Effects.RemoveEffect (effect.EffectMenuCategory, action);
        }
Пример #7
0
		internal AsyncEffectRenderer (Settings settings)
		{
			if (settings.ThreadCount < 1)
				settings.ThreadCount = 1;
			
			if (settings.TileWidth < 1)
				throw new ArgumentException ("EffectRenderSettings.TileWidth");
			
			if (settings.TileHeight < 1)
				throw new ArgumentException ("EffectRenderSettings.TileHeight");			
			
			if (settings.UpdateMillis <= 0)
				settings.UpdateMillis = 100;
			
			effect = null;
			source_surface = null;
			dest_surface = null;
			this.settings = settings;
			
			is_rendering = false;
			render_id = 0;
			updated_lock = new object ();
			is_updated = false;
			render_exceptions = new List<Exception> ();	
			
			timer_tick_id = 0;
		}		
Пример #8
0
        /// <summary>
        /// Register a new effect with Pinta, causing it to be added to the Effects menu.
        /// </summary>
        /// <param name="effect">The effect to register</param>
        /// <returns>The action created for this effect</returns>
        public Gtk.Action RegisterEffect(BaseEffect effect)
        {
            // Add icon to IconFactory
            Gtk.IconFactory fact = new Gtk.IconFactory ();
            fact.Add (effect.Icon, new Gtk.IconSet (PintaCore.Resources.GetIcon (effect.Icon)));
            fact.AddDefault ();

            // Create a gtk action and menu item for each effect
            Gtk.Action act = new Gtk.Action (effect.GetType ().Name, effect.Name + (effect.IsConfigurable ? Catalog.GetString ("...") : ""), string.Empty, effect.Icon);
            act.Activated += delegate (object sender, EventArgs e) { PintaCore.LivePreview.Start (effect); };

            PintaCore.Actions.Effects.AddEffect (effect.EffectMenuCategory, act);

            effects.Add (effect, act);

            return act;
        }
Пример #9
0
        /// <summary>
        /// Unregister an effect with Pinta, causing it to be removed from the Adjustments menu.
        /// </summary>
        /// <param name="adjustment">The adjustment to unregister</param>
        public void UnregisterAdjustment(BaseEffect adjustment)
        {
            if (!adjustments.ContainsKey (adjustment))
                return;

            var action = adjustments[adjustment];
            var menu_item = adjustment_menuitems[adjustment];

            adjustments.Remove (adjustment);
            PintaCore.Actions.Adjustments.Actions.Remove (action);

            ((Menu)((ImageMenuItem)PintaCore.Chrome.MainMenu.Children[5]).Submenu).Remove (menu_item);
        }
Пример #10
0
        public bool PerformEffect(BaseEffect effect)
        {
            PintaCore.Layers.FinishSelection ();

            if (effect.IsConfigurable) {
                bool result = effect.LaunchConfiguration ();

                if (!result)
                    return false;
            }

            SimpleHistoryItem hist = new SimpleHistoryItem (effect.Icon, effect.Text);
            hist.TakeSnapshotOfLayer (PintaCore.Layers.CurrentLayerIndex);

            // Use the existing ToolLayer instead of creating a new temp layer
            Layer tmp_layer = PintaCore.Layers.ToolLayer;
            tmp_layer.Clear ();

            ImageSurface dest = tmp_layer.Surface;

            Gdk.Rectangle roi = PintaCore.Layers.SelectionPath.GetBounds ().ToGdkRectangle ();
            roi = PintaCore.Workspace.ClampToImageSize (roi);

            if (PintaCore.System.RenderThreads <= 1) {
                effect.RenderEffect (PintaCore.Layers.CurrentLayer.Surface, dest, new Gdk.Rectangle[] { roi });
            } else {
                List<Thread> threads = new List<Thread> ();

                foreach (Gdk.Rectangle rect in SplitRectangle (roi, PintaCore.System.RenderThreads)) {
                    Thread t = new Thread (new ParameterizedThreadStart (ParallelRender));
                    t.Start (new StateInfo (PintaCore.Layers.CurrentLayer.Surface, dest, effect, rect));
                    threads.Add (t);
                }

                foreach (Thread t in threads)
                    t.Join ();
            }

            using (Context g = new Context (PintaCore.Layers.CurrentLayer.Surface)) {
                g.AppendPath (PintaCore.Layers.SelectionPath);
                g.FillRule = FillRule.EvenOdd;
                g.Clip ();

                g.SetSource (dest);
                g.Paint ();
            }

            PintaCore.Workspace.Invalidate ();
            PintaCore.History.PushNewItem (hist);

            return true;
        }
Пример #11
0
		public void Start (BaseEffect effect)
		{			
			if (live_preview_enabled)
				throw new InvalidOperationException ("LivePreviewManager.Start() called while live preview is already enabled.");
			
			// Create live preview surface.
			// Start rendering.
			// Listen for changes to effectConfiguration object, and restart render if needed.
			
			live_preview_enabled = true;
			apply_live_preview_flag = false;
			cancel_live_preview_flag = false;
			
			layer = PintaCore.Layers.CurrentLayer;
			this.effect = effect;
			
			// Handle selection path.
			PintaCore.Tools.Commit ();
			selection_path = (PintaCore.Layers.ShowSelection) ? PintaCore.Layers.SelectionPath : null;
			render_bounds = selection_path.GetBounds ();
			render_bounds = PintaCore.Workspace.ClampToImageSize (render_bounds);			
									
			//TODO Use the current tool layer instead.
			live_preview_surface = new Cairo.ImageSurface (Cairo.Format.Argb32,
			                                  PintaCore.Workspace.ImageSize.Width,
			                                  PintaCore.Workspace.ImageSize.Height);
			
			// Paint the pre-effect layer surface into into the working surface.
			using (var ctx = new Cairo.Context (live_preview_surface)) {
				ctx.SetSourceSurface (layer.Surface, (int) layer.Offset.X, (int) layer.Offset.Y);
				ctx.Paint ();
			}
			
			if (effect.EffectData != null)
				effect.EffectData.PropertyChanged += EffectData_PropertyChanged;
			
			if (Started != null) {
				Started (this, new LivePreviewStartedEventArgs());
			}
			
			var settings = new AsyncEffectRenderer.Settings () {
				ThreadCount = PintaCore.System.RenderThreads,
				TileWidth = render_bounds.Width,
				TileHeight = 1,
				ThreadPriority = ThreadPriority.BelowNormal
			};
			
			Debug.WriteLine (DateTime.Now.ToString("HH:mm:ss:ffff") + "Start Live preview.");
			
			renderer = new Renderer (this, settings);
			renderer.Start (effect, layer.Surface, live_preview_surface, render_bounds);
			
			if (effect.IsConfigurable) {		
				if (!effect.LaunchConfiguration ()) {
					PintaCore.Chrome.MainWindowBusy = true;
					Cancel ();
				} else {
					PintaCore.Chrome.MainWindowBusy = true;
					Apply ();
				}
			} else {
				PintaCore.Chrome.MainWindowBusy = true;
				Apply ();
			}
		}
Пример #12
0
        public void Start(BaseEffect effect)
        {
            if (live_preview_enabled)
            {
                throw new InvalidOperationException("LivePreviewManager.Start() called while live preview is already enabled.");
            }

            // Create live preview surface.
            // Start rendering.
            // Listen for changes to effectConfiguration object, and restart render if needed.

            var doc = PintaCore.Workspace.ActiveDocument;

            live_preview_enabled     = true;
            apply_live_preview_flag  = false;
            cancel_live_preview_flag = false;

            layer       = doc.Layers.CurrentUserLayer;
            this.effect = effect;

            //TODO Use the current tool layer instead.
            live_preview_surface = CairoExtensions.CreateImageSurface(Cairo.Format.Argb32,
                                                                      PintaCore.Workspace.ImageSize.Width,
                                                                      PintaCore.Workspace.ImageSize.Height);

            // Handle selection path.
            PintaCore.Tools.Commit();
            var selection = doc.Selection;

            selection_path = (selection.Visible) ? selection.SelectionPath : null;
            render_bounds  = (selection_path != null) ? selection_path.GetBounds() : live_preview_surface.GetBounds();
            render_bounds  = PintaCore.Workspace.ClampToImageSize(render_bounds);

            history_item = new SimpleHistoryItem(effect.Icon, effect.Name);
            history_item.TakeSnapshotOfLayer(doc.Layers.CurrentUserLayerIndex);

            // Paint the pre-effect layer surface into into the working surface.
            using (var ctx = new Cairo.Context(live_preview_surface)) {
                layer.Draw(ctx, layer.Surface, 1);
            }

            if (effect.EffectData != null)
            {
                effect.EffectData.PropertyChanged += EffectData_PropertyChanged;
            }

            if (Started != null)
            {
                Started(this, new LivePreviewStartedEventArgs());
            }

            var settings = new AsyncEffectRenderer.Settings()
            {
                ThreadCount    = PintaCore.System.RenderThreads,
                TileWidth      = render_bounds.Width,
                TileHeight     = 1,
                ThreadPriority = ThreadPriority.BelowNormal
            };

            Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + "Start Live preview.");

            renderer = new Renderer(this, settings);
            renderer.Start(effect, layer.Surface, live_preview_surface, render_bounds);

            if (effect.IsConfigurable)
            {
                if (!effect.LaunchConfiguration())
                {
                    PintaCore.Chrome.MainWindowBusy = true;
                    Cancel();
                }
                else
                {
                    PintaCore.Chrome.MainWindowBusy = true;
                    Apply();
                }
            }
            else
            {
                PintaCore.Chrome.MainWindowBusy = true;
                Apply();
            }
        }
Пример #13
0
		/// <summary>
		/// Launchs an effect dialog using Pinta's translation template.
		/// </summary>
		internal static bool LaunchSimpleEffectDialog (BaseEffect effect)
		{
			return LaunchSimpleEffectDialog (effect, new PintaLocalizer ());
		}
Пример #14
0
		// Clean up resources when live preview is disabled.
		void CleanUp ()
		{
			Debug.WriteLine (DateTime.Now.ToString("HH:mm:ss:ffff") + " LivePreviewManager.CleanUp()");
			
			live_preview_enabled = false;
			
			if (effect != null) {
				if (effect.EffectData != null)
					effect.EffectData.PropertyChanged -= EffectData_PropertyChanged;
				effect = null;
			}
							
			live_preview_surface = null;
			
			if (renderer != null) {
				renderer.Dispose ();
				renderer = null;
			}

			if (history_item != null) {
				history_item.Dispose ();
				history_item = null;
			}
			
			// Hide progress dialog and clean up events.
			var dialog = PintaCore.Chrome.ProgressDialog;
			dialog.Hide ();
			dialog.Canceled -= HandleProgressDialogCancel;
			
			PintaCore.Chrome.MainWindowBusy = false;
		}
Пример #15
0
		internal void Start (BaseEffect effect,
		                     Cairo.ImageSurface source,
		                     Cairo.ImageSurface dest,
		                     Gdk.Rectangle renderBounds)
		{
			Debug.WriteLine ("AsyncEffectRenderer.Start ()");
			
			if (effect == null)
				throw new ArgumentNullException ("effect");
			
			if (source == null)
				throw new ArgumentNullException ("source");
			
			if (dest == null)
				throw new ArgumentNullException ("dest");
			
			if (renderBounds.IsEmpty)
				throw new ArgumentException ("renderBounds.IsEmpty");
			
			// It is important the effect's properties don't change during rendering.
			// So a copy is made for the render.
			this.effect = effect.Clone();
			
			this.source_surface = source;
			this.dest_surface = dest;
			this.render_bounds = renderBounds;
			
			// If a render is already in progress, then cancel it,
			// and start a new render.
			if (IsRendering) {
				cancel_render_flag = true;
				restart_render_flag = true;
				return;
			}
			
			StartRender ();
		}
Пример #16
0
 private void RemoveAdjustment(BaseEffect adjustment)
 {
     var button = adjustment_command_map_buttons[adjustment];
     AdjustmentsCommandMapBox.Remove (button);
 }
Пример #17
0
 private void AddAdjustment(BaseEffect adjustment, Gtk.Action action)
 {
     var button = new CommandMapButton ("Adjustments", action);
     AdjustmentsCommandMapBox.Add (button);
     adjustment_command_map_buttons.Add (adjustment, button);
 }
Пример #18
0
 public StateInfo(ImageSurface src, ImageSurface dest, BaseEffect effect, Gdk.Rectangle roi)
 {
     Source = src;
     Destination = dest;
     Effect = effect;
     Area = roi;
 }
Пример #19
0
		public void Start (BaseEffect effect)
		{			
			if (live_preview_enabled)
				throw new InvalidOperationException ("LivePreviewManager.Start() called while live preview is already enabled.");
			
			// Create live preview surface.
			// Start rendering.
			// Listen for changes to effectConfiguration object, and restart render if needed.

			live_preview_enabled = true;
			apply_live_preview_flag = false;
			cancel_live_preview_flag = false;
			
			layer = PintaCore.Layers.CurrentLayer;
			this.effect = effect;

			//TODO Use the current tool layer instead.
			live_preview_surface = new Cairo.ImageSurface (Cairo.Format.Argb32,
			                                  PintaCore.Workspace.ImageSize.Width,
			                                  PintaCore.Workspace.ImageSize.Height);

			// Handle selection path.
			PintaCore.Tools.Commit ();
			selection_path = (PintaCore.Layers.ShowSelection) ? PintaCore.Workspace.ActiveDocument.Selection.SelectionPath : null;
			render_bounds = (selection_path != null) ? selection_path.GetBounds () : live_preview_surface.GetBounds ();
			render_bounds = PintaCore.Workspace.ClampToImageSize (render_bounds);	

			history_item = new SimpleHistoryItem (effect.Icon, effect.Name);
			history_item.TakeSnapshotOfLayer (PintaCore.Layers.CurrentLayerIndex);	
			
			// Paint the pre-effect layer surface into into the working surface.
			using (var ctx = new Cairo.Context (live_preview_surface)) {
				layer.Draw(ctx, layer.Surface, 1);
			}
			
			if (effect.EffectData != null)
				effect.EffectData.PropertyChanged += EffectData_PropertyChanged;
			
			if (Started != null) {
				Started (this, new LivePreviewStartedEventArgs());
			}
			
			var settings = new AsyncEffectRenderer.Settings () {
				ThreadCount = PintaCore.System.RenderThreads,
				TileWidth = render_bounds.Width,
				TileHeight = 1,
				ThreadPriority = ThreadPriority.BelowNormal
			};
			
			Debug.WriteLine (DateTime.Now.ToString("HH:mm:ss:ffff") + "Start Live preview.");
			
			renderer = new Renderer (this, settings);
			renderer.Start (effect, layer.Surface, live_preview_surface, render_bounds);
			
			if (effect.IsConfigurable) {		
				if (!effect.LaunchConfiguration ()) {
					PintaCore.Chrome.MainWindowBusy = true;
					Cancel ();
				} else {
					PintaCore.Chrome.MainWindowBusy = true;
					Apply ();
				}
			} else {
				PintaCore.Chrome.MainWindowBusy = true;
				Apply ();
			}
		}
Пример #20
0
		/// <summary>
		/// Launchs an effect dialog.
		/// </summary>
		/// <param name="localizer">
		/// The localizer for the effect add-in. This is used to fetch translations for the
		/// strings in the dialog.
		/// </param>
		public static bool LaunchSimpleEffectDialog (BaseEffect effect, AddinLocalizer localizer)
		{
			return LaunchSimpleEffectDialog (effect, new AddinLocalizerWrapper (localizer));
		}