pdfdancer-client-python 0.2.16__py3-none-any.whl → 0.2.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pdfdancer-client-python might be problematic. Click here for more details.
- pdfdancer/__init__.py +29 -2
- pdfdancer/exceptions.py +3 -3
- pdfdancer/fingerprint.py +121 -0
- pdfdancer/models.py +243 -27
- pdfdancer/paragraph_builder.py +2 -1
- pdfdancer/path_builder.py +557 -0
- pdfdancer/pdfdancer_v1.py +900 -113
- pdfdancer/types.py +3 -3
- pdfdancer_client_python-0.2.18.dist-info/METADATA +585 -0
- pdfdancer_client_python-0.2.18.dist-info/RECORD +15 -0
- pdfdancer_client_python-0.2.18.dist-info/licenses/LICENSE +202 -0
- pdfdancer_client_python-0.2.18.dist-info/licenses/NOTICE +8 -0
- pdfdancer_client_python-0.2.16.dist-info/METADATA +0 -190
- pdfdancer_client_python-0.2.16.dist-info/RECORD +0 -11
- {pdfdancer_client_python-0.2.16.dist-info → pdfdancer_client_python-0.2.18.dist-info}/WHEEL +0 -0
- {pdfdancer_client_python-0.2.16.dist-info → pdfdancer_client_python-0.2.18.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PathBuilder for the PDFDancer Python client.
|
|
3
|
+
Provides fluent interface for constructing vector paths with lines and curves.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional, List
|
|
7
|
+
|
|
8
|
+
from .exceptions import ValidationException
|
|
9
|
+
from .models import Path, Line, Bezier, PathSegment, Point, Color, Position
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PathBuilder:
|
|
13
|
+
"""
|
|
14
|
+
Builder class for constructing Path objects with fluent interface.
|
|
15
|
+
Allows building complex vector paths from multiple line and bezier segments.
|
|
16
|
+
All coordinates are absolute page coordinates.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, client: 'PDFDancer', page_index: int):
|
|
20
|
+
"""
|
|
21
|
+
Initialize the path builder with a client reference and page index.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
client: The PDFDancer instance for adding the path
|
|
25
|
+
page_index: The page number (0-indexed)
|
|
26
|
+
"""
|
|
27
|
+
if client is None:
|
|
28
|
+
raise ValidationException("Client cannot be null")
|
|
29
|
+
|
|
30
|
+
self._client = client
|
|
31
|
+
self._page_index = page_index
|
|
32
|
+
self._segments: List[PathSegment] = []
|
|
33
|
+
self._even_odd_fill: bool = False
|
|
34
|
+
self._current_stroke_color: Optional[Color] = Color(0, 0, 0) # Black default
|
|
35
|
+
self._current_fill_color: Optional[Color] = None
|
|
36
|
+
self._current_stroke_width: float = 1.0
|
|
37
|
+
self._current_dash_array: Optional[List[float]] = None
|
|
38
|
+
self._current_dash_phase: Optional[float] = None
|
|
39
|
+
|
|
40
|
+
def stroke_color(self, color: Color) -> 'PathBuilder':
|
|
41
|
+
"""
|
|
42
|
+
Set the stroke color for subsequent segments.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
color: The stroke color
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Self for method chaining
|
|
49
|
+
"""
|
|
50
|
+
self._current_stroke_color = color
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
def fill_color(self, color: Color) -> 'PathBuilder':
|
|
54
|
+
"""
|
|
55
|
+
Set the fill color for subsequent segments.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
color: The fill color
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Self for method chaining
|
|
62
|
+
"""
|
|
63
|
+
self._current_fill_color = color
|
|
64
|
+
return self
|
|
65
|
+
|
|
66
|
+
def stroke_width(self, width: float) -> 'PathBuilder':
|
|
67
|
+
"""
|
|
68
|
+
Set the stroke width for subsequent segments.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
width: The stroke width in points
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Self for method chaining
|
|
75
|
+
"""
|
|
76
|
+
if width <= 0:
|
|
77
|
+
raise ValidationException("Stroke width must be positive")
|
|
78
|
+
self._current_stroke_width = width
|
|
79
|
+
return self
|
|
80
|
+
|
|
81
|
+
def dash_pattern(self, dash_array: List[float], dash_phase: float = 0.0) -> 'PathBuilder':
|
|
82
|
+
"""
|
|
83
|
+
Set a dash pattern for subsequent segments.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
dash_array: List of on/off lengths (e.g., [10, 5] = 10pt on, 5pt off)
|
|
87
|
+
dash_phase: Offset into the pattern
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Self for method chaining
|
|
91
|
+
"""
|
|
92
|
+
self._current_dash_array = dash_array
|
|
93
|
+
self._current_dash_phase = dash_phase
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
def solid(self) -> 'PathBuilder':
|
|
97
|
+
"""
|
|
98
|
+
Set segments to solid (no dash pattern).
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Self for method chaining
|
|
102
|
+
"""
|
|
103
|
+
self._current_dash_array = None
|
|
104
|
+
self._current_dash_phase = None
|
|
105
|
+
return self
|
|
106
|
+
|
|
107
|
+
def add_line(self, p0: Point, p1: Point) -> 'PathBuilder':
|
|
108
|
+
"""
|
|
109
|
+
Add a straight line segment to the path.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
p0: Starting point
|
|
113
|
+
p1: Ending point
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Self for method chaining
|
|
117
|
+
"""
|
|
118
|
+
line = Line(
|
|
119
|
+
p0=p0,
|
|
120
|
+
p1=p1,
|
|
121
|
+
stroke_color=self._current_stroke_color,
|
|
122
|
+
fill_color=self._current_fill_color,
|
|
123
|
+
stroke_width=self._current_stroke_width,
|
|
124
|
+
dash_array=self._current_dash_array,
|
|
125
|
+
dash_phase=self._current_dash_phase
|
|
126
|
+
)
|
|
127
|
+
self._segments.append(line)
|
|
128
|
+
return self
|
|
129
|
+
|
|
130
|
+
def add_bezier(self, p0: Point, p1: Point, p2: Point, p3: Point) -> 'PathBuilder':
|
|
131
|
+
"""
|
|
132
|
+
Add a cubic Bezier curve segment to the path.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
p0: Starting point
|
|
136
|
+
p1: First control point
|
|
137
|
+
p2: Second control point
|
|
138
|
+
p3: Ending point
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Self for method chaining
|
|
142
|
+
"""
|
|
143
|
+
bezier = Bezier(
|
|
144
|
+
p0=p0,
|
|
145
|
+
p1=p1,
|
|
146
|
+
p2=p2,
|
|
147
|
+
p3=p3,
|
|
148
|
+
stroke_color=self._current_stroke_color,
|
|
149
|
+
fill_color=self._current_fill_color,
|
|
150
|
+
stroke_width=self._current_stroke_width,
|
|
151
|
+
dash_array=self._current_dash_array,
|
|
152
|
+
dash_phase=self._current_dash_phase
|
|
153
|
+
)
|
|
154
|
+
self._segments.append(bezier)
|
|
155
|
+
return self
|
|
156
|
+
|
|
157
|
+
def even_odd_fill(self, enabled: bool = True) -> 'PathBuilder':
|
|
158
|
+
"""
|
|
159
|
+
Set the fill rule to even-odd (vs nonzero winding).
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
enabled: True for even-odd, False for nonzero winding
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Self for method chaining
|
|
166
|
+
"""
|
|
167
|
+
self._even_odd_fill = enabled
|
|
168
|
+
return self
|
|
169
|
+
|
|
170
|
+
def add(self) -> bool:
|
|
171
|
+
"""
|
|
172
|
+
Build the path and add it to the PDF document.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
True if successful
|
|
176
|
+
|
|
177
|
+
Raises:
|
|
178
|
+
ValidationException: If required properties are missing
|
|
179
|
+
"""
|
|
180
|
+
if not self._segments:
|
|
181
|
+
raise ValidationException("Path must have at least one segment")
|
|
182
|
+
|
|
183
|
+
# Create position with only page index set
|
|
184
|
+
position = Position.at_page_coordinates(self._page_index, 0, 0)
|
|
185
|
+
|
|
186
|
+
# Build the Path object
|
|
187
|
+
path = Path(
|
|
188
|
+
position=position,
|
|
189
|
+
path_segments=self._segments,
|
|
190
|
+
even_odd_fill=self._even_odd_fill
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Add it using the client's internal method
|
|
194
|
+
# noinspection PyProtectedMember
|
|
195
|
+
return self._client._add_path(path)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class LineBuilder:
|
|
199
|
+
"""
|
|
200
|
+
Builder class for constructing Line objects with fluent interface.
|
|
201
|
+
Mirrors the Java client LineBuilder API.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
def __init__(self, client: 'PDFDancer', page_index: int):
|
|
205
|
+
"""
|
|
206
|
+
Initialize the line builder.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
client: The PDFDancer instance for adding the line
|
|
210
|
+
page_index: The page number (0-indexed)
|
|
211
|
+
"""
|
|
212
|
+
if client is None:
|
|
213
|
+
raise ValidationException("Client cannot be null")
|
|
214
|
+
|
|
215
|
+
self._client = client
|
|
216
|
+
self._page_index = page_index
|
|
217
|
+
self._p0: Optional[Point] = None
|
|
218
|
+
self._p1: Optional[Point] = None
|
|
219
|
+
self._stroke_color: Optional[Color] = Color(0, 0, 0) # Black default
|
|
220
|
+
self._fill_color: Optional[Color] = None
|
|
221
|
+
self._stroke_width: float = 1.0
|
|
222
|
+
self._dash_array: Optional[List[float]] = None
|
|
223
|
+
self._dash_phase: Optional[float] = None
|
|
224
|
+
|
|
225
|
+
def from_point(self, x: float, y: float) -> 'LineBuilder':
|
|
226
|
+
"""
|
|
227
|
+
Set the starting point of the line (absolute page coordinates).
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
x: X coordinate on the page
|
|
231
|
+
y: Y coordinate on the page
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Self for method chaining
|
|
235
|
+
"""
|
|
236
|
+
self._p0 = Point(x, y)
|
|
237
|
+
return self
|
|
238
|
+
|
|
239
|
+
def to_point(self, x: float, y: float) -> 'LineBuilder':
|
|
240
|
+
"""
|
|
241
|
+
Set the ending point of the line (absolute page coordinates).
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
x: X coordinate on the page
|
|
245
|
+
y: Y coordinate on the page
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
Self for method chaining
|
|
249
|
+
"""
|
|
250
|
+
self._p1 = Point(x, y)
|
|
251
|
+
return self
|
|
252
|
+
|
|
253
|
+
def stroke_color(self, color: Color) -> 'LineBuilder':
|
|
254
|
+
"""
|
|
255
|
+
Set the stroke color.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
color: The stroke color
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Self for method chaining
|
|
262
|
+
"""
|
|
263
|
+
self._stroke_color = color
|
|
264
|
+
return self
|
|
265
|
+
|
|
266
|
+
def fill_color(self, color: Color) -> 'LineBuilder':
|
|
267
|
+
"""
|
|
268
|
+
Set the fill color.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
color: The fill color
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
Self for method chaining
|
|
275
|
+
"""
|
|
276
|
+
self._fill_color = color
|
|
277
|
+
return self
|
|
278
|
+
|
|
279
|
+
def stroke_width(self, width: float) -> 'LineBuilder':
|
|
280
|
+
"""
|
|
281
|
+
Set the stroke width.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
width: The stroke width in points
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Self for method chaining
|
|
288
|
+
"""
|
|
289
|
+
if width <= 0:
|
|
290
|
+
raise ValidationException("Stroke width must be positive")
|
|
291
|
+
self._stroke_width = width
|
|
292
|
+
return self
|
|
293
|
+
|
|
294
|
+
def dash_pattern(self, dash_array: List[float], dash_phase: float = 0.0) -> 'LineBuilder':
|
|
295
|
+
"""
|
|
296
|
+
Set a dash pattern.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
dash_array: List of on/off lengths (e.g., [10, 5] = 10pt on, 5pt off)
|
|
300
|
+
dash_phase: Offset into the pattern
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
Self for method chaining
|
|
304
|
+
"""
|
|
305
|
+
self._dash_array = dash_array
|
|
306
|
+
self._dash_phase = dash_phase
|
|
307
|
+
return self
|
|
308
|
+
|
|
309
|
+
def solid(self) -> 'LineBuilder':
|
|
310
|
+
"""
|
|
311
|
+
Set line to solid (no dash pattern).
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
Self for method chaining
|
|
315
|
+
"""
|
|
316
|
+
self._dash_array = None
|
|
317
|
+
self._dash_phase = None
|
|
318
|
+
return self
|
|
319
|
+
|
|
320
|
+
def add(self) -> bool:
|
|
321
|
+
"""
|
|
322
|
+
Build the line and add it to the PDF document.
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
True if successful
|
|
326
|
+
|
|
327
|
+
Raises:
|
|
328
|
+
ValidationException: If required properties are missing
|
|
329
|
+
"""
|
|
330
|
+
if self._p0 is None:
|
|
331
|
+
raise ValidationException("Line start point must be set using from_point()")
|
|
332
|
+
if self._p1 is None:
|
|
333
|
+
raise ValidationException("Line end point must be set using to_point()")
|
|
334
|
+
|
|
335
|
+
# Build the Line object
|
|
336
|
+
line = Line(
|
|
337
|
+
p0=self._p0,
|
|
338
|
+
p1=self._p1,
|
|
339
|
+
stroke_color=self._stroke_color,
|
|
340
|
+
fill_color=self._fill_color,
|
|
341
|
+
stroke_width=self._stroke_width,
|
|
342
|
+
dash_array=self._dash_array,
|
|
343
|
+
dash_phase=self._dash_phase
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Create position with only page index set
|
|
347
|
+
position = Position.at_page_coordinates(self._page_index, 0, 0)
|
|
348
|
+
|
|
349
|
+
# Wrap in Path with single segment
|
|
350
|
+
path = Path(
|
|
351
|
+
position=position,
|
|
352
|
+
path_segments=[line],
|
|
353
|
+
even_odd_fill=False
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
# Add it using the client's internal method
|
|
357
|
+
# noinspection PyProtectedMember
|
|
358
|
+
return self._client._add_path(path)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class BezierBuilder:
|
|
362
|
+
"""
|
|
363
|
+
Builder class for constructing Bezier curve objects with fluent interface.
|
|
364
|
+
Mirrors the Java client BezierBuilder API.
|
|
365
|
+
"""
|
|
366
|
+
|
|
367
|
+
def __init__(self, client: 'PDFDancer', page_index: int):
|
|
368
|
+
"""
|
|
369
|
+
Initialize the bezier builder.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
client: The PDFDancer instance for adding the bezier
|
|
373
|
+
page_index: The page number (0-indexed)
|
|
374
|
+
"""
|
|
375
|
+
if client is None:
|
|
376
|
+
raise ValidationException("Client cannot be null")
|
|
377
|
+
|
|
378
|
+
self._client = client
|
|
379
|
+
self._page_index = page_index
|
|
380
|
+
self._p0: Optional[Point] = None
|
|
381
|
+
self._p1: Optional[Point] = None
|
|
382
|
+
self._p2: Optional[Point] = None
|
|
383
|
+
self._p3: Optional[Point] = None
|
|
384
|
+
self._stroke_color: Optional[Color] = Color(0, 0, 0) # Black default
|
|
385
|
+
self._fill_color: Optional[Color] = None
|
|
386
|
+
self._stroke_width: float = 1.0
|
|
387
|
+
self._dash_array: Optional[List[float]] = None
|
|
388
|
+
self._dash_phase: Optional[float] = None
|
|
389
|
+
|
|
390
|
+
def from_point(self, x: float, y: float) -> 'BezierBuilder':
|
|
391
|
+
"""
|
|
392
|
+
Set the starting point of the curve (absolute page coordinates).
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
x: X coordinate on the page
|
|
396
|
+
y: Y coordinate on the page
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Self for method chaining
|
|
400
|
+
"""
|
|
401
|
+
self._p0 = Point(x, y)
|
|
402
|
+
return self
|
|
403
|
+
|
|
404
|
+
def control_point_1(self, x: float, y: float) -> 'BezierBuilder':
|
|
405
|
+
"""
|
|
406
|
+
Set the first control point (absolute page coordinates).
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
x: X coordinate on the page
|
|
410
|
+
y: Y coordinate on the page
|
|
411
|
+
|
|
412
|
+
Returns:
|
|
413
|
+
Self for method chaining
|
|
414
|
+
"""
|
|
415
|
+
self._p1 = Point(x, y)
|
|
416
|
+
return self
|
|
417
|
+
|
|
418
|
+
def control_point_2(self, x: float, y: float) -> 'BezierBuilder':
|
|
419
|
+
"""
|
|
420
|
+
Set the second control point (absolute page coordinates).
|
|
421
|
+
|
|
422
|
+
Args:
|
|
423
|
+
x: X coordinate on the page
|
|
424
|
+
y: Y coordinate on the page
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
Self for method chaining
|
|
428
|
+
"""
|
|
429
|
+
self._p2 = Point(x, y)
|
|
430
|
+
return self
|
|
431
|
+
|
|
432
|
+
def to_point(self, x: float, y: float) -> 'BezierBuilder':
|
|
433
|
+
"""
|
|
434
|
+
Set the ending point of the curve (absolute page coordinates).
|
|
435
|
+
|
|
436
|
+
Args:
|
|
437
|
+
x: X coordinate on the page
|
|
438
|
+
y: Y coordinate on the page
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
Self for method chaining
|
|
442
|
+
"""
|
|
443
|
+
self._p3 = Point(x, y)
|
|
444
|
+
return self
|
|
445
|
+
|
|
446
|
+
def stroke_color(self, color: Color) -> 'BezierBuilder':
|
|
447
|
+
"""
|
|
448
|
+
Set the stroke color.
|
|
449
|
+
|
|
450
|
+
Args:
|
|
451
|
+
color: The stroke color
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
Self for method chaining
|
|
455
|
+
"""
|
|
456
|
+
self._stroke_color = color
|
|
457
|
+
return self
|
|
458
|
+
|
|
459
|
+
def fill_color(self, color: Color) -> 'BezierBuilder':
|
|
460
|
+
"""
|
|
461
|
+
Set the fill color.
|
|
462
|
+
|
|
463
|
+
Args:
|
|
464
|
+
color: The fill color
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
Self for method chaining
|
|
468
|
+
"""
|
|
469
|
+
self._fill_color = color
|
|
470
|
+
return self
|
|
471
|
+
|
|
472
|
+
def stroke_width(self, width: float) -> 'BezierBuilder':
|
|
473
|
+
"""
|
|
474
|
+
Set the stroke width.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
width: The stroke width in points
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
Self for method chaining
|
|
481
|
+
"""
|
|
482
|
+
if width <= 0:
|
|
483
|
+
raise ValidationException("Stroke width must be positive")
|
|
484
|
+
self._stroke_width = width
|
|
485
|
+
return self
|
|
486
|
+
|
|
487
|
+
def dash_pattern(self, dash_array: List[float], dash_phase: float = 0.0) -> 'BezierBuilder':
|
|
488
|
+
"""
|
|
489
|
+
Set a dash pattern.
|
|
490
|
+
|
|
491
|
+
Args:
|
|
492
|
+
dash_array: List of on/off lengths (e.g., [10, 5] = 10pt on, 5pt off)
|
|
493
|
+
dash_phase: Offset into the pattern
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
Self for method chaining
|
|
497
|
+
"""
|
|
498
|
+
self._dash_array = dash_array
|
|
499
|
+
self._dash_phase = dash_phase
|
|
500
|
+
return self
|
|
501
|
+
|
|
502
|
+
def solid(self) -> 'BezierBuilder':
|
|
503
|
+
"""
|
|
504
|
+
Set curve to solid (no dash pattern).
|
|
505
|
+
|
|
506
|
+
Returns:
|
|
507
|
+
Self for method chaining
|
|
508
|
+
"""
|
|
509
|
+
self._dash_array = None
|
|
510
|
+
self._dash_phase = None
|
|
511
|
+
return self
|
|
512
|
+
|
|
513
|
+
def add(self) -> bool:
|
|
514
|
+
"""
|
|
515
|
+
Build the bezier curve and add it to the PDF document.
|
|
516
|
+
|
|
517
|
+
Returns:
|
|
518
|
+
True if successful
|
|
519
|
+
|
|
520
|
+
Raises:
|
|
521
|
+
ValidationException: If required properties are missing
|
|
522
|
+
"""
|
|
523
|
+
if self._p0 is None:
|
|
524
|
+
raise ValidationException("Bezier start point must be set using from_point()")
|
|
525
|
+
if self._p1 is None:
|
|
526
|
+
raise ValidationException("Bezier first control point must be set using control_point_1()")
|
|
527
|
+
if self._p2 is None:
|
|
528
|
+
raise ValidationException("Bezier second control point must be set using control_point_2()")
|
|
529
|
+
if self._p3 is None:
|
|
530
|
+
raise ValidationException("Bezier end point must be set using to_point()")
|
|
531
|
+
|
|
532
|
+
# Build the Bezier object
|
|
533
|
+
bezier = Bezier(
|
|
534
|
+
p0=self._p0,
|
|
535
|
+
p1=self._p1,
|
|
536
|
+
p2=self._p2,
|
|
537
|
+
p3=self._p3,
|
|
538
|
+
stroke_color=self._stroke_color,
|
|
539
|
+
fill_color=self._fill_color,
|
|
540
|
+
stroke_width=self._stroke_width,
|
|
541
|
+
dash_array=self._dash_array,
|
|
542
|
+
dash_phase=self._dash_phase
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
# Create position with only page index set
|
|
546
|
+
position = Position.at_page_coordinates(self._page_index, 0, 0)
|
|
547
|
+
|
|
548
|
+
# Wrap in Path with single segment
|
|
549
|
+
path = Path(
|
|
550
|
+
position=position,
|
|
551
|
+
path_segments=[bezier],
|
|
552
|
+
even_odd_fill=False
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# Add it using the client's internal method
|
|
556
|
+
# noinspection PyProtectedMember
|
|
557
|
+
return self._client._add_path(path)
|