File: shapefile_rendering.py

package info (click to toggle)
ezdxf 1.4.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 104,528 kB
  • sloc: python: 182,341; makefile: 116; lisp: 20; ansic: 4
file content (184 lines) | stat: -rw-r--r-- 6,496 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#  Copyright (c) 2022-2023, Manfred Moitzi
#  License: MIT License
from typing import Set, List
import pathlib
import string
import ezdxf
from ezdxf import path, zoom
from ezdxf.fonts import shapefile
from ezdxf.math import Matrix44
from ezdxf.filemanagement import find_support_file

CWD = pathlib.Path("~/Desktop/Outbox").expanduser()
if not CWD.exists():
    CWD = pathlib.Path("..")

# ------------------------------------------------------------------------------
# The support of SHX- and SHP files is a work in progress not ready for
# production yet!
# ------------------------------------------------------------------------------

# I can not include the test files in the repository because these shape files
# are generated from copyright protected Autodesk SHX files by the program dumpshx.exe
# Add the directory containing the shx/shp files to your config file:
# 1. create a default config file in home directory at ~/.config/ezdxf/ezdxf.ini
#
#     $ ezdxf config --home
#
# 2. add the font directory as support dir, this is my config file:
# [core]
# default_dimension_text_style = OpenSansCondensed-Light
# test_files = ~/src/dxftest
# support_dirs = ~/src/shx-fonts
# 	~/src/ctb
# ...

SHAPE_FILE_DIRS = [r"C:\Source\shx-fonts"]

LETTERS = (
    string.ascii_uppercase,
    string.ascii_lowercase,
    string.digits + string.digits,
    string.punctuation,
)
RENDER_POS = 0
SPECIAL_CODES = "special_codes.shp"


def render_font(fontname: str):
    fontname = find_support_file(fontname, SHAPE_FILE_DIRS)
    font = shapefile.readfile(fontname)
    doc = ezdxf.new()
    msp = doc.modelspace()
    line_height = font.cap_height / 3 * 5
    y = RENDER_POS
    for text_line in (f"FONT: {fontname}",) + LETTERS:
        text_path = font.render_text(text_line)
        text_path = text_path.transform(Matrix44.translate(0, y, 0))
        path.render_splines_and_polylines(msp, [text_path])
        y -= line_height

    zoom.extents(msp)
    filename = pathlib.Path(fontname).name
    filename = CWD / (filename + ".dxf")
    doc.saveas(filename)
    print(f"created {filename}")


def render_txt(fontname: str, text: str):
    fontname = find_support_file(fontname, SHAPE_FILE_DIRS)
    font = shapefile.readfile(fontname)
    doc = ezdxf.new()
    msp = doc.modelspace()
    text_path = font.render_text(text)
    path.render_splines_and_polylines(msp, [text_path])

    zoom.extents(msp)
    filename = pathlib.Path(fontname).name
    filename = CWD / (filename + ".text.dxf")
    doc.saveas(filename)
    print(f"created {filename}")


def debug_letter(shp_data: bytes, num: int, filename: str):
    font = shapefile.shp_load(shp_data)
    doc = ezdxf.new()
    msp = doc.modelspace()
    text_path = font.render_shape(num)
    path.render_splines_and_polylines(msp, [text_path])
    zoom.extents(msp)
    doc.saveas(CWD / filename)
    print(f"created {filename}")


def render_all_chars(fontpath: pathlib.Path):
    # ignore non-ascii characters in comments and names
    shp_data = fontpath.read_bytes()
    font = shapefile.shp_load(shp_data)
    doc = ezdxf.new()
    msp = doc.modelspace()
    numbers = list(font.shapes.keys())
    text_path = font.render_shapes(numbers)
    path.render_splines_and_polylines(msp, [text_path])
    zoom.extents(msp)
    export_path = fontpath.with_suffix(".dxf")
    doc.saveas(export_path)
    print(f"created {export_path}")


def find_fonts_with_codes(folder: str, codes: Set[int]):
    shapefile.DEBUG = True
    shapefile.DEBUG_CODES = set(codes)
    export_data: List[bytes] = []
    num = 32
    for filepath in pathlib.Path(folder).glob("*.shp"):
        print("-" * 79)
        print(f"probing: {filepath}")
        # ignore non-ascii characters in comments and names
        shp_data = filepath.read_bytes()
        try:
            font = shapefile.shp_load(shp_data)
        except shapefile.ShapeFileException as e:
            print(str(e))
            continue
        shapefile.DEBUG_SHAPE_NUMBERS.clear()
        font.render_shapes(list(font.shapes.keys()))
        if len(shapefile.DEBUG_SHAPE_NUMBERS) == 0:
            continue
        export_data.append(b";;" + str(filepath).encode())
        for shape_number in shapefile.DEBUG_SHAPE_NUMBERS:
            export_data.append(f";; source shape number *{shape_number:05X}".encode())
            export_data.extend(font.shape_string(shape_number, as_num=num))
            export_data.append(b"")
            num += 1
    with open(CWD / SPECIAL_CODES, mode="wb") as fp:
        fp.write(b"\r\n".join(export_data))
    shapefile.DEBUG = False


# bold.shp letter C:
DEBUG_UCC = b"""
*00043,156,ucc
2,8,(-2,30),5,1,
11,(0,125,0,30,044),
078,2,6,5,1,
11,(0,125,0,30,-044),
078,2,6,010,5,1,11,(0,119,0,29,044),2,6,5,1,
11,(0,119,0,29,-044),2,6,010,5,1,11,(0,114,0,28,044),2,6,5,1,
11,(0,114,0,28,-044),2,6,010,5,1,11,(0,108,0,27,044),2,6,5,1,
11,(0,108,0,27,-044),2,6,010,5,1,11,(0,102,0,26,044),2,6,5,1,
11,(0,102,0,26,-044),2,6,010,5,1,11,(0,97,0,25,044),2,6,5,1,
11,(0,97,0,25,-044),2,6,010,5,1,11,(0,90,0,24,044),2,6,5,1,
11,(0,90,0,24,-044),2,6,8,(60,-30),0
"""
DEBUG_UCR = b"""*00052,259,ucr
060,8,(0,28),2,064,1,8,(0,20),8,(22,0),10,(10,-024),8,(-22,0),2,
06C,1,8,(23,0),10,(6,-022),8,(1,-18),11,(0,97,0,14,041),3,2,0D0,
4,2,11,(85,0,0,8,-051),8,(-1,18),11,(0,15,0,12,002),
11,(199,0,0,16,064),8,(-28,0),8,(0,-60),2,012,1,8,(0,58),
8,(27,0),11,(0,85,0,15,-024),11,(205,0,0,11,-022),8,(1,-18),5,
11,(0,148,0,9,041),2,6,018,1,5,11,(0,136,0,10,041),2,6,018,1,5,
11,(0,119,0,11,041),2,6,018,1,5,11,(0,108,0,12,041),2,6,018,1,5,
11,(0,102,0,13,041),2,6,1,8,(-1,18),10,(7,002),8,(-24,0),
8,(0,-28),048,2,012,1,8,(0,56),8,(26,0),11,(0,131,0,14,-024),
11,(142,0,0,10,-022),8,(1,-18),2,028,1,8,(-1,18),10,(8,002),
8,(-25,0),8,(0,-28),028,2,012,1,8,(0,54),8,(25,0),10,(13,-024),5,
010,10,(9,-022),8,(1,-18),6,8,(-25,0),2,012,1,8,(0,24),8,(24,0),
10,(12,-024),8,(-24,0),2,012,1,8,(0,22),8,(23,0),10,(11,-024),
8,(-23,0),2,8,(47,-33),0
"""
DEBUG = False
if __name__ == "__main__":
    render_font("symap.shx")
    render_font("bold.shx")
    render_font("ISO.shx")
    render_font("isocp.shx")
    render_txt("bold.shx", " ___A_A___ ___")
    if DEBUG:
        find_fonts_with_codes("C:\\Source\\shx-fonts", codes={11})
        render_all_chars(CWD / SPECIAL_CODES)
        render_txt("bold.shx", "R?")
        debug_letter(DEBUG_UCR, 0x43, "bold_c.dxf")
        render_all_chars(
            pathlib.Path(find_support_file("bold.shx", ezdxf.options.support_dirs))
        )