Browse Source

Added possibility to convert legacy color space

flabbet 8 months ago
parent
commit
37ea71eb6a

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit fcff0f9fb01a65935d1bd8bdf15d36edf5379c02
+Subproject commit bfb22ae2b5f17e0f750c8106ec4677614c697428

+ 5 - 0
src/PixiEditor.ChangeableDocument/ChangeInfos/Properties/ProcessingColorSpace_ChangeInfo.cs

@@ -0,0 +1,5 @@
+using Drawie.Backend.Core.Surfaces.ImageData;
+
+namespace PixiEditor.ChangeableDocument.ChangeInfos.Properties;
+
+public record ProcessingColorSpace_ChangeInfo(ColorSpace NewColorSpace) : IChangeInfo;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs

@@ -88,7 +88,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
     {
         if (_managedTextures.TryGetValue(id, out var texture))
         {
-            if (texture.Size != size || texture.IsDisposed)
+            if (texture.Size != size || texture.IsDisposed || texture.ColorSpace != processingCs)
             {
                 texture.Dispose();
                 texture = new Texture(CreateImageInfo(size, processingCs));

+ 4 - 2
src/PixiEditor.ChangeableDocument/Changes/Properties/ChangeProcessingColorSpace_Change.cs

@@ -1,4 +1,5 @@
 using Drawie.Backend.Core.Surfaces.ImageData;
+using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
 
 namespace PixiEditor.ChangeableDocument.Changes.Properties;
 
@@ -24,12 +25,13 @@ internal class ChangeProcessingColorSpace_Change : Change
         ignoreInUndo = false;
         target.ProcessingColorSpace = toColorSpace;
 
-        return new None();
+        return new ProcessingColorSpace_ChangeInfo(toColorSpace);
     }
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
         target.ProcessingColorSpace = original;
-        return new None();
+        
+        return new ProcessingColorSpace_ChangeInfo(original);
     }
 }

+ 3 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -779,5 +779,7 @@
   "VIEWPORT_ROTATION": "Viewport rotation",
   "NEXT_TOOL_SET": "Next tool set",
   "PREVIOUS_TOOL_SET": "Previous tool set",
-  "FILL_MODE": "Fill mode"
+  "FILL_MODE": "Fill mode",
+  "USE_LINEAR_SRGB_PROCESSING": "Use linear sRGB for processing colors",
+    "USE_LINEAR_SRGB_PROCESSING_DESC": "Convert document using legacy blending mode to linear sRGB for processing colors. This will affect the colors of the document, but will make blending more accurate."
 }

+ 1 - 1
src/PixiEditor/Helpers/Behaviours/TextBlockExtensions.cs

@@ -20,7 +20,7 @@ internal class TextBlockExtensions : AvaloniaObject
 
     private static void OnBindableInlinesChanged(AvaloniaPropertyChangedEventArgs<IEnumerable<Inline>> e)
     {
-        if (e.Sender is not TextBlock target)
+        if (e.Sender is not TextBlock target || e.NewValue.Value is null)
         {
             return;
         }

+ 8 - 0
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -204,6 +204,9 @@ internal class DocumentUpdater
             case SetPlayingState_PassthroughAction info:
                 ProcessPlayAnimation(info);
                 break;
+            case ProcessingColorSpace_ChangeInfo info:
+                ProcessProcessingColorSpace(info);
+                break;
         }
     }
 
@@ -708,4 +711,9 @@ internal class DocumentUpdater
     {
         doc.AnimationHandler.SetOnionFrames(info.OnionFrames, info.Opacity);
     }
+    
+    private void ProcessProcessingColorSpace(ProcessingColorSpace_ChangeInfo info)
+    {
+        doc.SetProcessingColorSpace(info.NewColorSpace);
+    }
 }

+ 6 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -8,6 +8,7 @@ using PixiEditor.ChangeableDocument.Actions.Undo;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Enums;
 using Drawie.Backend.Core;
+using Drawie.Backend.Core.Surfaces.ImageData;
 using Drawie.Backend.Core.Vector;
 using PixiEditor.Extensions.CommonApi.Palettes;
 using PixiEditor.Models.Clipboard;
@@ -812,4 +813,9 @@ internal class DocumentOperationsModule : IDocumentOperations
 
         Internals.ActionAccumulator.AddActions(targetAction);
     }
+
+    public void UseLinearSrgbProcessing()
+    {
+        Internals.ActionAccumulator.AddFinishedActions(new ChangeProcessingColorSpace_Action(ColorSpace.CreateSrgbLinear()));
+    }
 }

+ 2 - 0
src/PixiEditor/Models/Handlers/IDocument.cs

@@ -6,6 +6,7 @@ using PixiEditor.ChangeableDocument.Rendering;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces.ImageData;
 using Drawie.Backend.Core.Vector;
 using PixiEditor.Extensions.CommonApi.Palettes;
 using PixiEditor.Helpers;
@@ -54,6 +55,7 @@ internal interface IDocument : IHandler
     public void SetHorizontalSymmetryAxisEnabled(bool infoState);
     public void SetVerticalSymmetryAxisEnabled(bool infoState);
     public void UpdateSelectionPath(VectorPath infoNewPath);
+    public void SetProcessingColorSpace(ColorSpace infoColorSpace);
     public void SetSize(VecI infoSize);
     public Color PickColor(VecD controllerLastPrecisePosition, DocumentScope scope, bool includeReference, bool includeCanvas, int frame, bool isTopMost);
     public List<Guid> ExtractSelectedLayers(bool includeFoldersWithMask = false);

+ 4 - 0
src/PixiEditor/Models/Rendering/AffectedAreasGatherer.cs

@@ -189,6 +189,10 @@ internal class AffectedAreasGatherer
                     AddToImagePreviews(info.LayerId, info.Affected);
                     AddToNodePreviews(info.LayerId);
                     break;
+                case ProcessingColorSpace_ChangeInfo:
+                    AddWholeCanvasToMainImage();
+                    AddWholeCanvasToEveryImagePreview();
+                    break;
             }
         }
     }

+ 13 - 0
src/PixiEditor/ViewModels/Document/DocumentManagerViewModel.cs

@@ -208,4 +208,17 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
         
         ActiveDocument.Operations.CenterContent(ActiveDocument.GetSelectedMembers(), activeDocument.AnimationDataViewModel.ActiveFrameBindable);
     }
+    
+    [Command.Basic("PixiEditor.Document.UseLinearSrgbProcessing", "USE_LINEAR_SRGB_PROCESSING", "USE_LINEAR_SRGB_PROCESSING_DESC", CanExecute = "PixiEditor.DocumentUsesLegacyBlending", 
+        AnalyticsTrack = true)]
+    public void UseLinearSrgbProcessing()
+    {
+        if (ActiveDocument is null)
+            return;
+        
+        ActiveDocument.Operations.UseLinearSrgbProcessing();
+    }
+    
+    [Evaluator.CanExecute("PixiEditor.DocumentUsesLegacyBlending", nameof(ActiveDocument))]
+    public bool DocumentUsesLegacyBlending() => ActiveDocument?.UsesLegacyBlending ?? false;
 }

+ 6 - 2
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -215,7 +215,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     ILineOverlayHandler IDocument.LineToolOverlayHandler => LineToolOverlayViewModel;
     IReferenceLayerHandler IDocument.ReferenceLayerHandler => ReferenceLayerViewModel;
     IAnimationHandler IDocument.AnimationHandler => AnimationDataViewModel;
-
+    public bool UsesLegacyBlending { get; private set; }
 
     private DocumentViewModel()
     {
@@ -292,7 +292,6 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         var viewModel = new DocumentViewModel();
         viewModel.Operations.ResizeCanvas(new VecI(builderInstance.Width, builderInstance.Height), ResizeAnchor.Center);
 
-
         var acc = viewModel.Internals.ActionAccumulator;
 
         if (builderInstance.UsesLegacyColorBlending || IsFileWithOldColorBlending(serializerData))
@@ -759,6 +758,11 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         OnPropertyChanged(nameof(HorizontalSymmetryAxisYBindable));
     }
 
+    public void SetProcessingColorSpace(ColorSpace infoColorSpace)
+    {
+        UsesLegacyBlending = infoColorSpace.IsSrgb;
+    }
+
     public void SetSize(VecI size)
     {
         var oldSize = size;