12
12
using PaintDotNet . AppModel ;
13
13
using PaintDotNet . PropertySystem ;
14
14
using PaintDotNet . PropertySystem . Extensions ;
15
+ using SvgFileTypePlugin . Extensions ;
15
16
using SvgFileTypePlugin . Localization ;
17
+ using static PaintDotNet . UserBlendOps ;
16
18
17
19
namespace SvgFileTypePlugin . Export ;
18
20
@@ -101,11 +103,11 @@ public static void Export(Surface input, Stream output, PropertyCollection props
101
103
backend . Rx /= scale ;
102
104
backend . Ry /= scale ;
103
105
104
- bool dialogVisible = UIHelper . IsSaveConfigDialogVisible ( ) ;
106
+ bool isSaveConfigDialogVisible = UIHelper . IsSaveConfigDialogVisible ( ) ;
105
107
Surface surface ;
106
108
const int maxDimForPreview = 1280 ;
107
109
108
- if ( dialogVisible && previewMode == PreviewMode . Fast && input . Width * input . Height > maxDimForPreview * maxDimForPreview )
110
+ if ( isSaveConfigDialogVisible && previewMode == PreviewMode . Fast && input . Width * input . Height > maxDimForPreview * maxDimForPreview )
109
111
{
110
112
// Preview Only
111
113
// Image downscaled to speed up preview generation.
@@ -121,109 +123,111 @@ public static void Export(Surface input, Stream output, PropertyCollection props
121
123
surface . FitSurface ( ResamplingAlgorithm . Cubic , input ) ;
122
124
}
123
125
else
126
+ {
124
127
surface = input . Clone ( ) ;
128
+ }
129
+
130
+ using var _ = surface ;
131
+ surface . BlendOnto < NormalBlendOp > ( ColorBgra . White ) ;
125
132
126
- using ( surface )
127
- using ( CancellationTokenSource cts = new CancellationTokenSource ( ) )
133
+ using CancellationTokenSource cts = new CancellationTokenSource ( ) ;
134
+ float full = isSaveConfigDialogVisible ? 90f : 100f ;
135
+
136
+ CancellationToken cancellationToken = cts . Token ;
137
+ if ( scanMode == ScanMode . Opaque )
128
138
{
129
- float full = dialogVisible ? 90f : 100f ;
139
+ backend . Opaque = true ;
140
+ backend . FillColor = fillcolor ;
141
+ }
130
142
131
- void OnProgress ( float prog )
132
- {
133
- try
134
- {
135
- progressCallback . Invoke ( null , new ProgressEventArgs ( prog * full ) ) ;
136
- }
137
- catch ( OperationCanceledException )
138
- {
139
- try
140
- {
141
- cts . Cancel ( ) ;
142
- }
143
- catch ( ObjectDisposedException )
144
- {
145
- // ignore
146
- }
147
- }
148
- }
143
+ if ( highpass == 0 )
144
+ {
145
+ bm = PotraceBitmap . FromRgbx ( surface . Scan0 . Pointer , surface . Width , surface . Height , c : brightnessCutoff ) ;
146
+ }
147
+ else
148
+ {
149
+ using Greymap gm = Greymap . FromRgbx ( surface . Scan0 . Pointer , surface . Width , surface . Height ) ;
150
+ gm . HighPassFilter ( lambda : highpass ) ;
149
151
150
- CancellationToken cancellationToken = cts . Token ;
151
- if ( scanMode == ScanMode . Opaque )
152
- {
153
- backend . Opaque = true ;
154
- backend . FillColor = fillcolor ;
155
- }
152
+ if ( lowpass > 0 )
153
+ gm . LowPassFilter ( lambda : lowpass ) ;
156
154
157
- if ( highpass == 0 )
155
+ if ( gmScale > 1 )
158
156
{
159
- bm = PotraceBitmap . FromRgbx ( surface . Scan0 . Pointer , surface . Width , surface . Height , c : brightnessCutoff ) ;
157
+ bm = gm . InterpolateCubicBilevel ( gmScale , c : brightnessCutoff ) ;
158
+ backend . Rx *= gmScale ;
159
+ backend . Ry *= gmScale ;
160
160
}
161
161
else
162
- {
163
- using Greymap gm = Greymap . FromRgbx ( surface . Scan0 . Pointer , surface . Width , surface . Height ) ;
164
- gm . HighPassFilter ( lambda : highpass ) ;
162
+ bm = gm . Threshold ( c : brightnessCutoff ) ;
163
+ }
164
+
165
+ using ( bm )
166
+ {
167
+ if ( invert )
168
+ bm . Invert ( ) ;
165
169
166
- if ( lowpass > 0 )
167
- gm . LowPassFilter ( lambda : lowpass ) ;
170
+ if ( enclose )
171
+ bm . Enclose ( ) ;
168
172
169
- if ( gmScale > 1 )
170
- {
171
- bm = gm . InterpolateCubicBilevel ( gmScale , c : brightnessCutoff ) ;
172
- backend . Rx *= gmScale ;
173
- backend . Ry *= gmScale ;
174
- }
175
- else
176
- bm = gm . Threshold ( c : brightnessCutoff ) ;
177
- }
173
+ Progress < ProgressArgs > progress = new Progress < ProgressArgs > ( ( prog ) => OnProgress ( ConvertProgressValue ( prog ) ) ) ;
174
+ trace = bm . Trace ( turdsize , turnpolicy , alphamax , opttolerance , progress , cancellationToken ) ;
175
+ imginfo = bm . Info ;
176
+ imginfo . Tight = tight ;
177
+ }
178
+ imginfo . Angle = angle ;
179
+ if ( trace == null )
180
+ {
181
+ if ( UIHelper . IsSaveConfigDialogVisible ( ) )
182
+ return ;
183
+ else
184
+ throw new InvalidOperationException ( StringResources . NoPath ) ;
185
+ }
178
186
179
- using ( bm )
187
+ if ( isSaveConfigDialogVisible && scanMode == ScanMode . Transparent && shapePath . Length > 0 )
188
+ {
189
+ PdnShapeBackEnd pdnbackend = new PdnShapeBackEnd
180
190
{
181
- if ( invert )
182
- bm . Invert ( ) ;
191
+ ColumnWidth = int . MaxValue ,
192
+ DisplayName = shapeName
193
+ } ;
194
+ using ( FileStream shapeStream = File . Open ( shapePath , FileMode . Create , FileAccess . Write ) )
195
+ pdnbackend . Save ( shapeStream , trace , imginfo , cancellationToken ) ;
183
196
184
- if ( enclose )
185
- bm . Enclose ( ) ;
197
+ StringBuilder msg = new StringBuilder ( ) ;
198
+ msg . AppendFormat ( StringResources . ShapeSaved , shapePath ) ;
186
199
187
- Progress < ProgressArgs > progress = new Progress < ProgressArgs > ( ( prog ) => OnProgress ( ConvertProgressValue ( prog ) ) ) ;
188
- trace = bm . Trace ( turdsize , turnpolicy , alphamax , opttolerance , progress , cancellationToken ) ;
189
- imginfo = bm . Info ;
190
- imginfo . Tight = tight ;
191
- }
192
- imginfo . Angle = angle ;
193
- if ( trace == null )
200
+ if ( ShapesDirectory . Value != null && Path . GetDirectoryName ( shapePath ) ? . StartsWith ( ShapesDirectory . Value , StringComparison . OrdinalIgnoreCase ) == true )
194
201
{
195
- if ( UIHelper . IsSaveConfigDialogVisible ( ) )
196
- return ;
197
- else
198
- throw new InvalidOperationException ( StringResources . NoPath ) ;
202
+ msg . AppendLine ( ) ;
203
+ msg . AppendLine ( ) ;
204
+ msg . AppendLine ( StringResources . ShapeSavedRestart ) ;
199
205
}
200
206
201
- if ( dialogVisible && scanMode == ScanMode . Transparent && shapePath . Length > 0 )
207
+ UIHelper . RunOnUIThread ( ( ) =>
202
208
{
203
- PdnShapeBackEnd pdnbackend = new PdnShapeBackEnd
204
- {
205
- ColumnWidth = int . MaxValue ,
206
- DisplayName = shapeName
207
- } ;
208
- using ( FileStream shapeStream = File . Open ( shapePath , FileMode . Create , FileAccess . Write ) )
209
- pdnbackend . Save ( shapeStream , trace , imginfo , cancellationToken ) ;
210
-
211
- StringBuilder msg = new StringBuilder ( ) ;
212
- msg . AppendFormat ( StringResources . ShapeSaved , shapePath ) ;
209
+ MessageBox . Show ( msg . ToString ( ) , StringResources . ShapeSavedCaption , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
210
+ } ) ;
211
+ }
212
+ backend . Save ( output , trace , imginfo , cancellationToken ) ;
213
213
214
- if ( ShapesDirectory . Value != null && Path . GetDirectoryName ( shapePath ) ? . StartsWith ( ShapesDirectory . Value , StringComparison . OrdinalIgnoreCase ) == true )
214
+ void OnProgress ( float prog )
215
+ {
216
+ try
217
+ {
218
+ progressCallback . Invoke ( null , new ProgressEventArgs ( prog * full ) ) ;
219
+ }
220
+ catch ( OperationCanceledException )
221
+ {
222
+ try
215
223
{
216
- msg . AppendLine ( ) ;
217
- msg . AppendLine ( ) ;
218
- msg . AppendLine ( StringResources . ShapeSavedRestart ) ;
224
+ cts . Cancel ( ) ;
225
+ }
226
+ catch ( ObjectDisposedException )
227
+ {
228
+ // ignore
219
229
}
220
-
221
- UIHelper . RunOnUIThread ( ( ) =>
222
- {
223
- MessageBox . Show ( msg . ToString ( ) , StringResources . ShapeSavedCaption , MessageBoxButtons . OK , MessageBoxIcon . Information ) ;
224
- } ) ;
225
230
}
226
- backend . Save ( output , trace , imginfo , cancellationToken ) ;
227
231
}
228
232
}
229
233
0 commit comments