Skip to content

Commit 678f445

Browse files
committed
Added import group boundaries feature. It's used to have a possibility to restore original folders/groups structure and track what was the original groups.
1 parent e288739 commit 678f445

File tree

4 files changed

+138
-72
lines changed

4 files changed

+138
-72
lines changed

SvgFileType/SvgFileType.cs

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Windows.Forms;
1010
using System.Linq;
1111
using System.Reflection;
12+
using System.Drawing.Drawing2D;
1213

1314
namespace SvgFileTypePlugin
1415
{
@@ -22,7 +23,11 @@ public SvgFileType()
2223
{
2324
}
2425

25-
private static string groupAttribute = "import_grouped";
26+
// Dont change this text! It's used by a PSD import plugin to keep photoshop folder strure.
27+
public const string LayerGroupBegin = "Layer Group: {0}";
28+
public const string LayerGroupEnd = "End Layer Group: {0}";
29+
30+
private static string groupAttribute = "import_group_name";
2631
private static string visibilityAttribute = "import_visibility";
2732

2833
private static string[] allowedTitles = new string[] { "label", "title", "inskape:label" };
@@ -78,7 +83,7 @@ public static Document Get(Stream input)
7883
// Store opacity as layer options.
7984
var setOpacityForLayer = true;
8085
var importHiddenLayers = true;
81-
86+
var importGroupBoundariesAsLayers = false;
8287
DialogResult dr = DialogResult.Cancel;
8388
using (var dialog = new UiDialog())
8489
{
@@ -105,6 +110,7 @@ public static Document Get(Stream input)
105110
keepAspectRatio = dialog.KeepAspectRatio;
106111
setOpacityForLayer = dialog.ImportOpacity;
107112
importHiddenLayers = dialog.ImportHiddenLayers;
113+
importGroupBoundariesAsLayers = dialog.ImportGroupBoundariesAsLayers;
108114
}
109115

110116
doc.Ppi = resolution;
@@ -128,8 +134,16 @@ public static Document Get(Stream input)
128134
Document outputDocument = new Document(canvasw, canvash);
129135
if (layersMode == LayersMode.All)
130136
{
137+
// Dont render groups and boundaries if defined
131138
allElements = allElements.Where(p => !(p is SvgGroup)).ToList();
132-
RenderElements(setOpacityForLayer, importHiddenLayers, allElements, outputDocument);
139+
140+
// Filter out group boundaries if not set.
141+
if (!importGroupBoundariesAsLayers)
142+
{
143+
allElements = allElements.Where(p => !(p is PaintGroupBoundaries)).ToList();
144+
}
145+
146+
RenderElements(allElements, outputDocument, setOpacityForLayer, importHiddenLayers);
133147
}
134148
else if (layersMode == LayersMode.Groups)
135149
{
@@ -138,6 +152,9 @@ public static Document Get(Stream input)
138152

139153
foreach(var element in allElements)
140154
{
155+
if (element is PaintGroupBoundaries)
156+
continue;
157+
141158
if (element.ContainsAttribute(groupAttribute))
142159
{
143160
// Get only root level
@@ -175,7 +192,7 @@ public static Document Get(Stream input)
175192
}
176193
}
177194

178-
RenderElements(setOpacityForLayer, importHiddenLayers, groupsAndElementsWithoutGroup, outputDocument);
195+
RenderElements(groupsAndElementsWithoutGroup, outputDocument, setOpacityForLayer, importHiddenLayers);
179196
}
180197

181198
// Fallback. Nothing is added. Render one default layer.
@@ -221,14 +238,23 @@ private static int ConvertToPixels(SvgUnitType type, float value, float ppi)
221238
}
222239
}
223240

224-
private static void RenderElements(bool setOpacityForLayer, bool importHiddenLayers, List<SvgVisualElement> elements, Document outputDocument)
241+
private static void RenderElements( List<SvgVisualElement> elements, Document outputDocument, bool setOpacityForLayer, bool importHiddenLayers)
225242
{
226243
// I had problems to render each element directly while parent transformation can affect child.
227244
// But we can do a trick and render full document each time with only required nodes set as visible.
228245

229246
// Render all visual elements that are passed here.
230247
foreach (var element in elements)
231248
{
249+
if (element is PaintGroupBoundaries)
250+
{
251+
// Render empty boundary and continue
252+
var pdnLayer = new BitmapLayer(outputDocument.Width, outputDocument.Height);
253+
pdnLayer.Name = ((PaintGroupBoundaries)element).ID;
254+
outputDocument.Layers.Add(pdnLayer);
255+
continue;
256+
}
257+
232258
// Turn off visibility of all elements
233259
foreach (var elemntToChange in elements)
234260
{
@@ -396,15 +422,17 @@ private static string GetLayerTitle(SvgElement element)
396422
return layerName;
397423
}
398424

399-
private static IEnumerable<SvgElement> PrepareFlatElements(SvgElementCollection collection, bool grouped = false)
425+
private static IEnumerable<SvgElement> PrepareFlatElements(SvgElementCollection collection, string groupName = null)
400426
{
427+
// Prepare a collection of elements that about to be rendered.
401428
if (collection != null)
402429
{
403430
foreach (var toRender in collection)
404431
{
405-
if (!grouped && toRender is SvgGroup)
432+
// Dont prepare for a separate parsing def lists.
433+
if (toRender is SvgDefinitionList)
406434
{
407-
grouped = true;
435+
continue;
408436
}
409437

410438
// Dont prepare def lists for a separate rendering.
@@ -413,6 +441,15 @@ private static IEnumerable<SvgElement> PrepareFlatElements(SvgElementCollection
413441
continue;
414442
}
415443

444+
var isGroup = toRender is SvgGroup;
445+
if (isGroup)
446+
{
447+
groupName = GetLayerTitle((SvgGroup)toRender);
448+
449+
// Return fake node to indicate group end.
450+
yield return new PaintGroupBoundaries() { ID = string.Format(LayerGroupEnd, groupName) };
451+
}
452+
416453
var visual = toRender as SvgVisualElement;
417454

418455
if (visual != null)
@@ -427,14 +464,15 @@ private static IEnumerable<SvgElement> PrepareFlatElements(SvgElementCollection
427464
// Store opacity
428465
toRender.CustomAttributes.Add(visibilityAttribute, visual.Visible.ToString());
429466

430-
if (grouped && !toRender.ContainsAttribute(groupAttribute))
467+
// Save current group to indicate that elements inside a group.
468+
if (!string.IsNullOrEmpty(groupName) && !toRender.ContainsAttribute(groupAttribute))
431469
{
432470
// Store group info
433-
toRender.CustomAttributes.Add(groupAttribute, grouped.ToString());
471+
toRender.CustomAttributes.Add(groupAttribute, groupName);
434472
}
435473
}
436474

437-
var returned = PrepareFlatElements(toRender.Children, grouped);
475+
var returned = PrepareFlatElements(toRender.Children, groupName);
438476
if (returned != null)
439477
{
440478
foreach (var output in returned)
@@ -443,6 +481,14 @@ private static IEnumerable<SvgElement> PrepareFlatElements(SvgElementCollection
443481
}
444482
}
445483

484+
if (isGroup)
485+
{
486+
groupName = GetLayerTitle((SvgGroup)toRender);
487+
488+
// Return fake node to indicate group start.
489+
yield return new PaintGroupBoundaries() { ID = string.Format(LayerGroupBegin, groupName), IsStart = true };
490+
}
491+
446492
yield return toRender;
447493
}
448494
}
@@ -481,4 +527,21 @@ public void Dispose()
481527
#endregion
482528
}
483529
}
530+
531+
// Used to determine boundaries of a group.
532+
public class PaintGroupBoundaries : SvgVisualElement
533+
{
534+
public bool IsStart { get; set; }
535+
public override RectangleF Bounds => throw new NotImplementedException();
536+
537+
public override SvgElement DeepCopy()
538+
{
539+
throw new NotImplementedException();
540+
}
541+
542+
public override GraphicsPath Path(ISvgRenderer renderer)
543+
{
544+
throw new NotImplementedException();
545+
}
546+
}
484547
}

0 commit comments

Comments
 (0)