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.
- checksums.yaml +7 -0
- data/.rubocop.yml +19 -0
- data/.rubocop_todo.yml +141 -0
- data/Gemfile +15 -0
- data/LICENSE +25 -0
- data/README.adoc +473 -0
- data/Rakefile +10 -0
- data/docs/POSTSCRIPT.adoc +13 -0
- data/docs/postscript/fundamentals.adoc +356 -0
- data/docs/postscript/graphics-model.adoc +406 -0
- data/docs/postscript/implementation-notes.adoc +314 -0
- data/docs/postscript/index.adoc +153 -0
- data/docs/postscript/operators/arithmetic.adoc +461 -0
- data/docs/postscript/operators/control-flow.adoc +230 -0
- data/docs/postscript/operators/dictionary.adoc +191 -0
- data/docs/postscript/operators/graphics-state.adoc +528 -0
- data/docs/postscript/operators/index.adoc +288 -0
- data/docs/postscript/operators/painting.adoc +475 -0
- data/docs/postscript/operators/path-construction.adoc +553 -0
- data/docs/postscript/operators/stack-manipulation.adoc +374 -0
- data/docs/postscript/operators/transformations.adoc +479 -0
- data/docs/postscript/svg-mapping.adoc +369 -0
- data/exe/postsvg +6 -0
- data/lib/postsvg/cli.rb +103 -0
- data/lib/postsvg/colors.rb +33 -0
- data/lib/postsvg/converter.rb +214 -0
- data/lib/postsvg/errors.rb +11 -0
- data/lib/postsvg/graphics_state.rb +158 -0
- data/lib/postsvg/interpreter.rb +891 -0
- data/lib/postsvg/matrix.rb +106 -0
- data/lib/postsvg/parser/postscript_parser.rb +87 -0
- data/lib/postsvg/parser/transform.rb +21 -0
- data/lib/postsvg/parser.rb +18 -0
- data/lib/postsvg/path_builder.rb +101 -0
- data/lib/postsvg/svg_generator.rb +78 -0
- data/lib/postsvg/tokenizer.rb +161 -0
- data/lib/postsvg/version.rb +5 -0
- data/lib/postsvg.rb +78 -0
- data/postsvg.gemspec +38 -0
- data/scripts/regenerate_fixtures.rb +28 -0
- metadata +118 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
= Painting Operators
|
|
2
|
+
|
|
3
|
+
== General
|
|
4
|
+
|
|
5
|
+
Painting operators convert the current path into visible marks on the output
|
|
6
|
+
device. These operators consume the current path (except for clipping operators)
|
|
7
|
+
and use the current graphics state parameters (colors, line width, etc.) to
|
|
8
|
+
determine the appearance of the painted graphics.
|
|
9
|
+
|
|
10
|
+
The two fundamental painting operations are stroking (painting along the path)
|
|
11
|
+
and filling (painting the interior of the path).
|
|
12
|
+
|
|
13
|
+
[[stroke]]
|
|
14
|
+
== stroke
|
|
15
|
+
|
|
16
|
+
=== General
|
|
17
|
+
|
|
18
|
+
The `stroke` operator paints a line along the current path using the current
|
|
19
|
+
stroke color and line attributes. The path is consumed by this operation,
|
|
20
|
+
leaving an empty current path.
|
|
21
|
+
|
|
22
|
+
Stroking uses these graphics state parameters:
|
|
23
|
+
|
|
24
|
+
* Stroke color (set by `setrgbcolor`, `setgray`, etc.)
|
|
25
|
+
* Line width (set by `setlinewidth`)
|
|
26
|
+
* Line cap style (set by `setlinecap`)
|
|
27
|
+
* Line join style (set by `setlinejoin`)
|
|
28
|
+
* Miter limit (set by `setmiterlimit`)
|
|
29
|
+
* Dash pattern (set by `setdash`)
|
|
30
|
+
|
|
31
|
+
=== Syntax
|
|
32
|
+
|
|
33
|
+
[source,postscript]
|
|
34
|
+
----
|
|
35
|
+
stroke <1>
|
|
36
|
+
----
|
|
37
|
+
<1> Operator that strokes and consumes current path
|
|
38
|
+
|
|
39
|
+
Where,
|
|
40
|
+
|
|
41
|
+
Stack effect: `-- `
|
|
42
|
+
|
|
43
|
+
=== Examples
|
|
44
|
+
|
|
45
|
+
[example]
|
|
46
|
+
====
|
|
47
|
+
[source,postscript]
|
|
48
|
+
----
|
|
49
|
+
newpath
|
|
50
|
+
50 50 moveto
|
|
51
|
+
150 150 lineto
|
|
52
|
+
2 setlinewidth % Set line width to 2 points
|
|
53
|
+
0 0 0 setrgbcolor % Set stroke color to black
|
|
54
|
+
stroke % Paint the line
|
|
55
|
+
----
|
|
56
|
+
|
|
57
|
+
Creates a diagonal line from (50, 50) to (150, 150) with 2-point width.
|
|
58
|
+
====
|
|
59
|
+
|
|
60
|
+
[example]
|
|
61
|
+
====
|
|
62
|
+
[source,postscript]
|
|
63
|
+
----
|
|
64
|
+
newpath
|
|
65
|
+
100 100 50 0 360 arc % Circle path
|
|
66
|
+
1 0 0 setrgbcolor % Red color
|
|
67
|
+
3 setlinewidth % 3-point width
|
|
68
|
+
stroke % Stroke circle outline
|
|
69
|
+
----
|
|
70
|
+
|
|
71
|
+
Draws a red circle outline.
|
|
72
|
+
====
|
|
73
|
+
|
|
74
|
+
[[fill]]
|
|
75
|
+
== fill
|
|
76
|
+
|
|
77
|
+
=== General
|
|
78
|
+
|
|
79
|
+
The `fill` operator fills the interior of the current path with the current
|
|
80
|
+
fill color using the non-zero winding number rule. The path is consumed,
|
|
81
|
+
leaving an empty current path.
|
|
82
|
+
|
|
83
|
+
The non-zero winding rule determines whether a point is inside the path by
|
|
84
|
+
counting path crossings. It handles overlapping paths and paths with multiple
|
|
85
|
+
subpaths.
|
|
86
|
+
|
|
87
|
+
=== Syntax
|
|
88
|
+
|
|
89
|
+
[source,postscript]
|
|
90
|
+
----
|
|
91
|
+
fill <1>
|
|
92
|
+
----
|
|
93
|
+
<1> Operator that fills and consumes current path
|
|
94
|
+
|
|
95
|
+
Where,
|
|
96
|
+
|
|
97
|
+
Stack effect: `-- `
|
|
98
|
+
|
|
99
|
+
=== Examples
|
|
100
|
+
|
|
101
|
+
[example]
|
|
102
|
+
====
|
|
103
|
+
[source,postscript]
|
|
104
|
+
----
|
|
105
|
+
newpath
|
|
106
|
+
50 50 moveto
|
|
107
|
+
150 50 lineto
|
|
108
|
+
100 150 lineto
|
|
109
|
+
closepath
|
|
110
|
+
0 0 1 setrgbcolor % Blue fill color
|
|
111
|
+
fill % Fill the triangle
|
|
112
|
+
----
|
|
113
|
+
|
|
114
|
+
Creates a solid blue triangle.
|
|
115
|
+
====
|
|
116
|
+
|
|
117
|
+
[example]
|
|
118
|
+
====
|
|
119
|
+
[source,postscript]
|
|
120
|
+
----
|
|
121
|
+
newpath
|
|
122
|
+
100 100 50 0 360 arc % Circle
|
|
123
|
+
0.5 0.5 0.5 setrgbcolor % Gray fill
|
|
124
|
+
fill % Fill the circle
|
|
125
|
+
----
|
|
126
|
+
|
|
127
|
+
Draws a solid gray circle.
|
|
128
|
+
====
|
|
129
|
+
|
|
130
|
+
=== Non-zero winding rule
|
|
131
|
+
|
|
132
|
+
[example]
|
|
133
|
+
====
|
|
134
|
+
[source,postscript]
|
|
135
|
+
----
|
|
136
|
+
newpath
|
|
137
|
+
% Outer square (counterclockwise)
|
|
138
|
+
0 0 moveto
|
|
139
|
+
200 0 lineto
|
|
140
|
+
200 200 lineto
|
|
141
|
+
0 200 lineto
|
|
142
|
+
closepath
|
|
143
|
+
|
|
144
|
+
% Inner square (also counterclockwise)
|
|
145
|
+
50 50 moveto
|
|
146
|
+
150 50 lineto
|
|
147
|
+
150 150 lineto
|
|
148
|
+
50 150 lineto
|
|
149
|
+
closepath
|
|
150
|
+
|
|
151
|
+
fill
|
|
152
|
+
----
|
|
153
|
+
|
|
154
|
+
With both paths counterclockwise, both squares are filled. The winding numbers
|
|
155
|
+
add up, keeping both regions inside.
|
|
156
|
+
====
|
|
157
|
+
|
|
158
|
+
[[eofill]]
|
|
159
|
+
== eofill
|
|
160
|
+
|
|
161
|
+
=== General
|
|
162
|
+
|
|
163
|
+
The `eofill` operator fills the interior of the current path using the
|
|
164
|
+
even-odd rule instead of the non-zero winding rule. The path is consumed.
|
|
165
|
+
|
|
166
|
+
The even-odd rule determines whether a point is inside by counting crossings:
|
|
167
|
+
if the count is odd, the point is inside; if even, it's outside. This creates
|
|
168
|
+
alternating filled and unfilled regions for overlapping paths.
|
|
169
|
+
|
|
170
|
+
=== Syntax
|
|
171
|
+
|
|
172
|
+
[source,postscript]
|
|
173
|
+
----
|
|
174
|
+
eofill <1>
|
|
175
|
+
----
|
|
176
|
+
<1> Operator that fills using even-odd rule
|
|
177
|
+
|
|
178
|
+
Where,
|
|
179
|
+
|
|
180
|
+
Stack effect: `-- `
|
|
181
|
+
|
|
182
|
+
=== Examples
|
|
183
|
+
|
|
184
|
+
[example]
|
|
185
|
+
====
|
|
186
|
+
[source,postscript]
|
|
187
|
+
----
|
|
188
|
+
newpath
|
|
189
|
+
% Outer rectangle
|
|
190
|
+
0 0 moveto
|
|
191
|
+
200 0 lineto
|
|
192
|
+
200 200 lineto
|
|
193
|
+
0 200 lineto
|
|
194
|
+
closepath
|
|
195
|
+
|
|
196
|
+
% Inner rectangle (creates a hole)
|
|
197
|
+
50 50 moveto
|
|
198
|
+
150 50 lineto
|
|
199
|
+
150 150 lineto
|
|
200
|
+
50 150 lineto
|
|
201
|
+
closepath
|
|
202
|
+
|
|
203
|
+
eofill % Creates frame with hole
|
|
204
|
+
----
|
|
205
|
+
|
|
206
|
+
The even-odd rule creates a rectangular frame: the outer rectangle is filled,
|
|
207
|
+
but the inner rectangle becomes a hole.
|
|
208
|
+
====
|
|
209
|
+
|
|
210
|
+
[example]
|
|
211
|
+
====
|
|
212
|
+
[source,postscript]
|
|
213
|
+
----
|
|
214
|
+
newpath
|
|
215
|
+
100 100 80 0 360 arc % Outer circle
|
|
216
|
+
closepath
|
|
217
|
+
100 100 40 0 360 arc % Inner circle
|
|
218
|
+
closepath
|
|
219
|
+
eofill % Creates ring/donut shape
|
|
220
|
+
----
|
|
221
|
+
|
|
222
|
+
Creates a ring by treating overlapping circles as alternating regions.
|
|
223
|
+
====
|
|
224
|
+
|
|
225
|
+
[[clip]]
|
|
226
|
+
== clip
|
|
227
|
+
|
|
228
|
+
=== General
|
|
229
|
+
|
|
230
|
+
The `clip` operator establishes a clipping path from the current path using the
|
|
231
|
+
non-zero winding rule. Unlike `stroke` and `fill`, `clip` does not consume the
|
|
232
|
+
current path.
|
|
233
|
+
|
|
234
|
+
The clipping path restricts all subsequent painting operations to the interior
|
|
235
|
+
of the path. Only the intersection of painted marks and the clipping region
|
|
236
|
+
becomes visible.
|
|
237
|
+
|
|
238
|
+
Clipping paths can only be made more restrictive, not less. Use `gsave` and
|
|
239
|
+
`grestore` to save and restore the clipping region.
|
|
240
|
+
|
|
241
|
+
=== Syntax
|
|
242
|
+
|
|
243
|
+
[source,postscript]
|
|
244
|
+
----
|
|
245
|
+
clip <1>
|
|
246
|
+
----
|
|
247
|
+
<1> Operator that establishes clipping path
|
|
248
|
+
|
|
249
|
+
Where,
|
|
250
|
+
|
|
251
|
+
Stack effect: `-- `
|
|
252
|
+
|
|
253
|
+
=== Examples
|
|
254
|
+
|
|
255
|
+
[example]
|
|
256
|
+
====
|
|
257
|
+
[source,postscript]
|
|
258
|
+
----
|
|
259
|
+
gsave % Save state to restore clipping later
|
|
260
|
+
newpath
|
|
261
|
+
100 100 50 0 360 arc % Circle
|
|
262
|
+
clip % Clip to circle
|
|
263
|
+
|
|
264
|
+
% Draw something - only visible within circle
|
|
265
|
+
newpath
|
|
266
|
+
0 0 moveto
|
|
267
|
+
200 200 lineto
|
|
268
|
+
stroke
|
|
269
|
+
grestore % Restore original clipping
|
|
270
|
+
----
|
|
271
|
+
|
|
272
|
+
Clips subsequent drawing to a circular region.
|
|
273
|
+
====
|
|
274
|
+
|
|
275
|
+
[example]
|
|
276
|
+
====
|
|
277
|
+
[source,postscript]
|
|
278
|
+
----
|
|
279
|
+
gsave
|
|
280
|
+
% Clip to text shape (if text operators supported)
|
|
281
|
+
newpath
|
|
282
|
+
50 50 moveto
|
|
283
|
+
150 50 lineto
|
|
284
|
+
150 150 lineto
|
|
285
|
+
50 150 lineto
|
|
286
|
+
closepath
|
|
287
|
+
clip
|
|
288
|
+
|
|
289
|
+
% Fill with pattern or gradient (would be clipped)
|
|
290
|
+
0.8 0.8 0.8 setrgbcolor
|
|
291
|
+
0 0 200 200 rectfill
|
|
292
|
+
grestore
|
|
293
|
+
----
|
|
294
|
+
|
|
295
|
+
Common pattern: create clipping region, paint, then restore.
|
|
296
|
+
====
|
|
297
|
+
|
|
298
|
+
[[eoclip]]
|
|
299
|
+
== eoclip
|
|
300
|
+
|
|
301
|
+
=== General
|
|
302
|
+
|
|
303
|
+
The `eoclip` operator is identical to `clip` except it uses the even-odd rule
|
|
304
|
+
to determine the interior of the clipping path.
|
|
305
|
+
|
|
306
|
+
=== Syntax
|
|
307
|
+
|
|
308
|
+
[source,postscript]
|
|
309
|
+
----
|
|
310
|
+
eoclip <1>
|
|
311
|
+
----
|
|
312
|
+
<1> Operator that establishes even-odd clipping path
|
|
313
|
+
|
|
314
|
+
Where,
|
|
315
|
+
|
|
316
|
+
Stack effect: `-- `
|
|
317
|
+
|
|
318
|
+
=== Examples
|
|
319
|
+
|
|
320
|
+
[example]
|
|
321
|
+
====
|
|
322
|
+
[source,postscript]
|
|
323
|
+
----
|
|
324
|
+
gsave
|
|
325
|
+
newpath
|
|
326
|
+
% Outer circle
|
|
327
|
+
100 100 80 0 360 arc
|
|
328
|
+
closepath
|
|
329
|
+
% Inner circle (creates hole in clip)
|
|
330
|
+
100 100 40 0 360 arc
|
|
331
|
+
closepath
|
|
332
|
+
eoclip
|
|
333
|
+
|
|
334
|
+
% Draw in ring-shaped region
|
|
335
|
+
0.5 setgray
|
|
336
|
+
0 0 200 200 rectfill
|
|
337
|
+
grestore
|
|
338
|
+
----
|
|
339
|
+
|
|
340
|
+
Creates a ring-shaped clipping region using even-odd rule.
|
|
341
|
+
====
|
|
342
|
+
|
|
343
|
+
[[stroke-vs-fill]]
|
|
344
|
+
== Stroke vs Fill Comparison
|
|
345
|
+
|
|
346
|
+
=== General
|
|
347
|
+
|
|
348
|
+
Understanding when to use `stroke` versus `fill` is fundamental to PostScript
|
|
349
|
+
graphics.
|
|
350
|
+
|
|
351
|
+
=== Stroke characteristics
|
|
352
|
+
|
|
353
|
+
* Paints along the path outline
|
|
354
|
+
* Uses stroke color
|
|
355
|
+
* Width controlled by line width
|
|
356
|
+
* Affected by line cap and join styles
|
|
357
|
+
* Path can be open or closed
|
|
358
|
+
|
|
359
|
+
=== Fill characteristics
|
|
360
|
+
|
|
361
|
+
* Paints the path interior
|
|
362
|
+
* Uses fill color
|
|
363
|
+
* No width parameter
|
|
364
|
+
* Not affected by line attributes
|
|
365
|
+
* Best with closed paths
|
|
366
|
+
|
|
367
|
+
=== Combining stroke and fill
|
|
368
|
+
|
|
369
|
+
[example]
|
|
370
|
+
====
|
|
371
|
+
[source,postscript]
|
|
372
|
+
----
|
|
373
|
+
newpath
|
|
374
|
+
50 50 moveto
|
|
375
|
+
150 50 lineto
|
|
376
|
+
100 150 lineto
|
|
377
|
+
closepath
|
|
378
|
+
|
|
379
|
+
gsave
|
|
380
|
+
0 0 1 setrgbcolor % Blue fill
|
|
381
|
+
fill % Fill consumes path
|
|
382
|
+
grestore
|
|
383
|
+
|
|
384
|
+
% Must recreate path for stroke
|
|
385
|
+
newpath
|
|
386
|
+
50 50 moveto
|
|
387
|
+
150 50 lineto
|
|
388
|
+
100 150 lineto
|
|
389
|
+
closepath
|
|
390
|
+
|
|
391
|
+
1 0 0 setrgbcolor % Red stroke
|
|
392
|
+
3 setlinewidth
|
|
393
|
+
stroke
|
|
394
|
+
----
|
|
395
|
+
|
|
396
|
+
To both fill and stroke a shape, you must either:
|
|
397
|
+
1. Save state with `gsave`, fill, restore, then stroke
|
|
398
|
+
2. Or recreate the path after filling
|
|
399
|
+
====
|
|
400
|
+
|
|
401
|
+
== Path Consumption
|
|
402
|
+
|
|
403
|
+
=== General
|
|
404
|
+
|
|
405
|
+
Most painting operators consume the current path, replacing it with an empty
|
|
406
|
+
path. Understanding this behavior is crucial for correctly sequencing
|
|
407
|
+
operations.
|
|
408
|
+
|
|
409
|
+
=== Operators that consume the path
|
|
410
|
+
|
|
411
|
+
* `stroke` - Consumes path after stroking
|
|
412
|
+
* `fill` - Consumes path after filling
|
|
413
|
+
* `eofill` - Consumes path after filling
|
|
414
|
+
|
|
415
|
+
=== Operators that do not consume the path
|
|
416
|
+
|
|
417
|
+
* `clip` - Preserves path for subsequent operations
|
|
418
|
+
* `eoclip` - Preserves path for subsequent operations
|
|
419
|
+
|
|
420
|
+
=== Working with path consumption
|
|
421
|
+
|
|
422
|
+
[example]
|
|
423
|
+
====
|
|
424
|
+
[source,postscript]
|
|
425
|
+
----
|
|
426
|
+
% WRONG: Second operation has no path
|
|
427
|
+
newpath
|
|
428
|
+
50 50 moveto 150 150 lineto
|
|
429
|
+
stroke % Consumes path
|
|
430
|
+
fill % Nothing to fill!
|
|
431
|
+
|
|
432
|
+
% CORRECT: Use gsave/grestore or recreate
|
|
433
|
+
newpath
|
|
434
|
+
50 50 moveto 150 150 lineto
|
|
435
|
+
gsave
|
|
436
|
+
stroke % Consumes copy of path
|
|
437
|
+
grestore
|
|
438
|
+
fill % Original path preserved
|
|
439
|
+
----
|
|
440
|
+
====
|
|
441
|
+
|
|
442
|
+
== Painting Order
|
|
443
|
+
|
|
444
|
+
=== General
|
|
445
|
+
|
|
446
|
+
PostScript follows the painter's algorithm: later operations paint over earlier
|
|
447
|
+
ones. Objects are layered in the order they are painted.
|
|
448
|
+
|
|
449
|
+
[example]
|
|
450
|
+
====
|
|
451
|
+
[source,postscript]
|
|
452
|
+
----
|
|
453
|
+
% Red square (painted first, underneath)
|
|
454
|
+
newpath
|
|
455
|
+
0 0 moveto 100 0 lineto 100 100 lineto 0 100 lineto closepath
|
|
456
|
+
1 0 0 setrgbcolor
|
|
457
|
+
fill
|
|
458
|
+
|
|
459
|
+
% Blue circle (painted second, on top)
|
|
460
|
+
newpath
|
|
461
|
+
75 75 40 0 360 arc
|
|
462
|
+
0 0 1 setrgbcolor
|
|
463
|
+
fill
|
|
464
|
+
----
|
|
465
|
+
|
|
466
|
+
The blue circle appears on top of the red square because it was painted later.
|
|
467
|
+
====
|
|
468
|
+
|
|
469
|
+
== See Also
|
|
470
|
+
|
|
471
|
+
* link:path-construction.adoc[Path Construction] - Building paths to paint
|
|
472
|
+
* link:graphics-state.adoc[Graphics State] - Setting colors and line attributes
|
|
473
|
+
* link:../graphics-model.adoc#painting-model[Painting Model] - Conceptual
|
|
474
|
+
overview
|
|
475
|
+
* link:index.adoc[Back to Operator Reference]
|