/// <inheritdoc /> public void Close(DateTime originatingTime) { if (this.lastEnvelope.SequenceId != int.MaxValue) { var e = this.CreateEnvelope(originatingTime); e.SequenceId = int.MaxValue; // special "closing" ID this.Deliver(new Message <T>(default(T), e)); this.receivers = new Receiver <T> [0]; foreach (var handler in this.closedHandlers) { PipelineElement.TrackStateObjectOnContext(() => handler(originatingTime), this.Owner, this.pipeline).Invoke(); } } }
/// <summary> /// Called when the user clicks on the button to move a pipeline element /// up towards the beginning of the pipeline. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event arguments.</param> private void MoveElementUpBtn_Click(object sender, EventArgs e) { // We need to remove element and reinsert it. int selectedIdx = ElementsLst.SelectedIndex; PipelineElement element = elements[selectedIdx]; elements.RemoveAt(selectedIdx); elements.Insert(selectedIdx - 1, element); // Reselect the element and update our selection-dependent controls. ElementsLst.SelectedIndex = selectedIdx - 1; UpdateControls(); // Update preview. UpdatePluginInfo(); }
/// <summary> /// Initializes a new instance of the <see cref="EventSource{TEventHandler, TOut}"/> class. /// The component will subscribe to an event on startup via the <paramref name="subscribe"/> /// delegate, using the supplied <paramref name="converter"/> function to transform the /// <see cref="Post"/> action delegate into an event handler compatible with the external /// event that is being subscribed to. /// </summary> /// <param name="pipeline">The Psi pipeline.</param> /// <param name="subscribe">The delegate that subscribes to the external event.</param> /// <param name="unsubscribe">The delegate that unsubscribes from the external event.</param> /// <param name="converter"> /// A function used to convert the <see cref="Post"/> action delegate into an event /// handler of type <typeparamref name="TEventHandler"/> that will be subscribed to the /// external event by the <paramref name="subscribe"/> delegate. /// </param> public EventSource( Pipeline pipeline, Action <TEventHandler> subscribe, Action <TEventHandler> unsubscribe, Func <Action <TOut>, TEventHandler> converter) { this.pipeline = pipeline; this.Out = pipeline.CreateEmitter <TOut>(this, nameof(this.Out)); this.subscribe = subscribe; this.unsubscribe = unsubscribe; // If the source event is triggered from the execution context of some other receiver, then because the // execution context flows all the way through to the event handler, the tracked state object (if tracking // is enabled) would represent the owner of the receiver, which would be inconsistent with posting from a // pure source (no tracked state object). In order to rectify this, we set the tracked state object to null // just prior to the call to this.Post by wrapping it in TrackStateObjectOnContext with a null state object. this.eventHandler = converter(PipelineElement.TrackStateObjectOnContext <TOut>(this.Post, null, pipeline)); }
internal Receiver(int id, string name, PipelineElement element, object owner, Action <Message <T> > onReceived, SynchronizationLock context, Pipeline pipeline, bool enforceIsolation = false) { this.scheduler = pipeline.Scheduler; this.schedulerContext = pipeline.SchedulerContext; this.lastEnvelope = default; this.onReceived = m => { this.lastEnvelope = m.Envelope; PipelineElement.TrackStateObjectOnContext(onReceived, owner, pipeline)(m); }; this.Id = id; this.Name = name; this.element = element; this.Owner = owner; this.syncContext = context; this.enforceIsolation = enforceIsolation; this.Recycler = RecyclingPool.Create <T>(); this.pipeline = pipeline; this.receiverDiagnosticsCollector = new Lazy <DiagnosticsCollector.ReceiverCollector>(() => this.pipeline.DiagnosticsCollector?.GetReceiverDiagnosticsCollector(pipeline, element, this), true); }
private PipelineElement GetOrCreateNode(object component) { PipelineElement node = this.components.FirstOrDefault(c => c.StateObject == component); if (node == null) { var id = nextElementId++; var name = component.GetType().Name; var fullName = $"{id}.{name}"; node = new PipelineElement(fullName, component); this.AddComponent(node); if (this.started && node.IsSource && !(component is Subpipeline)) { throw new InvalidOperationException($"Source component added when pipeline already running. Consider using Subpipeline."); } } return(node); }
/// <summary> /// Get collector of diagnostics message flow statistics for a single receiver. /// </summary> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element to which receiver belongs.</param> /// <param name="receiver">Receiver having completed processing.</param> public ReceiverCollector GetReceiverDiagnosticsCollector(Pipeline pipeline, PipelineElement element, IReceiver receiver) { return(new ReceiverCollector(this.graphs[pipeline.Id].PipelineElements[element.Id].Receivers[receiver.Id], this.diagnosticsConfig)); }
/// <summary> /// Input unsubscribed to input. /// </summary> /// <remarks>Called upon unsubscribe (only if pipeline running).</remarks> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element to which receiver belongs.</param> /// <param name="receiver">Receiver unsubscribing to emitter.</param> /// <param name="emitter">Emitter from which receiver is unsubscribing.</param> public void PipelineElementReceiverUnsubscribe(Pipeline pipeline, PipelineElement element, IReceiver receiver, IEmitter emitter) { this.outputs[emitter.Id].Targets.TryRemove(receiver.Id, out var _); this.graphs[pipeline.Id].PipelineElements[element.Id].Receivers[receiver.Id].Source = null; }
/// <summary> /// Input (receiver) added to element. /// </summary> /// <remarks>Called just after element start (or dynamically if added once pipeline running).</remarks> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element to which receiver is being added.</param> /// <param name="receiver">Receiver being added.</param> public void PipelineElementAddReceiver(Pipeline pipeline, PipelineElement element, IReceiver receiver) { var node = this.graphs[pipeline.Id].PipelineElements[element.Id]; node.Receivers.TryAdd(receiver.Id, new PipelineDiagnosticsInternal.ReceiverDiagnostics(receiver.Id, receiver.Name, receiver.Type.FullName, node)); }
/// <summary> /// Element (representing component) created. /// </summary> /// <remarks>Called upon element disposal.</remarks> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element being created.</param> public void PipelineElementDisposed(Pipeline pipeline, PipelineElement element) { this.graphs[pipeline.Id].PipelineElements.TryRemove(element.Id, out var _); }
/// <summary> /// Element (representing component) being finalized. /// </summary> /// <remarks>Called after scheduling calls to final handler.</remarks> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element being finalized.</param> public void PipelineElementFinal(Pipeline pipeline, PipelineElement element) { this.graphs[pipeline.Id].PipelineElements[element.Id].Finalized = true; }
/// <summary> /// Element (representing component) being stopped. /// </summary> /// <remarks>Called after scheduling calls to stop handler.</remarks> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element being stopped.</param> public void PipelineElementStop(Pipeline pipeline, PipelineElement element) { this.graphs[pipeline.Id].PipelineElements[element.Id].IsRunning = false; }
/// <summary> /// Render canvas workspace using pipeline /// </summary> /// <param name="writer">Image writer</param> /// <param name="dpi">DPI of the rendered image</param> /// <param name="colorSpace">Color space of the rendered image</param> /// <param name="backgroundColor">Background color for the rendered image</param> /// <param name="isPreview"></param> public void RenderWorkspace(PipelineElement writer, float dpi, ColorSpace colorSpace, Color backgroundColor = null, bool isPreview = false) { new Renderer().Render(writer, this, dpi, colorSpace, backgroundColor, isPreview); }
/// <summary> /// Message processed by component. /// </summary> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element to which receiver belongs.</param> /// <param name="receiver">Receiver having completed processing.</param> /// <param name="envelope">Message envelope.</param> public void MessageProcessComplete(Pipeline pipeline, PipelineElement element, IReceiver receiver, Envelope envelope) { this.graphs[pipeline.Id].PipelineElements[element.Id].Receivers[receiver.Id].AddProcessingTime(pipeline.GetCurrentTime() - this.receiverProcessingStart[receiver.Id]); }
/// <summary> /// Called when the form is loaded. We use this opportunity to populate /// the controls with info about a plugin we're editing, if we have one. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event arguments.</param> private void PipelinePluginForm_Load(object sender, EventArgs e) { // First load list of plugins to display in the listbox for the base // plugin. We only load default and COM plugins for this since we // don't want a pipeline plugin to be based off another (for now at least). List <Plugin> plugins = PluginsRegistry.GetPluginsInDefaultOrder(Settings, false); // Add all plugins to the list box. BasePluginLst.Items.AddRange(plugins.ToArray()); // Check if we have a plugin info to load. Guid?basePluginId = null; if (oldPluginInfo != null) { Debug.Assert(oldPipeline != null); // Populate our controls. NameTxt.Text = oldPluginInfo.Description; PipelineElement element = oldPipeline.Elements.Find(el => el is ApplyPluginPipelineElement); if (element != null) { basePluginId = ((ApplyPluginPipelineElement)element).PluginID; } if (oldPipeline.Elements.Find(el => el is OptionalQuotesPipelineElement) != null) { QuotesChk.Checked = true; OptionalQuotesChk.Checked = true; } else if (oldPipeline.Elements.Find(el => el is QuotesPipelineElement) != null) { QuotesChk.Checked = true; } EmailLinksChk.Checked = oldPipeline.Elements.Find(el => el is EmailLinksPipelineElement) != null; if (oldPipeline.Elements.Find(el => el is EncodeURICharsPipelineElement) != null) { EncodeURIWhitespaceChk.Checked = true; EncodeURICharsChk.Checked = true; } else if (oldPipeline.Elements.Find(el => el is EncodeURIWhitespacePipelineElement) != null) { EncodeURIWhitespaceChk.Checked = true; } RemoveExtChk.Checked = oldPipeline.Elements.Find(el => el is RemoveExtPipelineElement) != null; if (oldPipeline.Elements.Find(el => el is BackToForwardSlashesPipelineElement) != null) { BackToForwardSlashesRadio.Checked = true; } else if (oldPipeline.Elements.Find(el => el is ForwardToBackslashesPipelineElement) != null) { ForwardToBackslashesRadio.Checked = true; } else { Debug.Assert(NoSlashesChangeRadio.Checked); } element = oldPipeline.Elements.Find(el => el is RegexPipelineElement); if (element != null) { UseRegexChk.Checked = true; IgnoreCaseChk.Enabled = true; TestRegexBtn.Enabled = true; RegexPipelineElement regexElement = (RegexPipelineElement)element; FindTxt.Text = regexElement.Regex; ReplaceTxt.Text = regexElement.Format; IgnoreCaseChk.Checked = regexElement.IgnoreCase; } else { Debug.Assert(!IgnoreCaseChk.Enabled); Debug.Assert(!TestRegexBtn.Enabled); element = oldPipeline.Elements.Find(el => el is FindReplacePipelineElement); if (element != null) { FindTxt.Text = ((FindReplacePipelineElement)element).OldValue; ReplaceTxt.Text = ((FindReplacePipelineElement)element).NewValue; } } // "Copy on same line" is a little special since it could be any string. element = oldPipeline.Elements.Find(el => el is PathsSeparatorPipelineElement); oldPathsSeparator = (element as PathsSeparatorPipelineElement)?.PathsSeparator; if (oldPathsSeparator == PipelinePluginEditor.PATHS_SEPARATOR_ON_SAME_LINE) { CopyOnSameLineChk.Checked = true; } else if (!String.IsNullOrEmpty(oldPathsSeparator)) { CopyOnSameLineChk.Enabled = false; } element = oldPipeline.Elements.Find(el => el is ExecutablePipelineElement); if (element != null) { LaunchExecutableChk.Checked = true; ExecutableTxt.Text = ((ExecutablePipelineElement)element).Executable; } else { element = oldPipeline.Elements.Find(el => el is ExecutableWithFilelistPipelineElement); if (element != null) { LaunchExecutableChk.Checked = true; WithFilelistChk.Checked = true; ExecutableTxt.Text = ((ExecutableWithFilelistPipelineElement)element).Executable; } else { Debug.Assert(!ExecutableLbl.Enabled); Debug.Assert(!ExecutableTxt.Enabled); Debug.Assert(!BrowserForExecutableBtn.Enabled); } } } // Validate base plugin ID if found. if (basePluginId != null) { if (plugins.Find(pl => pl.Id == basePluginId) == null) { // Invalid, clear it so that we'll fall back // on the default below. basePluginId = null; } } // If we didn't find a base plugin ID yet, use the "Long Path" plugin ID. if (basePluginId == null) { basePluginId = new Guid(Resources.LONG_PATH_PLUGIN_ID); } // Scan list of plugins to select the base plugin. for (int i = 0; i < BasePluginLst.Items.Count; ++i) { if (!(BasePluginLst.Items[i] is SeparatorPlugin) && ((Plugin)BasePluginLst.Items[i]).Id == basePluginId) { // This is the default plugin, select it and break. BasePluginLst.SelectedIndex = i; break; } } Debug.Assert(BasePluginLst.SelectedIndex != -1); // Immediately update plugin info so that preview box is initially filled. UpdatePluginInfo(); }
internal void AddComponent(PipelineElement pe) { pe.Initialize(this); this.components.Enqueue(pe); }
/// <summary> /// Initializes a new instance of the <see cref="PipelineElementDiagnostics"/> class. /// </summary> /// <param name="element">Pipeline element which this diagnostic information represents.</param> /// <param name="pipeline">Pipeline to which this pipeline element belongs.</param> internal PipelineElementDiagnostics(PipelineElement element, PipelineDiagnostics pipeline) : this(element.Id, element.Name, element.IsConnector ? PipelineElementKind.Connector : element.StateObject is Subpipeline ? PipelineElementKind.Subpipeline : element.IsSource ? PipelineElementKind.Source : PipelineElementKind.Reactive, pipeline) { }
/// <summary> /// Called when the form is loaded. We use this opportunity to populate /// the controls with info about a plugin we're editing, if we have one. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event arguments.</param> private void PipelinePluginForm_Load(object sender, EventArgs e) { // First load list of plugins in default order for the base plugin. // Note: we want *temp* pipeline plugins in order to use those saved by the MainForm, // in order to get the most recent snapshot of pipeline plugins. List <Plugin> pluginsInDefaultOrder = PluginsRegistry.GetPluginsInDefaultOrder( Settings, PipelinePluginsOptions.FetchTempPipelinePlugins); // Create sorted dictionary of all plugins from the list above, to be able to perform lookups. SortedDictionary <Guid, Plugin> dictionaryOfAllPlugins = new SortedDictionary <Guid, Plugin>(); foreach (Plugin plugin in pluginsInDefaultOrder) { if (!dictionaryOfAllPlugins.ContainsKey(plugin.Id)) { dictionaryOfAllPlugins.Add(plugin.Id, plugin); } } // Use UI display order from settings to order the plugins. // (See MainForm.LoadSettings for some more details on this process) List <Guid> uiDisplayOrder = Settings.UIDisplayOrder; if (uiDisplayOrder == null) { // No display order, just use all plugins in default order uiDisplayOrder = pluginsInDefaultOrder.Select(plugin => plugin.Id).ToList(); } SortedSet <Guid> uiDisplayOrderAsSet = new SortedSet <Guid>(uiDisplayOrder); List <Plugin> plugins = PluginsRegistry.OrderPluginsToDisplay(dictionaryOfAllPlugins, uiDisplayOrder, uiDisplayOrderAsSet, pluginsInDefaultOrder); // Add all plugins to the list box. BasePluginLst.Items.AddRange(plugins.ToArray()); // Check if we have a plugin info to load. Guid?basePluginId = null; if (oldPluginInfo != null) { Debug.Assert(oldPipeline != null); // Populate our controls. NameTxt.Text = oldPluginInfo.Description; PipelineElement element = oldPipeline.Elements.Find(el => el is PipelineElementWithPluginID); if (element != null) { basePluginId = ((PipelineElementWithPluginID)element).PluginID; } if (oldPipeline.Elements.Find(el => el is OptionalQuotesPipelineElement) != null) { QuotesChk.Checked = true; OptionalQuotesChk.Checked = true; } else if (oldPipeline.Elements.Find(el => el is QuotesPipelineElement) != null) { QuotesChk.Checked = true; } EmailLinksChk.Checked = oldPipeline.Elements.Find(el => el is EmailLinksPipelineElement) != null; if (oldPipeline.Elements.Find(el => el is EncodeURICharsPipelineElement) != null) { EncodeURIWhitespaceChk.Checked = true; EncodeURICharsChk.Checked = true; } else if (oldPipeline.Elements.Find(el => el is EncodeURIWhitespacePipelineElement) != null) { EncodeURIWhitespaceChk.Checked = true; } RemoveExtChk.Checked = oldPipeline.Elements.Find(el => el is RemoveExtPipelineElement) != null; if (oldPipeline.Elements.Find(el => el is BackToForwardSlashesPipelineElement) != null) { BackToForwardSlashesRadio.Checked = true; } else if (oldPipeline.Elements.Find(el => el is ForwardToBackslashesPipelineElement) != null) { ForwardToBackslashesRadio.Checked = true; } else { Debug.Assert(NoSlashesChangeRadio.Checked); } element = oldPipeline.Elements.Find(el => el is RegexPipelineElement); if (element != null) { UseRegexChk.Checked = true; IgnoreCaseChk.Enabled = true; TestRegexBtn.Enabled = true; RegexPipelineElement regexElement = (RegexPipelineElement)element; FindTxt.Text = regexElement.Regex; ReplaceTxt.Text = regexElement.Format; IgnoreCaseChk.Checked = regexElement.IgnoreCase; } else { Debug.Assert(!IgnoreCaseChk.Enabled); Debug.Assert(!TestRegexBtn.Enabled); element = oldPipeline.Elements.Find(el => el is FindReplacePipelineElement); if (element != null) { FindTxt.Text = ((FindReplacePipelineElement)element).OldValue; ReplaceTxt.Text = ((FindReplacePipelineElement)element).NewValue; } } if (oldPipeline.Elements.Find(el => el is UnexpandEnvironmentStringsPipelineElement) != null) { UnexpandEnvStringsChk.Checked = true; } // "Copy on same line" is a little special since it could be any string. element = oldPipeline.Elements.Find(el => el is PathsSeparatorPipelineElement); oldPathsSeparator = (element as PathsSeparatorPipelineElement)?.PathsSeparator; if (oldPathsSeparator == PipelinePluginEditor.PATHS_SEPARATOR_ON_SAME_LINE) { CopyOnSameLineChk.Checked = true; } else if (!string.IsNullOrEmpty(oldPathsSeparator)) { CopyOnSameLineChk.Enabled = false; } RecursiveCopyChk.Checked = oldPipeline.Elements.Find(el => el is RecursiveCopyPipelineElement) != null; element = oldPipeline.Elements.Find(el => el is ExecutablePipelineElement); if (element != null) { LaunchExecutableChk.Checked = true; ExecutableTxt.Text = ((ExecutablePipelineElement)element).Executable; } else { element = oldPipeline.Elements.Find(el => el is ExecutableWithFilelistPipelineElement); if (element != null) { LaunchExecutableChk.Checked = true; WithFilelistChk.Checked = true; ExecutableTxt.Text = ((ExecutableWithFilelistPipelineElement)element).Executable; } else { Debug.Assert(!ExecutableLbl.Enabled); Debug.Assert(!ExecutableTxt.Enabled); Debug.Assert(!BrowserForExecutableBtn.Enabled); } } } // Validate base plugin ID if found. if (basePluginId != null) { if (plugins.Find(pl => pl.Id == basePluginId) == null) { // Invalid, clear it so that we'll fall back // on the default below. basePluginId = null; } } // If we didn't find a base plugin ID yet, use the "Long Path" plugin ID. if (basePluginId == null) { basePluginId = new Guid(Resources.LONG_PATH_PLUGIN_ID); } // Scan list of plugins to select the base plugin. for (int i = 0; i < BasePluginLst.Items.Count; ++i) { if (!(BasePluginLst.Items[i] is SeparatorPlugin) && ((Plugin)BasePluginLst.Items[i]).Id == basePluginId) { // This is the default plugin, select it and break. BasePluginLst.SelectedIndex = i; break; } } Debug.Assert(BasePluginLst.SelectedIndex != -1); // Immediately update plugin info so that preview box is initially filled. UpdatePluginInfo(); }
/// <summary> /// Message processed synchronously by receiver. /// </summary> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element to which receiver belongs.</param> /// <param name="receiver">Receiver having been processed synchronously.</param> /// <param name="queueSize">Awaiting delivery queue size.</param> /// <param name="envelope">Message envelope.</param> /// <param name="messageSize">Message size (bytes).</param> public void MessageProcessedSynchronously(Pipeline pipeline, PipelineElement element, IReceiver receiver, int queueSize, Envelope envelope, int messageSize) { this.MessageProcessStart(pipeline, element, receiver, queueSize, envelope, messageSize); this.MessageProcessComplete(pipeline, element, receiver, envelope); }
/// <summary> /// Element (representing component) being started. /// </summary> /// <remarks>Called after scheduling calls to start handler.</remarks> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element being started.</param> public void PipelineElementStart(Pipeline pipeline, PipelineElement element) { this.graphs[pipeline.Id].PipelineElements[element.Id].IsRunning = true; }
public void RenderLayers(PipelineElement writer, IEnumerable <Layer> layers, SizeF workspace, float dpi = 300f, ColorSpace colorSpace = ColorSpace.Rgb, Color backgroundColor = null, bool isPreview = false, SizeF document = new SizeF(), ColorManagement colorManagement = null, float?targetDpi = null ) { if (workspace.Width <= 0 || workspace.Height <= 0) { throw new ArgumentException(null, "workspace"); } if (dpi <= 0) { throw new ArgumentOutOfRangeException("dpi", dpi, Exceptions.DpiOutOfRange); } colorSpace = colorSpace == ColorSpace.Unknown ? ColorSpace.Rgb : colorSpace; if (colorSpace != ColorSpace.Cmyk && colorSpace != ColorSpace.Grayscale && colorSpace != ColorSpace.Rgb) { throw new ArgumentException(null, "colorSpace"); } // Turn on proofing if (colorManagement != null && isPreview) var initialTargetColorSpace = colorManagement != null ? colorManagement.TargetColorSpace : null; if (colorManagement != null) { colorManagement.TargetColorSpace = isPreview ? new ColorSpace?(colorSpace) : null; colorSpace = isPreview ? ColorSpace.Rgb : colorSpace; } backgroundColor = backgroundColor ?? ColorManagement.GetWhiteColor(colorSpace); var format = ColorManagement.GetPixelFormat(colorSpace); var profile = ColorManagement.GetProfile(colorManagement, colorSpace, isPreview); var pixelSize = new Size( Common.ConvertPointsToPixels(dpi, workspace.Width), Common.ConvertPointsToPixels(dpi, workspace.Height)); var pdfWriter = writer as PdfWriter; if (pdfWriter != null) { var docWidth = pixelSize.Width; var docHeight = pixelSize.Height; var scale = 1f; var offset = PointF.Empty; if (!document.IsEmpty) { docWidth = Common.ConvertPointsToPixels(dpi, document.Width); docHeight = Common.ConvertPointsToPixels(dpi, document.Height); var scaleX = docWidth / (float)pixelSize.Width; var scaleY = docHeight / (float)pixelSize.Height; scale = System.Math.Min(scaleX, scaleY); if (Utils.EqualsOfFloatNumbers(scaleX, scaleY, 0.001f)) { scale = (float)System.Math.Round(scale, 2); docWidth = Common.ConvertPointsToPixels(dpi, workspace.Width * scale); docHeight = Common.ConvertPointsToPixels(dpi, workspace.Height * scale); } else { offset.X = (docWidth - pixelSize.Width * scale) / 2f; offset.Y = (docHeight - pixelSize.Height * scale) / 2f; } } pdfWriter.AddPage(docWidth, docHeight, dpi, dpi, backgroundColor, profile); using (var graphics = pdfWriter.GetGraphics()) { var path = new Path(); path.DrawRectangle(0, 0, pixelSize.Width, pixelSize.Height); graphics.Transform.Scale(scale, scale, MatrixOrder.Append); graphics.Transform.Translate(offset.X, offset.Y, MatrixOrder.Append); graphics.ClippingPaths.Add(path); var vObjects = GetVObjects(layers, workspace).ToArray(); using (var imageParams = new ImageGenerator(pixelSize, format, backgroundColor) { DpiX = dpi, DpiY = dpi, ColorProfile = profile }) { if (colorManagement != null) { colorManagement.InitColorMap(from v in vObjects from c in v.GetColors() select c, imageParams); } DrawVObjects(vObjects, graphics, imageParams, colorManagement); } graphics.ClippingPaths.Remove(path); graphics.Transform.Translate(-offset.X, -offset.Y, MatrixOrder.Append); graphics.Transform.Scale(1 / scale, 1 / scale, MatrixOrder.Append); } } else { var vObjectGroups = new List <List <VObject> >(); List <VObject> currentVObjectGroup = null; List <VObject> currentImageVObjectGroup = null; var vObjects = GetVObjects(layers, workspace).ToArray(); foreach (var vObject in vObjects) { if (vObject is IPipelineExtender) { if (currentVObjectGroup != null) { vObjectGroups.Add(currentVObjectGroup); currentVObjectGroup = null; } if (currentImageVObjectGroup == null) { currentImageVObjectGroup = new List <VObject>(); } currentImageVObjectGroup.Add(vObject); } else { if (currentImageVObjectGroup != null) { vObjectGroups.Add(currentImageVObjectGroup); currentImageVObjectGroup = null; } if (currentVObjectGroup == null) { currentVObjectGroup = new List <VObject>(); } currentVObjectGroup.Add(vObject); } } if (currentVObjectGroup != null) { vObjectGroups.Add(currentVObjectGroup); } if (currentImageVObjectGroup != null) { vObjectGroups.Add(currentImageVObjectGroup); } var pipeline = new Pipeline(); var deps = new List <IDisposable>(); var scale = dpi / targetDpi ?? 1; try { var bitmapGenerator = new ImageGenerator(pixelSize.Width, pixelSize.Height, format, backgroundColor) { DpiX = dpi / scale, DpiY = dpi / scale, ColorProfile = profile }; if (colorManagement != null) { colorManagement.InitColorMap(from v in vObjects from c in v.GetColors() select c, bitmapGenerator); } pipeline.Add(bitmapGenerator); foreach (var group in vObjectGroups) { if (group.Count == 0) { break; } if (group.FirstOrDefault() is IPipelineExtender) { foreach (var vObject in group) { IEnumerable <IDisposable> vObjectDeps; ((IPipelineExtender)vObject).ExtendPipeline(pipeline, bitmapGenerator, colorManagement, scale, out vObjectDeps); deps.AddRange(vObjectDeps); } } else { var groupVObjects = group.ToArray(); var drawer = new Drawer(); drawer.Draw += (sender, e) => { if (!Utils.EqualsOfFloatNumbers(scale, 1)) { e.Graphics.Transform.Scale(scale, scale); } DrawVObjects(groupVObjects, e.Graphics, bitmapGenerator, colorManagement); if (!Utils.EqualsOfFloatNumbers(scale, 1)) { e.Graphics.Transform.Scale(1 / scale, 1 / scale); } }; pipeline.Add(drawer); } } // Check if writer support pixel format with or without alpha. if (!writer.IsPixelFormatSupported(bitmapGenerator.PixelFormat) && writer.IsPixelFormatSupported(PixelFormat.DiscardAlpha(bitmapGenerator.PixelFormat))) { pipeline.Add(new RemoveAlpha(backgroundColor)); } if (!Utils.EqualsOfFloatNumbers(scale, 1)) { pipeline.Add(new ResolutionModifier(dpi, dpi)); } pipeline.Add(writer); pipeline.Run(); } finally { pipeline.Remove(writer); pipeline.DisposeAllElements(); if (deps != null) { foreach (var dep in deps) { dep.Dispose(); } } if (colorManagement != null) { colorManagement.TargetColorSpace = initialTargetColorSpace; } } } if (colorManagement != null) { colorManagement.TargetColorSpace = initialTargetColorSpace; } }
/// <summary> /// Element (representing component) being stopped. /// </summary> /// <remarks>Called after scheduling calls to stop handler.</remarks> /// <param name="pipeline">The pipeline to add the component to.</param> /// <param name="element">Element being stopped.</param> public void PipelineElementStop(Pipeline pipeline, PipelineElement element) { this.graphs[pipeline.Id].PipelineElements[element.Id].IsRunning = false; this.graphs[pipeline.Id].PipelineElements[element.Id].DiagnosticState = element.StateObject.ToString(); }
/// <summary> /// Initializes a new instance of the <see cref="PipelineElementDiagnostics"/> class. /// </summary> /// <param name="element">Pipeline element which this diagnostic information represents.</param> /// <param name="pipelineId">ID of Pipeline to which this element belongs.</param> internal PipelineElementDiagnostics(PipelineElement element, int pipelineId) : this(element.Id, element.StateObject.ToString(), element.StateObject.GetType().Name, element.IsConnector ? PipelineElementKind.Connector : element.StateObject is Subpipeline ? PipelineElementKind.Subpipeline : element.IsSource ? PipelineElementKind.Source : PipelineElementKind.Reactive, pipelineId) { }
/// <summary> /// Message enqueued by receiver. /// </summary> /// <param name="pipeline">Pipeline to which the element belongs.</param> /// <param name="element">Element to which receiver belongs.</param> /// <param name="receiver">Receiver being throttled/unthrottled.</param> /// <param name="throttled">Whether input is throttled.</param> public void PipelineElementReceiverThrottle(Pipeline pipeline, PipelineElement element, IReceiver receiver, bool throttled) { this.graphs[pipeline.Id].PipelineElements[element.Id].Receivers[receiver.Id].Throttled = throttled; }