1# Copyright (c) 2021, Manfred Moitzi 2# License: MIT License 3 4import pytest 5from ezdxf.entities.mtext import ( 6 load_columns_from_embedded_object, MText, ColumnType, MTextColumns, 7) 8from ezdxf.lldxf import const 9from ezdxf.lldxf.types import EMBEDDED_OBJ_STR, EMBEDDED_OBJ_MARKER 10from ezdxf.lldxf.tags import Tags 11from ezdxf.lldxf.tagwriter import TagCollector 12 13DYNAMIC_MANUAL_HEIGHT = """101 14Embedded Object 1570 161 1710 181.0 1920 200.0 2130 220.0 2311 2469.8 2521 26276.1 2731 280.0 2940 3062.6 3141 320.0 3342 34175.0 3543 36164.8 3771 382 3972 403 4144 4250.0 4345 4412.5 4573 460 4774 480 4946 50164.8 5146 52154.3 5346 540.0 55""" 56 57DYNAMIC_AUTO_HEIGHT = """101 58Embedded Object 5970 601 6110 621.0 6320 640.0 6530 660.0 6711 6869.8 6921 70276.1 7131 720.0 7340 7462.6 7541 76158.1 7742 78175.0 7943 80158.1 8171 822 8372 840 8544 8650.0 8745 8812.5 8973 901 9174 920 93""" 94 95STATIC = """101 96Embedded Object 9770 981 9910 1001.0 10120 1020.0 10330 1040.0 10511 10669.8 10721 108276.1 10931 1100.0 11140 11262.6 11341 114150.0 11542 116175.0 11743 118150.0 11971 1201 12172 1223 12344 12450.0 12545 12612.5 12773 1280 12974 1300 131""" 132 133 134# The dynamic auto height and static types are very similar, the difference is 135# important for CAD applications, but not for the DXF format itself. 136 137 138@pytest.mark.parametrize('obj', [ 139 DYNAMIC_MANUAL_HEIGHT, 140 DYNAMIC_AUTO_HEIGHT, 141 STATIC 142], ids=['DYN_MANUAL', 'DYN_AUTO', 'STATIC']) 143def test_load_mtext_attribs_from_embedded_object(obj): 144 embedded_obj = Tags.from_text(obj) 145 dxf = MText().dxf 146 dxf.rotation = 45 147 148 load_columns_from_embedded_object(dxf, embedded_obj) 149 assert dxf.width == 62.6 150 assert dxf.text_direction == (1, 0, 0) 151 assert dxf.hasattr('rotation') is False, "remove rotation attribute" 152 assert dxf.insert == (69.8, 276.1, 0) 153 154 155def test_load_dynamic_cols_manual_height(): 156 """ Every column can have a different height. """ 157 embedded_obj = Tags.from_text(DYNAMIC_MANUAL_HEIGHT) 158 cols = load_columns_from_embedded_object(MText().dxf, embedded_obj) 159 assert cols.count == 3 160 assert cols.column_type == ColumnType.DYNAMIC 161 assert cols.auto_height is False 162 assert cols.reversed_column_flow is False 163 assert cols.defined_height == 0.0, "not defined if auto_height is False" 164 assert cols.width == 50.0 165 assert cols.gutter_width == 12.5 166 assert cols.total_width == 175.0 # 3 * 50 + 2 * 12.5 167 # total_height = max(heights) even if the last column is the tallest 168 assert cols.total_height == 164.8 169 assert cols.total_height == max(cols.heights) 170 assert len(cols.linked_columns) == 0, "MTEXT is a single entity in R2018" 171 assert len(cols.heights) == 3 172 assert cols.heights[-1] == 0.0, "last column height has to be 0.0" 173 assert cols.heights == [164.8, 154.3, 0.0] 174 175 176def test_load_dynamic_cols_with_auto_height(): 177 """ All columns have the same column height. """ 178 embedded_obj = Tags.from_text(DYNAMIC_AUTO_HEIGHT) 179 cols = load_columns_from_embedded_object(MText().dxf, embedded_obj) 180 # Count is a calculated value, group code 72 (column height count) is 0! 181 assert cols.count == 3 182 assert cols.column_type == ColumnType.DYNAMIC 183 assert cols.auto_height is True 184 assert cols.reversed_column_flow is False 185 assert cols.defined_height == 158.1, "required if auto_height is True" 186 assert cols.width == 50.0 187 assert cols.gutter_width == 12.5 188 assert cols.total_width == 175.0 # 3 * 50 + 2 * 12.5 189 assert cols.total_height == 158.1 190 assert len(cols.linked_columns) == 0, "MTEXT is a single entity in R2018" 191 assert len(cols.heights) == 0 192 193 194def test_load_static_cols(): 195 """ All columns have the same column height. """ 196 embedded_obj = Tags.from_text(STATIC) 197 cols = load_columns_from_embedded_object(MText().dxf, embedded_obj) 198 assert cols.count == 3 199 assert cols.column_type == ColumnType.STATIC 200 assert cols.auto_height is False 201 assert cols.reversed_column_flow is False 202 assert cols.defined_height == 150.0, "required for static columns" 203 assert cols.width == 50.0 204 assert cols.gutter_width == 12.5 205 assert cols.total_width == 175.0 # 3 * 50 + 2 * 12.5 206 assert cols.total_height == 150.0 207 assert len(cols.linked_columns) == 0, "MTEXT is a single entity in R2018" 208 assert len(cols.heights) == 0 209 210 211def make_mtext(txt: str): 212 mtext = MText() 213 embedded_obj = Tags.from_text(txt) 214 mtext._columns = load_columns_from_embedded_object(mtext.dxf, embedded_obj) 215 return mtext 216 217 218def test_export_static_columns_as_embedded_object(): 219 mtext = make_mtext(STATIC) 220 collector = TagCollector(dxfversion=const.DXF2018) 221 mtext.export_embedded_object(collector) 222 tags = collector.tags 223 assert len(tags) == 18 224 assert tags[0] == (EMBEDDED_OBJ_MARKER, EMBEDDED_OBJ_STR) 225 assert tags[1] == (70, 1) 226 assert tags[2] == (10, 1) 227 assert tags[3] == (20, 0) 228 assert tags[4] == (30, 0) 229 assert tags[5] == (11, 69.8) 230 assert tags[6] == (21, 276.1) 231 assert tags[7] == (31, 0) 232 assert tags[8] == (40, 62.6) 233 assert tags[9] == (41, 150.0) 234 assert tags[10] == (42, 175.0) 235 assert tags[11] == (43, 150.0) 236 assert tags[12] == (71, 1) 237 assert tags[13] == (72, 3) 238 assert tags[14] == (44, 50.0) 239 assert tags[15] == (45, 12.5) 240 assert tags[16] == (73, 0) 241 assert tags[17] == (74, 0) 242 243 244def test_export_dynamic_columns_auto_height_as_embedded_object(): 245 mtext = make_mtext(DYNAMIC_AUTO_HEIGHT) 246 collector = TagCollector(dxfversion=const.DXF2018) 247 mtext.export_embedded_object(collector) 248 tags = collector.tags 249 assert len(tags) == 18 250 assert tags[0] == (EMBEDDED_OBJ_MARKER, EMBEDDED_OBJ_STR) 251 assert tags[1] == (70, 1) 252 assert tags[2] == (10, 1) 253 assert tags[3] == (20, 0) 254 assert tags[4] == (30, 0) 255 assert tags[5] == (11, 69.8) 256 assert tags[6] == (21, 276.1) 257 assert tags[7] == (31, 0) 258 assert tags[8] == (40, 62.6) 259 assert tags[9] == (41, 158.1) 260 assert tags[10] == (42, 175.0) 261 assert tags[11] == (43, 158.1) 262 assert tags[12] == (71, 2) 263 assert tags[13] == (72, 0) 264 assert tags[14] == (44, 50.0) 265 assert tags[15] == (45, 12.5) 266 assert tags[16] == (73, 1) 267 assert tags[17] == (74, 0) 268 269 270def test_export_dynamic_columns_manual_height_as_embedded_object(): 271 mtext = make_mtext(DYNAMIC_MANUAL_HEIGHT) 272 collector = TagCollector(dxfversion=const.DXF2018) 273 mtext.export_embedded_object(collector) 274 tags = collector.tags 275 assert len(tags) == 21 276 assert tags[0] == (EMBEDDED_OBJ_MARKER, EMBEDDED_OBJ_STR) 277 assert tags[1] == (70, 1) 278 assert tags[2] == (10, 1) 279 assert tags[3] == (20, 0) 280 assert tags[4] == (30, 0) 281 assert tags[5] == (11, 69.8) 282 assert tags[6] == (21, 276.1) 283 assert tags[7] == (31, 0) 284 assert tags[8] == (40, 62.6) 285 assert tags[9] == (41, 0.0) 286 assert tags[10] == (42, 175.0) 287 assert tags[11] == (43, 164.8) 288 assert tags[12] == (71, 2) 289 assert tags[13] == (72, 3) 290 assert tags[14] == (44, 50.0) 291 assert tags[15] == (45, 12.5) 292 assert tags[16] == (73, 0) 293 assert tags[17] == (74, 0) 294 assert tags[18] == (46, 164.8) 295 assert tags[19] == (46, 154.3) 296 assert tags[20] == (46, 0) 297 298 299def new_mtext_with_columns(count=3): 300 columns = MTextColumns() 301 columns.count = count 302 columns.width = 10 303 columns.gutter_width = 0.5 304 columns.defined_height = 50 305 mtext = MText.new() 306 mtext.setup_columns(columns, linked=False) 307 return mtext 308 309 310def test_create_new_mtext_with_columns(): 311 mtext = new_mtext_with_columns(3) 312 columns = mtext.columns 313 assert columns.column_type == ColumnType.STATIC 314 assert len(columns.linked_columns) == 0 315 assert len(columns.heights) == 0, "all columns have the same defined height" 316 assert mtext.dxf.width == columns.width 317 assert columns.total_height == columns.defined_height 318 assert columns.total_width == 31 319 320 # default location and text direction: 321 assert mtext.dxf.insert == (0, 0, 0) 322 assert mtext.dxf.text_direction == (1, 0, 0) 323 324 325if __name__ == '__main__': 326 pytest.main([__file__]) 327