/// <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; }
/// <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; }
/// <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); }
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(); }
// 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; }
/// <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); }
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; }
/// <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; }
/// <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); }
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; }
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 (); } }
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(); } }
/// <summary> /// Launchs an effect dialog using Pinta's translation template. /// </summary> internal static bool LaunchSimpleEffectDialog (BaseEffect effect) { return LaunchSimpleEffectDialog (effect, new PintaLocalizer ()); }
// 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; }
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 (); }
private void RemoveAdjustment(BaseEffect adjustment) { var button = adjustment_command_map_buttons[adjustment]; AdjustmentsCommandMapBox.Remove (button); }
private void AddAdjustment(BaseEffect adjustment, Gtk.Action action) { var button = new CommandMapButton ("Adjustments", action); AdjustmentsCommandMapBox.Add (button); adjustment_command_map_buttons.Add (adjustment, button); }
public StateInfo(ImageSurface src, ImageSurface dest, BaseEffect effect, Gdk.Rectangle roi) { Source = src; Destination = dest; Effect = effect; Area = roi; }
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 (); } }
/// <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)); }