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,479 @@
|
|
|
1
|
+
= Transformation Operators
|
|
2
|
+
|
|
3
|
+
== General
|
|
4
|
+
|
|
5
|
+
Transformation operators modify the current transformation matrix (CTM), which
|
|
6
|
+
maps user space coordinates to device space. Transformations affect all
|
|
7
|
+
subsequent graphics operations until the CTM is modified again or the graphics
|
|
8
|
+
state is restored.
|
|
9
|
+
|
|
10
|
+
The three basic transformations are translation, scaling, and rotation. These
|
|
11
|
+
can be combined to produce complex coordinate system changes.
|
|
12
|
+
|
|
13
|
+
[[translate]]
|
|
14
|
+
== translate
|
|
15
|
+
|
|
16
|
+
=== General
|
|
17
|
+
|
|
18
|
+
The `translate` operator moves the origin of the user coordinate system to a
|
|
19
|
+
new location. All subsequent coordinates are interpreted relative to this new
|
|
20
|
+
origin.
|
|
21
|
+
|
|
22
|
+
Translation is one of the most common transformations, used for positioning
|
|
23
|
+
graphics at specific locations.
|
|
24
|
+
|
|
25
|
+
=== Syntax
|
|
26
|
+
|
|
27
|
+
[source,postscript]
|
|
28
|
+
----
|
|
29
|
+
tx ty translate <1> <2> <3>
|
|
30
|
+
----
|
|
31
|
+
<1> X-offset for translation (number)
|
|
32
|
+
<2> Y-offset for translation (number)
|
|
33
|
+
<3> Operator that applies translation
|
|
34
|
+
|
|
35
|
+
Where,
|
|
36
|
+
|
|
37
|
+
`tx`:: Translation in X direction (number)
|
|
38
|
+
`ty`:: Translation in Y direction (number)
|
|
39
|
+
|
|
40
|
+
Stack effect: `tx ty -- `
|
|
41
|
+
|
|
42
|
+
=== Examples
|
|
43
|
+
|
|
44
|
+
[example]
|
|
45
|
+
====
|
|
46
|
+
[source,postscript]
|
|
47
|
+
----
|
|
48
|
+
100 50 translate % Move origin to (100, 50)
|
|
49
|
+
newpath
|
|
50
|
+
0 0 moveto % Now at (100, 50) in original space
|
|
51
|
+
50 0 lineto % Line to (150, 50)
|
|
52
|
+
stroke
|
|
53
|
+
----
|
|
54
|
+
|
|
55
|
+
After translation, (0, 0) refers to point (100, 50) in the original coordinate
|
|
56
|
+
system.
|
|
57
|
+
====
|
|
58
|
+
|
|
59
|
+
[example]
|
|
60
|
+
====
|
|
61
|
+
[source,postscript]
|
|
62
|
+
----
|
|
63
|
+
gsave
|
|
64
|
+
100 100 translate % Translate to (100, 100)
|
|
65
|
+
newpath
|
|
66
|
+
0 0 50 0 360 arc % Circle at translated origin
|
|
67
|
+
fill
|
|
68
|
+
grestore
|
|
69
|
+
|
|
70
|
+
% Back to original origin
|
|
71
|
+
----
|
|
72
|
+
|
|
73
|
+
Common pattern: translate, draw, then restore.
|
|
74
|
+
====
|
|
75
|
+
|
|
76
|
+
[[scale]]
|
|
77
|
+
== scale
|
|
78
|
+
|
|
79
|
+
=== General
|
|
80
|
+
|
|
81
|
+
The `scale` operator multiplies the user space units by specified scale
|
|
82
|
+
factors. This affects both coordinates and line widths.
|
|
83
|
+
|
|
84
|
+
Scaling with equal X and Y factors produces uniform scaling. Different factors
|
|
85
|
+
produce non-uniform (anisotropic) scaling.
|
|
86
|
+
|
|
87
|
+
=== Syntax
|
|
88
|
+
|
|
89
|
+
[source,postscript]
|
|
90
|
+
----
|
|
91
|
+
sx sy scale <1> <2> <3>
|
|
92
|
+
----
|
|
93
|
+
<1> X-axis scale factor (number)
|
|
94
|
+
<2> Y-axis scale factor (number)
|
|
95
|
+
<3> Operator that applies scaling
|
|
96
|
+
|
|
97
|
+
Where,
|
|
98
|
+
|
|
99
|
+
`sx`:: Scale factor for X direction (number)
|
|
100
|
+
`sy`:: Scale factor for Y direction (number)
|
|
101
|
+
|
|
102
|
+
Stack effect: `sx sy -- `
|
|
103
|
+
|
|
104
|
+
=== Examples
|
|
105
|
+
|
|
106
|
+
[example]
|
|
107
|
+
====
|
|
108
|
+
[source,postscript]
|
|
109
|
+
----
|
|
110
|
+
2 2 scale % Double all dimensions
|
|
111
|
+
newpath
|
|
112
|
+
50 50 moveto % Actually (100, 100)
|
|
113
|
+
25 0 rlineto % Line of length 50 (2 × 25)
|
|
114
|
+
stroke
|
|
115
|
+
----
|
|
116
|
+
|
|
117
|
+
After 2× scaling, all coordinates and dimensions are doubled.
|
|
118
|
+
====
|
|
119
|
+
|
|
120
|
+
[example]
|
|
121
|
+
====
|
|
122
|
+
[source,postscript]
|
|
123
|
+
----
|
|
124
|
+
gsave
|
|
125
|
+
2 1 scale % Stretch in X, not Y
|
|
126
|
+
newpath
|
|
127
|
+
50 50 50 0 360 arc % Ellipse (100×50)
|
|
128
|
+
stroke
|
|
129
|
+
grestore
|
|
130
|
+
----
|
|
131
|
+
|
|
132
|
+
Non-uniform scaling creates an ellipse from a circle.
|
|
133
|
+
====
|
|
134
|
+
|
|
135
|
+
[example]
|
|
136
|
+
====
|
|
137
|
+
[source,postscript]
|
|
138
|
+
----
|
|
139
|
+
72 72 scale % Scale to inches (72 points/inch)
|
|
140
|
+
newpath
|
|
141
|
+
1 1 moveto % 1 inch from origin
|
|
142
|
+
2 1 lineto % 1 inch line
|
|
143
|
+
stroke
|
|
144
|
+
----
|
|
145
|
+
|
|
146
|
+
Scaling can convert units (e.g., inches to points).
|
|
147
|
+
====
|
|
148
|
+
|
|
149
|
+
[[rotate]]
|
|
150
|
+
== rotate
|
|
151
|
+
|
|
152
|
+
=== General
|
|
153
|
+
|
|
154
|
+
The `rotate` operator rotates the user coordinate system by the specified angle
|
|
155
|
+
(in degrees) around the current origin. Positive angles rotate counterclockwise.
|
|
156
|
+
|
|
157
|
+
Rotation affects both the coordinate axes and all subsequent drawing operations.
|
|
158
|
+
|
|
159
|
+
=== Syntax
|
|
160
|
+
|
|
161
|
+
[source,postscript]
|
|
162
|
+
----
|
|
163
|
+
angle rotate <1> <2>
|
|
164
|
+
----
|
|
165
|
+
<1> Rotation angle in degrees (number)
|
|
166
|
+
<2> Operator that applies rotation
|
|
167
|
+
|
|
168
|
+
Where,
|
|
169
|
+
|
|
170
|
+
`angle`:: Rotation angle in degrees (number, positive=counterclockwise)
|
|
171
|
+
|
|
172
|
+
Stack effect: `angle -- `
|
|
173
|
+
|
|
174
|
+
=== Examples
|
|
175
|
+
|
|
176
|
+
[example]
|
|
177
|
+
====
|
|
178
|
+
[source,postscript]
|
|
179
|
+
----
|
|
180
|
+
45 rotate % Rotate 45° counterclockwise
|
|
181
|
+
newpath
|
|
182
|
+
100 0 moveto % At 45° angle from origin
|
|
183
|
+
50 0 rlineto
|
|
184
|
+
stroke
|
|
185
|
+
----
|
|
186
|
+
|
|
187
|
+
After 45° rotation, the positive X-axis points northeast.
|
|
188
|
+
====
|
|
189
|
+
|
|
190
|
+
[example]
|
|
191
|
+
====
|
|
192
|
+
[source,postscript]
|
|
193
|
+
----
|
|
194
|
+
gsave
|
|
195
|
+
100 100 translate % Move to rotation center
|
|
196
|
+
30 rotate % Rotate 30°
|
|
197
|
+
newpath
|
|
198
|
+
0 0 moveto
|
|
199
|
+
50 0 lineto % Rotated line from center
|
|
200
|
+
stroke
|
|
201
|
+
grestore
|
|
202
|
+
----
|
|
203
|
+
|
|
204
|
+
Typical pattern: translate to rotation center, then rotate.
|
|
205
|
+
====
|
|
206
|
+
|
|
207
|
+
[example]
|
|
208
|
+
====
|
|
209
|
+
[source,postscript]
|
|
210
|
+
----
|
|
211
|
+
% Draw 12 radial lines (like clock face)
|
|
212
|
+
0 1 11 { % Loop 0 to 11
|
|
213
|
+
gsave
|
|
214
|
+
100 100 translate % Center point
|
|
215
|
+
30 mul rotate % Rotate by 0°, 30°, 60°, etc.
|
|
216
|
+
0 0 moveto
|
|
217
|
+
40 0 lineto
|
|
218
|
+
stroke
|
|
219
|
+
grestore
|
|
220
|
+
} for
|
|
221
|
+
----
|
|
222
|
+
|
|
223
|
+
Multiple rotations create radial patterns.
|
|
224
|
+
====
|
|
225
|
+
|
|
226
|
+
[[concat]]
|
|
227
|
+
== concat
|
|
228
|
+
|
|
229
|
+
=== General
|
|
230
|
+
|
|
231
|
+
The `concat` operator concatenates (multiplies) an arbitrary matrix with the
|
|
232
|
+
current transformation matrix. This provides full control over transformations
|
|
233
|
+
beyond the basic translate/scale/rotate operations.
|
|
234
|
+
|
|
235
|
+
The matrix format is `[a b c d tx ty]` representing:
|
|
236
|
+
|
|
237
|
+
[source]
|
|
238
|
+
----
|
|
239
|
+
[ a b 0 ]
|
|
240
|
+
[ c d 0 ]
|
|
241
|
+
[ tx ty 1 ]
|
|
242
|
+
----
|
|
243
|
+
|
|
244
|
+
=== Syntax
|
|
245
|
+
|
|
246
|
+
[source,postscript]
|
|
247
|
+
----
|
|
248
|
+
[a b c d tx ty] concat <1> <2>
|
|
249
|
+
----
|
|
250
|
+
<1> 6-element transformation matrix
|
|
251
|
+
<2> Operator that concatenates matrix
|
|
252
|
+
|
|
253
|
+
Where,
|
|
254
|
+
|
|
255
|
+
`a, b, c, d`:: Matrix coefficients for rotation/scaling/shearing
|
|
256
|
+
`tx, ty`:: Translation components
|
|
257
|
+
|
|
258
|
+
Stack effect: `matrix -- `
|
|
259
|
+
|
|
260
|
+
=== Examples
|
|
261
|
+
|
|
262
|
+
[example]
|
|
263
|
+
====
|
|
264
|
+
[source,postscript]
|
|
265
|
+
----
|
|
266
|
+
% Identity matrix (no change)
|
|
267
|
+
[1 0 0 1 0 0] concat
|
|
268
|
+
|
|
269
|
+
% Translation by (100, 50)
|
|
270
|
+
[1 0 0 1 100 50] concat
|
|
271
|
+
|
|
272
|
+
% Scaling by 2× in both directions
|
|
273
|
+
[2 0 0 2 0 0] concat
|
|
274
|
+
|
|
275
|
+
% Rotation by 45° (approximately)
|
|
276
|
+
[0.707 0.707 -0.707 0.707 0 0] concat
|
|
277
|
+
----
|
|
278
|
+
|
|
279
|
+
Matrix format enables precise control over transformations.
|
|
280
|
+
====
|
|
281
|
+
|
|
282
|
+
[[currentmatrix]]
|
|
283
|
+
== currentmatrix
|
|
284
|
+
|
|
285
|
+
=== General
|
|
286
|
+
|
|
287
|
+
The `currentmatrix` operator retrieves the current transformation matrix and
|
|
288
|
+
stores it in the provided matrix object.
|
|
289
|
+
|
|
290
|
+
This is useful for saving the current transformation state or examining the
|
|
291
|
+
cumulative effect of multiple transformations.
|
|
292
|
+
|
|
293
|
+
=== Syntax
|
|
294
|
+
|
|
295
|
+
[source,postscript]
|
|
296
|
+
----
|
|
297
|
+
matrix currentmatrix <1> <2>
|
|
298
|
+
----
|
|
299
|
+
<1> Matrix object to receive CTM
|
|
300
|
+
<2> Operator that retrieves current matrix
|
|
301
|
+
|
|
302
|
+
Where,
|
|
303
|
+
|
|
304
|
+
`matrix`:: Matrix object (created with `matrix` operator)
|
|
305
|
+
|
|
306
|
+
Stack effect: `matrix -- matrix` (returns same matrix)
|
|
307
|
+
|
|
308
|
+
=== Examples
|
|
309
|
+
|
|
310
|
+
[example]
|
|
311
|
+
====
|
|
312
|
+
[source,postscript]
|
|
313
|
+
----
|
|
314
|
+
matrix currentmatrix % Get current CTM
|
|
315
|
+
% Matrix now contains [a b c d tx ty]
|
|
316
|
+
----
|
|
317
|
+
|
|
318
|
+
Returns the 6 coefficients of the current transformation.
|
|
319
|
+
====
|
|
320
|
+
|
|
321
|
+
[[setmatrix]]
|
|
322
|
+
== setmatrix
|
|
323
|
+
|
|
324
|
+
=== General
|
|
325
|
+
|
|
326
|
+
The `setmatrix` operator replaces the CTM with the specified matrix. Unlike
|
|
327
|
+
`concat`, which multiplies matrices, `setmatrix` completely replaces the CTM.
|
|
328
|
+
|
|
329
|
+
Use this with caution, as it bypasses the normal transformation accumulation.
|
|
330
|
+
|
|
331
|
+
=== Syntax
|
|
332
|
+
|
|
333
|
+
[source,postscript]
|
|
334
|
+
----
|
|
335
|
+
[a b c d tx ty] setmatrix <1> <2>
|
|
336
|
+
----
|
|
337
|
+
<1> New transformation matrix
|
|
338
|
+
<2> Operator that replaces CTM
|
|
339
|
+
|
|
340
|
+
Where,
|
|
341
|
+
|
|
342
|
+
`matrix`:: 6-element matrix to use as new CTM
|
|
343
|
+
|
|
344
|
+
Stack effect: `matrix -- `
|
|
345
|
+
|
|
346
|
+
[[matrix]]
|
|
347
|
+
== matrix
|
|
348
|
+
|
|
349
|
+
=== General
|
|
350
|
+
|
|
351
|
+
The `matrix` operator creates a new identity matrix object. This is typically
|
|
352
|
+
used with `currentmatrix` to capture the current transformation state.
|
|
353
|
+
|
|
354
|
+
=== Syntax
|
|
355
|
+
|
|
356
|
+
[source,postscript]
|
|
357
|
+
----
|
|
358
|
+
matrix <1>
|
|
359
|
+
----
|
|
360
|
+
<1> Create identity matrix object
|
|
361
|
+
|
|
362
|
+
Where,
|
|
363
|
+
|
|
364
|
+
Stack effect: `-- matrix`
|
|
365
|
+
|
|
366
|
+
=== Examples
|
|
367
|
+
|
|
368
|
+
[example]
|
|
369
|
+
====
|
|
370
|
+
[source,postscript]
|
|
371
|
+
----
|
|
372
|
+
/savedmatrix matrix def % Create matrix variable
|
|
373
|
+
savedmatrix currentmatrix pop % Save current CTM
|
|
374
|
+
|
|
375
|
+
% Make transformations
|
|
376
|
+
100 100 translate
|
|
377
|
+
45 rotate
|
|
378
|
+
|
|
379
|
+
% Restore saved transformation
|
|
380
|
+
savedmatrix setmatrix
|
|
381
|
+
----
|
|
382
|
+
|
|
383
|
+
Save and restore transformation state.
|
|
384
|
+
====
|
|
385
|
+
|
|
386
|
+
== Transformation Order
|
|
387
|
+
|
|
388
|
+
=== General
|
|
389
|
+
|
|
390
|
+
Transformations are cumulative and apply in the order specified. The order
|
|
391
|
+
matters because matrix multiplication is not commutative.
|
|
392
|
+
|
|
393
|
+
=== Order matters
|
|
394
|
+
|
|
395
|
+
[example]
|
|
396
|
+
====
|
|
397
|
+
[source,postscript]
|
|
398
|
+
----
|
|
399
|
+
% Pattern A: translate then rotate
|
|
400
|
+
gsave
|
|
401
|
+
100 100 translate % Step 1
|
|
402
|
+
45 rotate % Step 2
|
|
403
|
+
newpath
|
|
404
|
+
0 0 moveto 50 0 lineto stroke
|
|
405
|
+
grestore
|
|
406
|
+
|
|
407
|
+
% Pattern B: rotate then translate
|
|
408
|
+
gsave
|
|
409
|
+
45 rotate % Step 1
|
|
410
|
+
100 100 translate % Step 2
|
|
411
|
+
newpath
|
|
412
|
+
0 0 moveto 50 0 lineto stroke
|
|
413
|
+
grestore
|
|
414
|
+
----
|
|
415
|
+
|
|
416
|
+
These produce different results: A rotates around point (100, 100), while B
|
|
417
|
+
rotates around the origin then translates the result.
|
|
418
|
+
====
|
|
419
|
+
|
|
420
|
+
=== Typical transformation sequence
|
|
421
|
+
|
|
422
|
+
[example]
|
|
423
|
+
====
|
|
424
|
+
[source,postscript]
|
|
425
|
+
----
|
|
426
|
+
gsave
|
|
427
|
+
% 1. Translate to desired position
|
|
428
|
+
xpos ypos translate
|
|
429
|
+
|
|
430
|
+
% 2. Rotate around that position
|
|
431
|
+
angle rotate
|
|
432
|
+
|
|
433
|
+
% 3. Scale if needed
|
|
434
|
+
sx sy scale
|
|
435
|
+
|
|
436
|
+
% 4. Draw in local coordinate system
|
|
437
|
+
% (0, 0) is now at (xpos, ypos), rotated and scaled
|
|
438
|
+
newpath
|
|
439
|
+
0 0 moveto
|
|
440
|
+
width 0 lineto
|
|
441
|
+
stroke
|
|
442
|
+
grestore
|
|
443
|
+
----
|
|
444
|
+
|
|
445
|
+
Standard pattern: translate, rotate, scale, then draw.
|
|
446
|
+
====
|
|
447
|
+
|
|
448
|
+
== Coordinate System Inversion
|
|
449
|
+
|
|
450
|
+
=== General
|
|
451
|
+
|
|
452
|
+
PostScript uses a coordinate system with Y increasing upward, while many
|
|
453
|
+
graphics systems (including SVG) use Y increasing downward. To convert between
|
|
454
|
+
them, use a reflection transformation.
|
|
455
|
+
|
|
456
|
+
[example]
|
|
457
|
+
====
|
|
458
|
+
[source,postscript]
|
|
459
|
+
----
|
|
460
|
+
% Reflect Y-axis for top-to-bottom coordinates
|
|
461
|
+
1 -1 scale % Flip Y
|
|
462
|
+
0 -height translate % Move origin to top
|
|
463
|
+
|
|
464
|
+
% Now (0, 0) is top-left, Y increases downward
|
|
465
|
+
----
|
|
466
|
+
|
|
467
|
+
This transformation is commonly needed when converting PostScript to other
|
|
468
|
+
formats.
|
|
469
|
+
====
|
|
470
|
+
|
|
471
|
+
== See Also
|
|
472
|
+
|
|
473
|
+
* link:graphics-state.adoc[Graphics State] - Transformations are part of
|
|
474
|
+
graphics state
|
|
475
|
+
* link:../graphics-model.adoc#coordinate-transformations[Coordinate
|
|
476
|
+
Transformations] - Conceptual overview
|
|
477
|
+
* link:../svg-mapping.adoc#transformation-matrix[SVG Mapping] - Converting to
|
|
478
|
+
SVG transforms
|
|
479
|
+
* link:index.adoc[Back to Operator Reference]
|