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,356 @@
1
+ = PostScript Language Fundamentals
2
+
3
+ == General
4
+
5
+ PostScript is a stack-based, interpreted programming language created by Adobe
6
+ Systems in 1984. It was designed as a page description language for printers
7
+ and imagesetters, but its capabilities extend to general-purpose programming.
8
+
9
+ The Postsvg library implements the graphics subset of PostScript necessary for
10
+ converting vector graphics to SVG format.
11
+
12
+ == Stack-Based Execution Model
13
+
14
+ === General
15
+
16
+ PostScript uses a Last-In-First-Out (LIFO) stack called the operand stack to
17
+ hold data values. All operations in PostScript work by manipulating this stack.
18
+
19
+ When you execute a PostScript program, numbers and other literal values are
20
+ pushed onto the stack, and operators consume values from the stack and push
21
+ results back onto it.
22
+
23
+ === Stack operations
24
+
25
+ [source,postscript]
26
+ ----
27
+ 5 % Push 5 onto stack → [5]
28
+ 3 % Push 3 onto stack → [5 3]
29
+ add % Add: pop 3 and 5, push 8 → [8]
30
+ 2 % Push 2 onto stack → [8 2]
31
+ mul % Multiply: pop 2 and 8, push 16 → [16]
32
+ ----
33
+
34
+ Stack state notation: `[...]` shows stack contents, rightmost is top.
35
+
36
+ === Stack visualization
37
+
38
+ [example]
39
+ ====
40
+ [source]
41
+ ----
42
+ Initial: []
43
+ 10 [10]
44
+ 20 [10 20]
45
+ 30 [10 20 30]
46
+ add [10 50] % 20 + 30 = 50
47
+ mul [500] % 10 * 50 = 500
48
+ ----
49
+
50
+ The final result (500) remains on the stack.
51
+ ====
52
+
53
+ == Data Types
54
+
55
+ === General
56
+
57
+ PostScript supports several data types, each serving specific purposes in
58
+ graphics programming.
59
+
60
+ [[numbers]]
61
+ === Numbers
62
+
63
+ Numbers can be integers or real (floating-point) values.
64
+
65
+ Integers:: Whole numbers without a decimal point (e.g., `42`, `-7`, `0`)
66
+ Reals:: Numbers with decimal points (e.g., `3.14`, `-2.5`, `0.0`)
67
+
68
+ [example]
69
+ ====
70
+ [source,postscript]
71
+ ----
72
+ 100 % Integer
73
+ 72.5 % Real number
74
+ -3.14159 % Negative real
75
+ 1.0e6 % Scientific notation (1,000,000)
76
+ ----
77
+ ====
78
+
79
+ [[strings]]
80
+ === Strings
81
+
82
+ Strings are sequences of characters enclosed in parentheses.
83
+
84
+ [source,postscript]
85
+ ----
86
+ (Hello, World!) % Simple string
87
+ (Line 1\nLine 2) % String with newline
88
+ (Parentheses \( \)) % Escaped parentheses
89
+ ----
90
+
91
+ [[names]]
92
+ === Names
93
+
94
+ Names are identifiers used to reference operators, variables, and procedures.
95
+ Literal names begin with a forward slash (`/`).
96
+
97
+ [source,postscript]
98
+ ----
99
+ /MyVariable % Literal name
100
+ moveto % Executable name (operator)
101
+ /Times-Roman % Literal name for font
102
+ ----
103
+
104
+ [[arrays]]
105
+ === Arrays
106
+
107
+ Arrays are ordered collections of objects, enclosed in square brackets.
108
+
109
+ [source,postscript]
110
+ ----
111
+ [1 2 3 4 5] % Array of numbers
112
+ [/name 100 (string)] % Mixed-type array
113
+ [1 2 add 3] % Array with executable operator
114
+ ----
115
+
116
+ [[procedures]]
117
+ === Procedures
118
+
119
+ Procedures are executable arrays enclosed in curly braces, used for defining
120
+ reusable code blocks.
121
+
122
+ [source,postscript]
123
+ ----
124
+ { 2 mul } % Procedure to double a number
125
+ { 0 0 moveto 100 100 lineto stroke } % Drawing procedure
126
+ ----
127
+
128
+ [[booleans]]
129
+ === Booleans
130
+
131
+ Boolean values represent true or false.
132
+
133
+ [source,postscript]
134
+ ----
135
+ true % Boolean true
136
+ false % Boolean false
137
+ ----
138
+
139
+ == Coordinate System
140
+
141
+ === General
142
+
143
+ PostScript uses a Cartesian coordinate system where:
144
+
145
+ * Origin (0, 0) is at the bottom-left corner
146
+ * X-axis increases to the right
147
+ * Y-axis increases upward
148
+ * Default unit is 1 point (1/72 inch)
149
+
150
+ === Coordinate system diagram
151
+
152
+ [source]
153
+ ----
154
+ +Y
155
+
156
+ |
157
+ | (100, 100)
158
+ | •
159
+ |
160
+ |
161
+ | •
162
+ | (50, 50)
163
+ |
164
+ +---------------→ +X
165
+ (0, 0)
166
+ ----
167
+
168
+ === User space vs device space
169
+
170
+ User space:: The coordinate system used in PostScript programs
171
+ Device space:: The actual physical coordinates of the output device
172
+
173
+ Transformations convert between these spaces, allowing device-independent
174
+ graphics programming.
175
+
176
+ == Syntax Rules
177
+
178
+ === General
179
+
180
+ PostScript syntax is designed to be simple and consistent.
181
+
182
+ === Whitespace
183
+
184
+ Whitespace (spaces, tabs, newlines) separates tokens and is generally ignored.
185
+
186
+ [source,postscript]
187
+ ----
188
+ 10 20 add % Same as:
189
+ 10
190
+ 20
191
+ add
192
+ ----
193
+
194
+ === Comments
195
+
196
+ Comments begin with `%` and extend to the end of the line.
197
+
198
+ [source,postscript]
199
+ ----
200
+ % This is a comment
201
+ 100 100 moveto % Move to point (100, 100)
202
+ ----
203
+
204
+ Special comments:
205
+
206
+ `%!PS-Adobe-3.0`:: Header identifying PostScript version
207
+ `%%BoundingBox: llx lly urx ury`:: Defines document bounding box
208
+
209
+ [example]
210
+ ====
211
+ [source,postscript]
212
+ ----
213
+ %!PS-Adobe-3.0 EPSF-3.0
214
+ %%BoundingBox: 0 0 612 792
215
+ %%Title: My Document
216
+ %%Creator: Postsvg Example
217
+ ----
218
+
219
+ These structured comments provide metadata about the PostScript file.
220
+ ====
221
+
222
+ === Case sensitivity
223
+
224
+ PostScript is case-sensitive. `moveto`, `MoveTo`, and `MOVETO` are all
225
+ different names.
226
+
227
+ [source,postscript]
228
+ ----
229
+ /MyName 100 def % Defines MyName
230
+ /myname 200 def % Defines different name: myname
231
+ ----
232
+
233
+ === Token delimiters
234
+
235
+ Tokens are delimited by:
236
+
237
+ * Whitespace (space, tab, newline)
238
+ * Special characters: `()`, `<>`, `[]`, `{}`, `%`, `/`
239
+
240
+ [source,postscript]
241
+ ----
242
+ [1 2 3] % Array tokens: [ 1 2 3 ]
243
+ {2 mul} % Procedure tokens: { 2 mul }
244
+ /name 100 % Name token: /name followed by 100
245
+ ----
246
+
247
+ == Execution Model
248
+
249
+ === General
250
+
251
+ PostScript programs execute sequentially, processing tokens one at a time.
252
+
253
+ === Literal vs executable objects
254
+
255
+ Literal objects:: Pushed directly onto the stack (numbers, literal names,
256
+ strings)
257
+ Executable objects:: Executed when encountered (operators, procedures)
258
+
259
+ [example]
260
+ ====
261
+ [source,postscript]
262
+ ----
263
+ 100 % Literal: pushed to stack → [100]
264
+ /name % Literal name: pushed to stack → [100 /name]
265
+ dup % Executable: duplicates top stack item → [100 /name /name]
266
+ ----
267
+ ====
268
+
269
+ === Immediate execution
270
+
271
+ [source,postscript]
272
+ ----
273
+ 5 3 add % Executes add immediately: [8]
274
+ { 5 3 add } % Creates procedure, does not execute: [{ 5 3 add }]
275
+ exec % Executes procedure on stack: [8]
276
+ ----
277
+
278
+ == Dictionaries and Scopes
279
+
280
+ === General
281
+
282
+ Dictionaries are associative arrays that map keys to values. They implement
283
+ variable storage in PostScript.
284
+
285
+ === Dictionary stack
286
+
287
+ PostScript maintains a dictionary stack separate from the operand stack.
288
+ Name lookup searches from the top of the dictionary stack downward.
289
+
290
+ === Defining variables
291
+
292
+ [source,postscript]
293
+ ----
294
+ /MyVar 100 def % Define MyVar with value 100
295
+ MyVar 2 mul % Use MyVar: [200]
296
+ ----
297
+
298
+ The `def` operator stores a key-value pair in the current dictionary.
299
+
300
+ === Local dictionaries
301
+
302
+ [source,postscript]
303
+ ----
304
+ 10 dict begin % Create and enter new dictionary
305
+ /x 100 def % Define x locally
306
+ /y 200 def % Define y locally
307
+ x y add % Use local variables: [300]
308
+ end % Exit dictionary
309
+ ----
310
+
311
+ == Program Structure
312
+
313
+ === General
314
+
315
+ A typical PostScript graphics program follows this structure:
316
+
317
+ [example]
318
+ ====
319
+ [source,postscript]
320
+ ----
321
+ %!PS-Adobe-3.0 EPSF-3.0
322
+ %%BoundingBox: 0 0 200 200
323
+
324
+ % Define any procedures or variables
325
+ /box { % Procedure to draw a box
326
+ newpath
327
+ 0 0 moveto
328
+ 100 0 lineto
329
+ 100 100 lineto
330
+ 0 100 lineto
331
+ closepath
332
+ } def
333
+
334
+ % Main graphics commands
335
+ gsave % Save state
336
+ 50 50 translate % Position the box
337
+ box % Draw box outline
338
+ 0.5 setgray % Set gray color
339
+ stroke % Render the outline
340
+ grestore % Restore state
341
+
342
+ showpage % Display the page
343
+ %%EOF
344
+ ----
345
+
346
+ This example defines a reusable box procedure, positions it using
347
+ transformations, and renders it with specified styling.
348
+ ====
349
+
350
+ == See Also
351
+
352
+ * link:graphics-model.adoc[Graphics Model] - Graphics state and paths
353
+ * link:operators/stack-manipulation.adoc[Stack Operators] - Stack
354
+ manipulation commands
355
+ * link:operators/dictionary.adoc[Dictionary Operators] - Dictionary operations
356
+ * link:index.adoc[Back to PostScript Quick Reference]