mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Merge pull request #960 from jwagenet/text-update
Add OCCT text alignment to `Text`/`make_text`
This commit is contained in:
commit
6a4a3b54c4
7 changed files with 115 additions and 19 deletions
|
|
@ -228,7 +228,7 @@ Cheat Sheet
|
|||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.Extrinsic` | XYZ, XZY, YZX, YXZ, ZXY, ZYX, XYX, XZX, YZY, YXY, ZXZ, ZYZ |
|
||||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.FontStyle` | REGULAR, BOLD, ITALIC |
|
||||
| :class:`~build_enums.FontStyle` | REGULAR, BOLD, BOLDITALIC, ITALIC |
|
||||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.FrameMethod` | CORRECTED, FRENET |
|
||||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
|
@ -262,6 +262,8 @@ Cheat Sheet
|
|||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.SortBy` | LENGTH, RADIUS, AREA, VOLUME, DISTANCE |
|
||||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.TextAlign` | BOTTOM, CENTER, LEFT, RIGHT, TOP, TOPFIRSTLINE |
|
||||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.Transition` | RIGHT, ROUND, TRANSFORMED |
|
||||
+----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| :class:`~build_enums.Unit` | MC, MM, CM, M, IN, FT |
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ __all__ = [
|
|||
"Select",
|
||||
"Side",
|
||||
"SortBy",
|
||||
"TextAlign",
|
||||
"Transition",
|
||||
"Unit",
|
||||
"Until",
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ class FontStyle(Enum):
|
|||
REGULAR = auto()
|
||||
BOLD = auto()
|
||||
ITALIC = auto()
|
||||
BOLDITALIC = auto()
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__}.{self.name}>"
|
||||
|
|
@ -344,6 +345,20 @@ class SortBy(Enum):
|
|||
return f"<{self.__class__.__name__}.{self.name}>"
|
||||
|
||||
|
||||
class TextAlign(Enum):
|
||||
"""Text Alignment"""
|
||||
|
||||
BOTTOM = auto()
|
||||
CENTER = auto()
|
||||
LEFT = auto()
|
||||
RIGHT = auto()
|
||||
TOP = auto()
|
||||
TOPFIRSTLINE = auto()
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__}.{self.name}>"
|
||||
|
||||
|
||||
class Transition(Enum):
|
||||
"""Sweep discontinuity handling option"""
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ from typing import cast
|
|||
from collections.abc import Iterable
|
||||
|
||||
from build123d.build_common import LocationList, flatten_sequence, validate_inputs
|
||||
from build123d.build_enums import Align, FontStyle, Mode
|
||||
from build123d.build_enums import Align, FontStyle, Mode, TextAlign
|
||||
from build123d.build_sketch import BuildSketch
|
||||
from build123d.geometry import (
|
||||
Axis,
|
||||
|
|
@ -538,21 +538,37 @@ class Text(BaseSketchObject):
|
|||
"""Sketch Object: Text
|
||||
|
||||
Create text defined by text string and font size.
|
||||
May have difficulty finding non-system fonts depending on platform and render default.
|
||||
font_path defines an exact path to a font file and overrides font.
|
||||
|
||||
Fonts installed to the system can be specified by name and FontStyle. Fonts with
|
||||
subfamilies not in FontStyle should be specified with the subfamily name, e.g.
|
||||
"Arial Black". Alternatively, a specific font file can be specified with font_path.
|
||||
|
||||
Note: Windows 10+ users must "Install for all users" for fonts to be found by name.
|
||||
|
||||
Not all fonts have every FontStyle available, however ITALIC and BOLDITALIC will
|
||||
still italicize the font if the respective font file is not available.
|
||||
|
||||
text_align specifies alignment of text inside the bounding box, while align the
|
||||
aligns the bounding box itself.
|
||||
|
||||
Optionally, the Text can be positioned on a non-linear edge or wire with a path and
|
||||
position_on_path.
|
||||
|
||||
Args:
|
||||
txt (str): text to render
|
||||
font_size (float): size of the font in model units
|
||||
font (str, optional): font name. Defaults to "Arial"
|
||||
font_path (str, optional): system path to font file. Defaults to None
|
||||
font_style (Font_Style, optional): font style, REGULAR, BOLD, or ITALIC.
|
||||
Defaults to Font_Style.REGULAR
|
||||
align (Align | tuple[Align, Align], optional): align MIN, CENTER, or MAX of object.
|
||||
Defaults to (Align.CENTER, Align.CENTER)
|
||||
font_style (Font_Style, optional): font style, REGULAR, BOLD, BOLDITALIC, or
|
||||
ITALIC. Defaults to Font_Style.REGULAR
|
||||
text_align (tuple[TextAlign, TextAlign], optional): horizontal text align
|
||||
LEFT, CENTER, or RIGHT. Vertical text align BOTTOM, CENTER, TOP, or
|
||||
TOPFIRSTLINE. Defaults to (TextAlign.CENTER, TextAlign.CENTER)
|
||||
align (Align | tuple[Align, Align], optional): align MIN, CENTER, or MAX of
|
||||
object. Defaults to None
|
||||
path (Edge | Wire, optional): path for text to follow. Defaults to None
|
||||
position_on_path (float, optional): the relative location on path to position the
|
||||
text, values must be between 0.0 and 1.0. Defaults to 0.0
|
||||
position_on_path (float, optional): the relative location on path to position
|
||||
the text, values must be between 0.0 and 1.0. Defaults to 0.0
|
||||
rotation (float, optional): angle to rotate object. Defaults to 0
|
||||
mode (Mode, optional): combination mode. Defaults to Mode.ADD
|
||||
"""
|
||||
|
|
@ -567,7 +583,8 @@ class Text(BaseSketchObject):
|
|||
font: str = "Arial",
|
||||
font_path: str | None = None,
|
||||
font_style: FontStyle = FontStyle.REGULAR,
|
||||
align: Align | tuple[Align, Align] | None = (Align.CENTER, Align.CENTER),
|
||||
text_align: tuple[TextAlign, TextAlign] = (TextAlign.CENTER, TextAlign.CENTER),
|
||||
align: Align | tuple[Align, Align] | None = None,
|
||||
path: Edge | Wire | None = None,
|
||||
position_on_path: float = 0.0,
|
||||
rotation: float = 0.0,
|
||||
|
|
@ -581,6 +598,7 @@ class Text(BaseSketchObject):
|
|||
self.font = font
|
||||
self.font_path = font_path
|
||||
self.font_style = font_style
|
||||
self.text_align = text_align
|
||||
self.align = align
|
||||
self.text_path = path
|
||||
self.position_on_path = position_on_path
|
||||
|
|
@ -593,6 +611,7 @@ class Text(BaseSketchObject):
|
|||
font=font,
|
||||
font_path=font_path,
|
||||
font_style=font_style,
|
||||
text_align=text_align,
|
||||
align=align,
|
||||
position_on_path=position_on_path,
|
||||
text_path=path,
|
||||
|
|
|
|||
|
|
@ -67,11 +67,22 @@ import OCP.TopAbs as ta
|
|||
from OCP.BRepAlgoAPI import BRepAlgoAPI_Fuse
|
||||
from OCP.Font import (
|
||||
Font_FA_Bold,
|
||||
Font_FA_BoldItalic,
|
||||
Font_FA_Italic,
|
||||
Font_FA_Regular,
|
||||
Font_FontMgr,
|
||||
Font_SystemFont,
|
||||
)
|
||||
from OCP.gp import gp_Ax3
|
||||
from OCP.Graphic3d import (
|
||||
Graphic3d_HTA_LEFT,
|
||||
Graphic3d_HTA_CENTER,
|
||||
Graphic3d_HTA_RIGHT,
|
||||
Graphic3d_VTA_BOTTOM,
|
||||
Graphic3d_VTA_CENTER,
|
||||
Graphic3d_VTA_TOP,
|
||||
Graphic3d_VTA_TOPFIRSTLINE,
|
||||
)
|
||||
from OCP.GProp import GProp_GProps
|
||||
from OCP.NCollection import NCollection_Utf8String
|
||||
from OCP.StdPrs import StdPrs_BRepTextBuilder as Font_BRepTextBuilder, StdPrs_BRepFont
|
||||
|
|
@ -85,7 +96,7 @@ from OCP.TopoDS import (
|
|||
TopoDS_Shape,
|
||||
)
|
||||
from anytree import PreOrderIter
|
||||
from build123d.build_enums import Align, CenterOf, FontStyle
|
||||
from build123d.build_enums import Align, CenterOf, FontStyle, TextAlign
|
||||
from build123d.geometry import (
|
||||
TOLERANCE,
|
||||
Axis,
|
||||
|
|
@ -238,7 +249,8 @@ class Compound(Mixin3D, Shape[TopoDS_Compound]):
|
|||
font: str = "Arial",
|
||||
font_path: str | None = None,
|
||||
font_style: FontStyle = FontStyle.REGULAR,
|
||||
align: Align | tuple[Align, Align] | None = (Align.CENTER, Align.CENTER),
|
||||
text_align: tuple[TextAlign, TextAlign] = (TextAlign.CENTER, TextAlign.CENTER),
|
||||
align: Align | tuple[Align, Align] | None = None,
|
||||
position_on_path: float = 0.0,
|
||||
text_path: Edge | Wire | None = None,
|
||||
) -> Compound:
|
||||
|
|
@ -254,12 +266,15 @@ class Compound(Mixin3D, Shape[TopoDS_Compound]):
|
|||
font_size: size of the font in model units
|
||||
font: font name
|
||||
font_path: path to font file
|
||||
font_style: text style. Defaults to FontStyle.REGULAR.
|
||||
font_style: text style. Defaults to FontStyle.REGULAR
|
||||
text_align (tuple[TextAlign, TextAlign], optional): horizontal text align
|
||||
LEFT, CENTER, or RIGHT. Vertical text align BOTTOM, CENTER, TOP, or
|
||||
TOPFIRSTLINE. Defaults to (TextAlign.CENTER, TextAlign.CENTER)
|
||||
align (Union[Align, tuple[Align, Align]], optional): align min, center, or max
|
||||
of object. Defaults to (Align.CENTER, Align.CENTER).
|
||||
of object. Defaults to None
|
||||
position_on_path: the relative location on path to position the text,
|
||||
between 0.0 and 1.0. Defaults to 0.0.
|
||||
text_path: a path for the text to follows. Defaults to None - linear text.
|
||||
between 0.0 and 1.0. Defaults to 0.0
|
||||
text_path: a path for the text to follows. Defaults to None (linear text)
|
||||
|
||||
Returns:
|
||||
a Compound object containing multiple Faces representing the text
|
||||
|
|
@ -306,8 +321,39 @@ class Compound(Mixin3D, Shape[TopoDS_Compound]):
|
|||
FontStyle.REGULAR: Font_FA_Regular,
|
||||
FontStyle.BOLD: Font_FA_Bold,
|
||||
FontStyle.ITALIC: Font_FA_Italic,
|
||||
FontStyle.BOLDITALIC: Font_FA_BoldItalic,
|
||||
}[font_style]
|
||||
|
||||
if text_align[0] not in [TextAlign.LEFT, TextAlign.CENTER, TextAlign.RIGHT]:
|
||||
raise ValueError(
|
||||
"Horizontal TextAlign must be LEFT, CENTER, or RIGHT. "
|
||||
f"Got {text_align[0]}"
|
||||
)
|
||||
|
||||
if text_align[1] not in [
|
||||
TextAlign.BOTTOM,
|
||||
TextAlign.CENTER,
|
||||
TextAlign.TOP,
|
||||
TextAlign.TOPFIRSTLINE,
|
||||
]:
|
||||
raise ValueError(
|
||||
"Vertical TextAlign must be BOTTOM, CENTER, TOP, or TOPFIRSTLINE. "
|
||||
f"Got {text_align[1]}"
|
||||
)
|
||||
|
||||
horiz_align = {
|
||||
TextAlign.LEFT: Graphic3d_HTA_LEFT,
|
||||
TextAlign.CENTER: Graphic3d_HTA_CENTER,
|
||||
TextAlign.RIGHT: Graphic3d_HTA_RIGHT,
|
||||
}[text_align[0]]
|
||||
|
||||
vert_align = {
|
||||
TextAlign.BOTTOM: Graphic3d_VTA_BOTTOM,
|
||||
TextAlign.CENTER: Graphic3d_VTA_CENTER,
|
||||
TextAlign.TOP: Graphic3d_VTA_TOP,
|
||||
TextAlign.TOPFIRSTLINE: Graphic3d_VTA_TOPFIRSTLINE,
|
||||
}[text_align[1]]
|
||||
|
||||
mgr = Font_FontMgr.GetInstance_s()
|
||||
|
||||
if font_path and mgr.CheckFont(TCollection_AsciiString(font_path).ToCString()):
|
||||
|
|
@ -330,7 +376,12 @@ class Compound(Mixin3D, Shape[TopoDS_Compound]):
|
|||
font_kind,
|
||||
float(font_size),
|
||||
)
|
||||
text_flat = Compound(builder.Perform(font_i, NCollection_Utf8String(txt)))
|
||||
|
||||
text_flat = Compound(
|
||||
builder.Perform(
|
||||
font_i, NCollection_Utf8String(txt), gp_Ax3(), horiz_align, vert_align
|
||||
)
|
||||
)
|
||||
|
||||
# Align the text from the bounding box
|
||||
align_text = tuplify(align, 2)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class TestEnumRepr(unittest.TestCase):
|
|||
Side,
|
||||
SortBy,
|
||||
Transition,
|
||||
TextAlign,
|
||||
Unit,
|
||||
Until,
|
||||
]
|
||||
|
|
|
|||
|
|
@ -361,7 +361,8 @@ class TestBuildSketchObjects(unittest.TestCase):
|
|||
self.assertEqual(t.font, "Arial")
|
||||
self.assertIsNone(t.font_path)
|
||||
self.assertEqual(t.font_style, FontStyle.REGULAR)
|
||||
self.assertEqual(t.align, (Align.CENTER, Align.CENTER))
|
||||
self.assertEqual(t.text_align, (TextAlign.CENTER, TextAlign.CENTER))
|
||||
self.assertIsNone(t.align)
|
||||
self.assertIsNone(t.text_path)
|
||||
self.assertEqual(t.position_on_path, 0)
|
||||
self.assertEqual(t.rotation, 0)
|
||||
|
|
@ -369,6 +370,12 @@ class TestBuildSketchObjects(unittest.TestCase):
|
|||
self.assertEqual(len(test.sketch.faces()), 4)
|
||||
self.assertEqual(t.faces()[0].normal_at(), Vector(0, 0, 1))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
Text("test", 2, text_align=(TextAlign.BOTTOM, TextAlign.BOTTOM))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
Text("test", 2, text_align=(TextAlign.LEFT, TextAlign.LEFT))
|
||||
|
||||
def test_trapezoid(self):
|
||||
with BuildSketch() as test:
|
||||
t = Trapezoid(6, 2, 63.434948823)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue