def get_font_face(entity: DXFGraphic, doc=None) -> fonts.FontFace: """Returns the :class:`~ezdxf.tools.fonts.FontFace` defined by the associated text style. Returns the default font face if the `entity` does not have or support the DXF attribute "style". Pass a DXF document as argument `doc` to resolve text styles for virtual entities which are not assigned to a DXF document. The argument `doc` always overrides the DXF document to which the `entity` is assigned to. """ if entity.doc and doc is None: doc = entity.doc assert doc is not None, "valid DXF document required" style_name = "" # This works also for entities which do not support "style", # where style_name = entity.dxf.get("style") would fail. if entity.dxf.is_supported("style"): style_name = entity.dxf.style font_face = fonts.FontFace() if style_name and doc is not None: style = cast(Textstyle, doc.styles.get(style_name)) family, italic, bold = style.get_extended_font_data() if family: text_style = "italic" if italic else "normal" text_weight = "bold" if bold else "normal" font_face = fonts.FontFace(family=family, style=text_style, weight=text_weight) else: ttf = style.dxf.font if ttf: font_face = fonts.get_font_face(ttf) return font_face
def make_font(self, cap_height: float = None, width_factor: float = None) -> "AbstractFont": """Returns a font abstraction :class:`~ezdxf.tools.fonts.AbstractFont` for this text style. Returns a font for a cap height of 1, if the text style has auto height (:attr:`Textstyle.dxf.height` is 0) and the given `cap_height` is ``None`` or 0. Uses the :attr:`Textstyle.dxf.width` attribute if the given `width_factor` is ``None`` or 0, the default value is 1. The attribute :attr:`Textstyle.dxf.big_font` is ignored. """ from ezdxf import options from ezdxf.tools import fonts ttf = "" if options.use_matplotlib and self.has_extended_font_data: family, italic, bold = self.get_extended_font_data() if family: text_style = "italic" if italic else "normal" text_weight = "bold" if bold else "normal" font_face = fonts.FontFace(family=family, style=text_style, weight=text_weight) ttf = fonts.find_ttf_path(font_face) else: ttf = self.dxf.get("font", const.DEFAULT_TTF) if ttf == "": ttf = const.DEFAULT_TTF if cap_height is None or cap_height == 0.0: cap_height = self.dxf.height if cap_height == 0.0: cap_height = 1.0 if width_factor is None or width_factor == 0.0: width_factor = self.dxf.width return fonts.make_font(ttf, cap_height, width_factor) # type: ignore
def add_text_style(self, text_style: 'Textstyle'): """ Setup text style properties. """ name = table_key(text_style.dxf.name) font_file = text_style.dxf.font font_face = None if font_file == "": # Font family stored in XDATA? family, italic, bold = text_style.get_extended_font_data() if family: font_face = fonts.find_font_face_by_family(family, italic, bold) else: font_face = fonts.get_font_face(font_file, map_shx=True) if font_face is None: # fall back to default font font_face = fonts.FontFace() self.fonts[name] = font_face
import ezdxf from ezdxf import path, zoom from ezdxf.math import Matrix44 from ezdxf.tools import fonts from ezdxf.addons import text2path DIR = Path('~/Desktop/Outbox').expanduser() fonts.load() doc = ezdxf.new() doc.layers.new('OUTLINE') doc.layers.new('FILLING') msp = doc.modelspace() attr = {'color': 2} ff = fonts.FontFace(family="Arial") sx, sy = 4, 2 # create the target box: msp.add_lwpolyline([(0, 0), (sx, 0), (sx, sy), (0, sy)], close=True, dxfattribs={'color': 1}) # convert text string into path objects: text_as_paths = text2path.make_paths_from_str("Squeeze Me", ff) # fit text paths into a given box size by scaling, does not move the path objects: # uniform=True, keeps the text aspect ratio # uniform=False, scales the text to touch all 4 sides of the box final_paths = path.fit_paths_into_box(text_as_paths, size=(sx, sy, 0),
# Requires: matplotlib from pathlib import Path import ezdxf from ezdxf import path, zoom from ezdxf.tools import fonts from ezdxf.addons import text2path DIR = Path('~/Desktop/Outbox').expanduser() fonts.load() doc = ezdxf.new() doc.layers.new('OUTLINE') doc.layers.new('FILLING') msp = doc.modelspace() attr = {'layer': 'OUTLINE', 'color': 1} ff = fonts.FontFace(family="Noto Sans SC") s = "Noto Sans SC 0123456789 %@ 中国文字" align = "LEFT" path.render_splines_and_polylines( msp, text2path.make_paths_from_str(s, ff, align=align), dxfattribs=attr) attr['layer'] = 'FILLING' attr['color'] = 2 for hatch in text2path.make_hatches_from_str(s, ff, align=align, dxfattribs=attr): msp.add_entity(hatch) zoom.extents(msp) doc.saveas(DIR / 'text2path.dxf')
def test_same_font_faces_have_equal_hash_values(): f1 = fonts.FontFace("arial.ttf", "Arial") f2 = fonts.FontFace("arial.ttf", "Arial") assert hash(f1) == hash(f2)
def test_font_face_is_bold(): assert fonts.FontFace().is_bold is False assert fonts.FontFace(weight=300).is_bold is False assert fonts.FontFace(weight="bold").is_bold is True assert fonts.FontFace(weight="black").is_bold is True assert fonts.FontFace(weight=500).is_bold is True
def test_font_face_is_oblique(): assert fonts.FontFace(style="oblique").is_oblique is True assert fonts.FontFace(style="oblique-italic").is_oblique is True assert fonts.FontFace(style="").is_oblique is False assert fonts.FontFace().is_oblique is False