From 2e02c6a9448c9e5b05ab3c2895cfde0ffd9c1a72 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Sun, 4 May 2025 11:32:18 +0200 Subject: [PATCH] Draft: ShapeString: use an actual font file as default, allow TTC files * To help novice users supply an actual font file from the OS as the default for ShapeStringFontFile. * The Draft code blocked the use of TTC font files. `Part.makeWireString()` can however handle them (although only the first font in the file can be used). Additonally: In a previous PR the bottom spacer was removed from the task panel. This PR brings it back as it is required in some cases. Without it the "..." button of the file selector can become huge. --- src/Mod/Draft/Resources/ui/TaskShapeString.ui | 11 +++++- src/Mod/Draft/draftobjects/shapestring.py | 2 +- src/Mod/Draft/draftutils/params.py | 37 +++++++++++++++++-- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/Mod/Draft/Resources/ui/TaskShapeString.ui b/src/Mod/Draft/Resources/ui/TaskShapeString.ui index ab99f0264e..75ae57f9bf 100644 --- a/src/Mod/Draft/Resources/ui/TaskShapeString.ui +++ b/src/Mod/Draft/Resources/ui/TaskShapeString.ui @@ -149,7 +149,7 @@ Uncheck to use working plane coordinate system - + Text to be made into ShapeString @@ -166,12 +166,19 @@ Uncheck to use working plane coordinate system - Font files (*.ttf *.otf *.pfb *.TTF *.OTF *.PFB) + Font files (*.ttc *.ttf *.otf *.pfb *.TTC *.TTF *.OTF *.PFB) + + + + Qt::Vertical + + + diff --git a/src/Mod/Draft/draftobjects/shapestring.py b/src/Mod/Draft/draftobjects/shapestring.py index c855e3c86e..991e3bdc89 100644 --- a/src/Mod/Draft/draftobjects/shapestring.py +++ b/src/Mod/Draft/draftobjects/shapestring.py @@ -146,7 +146,7 @@ class ShapeString(DraftObject): if not os.path.isfile(font_file): _err(obj.Label + ": " + translate("draft", "Specified font file is not a file")) return - if not os.path.splitext(font_file)[1].upper() in (".TTF", ".OTF", ".PFB"): + if not os.path.splitext(font_file)[1].lower() in (".ttc", ".ttf", ".otf", ".pfb"): _err(obj.Label + ": " + translate("draft", "Specified font type is not supported")) return diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index a13d628881..9fd89b5df1 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -391,15 +391,44 @@ def _param_from_PrefFontBox(widget): return path, entry, value +def _get_shape_string_font_file(): + """Try to get the file name of a sans serif font (TTC or TTF) from the OS.""" + # https://forum.freecad.org/viewtopic.php?t=96770 + # Windows font: "arial" + # Mac fonts: "geneva" and "helvetica" + # Linux fonts: "dejavusans" and "freesans" + favorite_names = ("arial", "geneva", "helvetica", "dejavusans", "freesans") + font_file_sans = None # Font with name containing "sans". 1st fallback. + font_file_alpha = None # Font with name starting with a letter. 2nd fallback. + # Reverse the order of the paths so that user related paths come last: + for path in QtCore.QStandardPaths.standardLocations(QtCore.QStandardPaths.FontsLocation)[::-1]: + # We don't use os.path.join as dir_path has forward slashes even on Windows. + for (dir_path, dir_names, file_names) in os.walk(path): + for file_name in file_names: + base_name, ext = [s.lower() for s in os.path.splitext(file_name)] + if not ext in (".ttc", ".ttf"): + continue + if base_name in favorite_names: + return dir_path + "/" + file_name + if font_file_sans is None and "sans" in base_name: + font_file_sans = dir_path + "/" + file_name + if font_file_alpha is None and base_name[0].isalpha(): + font_file_alpha = dir_path + "/" + file_name + if font_file_sans is not None: + return font_file_sans + if font_file_alpha is not None: + return font_file_alpha + return "" + + def _get_param_dictionary(): # print("Creating preferences dictionary...") param_dict = {} - hatch_pattern_file = os.path.join( - App.getResourceDir().replace("\\", "/"), "Mod/TechDraw/PAT/FCPAT.pat" - ) + hatch_pattern_file = App.getResourceDir().replace("\\", "/").rstrip("/") \ + + "/Mod/TechDraw/PAT/FCPAT.pat" # Draft parameters that are not in the preferences: param_dict["Mod/Draft"] = { @@ -437,7 +466,7 @@ def _get_param_dictionary(): "ScaleCopy": ("bool", False), "ScaleRelative": ("bool", False), "ScaleUniform": ("bool", False), - "ShapeStringFontFile": ("string", ""), + "ShapeStringFontFile": ("string", _get_shape_string_font_file()), "ShapeStringHeight": ("float", 10.0), "ShapeStringText": ("string", translate("draft", "Default")), "snapModes": ("string", "100000000000000"),