diff --git a/mitreattack/navlayers/README.md b/mitreattack/navlayers/README.md index 52a77b0a..8d6cf5c8 100644 --- a/mitreattack/navlayers/README.md +++ b/mitreattack/navlayers/README.md @@ -267,7 +267,7 @@ If not provided, the configuration for the export will be set to default values. y = SVGConfig(width=8.5, height=11, headerHeight=1, unit="in", showSubtechniques="expanded", font="sans-serif", tableBorderColor="#6B7279", showHeader=True, legendDocked=True, legendX=0, legendY=0, legendWidth=2, legendHeight=1, showLegend=True, showFilters=True, - showAbout=True, showDomain=True, border=0.104) + showAbout=True, showDomain=True, border=0.104, fontSize=4) ``` The `SVGConfig` object is used to configure how an SVG export behaves. @@ -297,7 +297,7 @@ or stored to one using the `.save_to_file(filename="path/to/file.json)` method. | showDomain | Whether or not to show the Domain and Version Header Block | bool | True | | showAbout | Whether or not to show the About Header Block | bool | True | | border | What default border width to use | number | 0.104 | - +| fontSize | What font size to use | number | 4 | ### .to_svg() Method ```python diff --git a/mitreattack/navlayers/exporters/svg_objects.py b/mitreattack/navlayers/exporters/svg_objects.py index 53ad2d13..86203c1d 100644 --- a/mitreattack/navlayers/exporters/svg_objects.py +++ b/mitreattack/navlayers/exporters/svg_objects.py @@ -390,6 +390,7 @@ def build( technique, height, width, + config, tBC, subtechniques=[], exclude=[], @@ -403,6 +404,7 @@ def build( :param technique: The technique to build a block for :param height: The height of the technique block :param width: The width of the technique block + :param config: SVG configuration object :param tBC: The hex code of the technique block's border :param subtechniques: List of any visible subtechniques for this technique :param exclude: List of excluded techniques @@ -418,7 +420,7 @@ def build( id=technique.id, color=tuple(int(c[i : i + 2], 16) for i in (0, 2, 4)), ) - tech, text = self._block(t, height, width, tBC=tBC) + tech, text = self._block(t, height, width, config, tBC=tBC) g.append(tech) g.append(text) new_offset = height @@ -436,7 +438,7 @@ def build( id=entry.id, color=tuple(int(c[i : i + 2], 16) for i in (0, 2, 4)), ) - subtech, subtext = self._block(st, height, width - width / 5, tBC=tBC) + subtech, subtext = self._block(st, height, width - width / 5, config, tBC=tBC) gp.append(subtech) gp.append(subtext) new_offset = new_offset + height @@ -463,18 +465,19 @@ def build( return g, offset + new_offset @staticmethod - def _block(technique, height, width, tBC): + def _block(technique, height, width, config, tBC): """Build a technique block element. :param technique: Technique data dictionary :param height: Block height :param width: Block width + :param config: SVG configuration object :param tBC: Block border color :return: Block object, fit text object """ tech = Cell(height, width, technique["color"], ctype=technique["id"], tBC=tBC) - fs, patch_text = _optimalFontSize(technique["name"], width, height) + fs, patch_text = _optimalFontSize(technique["name"], width, height, config.fontSize) adjusted = "\n".join(patch_text) lines = adjusted.count("\n") diff --git a/mitreattack/navlayers/exporters/svg_templates.py b/mitreattack/navlayers/exporters/svg_templates.py index b63e5228..7ad12c72 100644 --- a/mitreattack/navlayers/exporters/svg_templates.py +++ b/mitreattack/navlayers/exporters/svg_templates.py @@ -340,6 +340,7 @@ def get_tech( technique, height, width, + config, subtechniques=subtechniques, exclude=exclude, mode=mode, @@ -435,7 +436,7 @@ def export(self, showName, showID, layer, config, sort=0, scores=[], colors=[], # create header text header_glob = G(tx=index, ty=header_offset) text_glob = G(tx=technique_width / 2, ty=technique_height / 2) - font_size, _ = _optimalFontSize(displayStr, technique_width, technique_height, maxFontSize=28) + font_size, _ = _optimalFontSize(displayStr, technique_width, technique_height, config.fontSize) text = Text(ctype="TacticName", font_size=font_size, text=displayStr, position="middle") text_glob.append(text) header_glob.append(text_glob) diff --git a/mitreattack/navlayers/exporters/to_svg.py b/mitreattack/navlayers/exporters/to_svg.py index b34f2e66..5f5f08aa 100644 --- a/mitreattack/navlayers/exporters/to_svg.py +++ b/mitreattack/navlayers/exporters/to_svg.py @@ -36,6 +36,7 @@ def __init__( showAbout=True, showDomain=True, border=0.104, + fontSize=4 ): """Define parameters to configure SVG export. @@ -57,6 +58,8 @@ def __init__( :param showAbout: Whether or not to show the About Header Block :param showDomain: Whether or not to show the Domain Version Header Block :param border: What default border width to use + :param font: What font size to use + """ self.width = width self.height = height @@ -76,6 +79,7 @@ def __init__( self.showFilters = showFilters self.showAbout = showAbout self.border = border + self.fontSize = fontSize def load_from_file(self, filename=""): """Load config from a json file. @@ -120,6 +124,7 @@ def save_to_file(self, filename=""): showFilters=self.showFilters, showAbout=self.showAbout, border=self.border, + fontSize=self.fontSize ) with open(filename, "w", encoding="utf-16") as file: json.dump(out, file, ensure_ascii=False) @@ -144,7 +149,8 @@ def __str__(self): f"- showLegend: {self.showLegend}\n" f"- showFilters: {self.showFilters}\n" f"- showAbout: {self.showAbout}\n" - f"- border: {self.border}" + f"- border: {self.border}\n" + f"- fontSize: {self.fontSize}" ) @property @@ -235,6 +241,20 @@ def font(self, font): else: print(f'[Warning] - Unable to set font to {font}: not one of ["serif", "sans-serif", "monospace"]') + @property + def fontSize(self): + """Font size getter.""" + if self.__fontSize is not None: + return self.__fontSize + + @fontSize.setter + def fontSize(self, fontSize): + """Font size setter.""" + if isinstance(fontSize, (int, float)): + self.__fontSize = fontSize + else: + print(f'[Warning] - Unable to set font to {fontSize}: not a number') + @property def tableBorderColor(self): """Table Border Color getter."""