Basic SVG iconset generator

This script addin lets you create an SVG iconset based on the content (individual svg files) of the source folder.

It defines a new command: GenSvgIconSet that you can call from a button, or directly from the FAYT command tool.

It will display a dialog to let you fill in information about the set:

Then it will build the iconset xml by reading and parsing every .svg file in the source folder, creating an icon in the set named after the .svg filename.
Doing so, malformed xml svg will be rejected.

Then it saves the set according to the Iconset Name provided, and generates the .dis file (a zipped version of the iconset xml file).

If you encounter issues, let me know.

Here's the script:
V2.1: SvgTools.opusscriptinstall (11.9 KB)
Enhanced configuration section:

  • Main UI checkboxes and edit fields can be pre-filled with values stored in script configuration:
    • Remove Padding
    • Use sizes and small & large sizes
  • New option introduced in the config: Categories smart triggering:
    • When the tool is launched, a count of SVG files in active folder and its direct subfolders is made. If that option is enabled (yes/true), the "Enable categories" option of the main dialog is automatically ticked if files are found in subfolders (yet still remains to be unticked if necessary).

UI changes / fixes & misc.:

  • Colors to display the number of SVG files found both in active folder and direct subfolders changed to something green (was orange before) when files found, and red when no file is found.
  • If post-processing is activated, a check is made that the provided command name exists in Opus. If not, a dialog is displayed to warn the user, and generation is not launched.
  • Min version raised to 13.23.1 so that the (SVG) logo on the main dialog can be loaded.
  • Fixed: Enabling post-processing in the configuration now properly activates that feature in the main dalog.
  • Fixed: If categories were enabled but not SVG existed in the active folder, an empty category without name was created. It's not created anymore.
Previous release notes

V2.0:

  • New external post-processing feature:
    • This feature can be enabled/disabled by default in the script configuration (default = disabled)
    • The configuration allows you to define an external Opus (probably custom :)) command to be called at the end of the XML building process. Some extra options can also be configured both in the UI and the script config (to avoid having to re-enter them each time).
    • The external command must implement a FILE argument. This argument will be used to give this command the path to the XML file built so far so it can modify it according to its needs. Here's an example "plugin" script containing a couple example commands and also providing a few side functions (read/write xml file as string, read/write xml file as a XML Document).
      SvgToolsPlugin.opusscriptinstall (2.1 KB)
      See https://resource.dopus.com/t/basic-svg-iconset-generator/59623/29?u=passthepeas for a look at the example plugin script code.
    • The external command must write back to XML to the same with it was provided with, so that the rest of the process goes on and the packaging to the .dis file can be made from it.
  • When no SVG file is found: Instead of not opening, the UI now opens and displays in red the #0 count of svg files found.
  • Code cleanup and factorisation

The goal of this external post-processing is to allow anyone to try and apply its own post-processing without having to change the core of the iconset making process.
And anyone not needing this will not have to bother and will just be able to leave things as they are pre-configured.

V1.4:
New UI for introduced options

  • Ability to use some new features (coming from 13.23.7)
    • remove_padding
    • small and large sizes can also be specified (optional)
  • If no proper xml is selected when lauching the GenSvgIconSet command, the name and display name are retrieved from current folder path name.
  • The generated temporary/embedded xml in .dis file is now reformatted to be more easily read (by human)
  • Added an optional experimental feature (use at your own risk) to replace white/#ffffff/black/#000000 in fill: and stroke: attributes in the xml by currentColor.

V1.3:
Recover information from a previously built xml iconset:

  • If an XML file is selected, the command will try to parse it as if it were the temporary XML file generated (before it gets zipped to .dis), in order to retrieve previously entered Svg set information (name, display name, copyright and artist).

V1.2
Added ability to manage categories:

  • Every subfolder of the source folder will be interpreted as a category (named after the subfolder name).
  • If svg files are found at the root of source folder, they are not assigned to a category
  • Enabling this feature is done by ticking the appropriate (new) checkbox in the SVG Info dialog
    V1.1
  • Fixed issue: copyright information not properly inserted in the set
  • Added extra informations in log: progress notification every 500 icons processed, end message after creating the .dis file.
Previous releases

V2.0: SvgTools.opusscriptinstall (11.1 KB)
V1.4: SvgTools.opusscriptinstall (12.5 KB)
V1.3: SvgTools.opusscriptinstall (11.1 KB)
V1.2: SvgTools.opusscriptinstall (10.8 KB)
V1.1: SvgTools.opusscriptinstall (10.3 KB)
V1.0: SvgTools.opusscriptinstall (10.2 KB)

Script Code for reference
// SvgTools
// (c) 2026 Stephane

// This is a script for Directory Opus.
// See https://www.gpsoft.com.au/endpoints/redirect.php?page=scripts for development information.



// Called by Directory Opus to initialize the script
/** @type {OpusOnInit} */
function OnInit(initData)
{
	initData.name = "SvgTools";
	initData.version = "2.1";
	initData.copyright = "(c) 2026 Stephane";
//	initData.url = "https://resource.dopus.com/c/buttons-scripts/16";
	initData.desc = "";
	initData.default_enable = true;
	initData.min_version = "13.23.1";

	// Script configuration
	// settings & defaults
	initData.config = DOpus.Create().OrderedMap();
	initData.config_desc = DOpus.Create().OrderedMap();
	initData.config_groups = DOpus.Create().OrderedMap();
	initData.config_group_order = DOpus.NewVector('General', 'External Post-Processing');

	var option_name = "";
	var option_group = "";

	// ===
	option_group = 'General';

	option_name = "Enable 'Remove padding'";
	initData.Config[option_name] = false;
	initData.config_desc(option_name) = "Sets the default status for 'Remove Padding' option in UI.\n";
	initData.config_desc(option_name) += "The option can still be changed in the dialog.";
	initData.config_groups(option_name) = option_group;

	option_name = "Enable 'Use sizes'";
	initData.Config[option_name] = false;
	initData.config_desc(option_name) = "Sets the default status for 'Use Sizes' option in UI.\n";
	initData.config_desc(option_name) += "The option can still be changed in the dialog.";
	initData.config_groups(option_name) = option_group;

	option_name = "Default small size";
	initData.Config[option_name] = 24;
	initData.config_desc(option_name) = "Sets the default value for 'Small Icon Size' in UI.\n";
	initData.config_desc(option_name) += "The value can still be changed in the dialog.";
	initData.config_groups(option_name) = option_group;

	option_name = "Default large size";
	initData.Config[option_name] = 32;
	initData.config_desc(option_name) = "Sets the default value for 'Large Icon Size' in UI.\n";
	initData.config_desc(option_name) += "The value can still be changed in the dialog.";
	initData.config_groups(option_name) = option_group;

	option_name = "Categories smart triggering";
	initData.Config[option_name] = true;
	initData.config_desc(option_name) = "When set to true, the 'Enable Categories' will be set to true when SVG files are found in subfolders.\n";
	initData.config_desc(option_name) += "The 'Enable Categories' option can still be changed in the dialog.";
	initData.config_groups(option_name) = option_group;

	option_name = "Enable XML formatting";
	initData.Config[option_name] = false;
	initData.config_desc(option_name) = "Defines wether the temporary XML file will be formatted (pretty print) before saving.\n";
	initData.config_desc(option_name) += "This will be more himan readable but takes a little longuer to generate large sets.\n";
	initData.config_desc(option_name) += "Note: This option has no effect on the generated .dis iconset file behaviour.";
	initData.config_groups(option_name) = option_group;

	// ===
	option_group = 'External Post-Processing';

	option_name = "Enable post-processing by default";
	initData.Config[option_name] = false;
	initData.config_desc(option_name) = "Defines wether the external post processing will be enabled by default.\nIf set to true, the external command should probably be defined.";
	initData.config_groups(option_name) = option_group;

	option_name = "External Command";
	initData.Config[option_name] = '';
	initData.config_desc(option_name) = "Command that will be called for external post-processing. That command must handle a 'FILE' argument which will be set with the xml file generated by this script.";
	initData.config_groups(option_name) = option_group;

	option_name = "External Command extra arguments";
	initData.Config[option_name] = '';
	initData.config_desc(option_name) = "Extra parameters to pass when calling the 'External Command'.\nExample: ARG1 ARG2=value";
	initData.config_groups(option_name) = option_group;
}

// Called to add commands to Opus
/** @type {OpusOnAddCommands} */
function OnAddCommands(addCmdData)
{
	var cmd = addCmdData.AddCommand();
	cmd.name = "GenSvgIconSet";
	cmd.method = "OnGenSvgIconSet";
	cmd.desc = "";
	cmd.label = "GenSvgIconSet";
	cmd.template = "";
	cmd.hide = false;
	cmd.icon = "script";
}

// Implement the GenSvgIconSet command
/** @type {OpusOnScriptCommand} */
function OnGenSvgIconSet(scriptCmdData)
{
	DOpus.Output("Generating iconset from SVG files...");

	var sourcetab = scriptCmdData.func.sourcetab;
	var fsu = DOpus.FSUtil;
	var currentPath = sourcetab.path;

	// === Get SVG files and filecounts

	var findSvgInfos = FindSvgFiles(fsu, currentPath);
	var svgFiles 				= findSvgInfos.svgFiles;
	var subfoldersFiles 		= findSvgInfos.subfoldersFiles;
	var svgInSubfoldersCount	= findSvgInfos.svgInSubfoldersCount;

	DOpus.Output("#" + svgFiles.length + " SVG files found in " + currentPath);
	DOpus.Output("#" + svgInSubfoldersCount + " additional SVG files found in " + subfoldersFiles.count + " subfolders.");

	// === Initializing Dialog
	var mainDlg = DOpus.Dlg();
	mainDlg.template = "SvgInfo";
	mainDlg.window = 0; 	//scriptCmdData.func.sourcetab;
	mainDlg.detach = true;
	mainDlg.want_close = true;
	mainDlg.title = "Iconset Information";
	mainDlg.Create();

	mainDlg.Control("sLogo").label = DOpus.LoadImage(dialogSvg3);
	var countColor = svgFiles.length > 0 ? "#90f172" : "#fd1259";
	var fileWord = svgFiles.length > 1 ? "files" : "file";
	mainDlg.Control("mSvgCount").title = "<b><" + countColor + ">#" + svgFiles.length + "</#></b> SVG " + fileWord + " found";
	mainDlg.Control("eIconSetName").value = currentPath.filepart;
	mainDlg.Control("eDisplayName").value = currentPath.filepart;

	if (svgInSubfoldersCount > 0) {
		mainDlg.Control("mSvgCount").title += " in source";
		countColor = svgInSubfoldersCount > 0 ? "#90f172" : "#fd1259";
		mainDlg.Control("mSvgCount").title += "\n<b><" + countColor + ">#" + svgInSubfoldersCount + "</#></b> additional SVG files";
		var subFoldersColor = "#099ded";
		mainDlg.Control("mSvgCount").title += "\nfound in <" + subFoldersColor + ">" + subfoldersFiles.count + "</#> subfolders\n\n";

		if (Script.Config["Categories smart triggering"])
			mainDlg.control("ckCategories").value = true;
	}

	if (svgFiles.length + svgInSubfoldersCount == 0)
		mainDlg.Control("bGenerate").enabled = false;

	_UpdateUIfromConfig();

	_GetSetInfoFromSelectedXml();

	// === Showing Dialog / Entering message loop
	var result = mainDlg.Show();
	var launchGenerate =  false;

	while (true) {
		var msg = mainDlg.GetMsg();
		// DOpus.Output("event = " + msg.event + " | Control = " + msg.Control + " | result = " + msg.result);
		if (!msg.result) break;

		//
		// -- Generate
		if (msg.event == "click" && msg.Control == "bGenerate") {
			// Check post-process command exists if P-Process is requested
			launchGenerate = true;
			if (mainDlg.control("ckPostProcessing").value) {
				var extCommand = mainDlg.control("eExtCommand").value;

				if (!scriptCmdData.func.command.CommandList().exists(extCommand)) {
					// Display popup to warn user, and go back in message loop.
					launchGenerate = false;
					var message = 'The command "' + extCommand + '" could not be found.\n';
					message += 'Either provide a valid command name or disable External Post Processing.';
					MsgDialog("Unknown command", message, mainDlg);
				}
			}

			if (launchGenerate) {
				DOpus.Output("Generating iconset.");
				break;
			}
		}

		// Size Management (enable/disable size inputs)
		if (msg.event == "click" && msg.Control == "ckUseSizes") {
			mainDlg.Control("eSmall").enabled = mainDlg.Control("ckUseSizes").value;
			mainDlg.Control("eLarge").enabled = mainDlg.Control("ckUseSizes").value;
			mainDlg.Control("sSmallIconSize").enabled = mainDlg.Control("ckUseSizes").value;
			mainDlg.Control("sLargeIconSize").enabled = mainDlg.Control("ckUseSizes").value;
		}

		// Post processing
		if (msg.event == "click" && msg.control == "ckPostProcessing") {
			_UpdateUIforExternalProcessStatus(mainDlg.control('ckPostProcessing').value);
		}

		// -- Close
		if (msg.event == "close") {
			DOpus.Output("Operation cancelled by user.");
			break;
		}
	}

	if (!launchGenerate) {
		DOpus.Output("Generation cancelled by user. Exiting.");
		return;
	}

	// === Get Infos from dialog when closed.
	var uiInfos = _GetUiInfos();

	// Sanity check
	if (!uiInfos.iconsetName) {
		DOpus.Output("Error: Iconset name is required.");
		return;
	}


	// === Preparing XML file from UI configuration
	var xmlDoc = new ActiveXObject("MSXML2.DOMDocument.6.0");
	xmlDoc.async = false;

	var xmlPrologue = xmlDoc.createProcessingInstruction("xml", 'version="1.0" encoding="utf-8"');
    xmlDoc.appendChild(xmlPrologue);

	var rootNode = xmlDoc.createElement("iconset");
    rootNode.setAttribute("name", uiInfos.iconsetName);
    xmlDoc.appendChild(rootNode);

	_AddInfoToRootNode(uiInfos.displayName, "display_name");
	_AddInfoToRootNode(uiInfos.copyright, 	"copyright");
	_AddInfoToRootNode(uiInfos.artist, 		"artist");
	
    var setNode = xmlDoc.createElement("set");
    setNode.setAttribute("size", "svg");
	rootNode.appendChild(setNode);

	if (uiInfos.useSizes) {
		setNode.setAttribute("small", uiInfos.smallSize);
		rootNode.appendChild(setNode);
	    setNode.setAttribute("large", uiInfos.largeSize);
		rootNode.appendChild(setNode);
	}

	if (uiInfos.removePadding) {
        setNode.setAttribute("remove_padding", "yes");
    	rootNode.appendChild(setNode);
	}

	var activeNode = setNode;
	var totalFilesCount = svgFiles.length;

	if (uiInfos.categoryMode) {
		totalFilesCount = svgFiles.length + svgInSubfoldersCount;
		
		if (svgFiles.length > 0) {		// If there are SVG files found at the 'root'
			var categoryNode = xmlDoc.createElement("category");
			categoryNode.setAttribute("name", "");	// Inserting empty name for 'root' SVG files (no category)
			setNode.appendChild(categoryNode);
			activeNode = categoryNode;	// moving active node to the category node so 'root' icons are attached to this node
		}	
	}

	// === Inserting SVG information into 'icon' nodes in the XML.
	var genIconIndex = 0;
	for (var i = 0; i < svgFiles.length; i++) {
        var file = svgFiles[i];       
		_AttachIconToNode(activeNode, file.name_stem, file);
    }

	if (uiInfos.categoryMode) {
		for (e = new Enumerator(subfoldersFiles); !e.atEnd(); e.moveNext()) {
			var folder = e.item();
			var files = subfoldersFiles(folder);
			if (files.length == 0) continue;

			var categoryNode = xmlDoc.createElement("category");
			categoryNode.setAttribute("name", fsu.GetItem(folder).name);
			setNode.appendChild(categoryNode);
			activeNode = categoryNode;

			for (var i = 0; i < files.length; i++) {
				_AttachIconToNode(activeNode, files[i].name_stem, files[i]);
			}
		}
	}

	// === Saving final XML
    var outputXmlPath = currentPath + "\\" + sanitizeFilename(uiInfos.iconsetName) + ".xml";
	WriteXmlToFile(outputXmlPath, xmlDoc, Script.config['Enable XML formatting']);
    
    DOpus.Output("Success ! File '" + sanitizeFilename(uiInfos.iconsetName) + ".xml' generated, containing " + totalFilesCount + " SVG icons.");

	// === Calling external command (user activated) to do some extra processing before packaging the iconset file.
	if (uiInfos.postProcessing) {
		DOpus.Output("Calling external (plugin) command : " + uiInfos.externalCommand);

		var cmdToRun = uiInfos.externalCommand + ' FILE="' + outputXmlPath + '"';
		if (uiInfos.extraArgs.length> 0)
			cmdToRun += ' ' + uiInfos.extraArgs;

		var cmd = DOpus.Create.Command();
		cmd.RunCommand(cmdToRun);
		DOpus.Output("External Command has been called.");
	}

	// === Zipping the XML into a .dis archive
	DOpus.Output("Now zipping to .dis iconset file ...");
	var zipCommand = DOpus.Create.Command();
	zipCommand.SetModifier('noprogress');
	zipCommand.SetDest(currentPath);
	zipCommand.AddFile(outputXmlPath);
	zipCommand.RunCommand('Copy ARCHIVE CREATEFOLDER="' + sanitizeFilename(uiInfos.iconsetName) + '.dis"');

	DOpus.Output("End of processing.");
	// ========================================================
	// Internal functions for this function
	//
	function _AddInfoToRootNode(source, nodeName) {
		if (!source) return;
		var node = xmlDoc.createElement(nodeName);
		node.text = source;
		rootNode.appendChild(node);
	}

	function _UpdateUIfromConfig() {
		// Note : When checking (changing default value) for a checkbox here, the change event is put
		// on the message loop and will be processed when we start the loop : No need to update here
		// the "enabled" statuses that go along with the checkbox status change.

		// Main UI checkboxes and values
		mainDlg.Control("ckPadding").value = Script.config["Enable 'Remove padding'"];

		mainDlg.Control("ckUseSizes").value = Script.config["Enable 'Use sizes'"];
		mainDlg.Control("eSmall").value = Script.config["Default small size"];
		mainDlg.Control("eLarge").value = Script.config["Default large size"];		
		
		// Post-processing
		mainDlg.control("ckPostProcessing").value = Script.config["Enable post-processing by default"];
		mainDlg.control('eExtCommand').value = Script.config["External Command"];
		mainDlg.control('eExtraArgs').value = Script.config["External Command extra arguments"];
	}

	function _GetUiInfos() {
		var uiInfos = {};
		uiInfos.iconsetName = mainDlg.Control("eIconSetName").value;
		uiInfos.displayName = mainDlg.Control("eDisplayName").value;
		uiInfos.copyright = mainDlg.Control("eCopyright").value;
		uiInfos.artist = mainDlg.Control("eArtist").value;
		uiInfos.useSizes = mainDlg.Control("ckUseSizes").value;
		uiInfos.smallSize = mainDlg.Control("eSmall").value;
		uiInfos.largeSize = mainDlg.Control("eLarge").value;
		uiInfos.removePadding = mainDlg.Control("ckPadding").value;
		uiInfos.postProcessing = mainDlg.Control("ckPostProcessing").value;
		uiInfos.externalCommand = mainDlg.Control("eExtCommand").value;
		uiInfos.extraArgs = mainDlg.Control("eExtraArgs").value;
		uiInfos.categoryMode = mainDlg.Control("ckCategories").value;
		return uiInfos;
	}

	function _AttachIconToNode(node, iconName,svgFile) {
        // Temporary DOM to load current SVG
        var svgDoc = new ActiveXObject("MSXML2.DOMDocument.6.0");
        svgDoc.async = false;
        svgDoc.validateOnParse = false;
        svgDoc.load(String(svgFile.realpath));
        
        if (svgDoc.parseError.errorCode === 0) {
			genIconIndex++;
            // <icon name="..."> container creation
            var iconNode = xmlDoc.createElement("icon");
            iconNode.setAttribute("name", iconName);
            
            // Getting the root tag <svg> (ignore metadata/comments)
            var svgRoot = svgDoc.documentElement;
            
            // Import and proper cloning of the node in the final document
            var importedSvg = xmlDoc.importNode(svgRoot, true);
            iconNode.appendChild(importedSvg);
            
            // Add the icon to the set
            node.appendChild(iconNode);

			if (genIconIndex%500 == 0) {
				DOpus.Output("Processed " + genIconIndex + " / " + totalFilesCount + " SVG files... (" + Math.round((genIconIndex/totalFilesCount)*100) + "%)");
			}
        } else {
            DOpus.Output("Reading/parsing error on " + svgFile.name + ": " + svgDoc.parseError.reason);
        }
	}

	function _GetSetInfoFromSelectedXml() {
		if (scriptCmdData.func.sourcetab.selected_files.count > 0) {
			for (var i = 0; i < scriptCmdData.func.sourcetab.selected_files.count; i++) {
				var file = scriptCmdData.func.sourcetab.selected_files(i);
				if (file.ext.toLocaleLowerCase() == ".xml") {
					DOpus.Output("Selected XML file found: " + file.name);
					var xmlDoc = new ActiveXObject("MSXML2.DOMDocument.6.0");
					xmlDoc.async = false;
					xmlDoc.load(String(file.realpath));
					if (xmlDoc.parseError.errorCode === 0) {
						var iconsetNode = xmlDoc.selectSingleNode("/iconset");
						if (!iconsetNode) continue;
						DOpus.Output("Iconset node found in XML. Looks like an iconset XML. Pre-filling dialog fields with existing data.");
						mainDlg.Control("eIconSetName").value = iconsetNode.getAttribute("name") || "";
						var displayNameNode = iconsetNode.selectSingleNode("display_name");
						mainDlg.Control("eDisplayName").value = displayNameNode ? displayNameNode.text : "";
						var copyrightNode = iconsetNode.selectSingleNode("copyright");
						mainDlg.Control("eCopyright").value = copyrightNode ? copyrightNode.text : "";
						var artistNode = iconsetNode.selectSingleNode("artist");
						mainDlg.Control("eArtist").value = artistNode ? artistNode.text : "";

						var setNode = xmlDoc.selectSingleNode("/iconset/set");
						if (setNode) {
							DOpus.Output("Set node found in XML. Checking for size and padding attributes to pre-fill dialog fields.");
							var small = setNode.getAttribute("small");
							var large = setNode.getAttribute("large");
							var padding = setNode.getAttribute("remove_padding");

							if (small || large) {
								mainDlg.Control("ckUseSizes").value = true;
								mainDlg.Control("eSmall").value = small || "";
								mainDlg.Control("eLarge").value = large || "";
							}
							if (padding && padding.toLowerCase() == "yes")
								mainDlg.Control("ckPadding").value = true;
						}
					}
				}
			}
		}
	}

	function _UpdateUIforExternalProcessStatus(bExtStatus) {
		mainDlg.control('eExtCommand').enabled = bExtStatus;
		mainDlg.control('eExtraArgs').enabled = bExtStatus;
		mainDlg.control('sExtraArgs').enabled = bExtStatus;
	}

	//
	// End of Internal functions for this function
	// ========================================================

}



function FindSvgFiles(fsu, currentPath) {
	var svgFilesEnum = fsu.ReadDir(currentPath, false);
	var svgFiles = [];
	var subfoldersFiles = DOpus.Create.Map();
	while (!svgFilesEnum.complete) {
		var file = svgFilesEnum.Next();
		if (!file.is_dir && file.ext.toLocaleLowerCase() == ".svg") {
			svgFiles.push(file);
		}
		if (file.is_dir) {
			subfoldersFiles(file) = [];
		}
	}

	var svgInSubfoldersCount = 0;
	for (var e = new Enumerator(subfoldersFiles); !e.atEnd(); e.moveNext()) {
		var folder = e.item();
		DOpus.Output("Scanning subfolder: " + folder);
		DOpus.Output("Type: " + DOpus.TypeOf(folder));
		var subfolderFilesEnum = fsu.ReadDir(folder, false);
		while (!subfolderFilesEnum.complete) {
			var file = subfolderFilesEnum.Next();
			if (!file.is_dir && file.ext.toLocaleLowerCase() == ".svg") {
				subfoldersFiles(folder).push(file);
				svgInSubfoldersCount++;
			}
		}
	}
	return { "svgFiles": svgFiles, "subfoldersFiles": subfoldersFiles, "svgInSubfoldersCount": svgInSubfoldersCount };
}

function WriteXmlToFile(filePath, xmlDoc, prettyPrint) {
    prettyPrint = prettyPrint || false;

    var success = false;

    // --- First try : Pretty Print (if requested) ---
    if (prettyPrint) {
        try {
            var xmlWriter = new ActiveXObject("MSXML2.MXXMLWriter.6.0");
            xmlWriter.indent = true;
            xmlWriter.omitXMLDeclaration = false;
            xmlWriter.encoding = "UTF-8";

            var saxReader = new ActiveXObject("MSXML2.SAXXMLReader.6.0");
            saxReader.contentHandler = xmlWriter;
            saxReader.dtdHandler = xmlWriter;
            saxReader.errorHandler = xmlWriter;

            // Can throw if the XML is not well-formed
            saxReader.parse(xmlDoc);

            // Opus Writing
            var fsu = DOpus.FSUtil();
            var textFile = fsu.OpenFile(filePath, "wa", "utf8");
            if (textFile.error == 0) {
                textFile.Write(xmlWriter.output);
                textFile.Close();
                success = true;
            } else {
                DOpus.Output("Error on DOpus OpenFile : " + textFile.error, true);
            }
        } 
        catch (e) {
            DOpus.Output("Failed to format XML : " + e.description, true);
        }
    }

    // --- Attempt #2 : Fallback or standard Raw save ---
    if (!success) {
        if (prettyPrint) {
            DOpus.Output("Trying to save XML in raw format as fallback...", false);
        } else {
            DOpus.Output("Saving XML in raw format...", false);
        }

        try {
            xmlDoc.save(filePath);
            DOpus.Output("Raw save successful.", false);
        } 
        catch (e) {
            DOpus.Output("Critical failure : Unable to save the file. " + e.description, true);
        }
    }
}
///////////////////////////////////////////////////////////////////////////
function sanitizeFilename(input, replacement) {
	// inspired from node sanitize filename : https://github.com/parshap/node-sanitize-filename/blob/master/index.js
	if (typeof input !== 'string') {
		throw new Error('Input must be string');
	}
	if (replacement == undefined)	replacement = "";

	var illegalRe = new RegExp('[\/\?<>\\:\*\|"]', "g");
	var controlRe = /[\x00-\x1f\x80-\x9f]/g;
	var reservedRe = /^\.+$/;
	var windowsTrailingRe = /[\. ]+$/;

	var sanitized = input
		.replace(illegalRe, replacement)
		.replace(controlRe, replacement)
		.replace(reservedRe, replacement)
		.replace(windowsTrailingRe, replacement);
	return sanitized;
}

function MsgDialog(title, message, window) {
	var dlg = DOpus.Dlg;
	dlg.window = window;
	dlg.title = title;
	dlg.message = message;
	dlg.buttons = "OK";

	dlg.Show();
}


///////////////////////////////////////////////////////////////////////////
// SVG ASSETS
///////////////////////////////////////////////////////////////////////////
var dialogSvg3 = '<svg width="800px" height="800px" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"';
dialogSvg3 += '    xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img"';
dialogSvg3 += '    class="iconify iconify--noto" preserveAspectRatio="xMidYMid meet">';
dialogSvg3 += '    <path fill="#ffffff" d="M-183.97 248.8h302.33v169.12h-302.33z">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M62.54 4.84L10.38 31.73c-1.14.67-1.47 1.67-1.46 3.12l.1 1.81L64.09 64.9l54.94-27.79s.06-.28.06-1.26c0 0-.05-1.29-.34-1.89c-.32-.68-1-1.29-1.44-1.66c-1.17-.97-2.34-1.83-4.33-2.95C84.45 13.22 65.69 4.91 65.69 4.91c-1.21-.45-2.21-.61-3.15-.07z"';
dialogSvg3 += '        fill="#dea66c">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M9.74 96.16c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c1.11.46 1.77.68 2.54.72c.57.03 1.51-.35 1.51-.35s-1.53-55.19-1.62-58.34c-.09-3.08-1.38-4.1-2.52-4.84c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.07-.51-2.33.13-2.33 1.33v59.8c0 .57.35 1.05.83 1.36z"';
dialogSvg3 += '        fill="#b38251">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M117.58 96.51L65.82 123.2c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.17-1.76-.34-2.24c-.47-1.4.55-1.96 1.01-2.19l51.34-26.44c1.36-.7 2.99.29 2.99 1.82v58.19c0 1.03-.58 1.98-1.51 2.46z"';
dialogSvg3 += '        fill="#966239">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M94.46 47.59S66.09 62.1 65.63 63.33c-.46 1.22 22.26-9.7 24.92-11.07c3.01-1.55 26.65-14.19 26.65-15.58c.01-1.14-22.74 10.91-22.74 10.91z"';
dialogSvg3 += '        opacity=".5" fill="#212121">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <g opacity=".5">';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M12.81 92.85c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M20.58 93.66c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.02 3.1-.03 4.64-.04 7.74z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M14.12 90.34c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.34-1.21c-.01 3.1-.02 4.65-.03 7.74z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M18.95 85.99c2.37 1.21 3.63 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.17.76-1.78 1.13-2.97 1.87z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M12.81 82.84c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.6 1.2-2.49 2.1z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g opacity=".5">';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M31.81 101.4c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.03 3.66.04 5.49.07 9.15z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M28.76 100.75c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.32-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.12-.57-1.95-.16-1.95.87z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M34.55 90.36l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32c-3.52-1.83-5.85-5.92-5.85-9.51c2.62 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M100.74 41.49c-.5-.37-54.19-28.42-54.19-28.42l-16.66 8.61l55.05 28.39l.03.03l16.11-8.25s-.03-.08-.12-.18c-.07-.06-.19-.15-.22-.18z"';
dialogSvg3 += '        fill="#ffe0b2">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M101 41.73c-9.12 4.49-16.06 8.34-16.06 8.34c.23.23.24.53.24.68c-.03 1.16-.05 2.08-.08 3.23c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.19-18.15-.26-21.2c-.02-1.08-.25-1.19-.25-1.19z"';
dialogSvg3 += '        fill="#bf9f85">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M-98.73 4.84l-51.83 26.68c-2.52 1.48-1.8 5.09-1.8 5.09l55.17 28.3l55.07-27.86c.05-.17.11-1.21-.15-3.19c-.14-1.04-3.25-2.94-6.03-4.51C-76.82 13.22-95.58 4.91-95.58 4.91c-1.21-.45-2.2-.61-3.15-.07z"';
dialogSvg3 += '        fill="#dea66c">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M-151.53 96.16c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c2.45 1.01 3.75.51 3.75.51s-1.15-56.3-1.11-59.45c.02-1.32-1.59-3.12-2.74-3.86c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.06-.52-2.33.12-2.32 1.31v59.8c0 .58.36 1.06.83 1.37z"';
dialogSvg3 += '        fill="#bf8049">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M-43.69 96.51l-51.76 26.69c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.41-1.98-.56-2.48c-.14-.5.35-1.51.81-1.74l51.76-26.66c1.36-.7 2.99.29 2.99 1.82v58.19c0 1.04-.58 1.99-1.51 2.47z"';
dialogSvg3 += '        fill="#9e673c">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M-70.71 52.26c3.01-1.55 26.65-14.19 26.65-15.58c0-1.14-22.75 10.91-22.75 10.91S-95.18 62.1-95.64 63.33c-.45 1.22 22.26-9.7 24.93-11.07z"';
dialogSvg3 += '        fill="#212121" opacity=".5">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <g opacity=".5">';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-148.46 92.85c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-140.69 93.66c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.01 3.1-.02 4.64-.04 7.74z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-147.15 90.34c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.34-1.21c-.01 3.1-.02 4.65-.03 7.74z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-142.32 85.99c2.37 1.21 3.63 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.17.76-1.78 1.13-2.97 1.87z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-148.46 82.84c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.6 1.2-2.49 2.1z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g opacity=".5">';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-129.46 101.4c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.03 3.66.04 5.49.07 9.15z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-132.51 100.75c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.32-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.12-.57-1.94-.16-1.95.87z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-126.72 90.36l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32c-3.52-1.83-5.85-5.92-5.85-9.51c2.63 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '            fill="#212121">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M-61.86 42.33c-.5-.37-54.32-28.49-54.32-28.49l-16.68 8.6l55.11 28.37c4.76-2.45 12.32-6.35 16.12-8.3a1.15 1.15 0 0 0-.23-.18z"';
dialogSvg3 += '        fill="#ffe0b2">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M-61.63 42.5c-8.34 3.77-16.5 8.11-16.5 8.11c.21.09.73.74.73.74c-.03 1.16-.05 2.31-.08 3.47c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.21-18.15-.26-21.2c-.02-.87-.3-1.26-.3-1.26z"';
dialogSvg3 += '        fill="#bf9f85">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M223.81 4.84l-51.83 26.68c-2.52 1.48-1.8 5.09-1.8 5.09l55.17 28.3l55.07-27.86c.05-.17.11-1.21-.15-3.19c-.14-1.04-3.25-2.94-6.03-4.51c-28.53-16.12-47.29-24.42-47.29-24.42c-1.2-.47-2.2-.63-3.14-.09z"';
dialogSvg3 += '            fill="#dea66c">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M171.01 96.16c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c2.45 1.01 3.75.51 3.75.51s-1.15-56.3-1.11-59.45c.02-1.32-1.59-3.12-2.74-3.86c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.06-.52-2.33.12-2.32 1.31v59.8c0 .58.35 1.06.83 1.37z"';
dialogSvg3 += '            fill="#bf8049">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M278.85 96.51l-51.76 26.69c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.41-1.98-.56-2.48c-.14-.5.35-1.51.81-1.74l51.76-26.66c1.36-.7 2.99.29 2.99 1.82v58.19c0 1.04-.59 1.99-1.51 2.47z"';
dialogSvg3 += '            fill="#9e673c">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M251.82 52.26c3.01-1.55 26.65-14.19 26.65-15.58c0-1.14-22.75 10.91-22.75 10.91S227.36 62.1 226.9 63.33c-.46 1.22 22.26-9.7 24.92-11.07z"';
dialogSvg3 += '            fill="#784d30">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <g opacity=".85">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M173.36 93.22c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M181.13 94.02c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.02 3.1-.03 4.65-.04 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M174.67 90.71c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.34-1.21c-.01 3.09-.02 4.64-.03 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M179.5 86.36c2.37 1.21 3.63 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.17.76-1.78 1.13-2.97 1.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M173.36 83.2c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.6 1.2-2.49 2.1z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <g opacity=".85">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M192.35 101.77c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.04 3.66.05 5.49.07 9.15z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M189.31 101.12c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.32-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.12-.57-1.95-.16-1.95.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M195.1 90.73l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32c-3.52-1.83-5.85-5.92-5.85-9.51c2.62 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M260.68 42.33c-.5-.37-54.32-28.49-54.32-28.49l-16.68 8.6l55.11 28.37c4.76-2.45 12.32-6.35 16.12-8.3c-.07-.06-.14-.12-.23-.18z"';
dialogSvg3 += '            fill="#ffe0b2">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M260.91 42.5c-8.34 3.77-16.5 8.11-16.5 8.11c.21.09.73.74.73.74c-.03 1.16-.05 2.31-.08 3.47c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.21-18.15-.26-21.2c-.02-.87-.3-1.26-.3-1.26z"';
dialogSvg3 += '            fill="#bf9f85">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M566.51 4.84l-51.83 26.68c-2.52 1.48-1.8 5.09-1.8 5.09l55.17 28.3l55.07-27.86c.05-.17.11-1.21-.15-3.19c-.14-1.04-3.25-2.94-6.03-4.51c-28.53-16.12-47.29-24.42-47.29-24.42c-1.2-.47-2.2-.63-3.14-.09z"';
dialogSvg3 += '            fill="#dea66c">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M513.71 96.16c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c2.45 1.01 3.75.51 3.75.51s-1.15-56.3-1.11-59.45c.02-1.32-1.59-3.12-2.74-3.86c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.06-.52-2.33.12-2.32 1.31v59.8c0 .58.35 1.06.83 1.37z"';
dialogSvg3 += '            fill="#bf8049">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M621.55 96.51l-51.76 26.69c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.41-1.98-.56-2.48c-.14-.5.35-1.51.81-1.74l51.76-26.66c1.36-.7 2.99.29 2.99 1.82v58.19a2.815 2.815 0 0 1-1.51 2.47z"';
dialogSvg3 += '            fill="#9e673c">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M594.52 52.26c3.01-1.55 26.65-14.19 26.65-15.58c0-1.14-22.75 10.91-22.75 10.91S570.06 62.1 569.6 63.33c-.46 1.22 22.26-9.7 24.92-11.07z"';
dialogSvg3 += '            fill="#784d30">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <g opacity=".85">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M516.06 93.22c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M523.82 94.02c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.01 3.1-.02 4.65-.04 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M517.37 90.71c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.34-1.21c-.01 3.09-.02 4.64-.03 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M522.2 86.36c2.37 1.21 3.64 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.17.76-1.78 1.13-2.97 1.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M516.06 83.2c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.61 1.2-2.49 2.1z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <g opacity=".85">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M535.05 101.77c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.04 3.66.05 5.49.07 9.15z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M532.01 101.12c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.32-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.13-.57-1.95-.16-1.95.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M537.8 90.73l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32s-5.85-5.92-5.85-9.51c2.62 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M603.38 42.33c-.5-.37-54.32-28.49-54.32-28.49l-16.68 8.6l55.11 28.37c4.76-2.45 12.32-6.35 16.12-8.3c-.07-.06-.14-.12-.23-.18z"';
dialogSvg3 += '            fill="#fce8b2">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M603.61 42.5c-8.34 3.77-16.5 8.11-16.5 8.11c.21.09.72.74.72.74c-.03 1.16-.05 2.31-.08 3.47c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.21-18.15-.26-21.2c-.01-.87-.29-1.26-.29-1.26z"';
dialogSvg3 += '            fill="#ecb354">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M62.54 216.07l-51.83 26.68c-2.52 1.48-1.8 5.09-1.8 5.09l55.17 28.3l55.07-27.86c.05-.17.11-1.21-.15-3.19c-.14-1.04-3.25-2.94-6.03-4.51c-28.53-16.12-47.29-24.42-47.29-24.42c-1.2-.47-2.2-.63-3.14-.09z"';
dialogSvg3 += '            fill="#dea66c">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M9.74 307.39c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c2.45 1.01 3.75.51 3.75.51s-1.15-56.3-1.11-59.45c.02-1.32-1.59-3.12-2.74-3.86c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.06-.52-2.33.12-2.32 1.31v59.8c0 .59.35 1.06.83 1.37z"';
dialogSvg3 += '            fill="#bd8955">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M117.58 307.74l-51.76 26.69c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.41-1.98-.56-2.48c-.14-.5.35-1.51.81-1.74l51.76-26.66c1.36-.7 2.99.29 2.99 1.82v58.19c0 1.04-.58 1.99-1.51 2.47z"';
dialogSvg3 += '            fill="#a06841">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M90.55 263.49c3.01-1.55 26.65-14.19 26.65-15.58c0-1.14-22.75 10.91-22.75 10.91s-28.37 14.51-28.83 15.74c-.44 1.22 22.27-9.7 24.93-11.07z"';
dialogSvg3 += '            fill="#784d30">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <g opacity=".73">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M12.09 304.45c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M19.86 305.25c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.02 3.1-.03 4.65-.04 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M13.4 301.94c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.34-1.21c-.01 3.09-.02 4.64-.03 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M18.23 297.59c2.37 1.21 3.63 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.17.76-1.78 1.13-2.97 1.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M12.09 294.43c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.6 1.2-2.49 2.1z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <g opacity=".73">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M31.09 313c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.03 3.66.04 5.49.07 9.15z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M28.04 312.35c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.33-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.12-.57-1.95-.16-1.95.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M33.83 301.96l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32c-3.52-1.83-5.85-5.92-5.85-9.51c2.62 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M99.41 253.56c-.5-.37-54.32-28.49-54.32-28.49l-16.68 8.6l55.11 28.37c4.76-2.45 12.32-6.35 16.12-8.3c-.06-.06-.14-.12-.23-.18z"';
dialogSvg3 += '            fill="#fce8b2">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M99.64 253.73c-8.34 3.77-16.5 8.11-16.5 8.11c.21.09.73.74.73.74c-.03 1.16-.05 2.31-.08 3.47c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.21-18.15-.26-21.2c-.02-.87-.3-1.26-.3-1.26z"';
dialogSvg3 += '            fill="#ecb354">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M401.82 4.84l-51.83 26.68c-2.52 1.48-1.8 5.09-1.8 5.09l55.17 28.3l55.07-27.86c.05-.17.11-1.21-.15-3.19c-.14-1.04-3.25-2.94-6.03-4.51c-28.53-16.12-47.29-24.42-47.29-24.42c-1.2-.47-2.2-.63-3.14-.09z"';
dialogSvg3 += '            fill="#e6a467">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M349.02 96.16c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c2.45 1.01 3.75.51 3.75.51s-1.15-56.3-1.11-59.45c.02-1.32-1.59-3.12-2.74-3.86c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.06-.52-2.33.12-2.32 1.31v59.8c0 .58.35 1.06.83 1.37z"';
dialogSvg3 += '            fill="#d68b52">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M456.86 96.51L405.1 123.2c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.41-1.98-.56-2.48c-.14-.5.35-1.51.81-1.74l51.76-26.66c1.36-.7 2.99.29 2.99 1.82v58.19a2.815 2.815 0 0 1-1.51 2.47z"';
dialogSvg3 += '            fill="#a06841">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M429.83 52.26c3.01-1.55 26.65-14.19 26.65-15.58c0-1.14-22.75 10.91-22.75 10.91S405.36 62.1 404.9 63.33c-.45 1.22 22.27-9.7 24.93-11.07z"';
dialogSvg3 += '            fill="#784d30">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <g opacity=".73">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M351.37 93.22c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M359.13 94.02c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.01 3.1-.02 4.65-.04 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M352.68 90.71c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.35-1.21c0 3.09-.01 4.64-.02 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M357.51 86.36c2.37 1.21 3.64 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.17.76-1.78 1.13-2.97 1.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M351.37 83.2c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.61 1.2-2.49 2.1z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <g opacity=".73">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M370.36 101.77c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.04 3.66.05 5.49.07 9.15z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M367.32 101.12c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.32-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.13-.57-1.95-.16-1.95.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M373.11 90.73l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32c-3.52-1.83-5.85-5.92-5.85-9.51c2.62 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M438.69 42.33c-.5-.37-54.32-28.49-54.32-28.49l-16.68 8.6l55.11 28.37c4.76-2.45 12.32-6.35 16.12-8.3c-.07-.06-.14-.12-.23-.18z"';
dialogSvg3 += '            fill="#fce8b2">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M438.92 42.5c-8.34 3.77-16.5 8.11-16.5 8.11c.21.09.73.74.73.74c-.03 1.16-.05 2.31-.08 3.47c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.21-18.15-.26-21.2c-.02-.87-.3-1.26-.3-1.26z"';
dialogSvg3 += '            fill="#ecb354">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-240.63 4.84l-51.83 26.68c-2.52 1.48-1.8 5.09-1.8 5.09l55.17 28.3l55.07-27.86c.05-.17.11-1.21-.15-3.19c-.14-1.04-3.25-2.94-6.03-4.51c-28.53-16.12-47.29-24.42-47.29-24.42c-1.2-.47-2.2-.63-3.14-.09z"';
dialogSvg3 += '            fill="#e6a475">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-293.43 96.16c3.04 2.01 8.59 4.65 14.2 7.69c13.04 7.06 29.52 15.64 37.72 19.01c2.45 1.01 3.75.51 3.75.51s-1.15-56.3-1.11-59.45c.02-1.32-1.59-3.12-2.74-3.86c-1.78-1.14-5.64-2.92-5.64-2.92s-13.52-6.72-27.02-13.8c-6.42-3.37-11.84-6.82-17.67-9.66c-1.06-.52-2.33.12-2.32 1.31v59.8c0 .58.35 1.06.83 1.37z"';
dialogSvg3 += '            fill="#c78c61">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-185.59 96.51l-51.76 26.69c-.83.43-1.82-.17-1.82-1.11l.09-57.18c0-.55-.41-1.98-.56-2.48c-.14-.5.35-1.51.81-1.74l51.76-26.66c1.36-.7 2.99.29 2.99 1.82v58.19a2.815 2.815 0 0 1-1.51 2.47z"';
dialogSvg3 += '            fill="#a06841">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-212.62 52.26c3.01-1.55 26.65-14.19 26.65-15.58c0-1.14-22.75 10.91-22.75 10.91s-28.37 14.51-28.83 15.74c-.45 1.22 22.26-9.7 24.93-11.07z"';
dialogSvg3 += '            fill="#784d30">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <g opacity=".73">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-291.08 93.22c3.69 1.86 7.35 3.78 11.91 6.11v-1.78c-4.54-2.32-8.21-4.23-11.91-6.11v1.78z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-283.32 94.02c1.04.53 1.56.8 2.54 1.3c.01-3.1.01-4.65.02-7.75c-.98-.5-1.49-.76-2.52-1.29c-.01 3.1-.02 4.65-.04 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-289.77 90.71c.86.44 1.34.69 2.32 1.19l.05-7.72c-.99-.51-1.47-.75-2.34-1.21c-.01 3.09-.02 4.64-.03 7.74z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-284.95 86.36c2.37 1.21 3.63 1.86 5.72 2.92c-1.04-1.89-1.61-2.85-2.75-4.79c-1.16.76-1.77 1.13-2.97 1.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-291.08 83.2c1.77.92 2.96 1.53 5.3 2.73c-1.16-1.95-1.74-2.92-2.81-4.83c-1.09.79-1.61 1.2-2.49 2.1z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <g opacity=".73">';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-272.09 101.77c.83.43 1.26.66 2.09 1.09c-.06-3.68-.09-5.52-.16-9.2c-.8-.42-1.2-.63-2-1.04c.04 3.66.05 5.49.07 9.15z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-275.13 101.12c3.04 1.6 5.4 2.8 8.32 4.36c-.02-1.05-.83-2.32-1.93-2.91c-1.72-.91-2.7-1.41-4.44-2.32c-1.13-.57-1.95-.16-1.95.87z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '            <path';
dialogSvg3 += '                d="M-269.34 90.73l1.28 2.71c-.4.85-.61 1.28-1.03 2.12c.36-.03.54-.04.9-.07c.48-.64.72-.96 1.18-1.6c-.42-.99-.64-1.49-1.08-2.48c1.22.67 1.82 1.01 2.93 1.66c0 3.58-2.34 5.16-5.86 3.32s-5.85-5.92-5.85-9.51c2.62 1.31 4.38 2.17 7.53 3.85z"';
dialogSvg3 += '                fill="#784d30">';
dialogSvg3 += '            </path>';
dialogSvg3 += '        </g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-203.76 42.33c-.5-.37-54.32-28.49-54.32-28.49l-16.68 8.6l55.11 28.37c4.76-2.45 12.32-6.35 16.12-8.3c-.07-.06-.14-.12-.23-.18z"';
dialogSvg3 += '            fill="#fce8b2">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M-203.54 42.5c-8.34 3.77-16.5 8.11-16.5 8.11c.21.09.73.74.73.74c-.03 1.16-.05 2.31-.08 3.47c-.14 5.95-.22 11.91-.42 17.86c.67-.4 1.48.48 2.09 0c.94-.74 2.94-4 3.24-4.1c.4-.13.83-.03 1.24-.05c1.8-.1 5.83-3.77 6.69-3.94c.83-.16 3.57.37 3.57.37s-.21-18.15-.26-21.2c-.01-.87-.3-1.26-.3-1.26z"';
dialogSvg3 += '            fill="#ecb354">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M90.29-146.79l-10.47 5.4l-21.48 11.07c-3.76 1.94-7.53 3.87-11.29 5.81c-2.52 1.3-7.89 2.93-8.71 6.08c-.18.71-.11 1.45-.03 2.18c.36 3.32.27 6.27 2.43 8.9c2.04 2.48 5.47 5.8 9.01 5.8c8.11 2.65 15.85 6.28 23.82 9.3c7.12 2.7 16.09 6.9 23.36 2.82c.88-.49 1.6-1.16 2.49-1.6c1.19-.59 2.43-1.05 3.61-1.68c3.35-1.77 6.3-4.2 9.47-6.26c5.34-3.48 11.24-5.92 16.99-8.61c2.89-1.35 5.76-2.77 8.49-4.42a47.9 47.9 0 0 0 3.96-2.65c.98-.73 2.71-1.74 3.05-3.01c.05-.17.07-.34.07-.52c-.01-.7-.41-1.34-.94-1.79c-1.76-1.5-4.26-2.28-6.33-3.19c-2.7-1.18-5.24-2.87-7.81-4.32c-5.42-3.06-10.88-6.04-16.38-8.93a675.49 675.49 0 0 0-12.28-6.3c-2.11-1.05-4.22-2.09-6.34-3.13c-1.36-.66-3.13-1.75-4.69-.95z"';
dialogSvg3 += '        fill="#e6a475">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M38.78-57.74c.77.88 1.81 1.52 2.83 2.1c5.09 2.89 10.31 5.52 15.53 8.2c2.61 1.35 5.23 2.69 7.84 4.04c2.57 1.33 5.15 2.65 7.72 3.98l6.93 3.57c1.82.94 3.64 1.88 5.46 2.81c1.1.57 2.2 1.14 3.31 1.7c1.41.73 2.39 1.44 4.02.85c1.36-.49 1.44-2.15 1.75-3.43c.86-3.51 1.22-7.13 1.37-10.74c.21-4.78.05-9.58-.1-14.36c-.18-5.74.18-11.49-.06-17.26c-.07-1.58-.11-3.17-.16-4.74c-.04-1.39-.89-2.66-1.7-3.74c-.99-1.31-2.11-2.69-2.18-4.33c-.13-2.69-2.81-3.47-4.83-4.36c-3.05-1.35-5.99-3.01-8.96-4.53a1074.144 1074.144 0 0 1-31.34-16.7c-1.25-.69-8.13-6.01-8.16-2.05c-.16 17.81-.33 35.61-.62 53.42c-.03 1.6-.03 3.29.75 4.68c.17.35.37.63.6.89z"';
dialogSvg3 += '        fill="#a06841">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M144.15-57.63c-1.05 1.05-2.57 1.8-4.5 2.79c-4.13 2.12-8.27 4.25-12.4 6.37c-8.41 4.32-16.81 8.64-25.22 12.95c-1.83.94-8.1 5.04-10.16 4.15c-1.58-.68-.62-8.5-.62-10.22v-22.09v-11.41c0-4.14.39-8.53-.27-12.61c-.2-1.24-.42-2.39.33-3.49c1.2-1.74 4.09-2.67 5.93-3.62c2.23-1.15 4.46-2.3 6.7-3.45c5.66-2.92 11.31-5.83 16.97-8.75l13.5-6.96c2.41-1.24 5.07-3.18 7.66-3.95c2.3-.68 2.74 1.36 2.88 3.28c.4 5.75.33 11.58.46 17.34c.26 11.46.42 22.91.5 34.37c.02 2.61-.58 4.13-1.76 5.3z"';
dialogSvg3 += '        fill="#c78c61">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M117.23-100.16c2.95-1.52 26.07-13.88 26.08-15.24c0-1.12-22.26 10.67-22.26 10.67s-27.76 14.2-28.2 15.4c-.45 1.2 21.77-9.48 24.38-10.83z"';
dialogSvg3 += '            fill="#a06841">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <linearGradient id="IconifyId17ecdb2904d178eab14737" gradientUnits="userSpaceOnUse" x1="28.2"';
dialogSvg3 += '        y1="-108.368" x2="14.107" y2="-79.066" gradientTransform="matrix(-1 0 0 1 124.88 0)">';
dialogSvg3 += '        <stop offset=".31" stop-color="#fce8b2">';
dialogSvg3 += '        </stop>';
dialogSvg3 += '        <stop offset=".399" stop-color="#ffcc80">';
dialogSvg3 += '        </stop>';
dialogSvg3 += '    </linearGradient>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M110.19-80.18c.2-5.82.28-11.65.41-17.47c.03-1.13.05-2.26.08-3.39c0 0-.01-.38-.21-.47l-54.04-27.82l16.32-8.41s52.65 27.51 53.14 27.87c.49.36.49.36.51 1.41c.04 2.98.09 5.96.13 8.94l.09 6.16c.01.88.48 3.14.03 3.94c-.44.78-2.68 1.18-3.49 1.34c-.84.16-1.73.23-2.48.66c-1.54.87-2.31 3.09-4.07 3.2c-.41.02-.83-.08-1.22.05c-.29.1-.52.31-.74.52c-.85.81-1.67 1.73-2.59 2.46c-.59.45-1.21.61-1.87 1.01z"';
dialogSvg3 += '        fill="url(#IconifyId17ecdb2904d178eab14737)">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <path';
dialogSvg3 += '        d="M127.72-48.65c0-2.64-.18-8.15-.18-8.15s-2.07 1.76-3.37 2.25c-1.02.38-2.13.58-3.02 1.21c-.92.66-1.52 1.71-2.46 2.35c-2.32 1.59-5.48.96-5.48.96v8.86l14.51-7.48z"';
dialogSvg3 += '        fill="#ffcc80">';
dialogSvg3 += '    </path>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M40.47-60.08c3.61 1.82 7.19 3.7 11.66 5.98v-1.74c-4.44-2.27-8.03-4.14-11.66-5.98v1.74z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M48.07-59.3c1.01.52 1.52.78 2.49 1.28c.01-3.03.01-4.55.02-7.58c-.95-.49-1.46-.74-2.47-1.26c-.02 3.02-.03 4.54-.04 7.56z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M41.75-62.54c.85.43 1.31.67 2.27 1.16l.05-7.56c-.97-.5-1.43-.74-2.29-1.18c-.01 3.04-.02 4.55-.03 7.58z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M46.47-66.8c2.31 1.19 3.56 1.82 5.59 2.86c-1.02-1.84-1.57-2.79-2.7-4.69c-1.12.75-1.72 1.11-2.89 1.83z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M40.47-69.88c1.73.9 2.89 1.49 5.19 2.67c-1.14-1.91-1.7-2.86-2.75-4.72c-1.07.77-1.57 1.17-2.44 2.05z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '    <g>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M59.01-52.15c.82.42 1.23.64 2.05 1.07l-.15-9c-.78-.41-1.18-.62-1.95-1.02c.01 3.58.02 5.37.05 8.95z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M56.03-52.78c2.97 1.57 5.29 2.74 8.14 4.27c-.02-1.03-.81-2.27-1.89-2.84c-1.68-.89-2.64-1.38-4.35-2.27c-1.09-.58-1.9-.17-1.9.84z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '        <path';
dialogSvg3 += '            d="M61.69-62.95c.5 1.06.76 1.59 1.25 2.65c-.4.83-.6 1.25-1.01 2.08c.36-.03.53-.04.88-.07c.47-.63.7-.94 1.15-1.57c-.41-.97-.63-1.45-1.05-2.43c1.2.65 1.78.99 2.87 1.63c0 3.51-2.29 5.04-5.73 3.25c-3.44-1.79-5.72-5.8-5.72-9.3c2.56 1.28 4.28 2.11 7.36 3.76z"';
dialogSvg3 += '            fill="#7d5133">';
dialogSvg3 += '        </path>';
dialogSvg3 += '    </g>';
dialogSvg3 += '</svg>';




==SCRIPT RESOURCES
<resources>
	<resource name="SvgInfo" type="dialog">
		<dialog height="212" lang="francais" width="324">
			<control halign="left" height="44" image="yes" name="sLogo" type="static" valign="top" width="60" x="236" y="4" />
			<control halign="left" height="8" name="static2" title="Iconset Name:" type="static" valign="top" width="48" x="8" y="10" />
			<control halign="left" height="8" name="static3" title="Display Name:" type="static" valign="top" width="48" x="8" y="28" />
			<control halign="left" height="8" name="static4" title="Copyright:" type="static" valign="top" width="48" x="8" y="46" />
			<control halign="left" height="8" name="static5" title="Artist:" type="static" valign="top" width="48" x="8" y="64" />
			<control halign="left" height="12" name="eIconSetName" type="edit" width="152" x="60" y="8" />
			<control halign="left" height="12" name="eDisplayName" type="edit" width="152" x="60" y="26" />
			<control halign="left" height="12" name="eCopyright" type="edit" width="152" x="60" y="44" />
			<control halign="left" height="12" name="eArtist" type="edit" width="152" x="60" y="62" />
			<control halign="center" height="26" name="mSvgCount" type="markuptext" width="100" x="216" y="50" />
			<control height="28" name="group1" title="Input Folder Management" type="group" width="316" x="4" y="78" />
			<control height="10" name="ckCategories" title="Enable Categories (each subfolder is a category)" type="check" width="172" x="12" y="90" />
			<control height="36" name="group2" title="Output XML Management" type="group" width="316" x="4" y="108" />
			<control height="10" name="ckPadding" title="Remove Padding" type="check" width="64" x="12" y="118" />
			<control height="10" name="ckUseSizes" title="Use Sizes" type="check" width="64" x="12" y="130" />
			<control enable="no" halign="center" height="12" name="eSmall" number="yes" title="24" type="edit" width="23" x="185" y="128" />
			<control enable="no" halign="left" height="8" name="sSmallIconSize" title="Small Icon Size:" type="static" valign="top" width="51" x="132" y="130" />
			<control enable="no" halign="left" height="8" name="sLargeIconSize" title="Large Icon Size:" type="static" valign="top" width="53" x="219" y="130" />
			<control enable="no" halign="center" height="12" name="eLarge" number="yes" title="32" type="edit" width="23" x="274" y="128" />
			<control height="10" name="ckPostProcessing" title="Enable post-processing with external command:" type="check" width="164" x="12" y="156" />
			<control height="44" name="group3" title="Post-processing" type="group" width="316" x="4" y="146" />
			<control enable="no" halign="left" height="12" name="eExtCommand" type="edit" width="132" x="180" y="155" />
			<control enable="no" halign="left" height="8" name="sExtraArgs" title="Extra Arguments:" type="static" valign="top" width="60" x="12" y="174" />
			<control enable="no" halign="left" height="12" name="eExtraArgs" type="edit" width="236" x="76" y="172" />
			<control default="yes" height="14" name="bGenerate" title="Generate !" type="button" width="50" x="107" y="194" />
			<control close="0" height="14" name="bCancel" title="Cancel" type="button" width="50" x="167" y="194" />
		</dialog>
	</resource>
</resources>

15 Likes

So you create static icons from svg files? This is indeed useful for the purpose of creating icon sets.

By contrast, I immediately started using svg icons when DOpus started supporting them directly in buttons and scripts a few days/weeks ago, because of their flexibility. Because you now have a single icon and give it different colors, like this:

var c_blue ='<svg width="32" height="32" fill="#0090ff" viewBox="0 0 256 256">';
var c_red  ='<svg width="32" height="32" fill="#ff0000" viewBox="0 0 256 256">';
var svgsaveicon = '<path d="M222.14,69.17,186.83,33.86A19.86,19.86,0,0,0,172.69,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V83.31A19.86,19.86,0,0,0,222.14,69.17ZM164,204H92V160h72Zm40,0H188V156a20,20,0,0,0-20-20H88a20,20,0,0,0-20,20v48H52V52H171l33,33ZM164,84a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h56A12,12,0,0,1,164,84Z"></path></svg>';//"floppy-disk" icon
buttonObj.image=DOpus.LoadImage(c_blue + svg_saveicon);
FlashColor(buttonObj, svgsaveicon, c_red, c_blue);
function FlashColor(buttonObject, svgicon, flashcolor, originalcolor) {
	buttonObj.image=DOpus.LoadImage(flashcolor + svgicon); DOpus.Delay(500);
	buttonObj.image=DOpus.LoadImage(originalcolor + svgicon);
}

But if you are creating static icons that sounds a bit topsy-turvy to me. Or is it not really like the static image you were showing in the icons sets you uploaded on the other page?

Icon sets have been present in Opus for a long time (I think I've always seen them, even though I was not here from the begining).
They are handy has they do not require reading each icon from one file, but they are probably loaded in memory as a set as soon as one of the icons from the set is used somewhere in a toolbar.
That means better performance.
It also allows for icon association with a button through the UI with name search.
SVG introduction is leading to the ability to build icon sets with icons in SVG format, not having to bother with size (which was one of the "pain points" of the older sets: each set has a defined size).

Of course, the introduction of SVG icons also opens up a new set of possibilities, and what you're doing here is one of them (even though you could do the same thing with loading alternatively two png files).
As a side note, in your code, I think you could avoid writing/loading to/from a file. The DOpus.LoadImage accepts an SVG string to be passed as an argument (as you can see in the code I provided, the package icon is indeed in a code variable and is loaded directly from DOpus.LoadImage).
EDIT: I misread your code, you are already doing that. The writing to disk is about what you're saving. My bad.

As per your last comment:

I am not sure I understand it right. You'd want the icon set format (colors primarily) to be customizable?

It was just a clunky little example, and is irrelevant to your post which is about icon sets.

My remark about icon sets: I mean an icon set is always a static image containing multiple Icons, I suppose. I just thought an icon set could also be an array of svg files with some sort of accompanying identification system (numbering?) that replaces the "coordinates" needed to pick up icons from one large picture full of icons. That's the part I find "topsy-turvy" - but if that's the only way to define icon sets (in general, but more specific in Directory Opus in our case), then I can't blame you for it.

Yeah, I saw that after posting (and edited my original post).

The static image with coordinates is the way to go with non SVG icons. You define the set (.dis file which is a compressed xml file) by defining where each icon in the set is located in the big static image.
Actually, the new way to define iconsets with SVG icons is pretty much what you describe:

  • Some global information at the top of the xml
  • Then a collection of icon nodes, each giving a name to the icon and then include their svg code.

Here is the start of an SVG icon set:

<?xml version="1.0" encoding="utf-8"?>
<iconset name="tabler_io_filled">
<display_name>Tabler.io Filled</display_name>
<artist>Paweł Kuna</artist>
<set size="svg">
	<icon name="accessible">
		<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.051 6.844a1 1 0 0 0 -1.152 -.663l-.113 .03l-2.684 .895l-2.684 -.895l-.113 -.03a1 1 0 0 0 -.628 1.884l.109 .044l2.316 .771v.976l-1.832 2.75l-.06 .1a1 1 0 0 0 .237 1.21l.1 .076l.101 .06a1 1 0 0 0 1.21 -.237l.076 -.1l1.168 -1.752l1.168 1.752l.07 .093a1 1 0 0 0 1.653 -1.102l-.059 -.1l-1.832 -2.75v-.977l2.316 -.771l.109 -.044a1 1 0 0 0 .524 -1.221zm-3.949 -4.184a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0 -3"/>
		</svg>
	</icon>
	<icon name="ad-circle">
		<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10 -10 10c-5.43 0 -9.848 -4.327 -9.996 -9.72l-.004 -.28l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm-3.5 6a2.5 2.5 0 0 0 -2.495 2.336l-.005 .164v4.5l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-1h1v1l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4.5l-.005 -.164a2.5 2.5 0 0 0 -2.495 -2.336zm6.5 0h-1a1 1 0 0 0 -1 1v6a1 1 0 0 0 1 1h1a3 3 0 0 0 3 -3v-2a3 3 0 0 0 -3 -3zm0 2a1 1 0 0 1 1 1v2a1 1 0 0 1 -.883 .993l-.117 .007v-4zm-6.5 0a.5 .5 0 0 1 .492 .41l.008 .09v1.5h-1v-1.5l.008 -.09a.5 .5 0 0 1 .492 -.41z"/>
		</svg>
	</icon>
1 Like

Oh, great. I didn't yet check the format for svg into icon sets, so I was talking like an ignoramus. If it works that way in Opus, that's very nice and up to today's standards.

I will look into the possibility to pick up svg code from an icon set, and to the trick that I did in my function. In fact, I guess I would need to load the xml file... Hmm, it would not be an "out of the box" thing. And of course, letting colors "flash" in that kind of way, or just change color, is only a simple thing when the icons are simple (having only a single color).

I don't think current object model lets you access the icon sets, so you'd actually need to get the set file (located in /dopusdata/Icons), unzip it to a temp folder (that you could get from FSUtil.GetTempDirPath or some user defined folder), then load the xml and get the proper icon node by searching by its name attribute.

Good thing is, this is always the same process, so it can be set in an include file you'll add to every script where you need to do this.

Yet, if you do that often in your scripts, chances are you'll deal with your own sets.
In that case, there might be a better solution: create include files that are acting as a set of icons.
In these include files, define your icons with variables in arrays, or, probably better, Maps, so you can access them just by including your side icon/include file, and get your svg code with something like:

dlg.Control("btnSave").image=DOpus.LoadImage(SvgIconSetWhateverMap("save"));
1 Like

Yes that would be a more efficient approach.

V1.1:

  • Fixed issue: copyright information not properly inserted in the set
  • Added extra informations in log: progress notification every 500 icons processed, end message after creating the .dis file.

SvgTools.opusscriptinstall (10.3 KB)

By the way, great svg iconsets you posted here (and which I could import with the newest Opus install). Extensive selection of useful icons - even too large (many with tiny variations) but that can't spoil the fun.

2 Likes

V1.2:
Added ability to manage categories:

  • Every subfolder of the source folder will be interpreted as a category (named after the subfolder name).
  • If svg files are found at the root of source folder, they are not assigned to a category
  • Enabling this feature is done by ticking the appropriate (new) checkbox in the SVG Info dialog

SvgTools.opusscriptinstall (10.8 KB)

5 Likes

How do you run it? I put "GenSvgIconSet" in a button and nothing happens.

Strange. It's working fine here.
Do you run 13.23.1 at least?
What's the status of SvgTools.js in the script addins dialo?

EDIT: Any error message in the scripts log when trying to run the button?
EDIT2: Since you didn't mention an error message, it means the command is found, so script is properly installed.
You need to be in a folder with svg files either directly in the active folder, or in the first level of subfolders.
Otherwise, script log should say something about no svg file found, and exits.
Maybe I should make this more obvious with some kind of popup rather than just the logs.

Ok it popped up when the source folder has SVGs, thanks!
This is an awesome tool.

1 Like

This site has a ridiculous amount of SVG assets: Full Icon Themes - Gnome-look.org

2 Likes

Wow, looks great indeed!

1 Like

V1.3:

  • If an XML file is selected, the command will try to parse it as if it were the temporary XML file generated before it gets zipped to .dis in order to retrieve previously entered Svg set information (name, display name, copyright and artist).

This mechanism is intended to avoid having to copy find and copy the same information when building a new version of a previously built iconset.

SvgTools.opusscriptinstall (11.1 KB)

1 Like

Thanks to @kundal suggestions and provided code (in PM), here's version 1.4:
SvgTools.opusscriptinstall (12.5 KB)

Changes:

  • New UI for introduced options
  • Ability to use some new features (coming from 13.23.7)
    • remove_padding
    • small and large sizes can also be specified (optional)
  • If no proper xml is selected when lauching the GenSvgIconSet command, the name and display name are retrieved from current folder path name.
  • The generated temporary/embedded xml in .dis file is now reformatted to be more easily read (by human)
  • Added an optional experimental feature (use at your own risk) to replace white/#ffffff/black/#000000 in fill: and stroke: attributes in the xml by currentColor.

New UI:

Hi PassThePeas, thanks for implementing my suggestions. The color-replacement should only be used with white/black monochrome icons. For those it's working fine for me. With currentColor the color of the icons follow the text/label color of a button making it easy to toggle the color if the button state changes. This can be done with an evaluator code:

@color:text=$glob:state_MyButtonState?"#ff8080":"default";
=$glob:state_MyButtonState=!$glob:state_MyButtonState;return "@toggle:update";

The color replacement doesn't catch occurances of (stroke|fill)="color".
To get these also changed I changed the regexes to this:

		var regexpFillList = [];
		var regexpStrokeList = [];
		var regexpFillList2 = [];
		var regexpStrokeList2 = [];
        regexpFillList.push(new RegExp("\\bfill:(?:white|black|#fff|#ffffff|#000|#000000)\\b", "gi"));
		regexpFillList2.push(new RegExp("fill\s*=\s*\"(?:#fff|#ffffff|#000|#000000|white|black)\"","gi"));
        regexpStrokeList.push(new RegExp("\\bstroke:(?:white|black|#fff|#ffffff|#000|#000000)\\b", "gi"));
        regexpStrokeList2.push(new RegExp("stroke\s*=\s*\"(?:#fff|#ffffff|#000|#000000|white|black)\"","gi"));

		for (var i=0; i<regexpFillList.length; i++) {
			content = content.replace(regexpFillList[i], "fill:currentColor");
		}
		for (var i=0; i<regexpFillList2.length; i++) {
			content = content.replace(regexpFillList2[i], 'fill="currentColor"');
		}
		for (var i=0; i<regexpStrokeList.length; i++) {
			content = content.replace(regexpStrokeList[i], "stroke:currentColor");
		}
		for (var i=0; i<regexpStrokeList2.length; i++) {
			content = content.replace(regexpStrokeList2[i], 'stroke="currentColor"');
		}

A remark to the "Remove Padding" option: Use this with care. If some icons in your set aren't equal in height and wide they will possibly change it's position. A simple line from left to right will no longer be shown vertically centered but move to the top of the icon space because the empty space above the line will be removed.