postsvg 0.1.0

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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +19 -0
  3. data/.rubocop_todo.yml +141 -0
  4. data/Gemfile +15 -0
  5. data/LICENSE +25 -0
  6. data/README.adoc +473 -0
  7. data/Rakefile +10 -0
  8. data/docs/POSTSCRIPT.adoc +13 -0
  9. data/docs/postscript/fundamentals.adoc +356 -0
  10. data/docs/postscript/graphics-model.adoc +406 -0
  11. data/docs/postscript/implementation-notes.adoc +314 -0
  12. data/docs/postscript/index.adoc +153 -0
  13. data/docs/postscript/operators/arithmetic.adoc +461 -0
  14. data/docs/postscript/operators/control-flow.adoc +230 -0
  15. data/docs/postscript/operators/dictionary.adoc +191 -0
  16. data/docs/postscript/operators/graphics-state.adoc +528 -0
  17. data/docs/postscript/operators/index.adoc +288 -0
  18. data/docs/postscript/operators/painting.adoc +475 -0
  19. data/docs/postscript/operators/path-construction.adoc +553 -0
  20. data/docs/postscript/operators/stack-manipulation.adoc +374 -0
  21. data/docs/postscript/operators/transformations.adoc +479 -0
  22. data/docs/postscript/svg-mapping.adoc +369 -0
  23. data/exe/postsvg +6 -0
  24. data/lib/postsvg/cli.rb +103 -0
  25. data/lib/postsvg/colors.rb +33 -0
  26. data/lib/postsvg/converter.rb +214 -0
  27. data/lib/postsvg/errors.rb +11 -0
  28. data/lib/postsvg/graphics_state.rb +158 -0
  29. data/lib/postsvg/interpreter.rb +891 -0
  30. data/lib/postsvg/matrix.rb +106 -0
  31. data/lib/postsvg/parser/postscript_parser.rb +87 -0
  32. data/lib/postsvg/parser/transform.rb +21 -0
  33. data/lib/postsvg/parser.rb +18 -0
  34. data/lib/postsvg/path_builder.rb +101 -0
  35. data/lib/postsvg/svg_generator.rb +78 -0
  36. data/lib/postsvg/tokenizer.rb +161 -0
  37. data/lib/postsvg/version.rb +5 -0
  38. data/lib/postsvg.rb +78 -0
  39. data/postsvg.gemspec +38 -0
  40. data/scripts/regenerate_fixtures.rb +28 -0
  41. metadata +118 -0
@@ -0,0 +1,553 @@
1
+ = Path Construction Operators
2
+
3
+ == General
4
+
5
+ Path construction operators build geometric shapes by defining sequences of
6
+ connected and disconnected line and curve segments. These operators modify the
7
+ current path in the graphics state without producing any visible output until
8
+ a painting operator is executed.
9
+
10
+ All path construction operations work in the current user space coordinate
11
+ system, which may be transformed by the current transformation matrix (CTM).
12
+
13
+ [[newpath]]
14
+ == newpath
15
+
16
+ === General
17
+
18
+ The `newpath` operator initializes a new empty current path, discarding any
19
+ existing path. This is typically the first operation when beginning to
20
+ construct a new shape.
21
+
22
+ === Syntax
23
+
24
+ [source,postscript]
25
+ ----
26
+ newpath <1>
27
+ ----
28
+ <1> Initialize empty path
29
+
30
+ Where,
31
+
32
+ Stack effect: `-- ` (no arguments, no return values)
33
+
34
+ === Examples
35
+
36
+ [example]
37
+ ====
38
+ [source,postscript]
39
+ ----
40
+ newpath % Clear any existing path
41
+ 100 100 moveto % Begin constructing new path
42
+ ----
43
+
44
+ Always call `newpath` before starting a new shape to ensure no leftover path
45
+ segments from previous operations.
46
+ ====
47
+
48
+ [[moveto]]
49
+ == moveto
50
+
51
+ === General
52
+
53
+ The `moveto` operator begins a new subpath at the specified coordinates (x, y),
54
+ establishing the current point without drawing any visible marks. If a current
55
+ point already exists, `moveto` starts a disconnected subpath.
56
+
57
+ === Syntax
58
+
59
+ [source,postscript]
60
+ ----
61
+ x y moveto <1> <2> <3>
62
+ ----
63
+ <1> X-coordinate for new current point (number)
64
+ <2> Y-coordinate for new current point (number)
65
+ <3> Operator that consumes x and y from stack
66
+
67
+ Where,
68
+
69
+ `x`:: X-coordinate in user space (number)
70
+ `y`:: Y-coordinate in user space (number)
71
+
72
+ Stack effect: `x y -- `
73
+
74
+ === Examples
75
+
76
+ [example]
77
+ ====
78
+ [source,postscript]
79
+ ----
80
+ newpath
81
+ 50 50 moveto % Move to point (50, 50)
82
+ 150 50 lineto % Draw line from (50, 50) to (150, 50)
83
+ ----
84
+
85
+ The `moveto` establishes the starting point for the line drawn by `lineto`.
86
+ ====
87
+
88
+ [example]
89
+ ====
90
+ [source,postscript]
91
+ ----
92
+ newpath
93
+ 10 10 moveto % First subpath starts at (10, 10)
94
+ 90 10 lineto
95
+ 90 90 lineto
96
+ closepath
97
+
98
+ 20 20 moveto % Second disconnected subpath at (20, 20)
99
+ 80 20 lineto
100
+ 80 80 lineto
101
+ closepath
102
+ ----
103
+
104
+ Multiple `moveto` operations create disconnected subpaths within the same path.
105
+ ====
106
+
107
+ [[rmoveto]]
108
+ == rmoveto
109
+
110
+ === General
111
+
112
+ The `rmoveto` operator is similar to `moveto` but uses relative coordinates.
113
+ It adds the specified offsets (dx, dy) to the current point to determine the
114
+ new current point location.
115
+
116
+ === Syntax
117
+
118
+ [source,postscript]
119
+ ----
120
+ dx dy rmoveto <1> <2> <3>
121
+ ----
122
+ <1> X-offset from current point (number)
123
+ <2> Y-offset from current point (number)
124
+ <3> Operator that consumes dx and dy from stack
125
+
126
+ Where,
127
+
128
+ `dx`:: X-offset relative to current point (number)
129
+ `dy`:: Y-offset relative to current point (number)
130
+
131
+ Stack effect: `dx dy -- `
132
+
133
+ === Examples
134
+
135
+ [example]
136
+ ====
137
+ [source,postscript]
138
+ ----
139
+ newpath
140
+ 100 100 moveto % Absolute position
141
+ 50 0 rmoveto % Move 50 units right, now at (150, 100)
142
+ 0 50 rmoveto % Move 50 units up, now at (150, 150)
143
+ ----
144
+
145
+ Relative movements are useful for drawing shapes where only the offsets are
146
+ known, not absolute coordinates.
147
+ ====
148
+
149
+ [[lineto]]
150
+ == lineto
151
+
152
+ === General
153
+
154
+ The `lineto` operator appends a straight line segment from the current point
155
+ to the specified coordinates (x, y), which becomes the new current point.
156
+
157
+ === Syntax
158
+
159
+ [source,postscript]
160
+ ----
161
+ x y lineto <1> <2> <3>
162
+ ----
163
+ <1> X-coordinate of line endpoint (number)
164
+ <2> Y-coordinate of line endpoint (number)
165
+ <3> Operator that appends line segment
166
+
167
+ Where,
168
+
169
+ `x`:: X-coordinate of endpoint in user space (number)
170
+ `y`:: Y-coordinate of endpoint in user space (number)
171
+
172
+ Stack effect: `x y -- `
173
+
174
+ === Examples
175
+
176
+ [example]
177
+ ====
178
+ [source,postscript]
179
+ ----
180
+ newpath
181
+ 10 10 moveto % Start at (10, 10)
182
+ 90 10 lineto % Draw horizontal line to (90, 10)
183
+ 90 90 lineto % Draw vertical line to (90, 90)
184
+ 10 90 lineto % Draw horizontal line to (10, 90)
185
+ closepath % Close back to start
186
+ stroke % Render the square
187
+ ----
188
+
189
+ Creates a square outline using four line segments.
190
+ ====
191
+
192
+ [[rlineto]]
193
+ == rlineto
194
+
195
+ === General
196
+
197
+ The `rlineto` operator appends a straight line segment from the current point
198
+ by the specified offsets (dx, dy). The endpoint becomes the new current point.
199
+
200
+ === Syntax
201
+
202
+ [source,postscript]
203
+ ----
204
+ dx dy rlineto <1> <2> <3>
205
+ ----
206
+ <1> X-offset for line endpoint (number)
207
+ <2> Y-offset for line endpoint (number)
208
+ <3> Operator that appends relative line
209
+
210
+ Where,
211
+
212
+ `dx`:: X-offset from current point (number)
213
+ `dy`:: Y-offset from current point (number)
214
+
215
+ Stack effect: `dx dy -- `
216
+
217
+ === Examples
218
+
219
+ [example]
220
+ ====
221
+ [source,postscript]
222
+ ----
223
+ newpath
224
+ 50 50 moveto % Start at (50, 50)
225
+ 100 0 rlineto % Draw 100 units right
226
+ 0 100 rlineto % Draw 100 units up
227
+ -100 0 rlineto % Draw 100 units left
228
+ closepath % Close the square
229
+ ----
230
+
231
+ Using relative coordinates makes it easy to draw regular shapes.
232
+ ====
233
+
234
+ [[curveto]]
235
+ == curveto
236
+
237
+ === General
238
+
239
+ The `curveto` operator appends a cubic Bézier curve segment from the current
240
+ point to (x3, y3), using (x1, y1) and (x2, y2) as control points. The endpoint
241
+ (x3, y3) becomes the new current point.
242
+
243
+ Cubic Bézier curves provide smooth, controllable curves essential for vector
244
+ graphics.
245
+
246
+ === Syntax
247
+
248
+ [source,postscript]
249
+ ----
250
+ x1 y1 x2 y2 x3 y3 curveto <1> <2> <3> <4> <5> <6> <7>
251
+ ----
252
+ <1> X-coordinate of first control point
253
+ <2> Y-coordinate of first control point
254
+ <3> X-coordinate of second control point
255
+ <4> Y-coordinate of second control point
256
+ <5> X-coordinate of curve endpoint
257
+ <6> Y-coordinate of curve endpoint
258
+ <7> Operator that appends Bézier curve
259
+
260
+ Where,
261
+
262
+ `x1, y1`:: First control point coordinates (numbers)
263
+ `x2, y2`:: Second control point coordinates (numbers)
264
+ `x3, y3`:: Curve endpoint coordinates (numbers)
265
+
266
+ Stack effect: `x1 y1 x2 y2 x3 y3 -- `
267
+
268
+ === Examples
269
+
270
+ [example]
271
+ ====
272
+ [source,postscript]
273
+ ----
274
+ newpath
275
+ 50 50 moveto % Start point
276
+ 50 150 150 150 150 50 curveto % S-curve
277
+ stroke
278
+ ----
279
+
280
+ Creates an S-shaped curve. The control points pull the curve in their
281
+ directions.
282
+ ====
283
+
284
+ [example]
285
+ ====
286
+ [source,postscript]
287
+ ----
288
+ newpath
289
+ 100 100 moveto % Start at center
290
+ 150 50 200 100 200 150 curveto % First curve
291
+ 200 200 150 250 100 250 curveto % Second curve
292
+ closepath
293
+ fill
294
+ ----
295
+
296
+ Combines multiple curves to create complex shapes.
297
+ ====
298
+
299
+ [[rcurveto]]
300
+ == rcurveto
301
+
302
+ === General
303
+
304
+ The `rcurveto` operator is similar to `curveto` but uses relative coordinates
305
+ for all three point pairs (control points and endpoint).
306
+
307
+ === Syntax
308
+
309
+ [source,postscript]
310
+ ----
311
+ dx1 dy1 dx2 dy2 dx3 dy3 rcurveto
312
+ ----
313
+
314
+ Where,
315
+
316
+ `dx1, dy1`:: First control point offset from current point
317
+ `dx2, dy2`:: Second control point offset from current point
318
+ `dx3, dy3`:: Endpoint offset from current point
319
+
320
+ Stack effect: `dx1 dy1 dx2 dy2 dx3 dy3 -- `
321
+
322
+ [[arc]]
323
+ == arc
324
+
325
+ === General
326
+
327
+ The `arc` operator appends a counterclockwise circular arc to the current path.
328
+ The arc is centered at (x, y) with the specified radius, sweeping from angle1
329
+ to angle2 (measured in degrees).
330
+
331
+ If there is a current point, `arc` draws a straight line from the current point
332
+ to the arc's starting point before drawing the arc.
333
+
334
+ === Syntax
335
+
336
+ [source,postscript]
337
+ ----
338
+ x y r angle1 angle2 arc <1> <2> <3> <4> <5> <6>
339
+ ----
340
+ <1> X-coordinate of arc center
341
+ <2> Y-coordinate of arc center
342
+ <3> Radius of arc
343
+ <4> Starting angle in degrees
344
+ <5> Ending angle in degrees
345
+ <6> Operator that appends arc
346
+
347
+ Where,
348
+
349
+ `x`:: X-coordinate of center point (number)
350
+ `y`:: Y-coordinate of center point (number)
351
+ `r`:: Radius of the arc (number, must be positive)
352
+ `angle1`:: Starting angle in degrees (number, 0° is 3 o'clock)
353
+ `angle2`:: Ending angle in degrees (number)
354
+
355
+ Stack effect: `x y r angle1 angle2 -- `
356
+
357
+ === Examples
358
+
359
+ [example]
360
+ ====
361
+ [source,postscript]
362
+ ----
363
+ newpath
364
+ 100 100 50 0 360 arc % Full circle
365
+ fill
366
+ ----
367
+
368
+ Draws a complete circle centered at (100, 100) with radius 50.
369
+ ====
370
+
371
+ [example]
372
+ ====
373
+ [source,postscript]
374
+ ----
375
+ newpath
376
+ 100 100 50 0 180 arc % Semicircle (top half)
377
+ closepath
378
+ fill
379
+ ----
380
+
381
+ Draws the upper half of a circle (0° to 180°).
382
+ ====
383
+
384
+ [example]
385
+ ====
386
+ [source,postscript]
387
+ ----
388
+ newpath
389
+ 100 100 moveto % Start at center
390
+ 100 100 50 45 135 arc % Quarter circle
391
+ closepath
392
+ fill
393
+ ----
394
+
395
+ Creates a pie slice from 45° to 135° (90° wedge).
396
+ ====
397
+
398
+ [[arcn]]
399
+ == arcn
400
+
401
+ === General
402
+
403
+ The `arcn` operator is identical to `arc` except it draws the arc clockwise
404
+ instead of counterclockwise.
405
+
406
+ === Syntax
407
+
408
+ [source,postscript]
409
+ ----
410
+ x y r angle1 angle2 arcn
411
+ ----
412
+
413
+ Where parameters are the same as `arc`, but the arc sweeps clockwise from
414
+ angle1 to angle2.
415
+
416
+ Stack effect: `x y r angle1 angle2 -- `
417
+
418
+ === Examples
419
+
420
+ [example]
421
+ ====
422
+ [source,postscript]
423
+ ----
424
+ newpath
425
+ 100 100 50 180 0 arcn % Clockwise from 180° to 0°
426
+ closepath % Creates bottom semicircle
427
+ fill
428
+ ----
429
+
430
+ Draws the lower half of a circle using clockwise direction.
431
+ ====
432
+
433
+ [[closepath]]
434
+ == closepath
435
+
436
+ === General
437
+
438
+ The `closepath` operator closes the current subpath by appending a straight
439
+ line segment from the current point back to the subpath's starting point. This
440
+ is essential for creating closed shapes.
441
+
442
+ After closing, the current point is set to the subpath's starting point.
443
+
444
+ === Syntax
445
+
446
+ [source,postscript]
447
+ ----
448
+ closepath <1>
449
+ ----
450
+ <1> Operator that closes current subpath
451
+
452
+ Where,
453
+
454
+ Stack effect: `-- `
455
+
456
+ === Examples
457
+
458
+ [example]
459
+ ====
460
+ [source,postscript]
461
+ ----
462
+ newpath
463
+ 10 10 moveto
464
+ 90 10 lineto
465
+ 90 90 lineto
466
+ 10 90 lineto
467
+ closepath % Closes back to (10, 10)
468
+ stroke
469
+ ----
470
+
471
+ Creates a closed square. The `closepath` adds the final edge from (10, 90)
472
+ back to (10, 10).
473
+ ====
474
+
475
+ [example]
476
+ ====
477
+ [source,postscript]
478
+ ----
479
+ newpath
480
+ 50 50 moveto
481
+ 150 50 lineto
482
+ 100 150 lineto
483
+ % Don't close the path
484
+ stroke
485
+ ----
486
+
487
+ Without `closepath`, the triangle remains open - the line from (100, 150) back
488
+ to (50, 50) is not drawn.
489
+ ====
490
+
491
+ == Path Construction Workflow
492
+
493
+ === Typical pattern
494
+
495
+ [example]
496
+ ====
497
+ [source,postscript]
498
+ ----
499
+ % 1. Initialize new path
500
+ newpath
501
+
502
+ % 2. Set starting point
503
+ x y moveto
504
+
505
+ % 3. Add path segments
506
+ x1 y1 lineto
507
+ x2 y2 lineto
508
+ % ... more segments
509
+
510
+ % 4. Close if desired
511
+ closepath
512
+
513
+ % 5. Paint the path
514
+ stroke % or fill
515
+ ----
516
+
517
+ This pattern is used for most shape construction in PostScript.
518
+ ====
519
+
520
+ === Complex paths
521
+
522
+ [example]
523
+ ====
524
+ [source,postscript]
525
+ ----
526
+ newpath
527
+ % Outer rectangle
528
+ 0 0 moveto
529
+ 200 0 lineto
530
+ 200 200 lineto
531
+ 0 200 lineto
532
+ closepath
533
+
534
+ % Inner hole
535
+ 50 50 moveto
536
+ 150 50 lineto
537
+ 150 150 lineto
538
+ 50 150 lineto
539
+ closepath
540
+
541
+ % Fill creates a frame (outer filled, inner hollow)
542
+ fill
543
+ ----
544
+
545
+ Multiple closed subpaths can create shapes with holes.
546
+ ====
547
+
548
+ == See Also
549
+
550
+ * link:painting.adoc[Painting Operators] - Rendering paths with stroke and fill
551
+ * link:../graphics-model.adoc#current-path[Current Path] - Path concepts
552
+ * link:transformations.adoc[Transformations] - Coordinate transformations
553
+ * link:index.adoc[Back to Operator Reference]