Draft: Improve ShapeString execute function
This commit is contained in:
@@ -123,100 +123,102 @@ class ShapeString(DraftObject):
|
||||
+ translate("draft", "changed 'Tracking' property type"))
|
||||
|
||||
def execute(self, obj):
|
||||
if self.props_changed_placement_only():
|
||||
if self.props_changed_placement_only() \
|
||||
or not obj.String \
|
||||
or not obj.FontFile:
|
||||
obj.positionBySupport()
|
||||
self.props_changed_clear()
|
||||
return
|
||||
|
||||
if obj.String and obj.FontFile:
|
||||
plm = obj.Placement
|
||||
if obj.FontFile[0] == ".":
|
||||
# FontFile path relative to the FreeCAD file directory.
|
||||
font_file = os.path.join(os.path.dirname(obj.Document.FileName), obj.FontFile)
|
||||
# We need the absolute path to do some file checks.
|
||||
font_file = os.path.abspath(font_file)
|
||||
else:
|
||||
font_file = obj.FontFile
|
||||
|
||||
if obj.FontFile[0] == ".":
|
||||
# FontFile path relative to the FreeCAD file directory.
|
||||
font_file = os.path.join(os.path.dirname(obj.Document.FileName), obj.FontFile)
|
||||
# We need the absolute path to do some file checks.
|
||||
font_file = os.path.abspath(font_file)
|
||||
# File checks:
|
||||
if not os.path.exists(font_file):
|
||||
_err(obj.Label + ": " + translate("draft", "Font file not found"))
|
||||
self.props_changed_clear()
|
||||
return
|
||||
if not os.path.isfile(font_file):
|
||||
_err(obj.Label + ": " + translate("draft", "Specified font file is not a file"))
|
||||
self.props_changed_clear()
|
||||
return
|
||||
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"))
|
||||
self.props_changed_clear()
|
||||
return
|
||||
|
||||
plm = obj.Placement
|
||||
fill = obj.MakeFace
|
||||
if fill is True:
|
||||
# Test a simple letter to know if we have a sticky font or not.
|
||||
# If the font is sticky change fill to `False`.
|
||||
# The 0.03 total area minimum is based on tests with:
|
||||
# 1CamBam_Stick_0.ttf and 1CamBam_Stick_0C.ttf.
|
||||
# See the make_faces function for more information.
|
||||
char = Part.makeWireString("L", font_file, 1, 0)[0]
|
||||
shapes = self.make_faces(char) # char is list of wires
|
||||
if not shapes:
|
||||
fill = False
|
||||
else:
|
||||
font_file = obj.FontFile
|
||||
# Depending on the font the size of char can be very small.
|
||||
# For the area check to make sense we need to use a scale factor.
|
||||
# https://github.com/FreeCAD/FreeCAD/issues/21501
|
||||
char_comp = Part.Compound(char)
|
||||
factor = 1 / char_comp.BoundBox.YLength
|
||||
fill = sum([shape.Area for shape in shapes]) > (0.03 / factor ** 2) \
|
||||
and math.isclose(char_comp.BoundBox.DiagonalLength,
|
||||
Part.Compound(shapes).BoundBox.DiagonalLength,
|
||||
rel_tol=1e-7)
|
||||
|
||||
# File checks:
|
||||
if not os.path.exists(font_file):
|
||||
_err(obj.Label + ": " + translate("draft", "Font file not found"))
|
||||
return
|
||||
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].lower() in (".ttc", ".ttf", ".otf", ".pfb"):
|
||||
_err(obj.Label + ": " + translate("draft", "Specified font type is not supported"))
|
||||
return
|
||||
chars = Part.makeWireString(obj.String, font_file, obj.Size, obj.Tracking)
|
||||
shapes = []
|
||||
|
||||
fill = obj.MakeFace
|
||||
if fill is True:
|
||||
# Test a simple letter to know if we have a sticky font or not.
|
||||
# If the font is sticky change fill to `False`.
|
||||
# The 0.03 total area minimum is based on tests with:
|
||||
# 1CamBam_Stick_0.ttf and 1CamBam_Stick_0C.ttf.
|
||||
# See the make_faces function for more information.
|
||||
char = Part.makeWireString("L", font_file, 1, 0)[0]
|
||||
shapes = self.make_faces(char) # char is list of wires
|
||||
if not shapes:
|
||||
fill = False
|
||||
else:
|
||||
# Depending on the font the size of char can be very small.
|
||||
# For the area check to make sense we need to use a scale factor.
|
||||
# https://github.com/FreeCAD/FreeCAD/issues/21501
|
||||
char_comp = Part.Compound(char)
|
||||
factor = 1 / char_comp.BoundBox.YLength
|
||||
fill = sum([shape.Area for shape in shapes]) > (0.03 / factor ** 2) \
|
||||
and math.isclose(char_comp.BoundBox.DiagonalLength,
|
||||
Part.Compound(shapes).BoundBox.DiagonalLength,
|
||||
rel_tol=1e-7)
|
||||
|
||||
chars = Part.makeWireString(obj.String, font_file, obj.Size, obj.Tracking)
|
||||
shapes = []
|
||||
|
||||
for char in chars:
|
||||
if fill is False:
|
||||
shapes.extend(char)
|
||||
elif char:
|
||||
shapes.extend(self.make_faces(char))
|
||||
if shapes:
|
||||
if fill and obj.Fuse:
|
||||
ss_shape = shapes[0].fuse(shapes[1:])
|
||||
ss_shape = faces.concatenate(ss_shape)
|
||||
# Concatenate returns a Face or a Compound. We always
|
||||
# need a Compound as we use ss_shape.SubShapes later.
|
||||
if ss_shape.ShapeType == "Face":
|
||||
ss_shape = Part.Compound([ss_shape])
|
||||
else:
|
||||
ss_shape = Part.Compound(shapes)
|
||||
cap_char = Part.makeWireString("M", font_file, obj.Size, obj.Tracking)[0]
|
||||
cap_height = Part.Compound(cap_char).BoundBox.YMax
|
||||
if obj.ScaleToSize:
|
||||
ss_shape.scale(obj.Size / cap_height)
|
||||
cap_height = obj.Size
|
||||
if obj.ObliqueAngle:
|
||||
if -80 <= obj.ObliqueAngle <= 80:
|
||||
mtx = App.Matrix()
|
||||
mtx.A12 = math.tan(math.radians(obj.ObliqueAngle))
|
||||
ss_shape = ss_shape.transformGeometry(mtx)
|
||||
else:
|
||||
wrn = translate("draft", "ShapeString: oblique angle must be in the -80 to +80 degree range") + "\n"
|
||||
App.Console.PrintWarning(wrn)
|
||||
just_vec = self.justification_vector(ss_shape,
|
||||
cap_height,
|
||||
obj.Justification,
|
||||
obj.JustificationReference,
|
||||
obj.KeepLeftMargin)
|
||||
shapes = ss_shape.SubShapes
|
||||
for shape in shapes:
|
||||
shape.translate(just_vec)
|
||||
obj.Shape = Part.Compound(shapes)
|
||||
for char in chars:
|
||||
if fill is False:
|
||||
shapes.extend(char)
|
||||
elif char:
|
||||
shapes.extend(self.make_faces(char))
|
||||
if shapes:
|
||||
if fill and obj.Fuse:
|
||||
ss_shape = shapes[0].fuse(shapes[1:])
|
||||
ss_shape = faces.concatenate(ss_shape)
|
||||
# Concatenate returns a Face or a Compound. We always
|
||||
# need a Compound as we use ss_shape.SubShapes later.
|
||||
if ss_shape.ShapeType == "Face":
|
||||
ss_shape = Part.Compound([ss_shape])
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft", "ShapeString: string has no wires") + "\n")
|
||||
|
||||
obj.Placement = plm
|
||||
ss_shape = Part.Compound(shapes)
|
||||
cap_char = Part.makeWireString("M", font_file, obj.Size, obj.Tracking)[0]
|
||||
cap_height = Part.Compound(cap_char).BoundBox.YMax
|
||||
if obj.ScaleToSize:
|
||||
ss_shape.scale(obj.Size / cap_height)
|
||||
cap_height = obj.Size
|
||||
if obj.ObliqueAngle:
|
||||
if -80 <= obj.ObliqueAngle <= 80:
|
||||
mtx = App.Matrix()
|
||||
mtx.A12 = math.tan(math.radians(obj.ObliqueAngle))
|
||||
ss_shape = ss_shape.transformGeometry(mtx)
|
||||
else:
|
||||
wrn = translate("draft", "ShapeString: oblique angle must be in the -80 to +80 degree range") + "\n"
|
||||
App.Console.PrintWarning(wrn)
|
||||
just_vec = self.justification_vector(ss_shape,
|
||||
cap_height,
|
||||
obj.Justification,
|
||||
obj.JustificationReference,
|
||||
obj.KeepLeftMargin)
|
||||
shapes = ss_shape.SubShapes
|
||||
for shape in shapes:
|
||||
shape.translate(just_vec)
|
||||
obj.Shape = Part.Compound(shapes)
|
||||
else:
|
||||
App.Console.PrintWarning(translate("draft", "ShapeString: string has no wires") + "\n")
|
||||
|
||||
obj.Placement = plm
|
||||
obj.positionBySupport()
|
||||
self.props_changed_clear()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user