返回 ppt-master
models.py
1 #!/usr/bin/env python3
2 """
3 PPT Master - PPTX Shape Models
4
5 Immutable value objects shared by the preset catalog loader and evaluator.
6
7 Usage:
8 Import model classes from pptx_shapes.models.
9
10 Examples:
11 from pptx_shapes.models import GuideDefinition
12
13 Dependencies:
14 None (only uses standard library)
15 """
16
17 from __future__ import annotations
18
19 from dataclasses import dataclass
20 from types import MappingProxyType
21 from typing import Mapping
22
23
24 @dataclass(frozen=True)
25 class GuideDefinition:
26 """One named DrawingML guide formula."""
27
28 name: str
29 formula: str
30
31
32 @dataclass(frozen=True)
33 class PointExpression:
34 """A point whose coordinates are numeric literals or guide names."""
35
36 x: str
37 y: str
38
39
40 @dataclass(frozen=True)
41 class AdjustHandleDefinition:
42 """An XY or polar adjustment handle from ``a:ahLst``."""
43
44 kind: str
45 position: PointExpression
46 x_reference: str | None = None
47 minimum_x: str | None = None
48 maximum_x: str | None = None
49 y_reference: str | None = None
50 minimum_y: str | None = None
51 maximum_y: str | None = None
52 angle_reference: str | None = None
53 minimum_angle: str | None = None
54 maximum_angle: str | None = None
55 radius_reference: str | None = None
56 minimum_radius: str | None = None
57 maximum_radius: str | None = None
58
59
60 @dataclass(frozen=True)
61 class ConnectionSiteDefinition:
62 """One preset connection site before guide evaluation."""
63
64 angle: str
65 position: PointExpression
66
67
68 @dataclass(frozen=True)
69 class TextRectangleDefinition:
70 """The preset's internal text rectangle expressions."""
71
72 left: str
73 top: str
74 right: str
75 bottom: str
76
77
78 @dataclass(frozen=True)
79 class PathCommandDefinition:
80 """A DrawingML path command with parameters in document order.
81
82 Parameter order is ``x,y`` for move/line, point order for Bezier commands,
83 and ``wR,hR,stAng,swAng`` for arcs. ``close`` has no parameters.
84 """
85
86 name: str
87 parameters: tuple[str, ...]
88
89
90 @dataclass(frozen=True)
91 class ShapePathDefinition:
92 """One path in a preset geometry definition."""
93
94 coordinate_width: str | None
95 coordinate_height: str | None
96 fill: str
97 stroke: bool
98 extrusion_ok: bool
99 commands: tuple[PathCommandDefinition, ...]
100
101
102 @dataclass(frozen=True)
103 class PresetShapeDefinition:
104 """Complete immutable source definition for one preset shape."""
105
106 name: str
107 adjustments: tuple[GuideDefinition, ...]
108 guides: tuple[GuideDefinition, ...]
109 handles: tuple[AdjustHandleDefinition, ...]
110 connections: tuple[ConnectionSiteDefinition, ...]
111 text_rectangle: TextRectangleDefinition | None
112 paths: tuple[ShapePathDefinition, ...]
113
114
115 @dataclass(frozen=True)
116 class EvaluatedPoint:
117 """A point in the evaluated shape-local coordinate system."""
118
119 x: float
120 y: float
121
122
123 @dataclass(frozen=True)
124 class EvaluatedAdjustHandle:
125 """An adjustment handle with resolved position and constraint bounds."""
126
127 kind: str
128 position: EvaluatedPoint
129 x_reference: str | None = None
130 minimum_x: float | None = None
131 maximum_x: float | None = None
132 y_reference: str | None = None
133 minimum_y: float | None = None
134 maximum_y: float | None = None
135 angle_reference: str | None = None
136 minimum_angle: float | None = None
137 maximum_angle: float | None = None
138 radius_reference: str | None = None
139 minimum_radius: float | None = None
140 maximum_radius: float | None = None
141
142
143 @dataclass(frozen=True)
144 class EvaluatedConnectionSite:
145 """A connection site with resolved angle and position."""
146
147 angle: float
148 position: EvaluatedPoint
149
150
151 @dataclass(frozen=True)
152 class EvaluatedTextRectangle:
153 """A resolved internal text rectangle."""
154
155 left: float
156 top: float
157 right: float
158 bottom: float
159
160
161 @dataclass(frozen=True)
162 class EvaluatedPathCommand:
163 """A path command whose parameters have all been resolved to numbers."""
164
165 name: str
166 parameters: tuple[float, ...]
167
168
169 @dataclass(frozen=True)
170 class EvaluatedShapePath:
171 """One resolved path and its DrawingML paint behavior."""
172
173 coordinate_width: float
174 coordinate_height: float
175 fill: str
176 stroke: bool
177 extrusion_ok: bool
178 commands: tuple[EvaluatedPathCommand, ...]
179
180
181 @dataclass(frozen=True)
182 class EvaluatedPresetGeometry:
183 """All evaluated semantic geometry for one preset shape instance."""
184
185 name: str
186 width: float
187 height: float
188 left: float
189 top: float
190 adjustments: Mapping[str, float]
191 guides: Mapping[str, float]
192 handles: tuple[EvaluatedAdjustHandle, ...]
193 connections: tuple[EvaluatedConnectionSite, ...]
194 text_rectangle: EvaluatedTextRectangle | None
195 paths: tuple[EvaluatedShapePath, ...]
196
197
198 def immutable_mapping(values: Mapping[str, float]) -> Mapping[str, float]:
199 """Return a detached, read-only copy of a numeric mapping."""
200
201 return MappingProxyType(dict(values))
202
202 lines PYTHON