postsvg 0.1.0 → 0.3.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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +105 -0
  3. data/CLAUDE.md +173 -0
  4. data/Gemfile +2 -3
  5. data/README.adoc +456 -179
  6. data/Rakefile +100 -0
  7. data/TODO.roadmap/00-architecture.md +139 -0
  8. data/TODO.roadmap/01-autoload-migration.md +39 -0
  9. data/TODO.roadmap/02-isolate-dormant-code.md +51 -0
  10. data/TODO.roadmap/03-domain-model.md +66 -0
  11. data/TODO.roadmap/04-lexer.md +40 -0
  12. data/TODO.roadmap/05-parser.md +43 -0
  13. data/TODO.roadmap/06-graphics-state.md +45 -0
  14. data/TODO.roadmap/07-matrix-and-color.md +37 -0
  15. data/TODO.roadmap/08-svg-builder.md +51 -0
  16. data/TODO.roadmap/09-renderer.md +52 -0
  17. data/TODO.roadmap/10-visitor.md +58 -0
  18. data/TODO.roadmap/11-operator-coverage.md +103 -0
  19. data/TODO.roadmap/12-svg-domain.md +62 -0
  20. data/TODO.roadmap/13-translation-handlers.md +69 -0
  21. data/TODO.roadmap/14-ps-serializer.md +49 -0
  22. data/TODO.roadmap/15-cli-and-public-api.md +47 -0
  23. data/TODO.roadmap/16-specs.md +84 -0
  24. data/TODO.roadmap/17-docs-sync.md +47 -0
  25. data/TODO.roadmap/18-performance-and-determinism.md +47 -0
  26. data/TODO.roadmap/19-error-model.md +45 -0
  27. data/TODO.roadmap/20-font-and-text.md +46 -0
  28. data/TODO.roadmap/21-images.md +45 -0
  29. data/TODO.roadmap/22-forms-and-resources.md +25 -0
  30. data/TODO.roadmap/23-level2-level3.md +52 -0
  31. data/TODO.roadmap/24-ci-and-release.md +42 -0
  32. data/TODO.roadmap/README.md +77 -0
  33. data/docs/.gitignore +29 -0
  34. data/docs/CHANGELOG.md +114 -0
  35. data/docs/COMPLETE_DOCUMENTATION_STATUS.md +376 -0
  36. data/docs/DEPLOYMENT.md +456 -0
  37. data/docs/DEPLOYMENT_INSTRUCTIONS.md +229 -0
  38. data/docs/DOCUMENTATION_PLAN.md +425 -0
  39. data/docs/FINAL_SUMMARY.md +657 -0
  40. data/docs/Gemfile +15 -0
  41. data/docs/README.md +327 -0
  42. data/docs/_config.yml +99 -0
  43. data/docs/advanced-topics.adoc +370 -0
  44. data/docs/api-reference/colors.adoc +705 -0
  45. data/docs/api-reference/converter.adoc +699 -0
  46. data/docs/api-reference/execution-context.adoc +1210 -0
  47. data/docs/api-reference/graphics-state.adoc +1070 -0
  48. data/docs/api-reference/interpreter.adoc +810 -0
  49. data/docs/api-reference/matrix.adoc +1179 -0
  50. data/docs/api-reference/path-builder.adoc +1284 -0
  51. data/docs/api-reference/postsvg-module.adoc +388 -0
  52. data/docs/api-reference/svg-generator.adoc +891 -0
  53. data/docs/api-reference/tokenizer.adoc +925 -0
  54. data/docs/api-reference.adoc +221 -0
  55. data/docs/architecture/command-registry.adoc +1191 -0
  56. data/docs/architecture/conversion-pipeline.adoc +746 -0
  57. data/docs/architecture/design-decisions.adoc +999 -0
  58. data/docs/architecture/generator-stage.adoc +1115 -0
  59. data/docs/architecture/graphics-state-model.adoc +1089 -0
  60. data/docs/architecture/interpreter-stage.adoc +1125 -0
  61. data/docs/architecture/parser-stage.adoc +1051 -0
  62. data/docs/architecture.adoc +354 -0
  63. data/docs/cli-reference/batch-command.adoc +616 -0
  64. data/docs/cli-reference/check-command.adoc +677 -0
  65. data/docs/cli-reference/cli-options.adoc +802 -0
  66. data/docs/cli-reference/convert-command.adoc +462 -0
  67. data/docs/cli-reference/version-command.adoc +296 -0
  68. data/docs/cli-reference.adoc +317 -0
  69. data/docs/concepts/conversion-pipeline.adoc +903 -0
  70. data/docs/concepts/coordinate-systems.adoc +836 -0
  71. data/docs/concepts/graphics-state.adoc +861 -0
  72. data/docs/concepts/path-operations.adoc +1076 -0
  73. data/docs/concepts/postscript-language.adoc +859 -0
  74. data/docs/concepts/svg-generation.adoc +937 -0
  75. data/docs/concepts.adoc +198 -0
  76. data/docs/contributing.adoc +443 -0
  77. data/docs/development.adoc +420 -0
  78. data/docs/faq.adoc +493 -0
  79. data/docs/getting-started/basic-usage.adoc +538 -0
  80. data/docs/getting-started/common-workflows.adoc +577 -0
  81. data/docs/getting-started/first-conversion.adoc +492 -0
  82. data/docs/getting-started/installation.adoc +534 -0
  83. data/docs/getting-started.adoc +94 -0
  84. data/docs/index.adoc +248 -0
  85. data/docs/optimization.adoc +196 -0
  86. data/docs/ps2svg_compatibility.adoc +149 -0
  87. data/docs/quick-reference.adoc +453 -0
  88. data/docs/sitemap.adoc +337 -0
  89. data/docs/troubleshooting.adoc +486 -0
  90. data/docs/validation.adoc +772 -0
  91. data/exe/postsvg +1 -0
  92. data/lib/postsvg/cli.rb +104 -57
  93. data/lib/postsvg/color.rb +132 -0
  94. data/lib/postsvg/errors.rb +68 -3
  95. data/lib/postsvg/format_number.rb +22 -0
  96. data/lib/postsvg/graphics_context.rb +80 -0
  97. data/lib/postsvg/graphics_stack.rb +43 -0
  98. data/lib/postsvg/model/literals/array.rb +41 -0
  99. data/lib/postsvg/model/literals/dictionary.rb +34 -0
  100. data/lib/postsvg/model/literals/hex.rb +37 -0
  101. data/lib/postsvg/model/literals/name.rb +40 -0
  102. data/lib/postsvg/model/literals/number.rb +36 -0
  103. data/lib/postsvg/model/literals/procedure.rb +41 -0
  104. data/lib/postsvg/model/literals/string.rb +30 -0
  105. data/lib/postsvg/model/literals.rb +19 -0
  106. data/lib/postsvg/model/operator.rb +58 -0
  107. data/lib/postsvg/model/operators/arithmetic.rb +264 -0
  108. data/lib/postsvg/model/operators/boolean.rb +182 -0
  109. data/lib/postsvg/model/operators/color.rb +74 -0
  110. data/lib/postsvg/model/operators/container.rb +186 -0
  111. data/lib/postsvg/model/operators/control_flow.rb +119 -0
  112. data/lib/postsvg/model/operators/device.rb +21 -0
  113. data/lib/postsvg/model/operators/dictionary.rb +118 -0
  114. data/lib/postsvg/model/operators/font.rb +121 -0
  115. data/lib/postsvg/model/operators/graphics_state.rb +84 -0
  116. data/lib/postsvg/model/operators/painting.rb +29 -0
  117. data/lib/postsvg/model/operators/path.rb +169 -0
  118. data/lib/postsvg/model/operators/stack.rb +72 -0
  119. data/lib/postsvg/model/operators/transformations.rb +103 -0
  120. data/lib/postsvg/model/operators.rb +89 -0
  121. data/lib/postsvg/model/program.rb +68 -0
  122. data/lib/postsvg/model/token.rb +43 -0
  123. data/lib/postsvg/model.rb +17 -0
  124. data/lib/postsvg/options.rb +29 -0
  125. data/lib/postsvg/renderer.rb +85 -0
  126. data/lib/postsvg/serializer.rb +325 -0
  127. data/lib/postsvg/source/ast_builder.rb +308 -0
  128. data/lib/postsvg/source/lexer.rb +322 -0
  129. data/lib/postsvg/source/operand_stack.rb +55 -0
  130. data/lib/postsvg/source.rb +21 -0
  131. data/lib/postsvg/svg/attribute_parser.rb +45 -0
  132. data/lib/postsvg/svg/clip_path_registry.rb +44 -0
  133. data/lib/postsvg/svg/document.rb +22 -0
  134. data/lib/postsvg/svg/element.rb +84 -0
  135. data/lib/postsvg/svg/elements/circle.rb +36 -0
  136. data/lib/postsvg/svg/elements/clip_path.rb +26 -0
  137. data/lib/postsvg/svg/elements/defs.rb +24 -0
  138. data/lib/postsvg/svg/elements/ellipse.rb +38 -0
  139. data/lib/postsvg/svg/elements/group.rb +37 -0
  140. data/lib/postsvg/svg/elements/image.rb +35 -0
  141. data/lib/postsvg/svg/elements/line.rb +36 -0
  142. data/lib/postsvg/svg/elements/path.rb +32 -0
  143. data/lib/postsvg/svg/elements/polygon.rb +12 -0
  144. data/lib/postsvg/svg/elements/polyline.rb +32 -0
  145. data/lib/postsvg/svg/elements/rect.rb +44 -0
  146. data/lib/postsvg/svg/elements/svg.rb +39 -0
  147. data/lib/postsvg/svg/elements/text.rb +42 -0
  148. data/lib/postsvg/svg/elements.rb +31 -0
  149. data/lib/postsvg/svg/paint.rb +34 -0
  150. data/lib/postsvg/svg/parser.rb +39 -0
  151. data/lib/postsvg/svg/path_data/command.rb +27 -0
  152. data/lib/postsvg/svg/path_data/parser.rb +82 -0
  153. data/lib/postsvg/svg/path_data.rb +17 -0
  154. data/lib/postsvg/svg/stroke.rb +31 -0
  155. data/lib/postsvg/svg/transform_list.rb +59 -0
  156. data/lib/postsvg/svg.rb +22 -0
  157. data/lib/postsvg/svg_builder.rb +249 -0
  158. data/lib/postsvg/translation/arc_converter.rb +86 -0
  159. data/lib/postsvg/translation/bounding_box.rb +59 -0
  160. data/lib/postsvg/translation/context.rb +34 -0
  161. data/lib/postsvg/translation/handler_registry.rb +38 -0
  162. data/lib/postsvg/translation/handlers/circle_handler.rb +28 -0
  163. data/lib/postsvg/translation/handlers/clip_path_handler.rb +13 -0
  164. data/lib/postsvg/translation/handlers/defs_handler.rb +15 -0
  165. data/lib/postsvg/translation/handlers/ellipse_handler.rb +31 -0
  166. data/lib/postsvg/translation/handlers/group_handler.rb +21 -0
  167. data/lib/postsvg/translation/handlers/image_handler.rb +20 -0
  168. data/lib/postsvg/translation/handlers/line_handler.rb +23 -0
  169. data/lib/postsvg/translation/handlers/open_handler.rb +18 -0
  170. data/lib/postsvg/translation/handlers/path_handler.rb +356 -0
  171. data/lib/postsvg/translation/handlers/polygon_handler.rb +33 -0
  172. data/lib/postsvg/translation/handlers/polyline_handler.rb +31 -0
  173. data/lib/postsvg/translation/handlers/rect_handler.rb +27 -0
  174. data/lib/postsvg/translation/handlers/shared.rb +110 -0
  175. data/lib/postsvg/translation/handlers/svg_handler.rb +25 -0
  176. data/lib/postsvg/translation/handlers/text_handler.rb +56 -0
  177. data/lib/postsvg/translation/handlers.rb +25 -0
  178. data/lib/postsvg/translation/ps_renderer.rb +105 -0
  179. data/lib/postsvg/translation/record_emitter.rb +35 -0
  180. data/lib/postsvg/translation.rb +17 -0
  181. data/lib/postsvg/version.rb +1 -1
  182. data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +125 -0
  183. data/lib/postsvg/visitors/ps_visitor/boolean.rb +105 -0
  184. data/lib/postsvg/visitors/ps_visitor/color.rb +53 -0
  185. data/lib/postsvg/visitors/ps_visitor/common.rb +66 -0
  186. data/lib/postsvg/visitors/ps_visitor/container.rb +164 -0
  187. data/lib/postsvg/visitors/ps_visitor/control_flow.rb +110 -0
  188. data/lib/postsvg/visitors/ps_visitor/device.rb +20 -0
  189. data/lib/postsvg/visitors/ps_visitor/dictionary.rb +89 -0
  190. data/lib/postsvg/visitors/ps_visitor/font.rb +93 -0
  191. data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +55 -0
  192. data/lib/postsvg/visitors/ps_visitor/painting.rb +90 -0
  193. data/lib/postsvg/visitors/ps_visitor/path.rb +112 -0
  194. data/lib/postsvg/visitors/ps_visitor/stack.rb +47 -0
  195. data/lib/postsvg/visitors/ps_visitor/transformations.rb +101 -0
  196. data/lib/postsvg/visitors/ps_visitor.rb +208 -0
  197. data/lib/postsvg/visitors.rb +9 -0
  198. data/lib/postsvg.rb +93 -59
  199. data/lychee.toml +86 -0
  200. metadata +216 -11
  201. data/postsvg.gemspec +0 -38
@@ -0,0 +1,859 @@
1
+ = PostScript Language Fundamentals
2
+ :page-nav_order: 6
3
+ :page-parent: Core Concepts
4
+
5
+ == Purpose
6
+
7
+ This document provides an introduction to the PostScript language fundamentals that are essential for understanding how Postsvg interprets PostScript code. While not a complete PostScript reference, it covers the core concepts needed to work effectively with Postsvg.
8
+
9
+ == References
10
+
11
+ * link:../index.adoc[Documentation Home]
12
+ * link:../concepts.adoc[Core Concepts Overview]
13
+ * link:conversion-pipeline.adoc[Conversion Pipeline]
14
+ * link:path-operations.adoc[Path Operations]
15
+ * link:graphics-state.adoc[Graphics State Management]
16
+
17
+ == Concepts
18
+
19
+ **Stack-Based Execution**:: PostScript uses a Last-In-First-Out (LIFO) stack for storing and manipulating values.
20
+
21
+ **Postfix Notation**:: Operators follow their operands (reverse Polish notation).
22
+
23
+ **Operator**:: A command that performs an operation, typically consuming operands from the stack.
24
+
25
+ **Operand**:: A value (number, string, array, etc.) that operators work with.
26
+
27
+ **Dictionary**:: A key-value data structure for storing definitions and variables.
28
+
29
+ == PostScript Language Overview
30
+
31
+ === What is PostScript?
32
+
33
+ PostScript is a page description language developed by Adobe Systems in 1984. It's:
34
+
35
+ * **Stack-based** - Uses a LIFO stack for operations
36
+ * **Interpreted** - Executed line-by-line or token-by-token
37
+ * **Turing-complete** - Can perform any computation
38
+ * **Device-independent** - Same code produces same result on any device
39
+
40
+ **Primary Uses:**
41
+
42
+ * Printer control language
43
+ * Vector graphics description
44
+ * Font rendering
45
+ * Page layout for professional printing
46
+
47
+ === PostScript vs. Other Languages
48
+
49
+ .Language Comparison
50
+ [source]
51
+ ----
52
+ Infix (Most Languages): PostScript (Postfix):
53
+ a = 2 + 3 2 3 add
54
+ result = (a + b) * c a b add c mul
55
+ if (x > 0) { ... } x 0 gt { ... } if
56
+ ----
57
+
58
+ **Advantages of Postfix:**
59
+
60
+ * No operator precedence ambiguity
61
+ * No parentheses needed for grouping
62
+ * Natural for stack-based execution
63
+ * Efficient for interpreters
64
+
65
+ == Stack Model
66
+
67
+ === The Operand Stack
68
+
69
+ The **operand stack** is the primary data structure in PostScript execution.
70
+
71
+ .Stack Visualization
72
+ [source]
73
+ ----
74
+ Bottom of Stack
75
+
76
+
77
+ ┌─────┐
78
+ │ 10 │ ← First value pushed
79
+ ├─────┤
80
+ │ 20 │ ← Second value pushed
81
+ ├─────┤
82
+ │ 30 │ ← Third value pushed (top)
83
+ └─────┘
84
+
85
+
86
+ Top of Stack
87
+ ----
88
+
89
+ **Stack Operations:**
90
+
91
+ * **Push** - Add value to top
92
+ * **Pop** - Remove value from top
93
+ * **Peek** - Look at top value without removing
94
+
95
+ === Stack Execution Example
96
+
97
+ .Stack Evolution
98
+ [example]
99
+ ====
100
+ [source,postscript]
101
+ ----
102
+ 10 % Push 10
103
+ 20 % Push 20
104
+ add % Pop 20 and 10, push 30
105
+ 3 % Push 3
106
+ mul % Pop 3 and 30, push 90
107
+ ----
108
+
109
+ Step-by-step stack evolution:
110
+
111
+ [source]
112
+ ----
113
+ Command Stack State Operation
114
+ ─────────────────────────────────────────
115
+ 10 [10] Push 10
116
+ 20 [10, 20] Push 20
117
+ add [30] Pop 20,10 → Push 10+20
118
+ 3 [30, 3] Push 3
119
+ mul [90] Pop 3,30 → Push 30×3
120
+ ----
121
+
122
+ Final result: 90 on stack
123
+ ====
124
+
125
+ === Stack Manipulation Operators
126
+
127
+ **Basic Stack Operations:**
128
+
129
+ `pop`:: Remove top item
130
+
131
+ [source,postscript]
132
+ ----
133
+ 10 20 pop % Stack: [10]
134
+ ----
135
+
136
+ `dup`:: Duplicate top item
137
+
138
+ [source,postscript]
139
+ ----
140
+ 10 dup % Stack: [10, 10]
141
+ ----
142
+
143
+ `exch`:: Exchange top two items
144
+
145
+ [source,postscript]
146
+ ----
147
+ 10 20 exch % Stack: [20, 10]
148
+ ----
149
+
150
+ `roll`:: Rotate n items j times
151
+
152
+ [source,postscript]
153
+ ----
154
+ 1 2 3 4 5 % Stack: [1,2,3,4,5]
155
+ 3 1 roll % Rotate top 3 items once
156
+ % Stack: [1,2,5,3,4]
157
+ ----
158
+
159
+ `copy`:: Duplicate top n items
160
+
161
+ [source,postscript]
162
+ ----
163
+ 10 20 30 % Stack: [10,20,30]
164
+ 2 copy % Stack: [10,20,30,20,30]
165
+ ----
166
+
167
+ `index`:: Copy nth item to top
168
+
169
+ [source,postscript]
170
+ ----
171
+ 10 20 30 40 % Stack: [10,20,30,40]
172
+ 2 index % Stack: [10,20,30,40,20]
173
+ ----
174
+
175
+ `clear`:: Clear entire stack
176
+
177
+ [source,postscript]
178
+ ----
179
+ 1 2 3 4 5 % Stack: [1,2,3,4,5]
180
+ clear % Stack: []
181
+ ----
182
+
183
+ `count`:: Count items on stack
184
+
185
+ [source,postscript]
186
+ ----
187
+ 10 20 30 % Stack: [10,20,30]
188
+ count % Stack: [10,20,30,3]
189
+ ----
190
+
191
+ == Data Types
192
+
193
+ === Numbers
194
+
195
+ **Integers:**
196
+
197
+ [source,postscript]
198
+ ----
199
+ 42 % Decimal integer
200
+ -17 % Negative integer
201
+ 0 % Zero
202
+ 16#FF % Hexadecimal (255 decimal)
203
+ 8#77 % Octal (63 decimal)
204
+ ----
205
+
206
+ **Real Numbers (Floats):**
207
+
208
+ [source,postscript]
209
+ ----
210
+ 3.14159 % Decimal float
211
+ -0.5 % Negative float
212
+ 1.5e-3 % Scientific notation (0.0015)
213
+ 6.02e23 % Large number
214
+ ----
215
+
216
+ === Strings
217
+
218
+ **Literal Strings:**
219
+
220
+ [source,postscript]
221
+ ----
222
+ (Hello World) % Simple string
223
+ (Line 1\nLine 2) % With newline
224
+ (It's a nice day) % Single quotes OK
225
+ (Backslash: \\) % Escaped backslash
226
+ (Parentheses: \( and \)) % Escaped parens
227
+ ----
228
+
229
+ **Hexadecimal Strings:**
230
+
231
+ [source,postscript]
232
+ ----
233
+ <48656C6C6F> % "Hello" in hex
234
+ <> % Empty string
235
+ <48 65 6C> % Same as <48656C>
236
+ ----
237
+
238
+ === Names
239
+
240
+ Names start with `/` and are used for variables and dictionary keys:
241
+
242
+ [source,postscript]
243
+ ----
244
+ /MyVariable % Name literal
245
+ /x % Short name
246
+ /CamelCase % Valid name
247
+ /with-dashes % Valid name
248
+ /name_123 % Valid name
249
+ ----
250
+
251
+ === Boolean
252
+
253
+ [source,postscript]
254
+ ----
255
+ true % Boolean true
256
+ false % Boolean false
257
+ ----
258
+
259
+ === Arrays
260
+
261
+ **Array Syntax:**
262
+
263
+ [source,postscript]
264
+ ----
265
+ [1 2 3 4 5] % Array of numbers
266
+ [/name1 /name2 /name3] % Array of names
267
+ [(Hello) (World)] % Array of strings
268
+ [1 (two) /three true] % Mixed types
269
+ [] % Empty array
270
+ ----
271
+
272
+ **Nested Arrays:**
273
+
274
+ [source,postscript]
275
+ ----
276
+ [[1 2] [3 4] [5 6]] % 2D array
277
+ [1 [2 [3 [4 [5]]]]] % Nested array
278
+ ----
279
+
280
+ === Procedures
281
+
282
+ Procedures are executable arrays enclosed in braces:
283
+
284
+ [source,postscript]
285
+ ----
286
+ { 2 mul } % Procedure: multiply by 2
287
+ { dup mul } % Procedure: square (x → x²)
288
+ { 100 100 moveto } % Graphics procedure
289
+ { exch sub } % Subtract reversed (b a → a-b)
290
+ ----
291
+
292
+ === Dictionaries
293
+
294
+ Dictionaries store key-value pairs:
295
+
296
+ [source,postscript]
297
+ ----
298
+ % Create dictionary with 10 entries
299
+ 10 dict begin
300
+ /x 100 def
301
+ /y 200 def
302
+ /name (MyName) def
303
+ end
304
+
305
+ % Inline dictionary (PostScript Level 2+)
306
+ << /x 100 /y 200 /name (MyName) >>
307
+ ----
308
+
309
+ == Operators
310
+
311
+ === Arithmetic Operators
312
+
313
+ **Basic Arithmetic:**
314
+
315
+ [source,postscript]
316
+ ----
317
+ 3 4 add % Addition: 3 + 4 = 7
318
+ 10 3 sub % Subtraction: 10 - 3 = 7
319
+ 5 6 mul % Multiplication: 5 × 6 = 30
320
+ 20 4 div % Division: 20 ÷ 4 = 5
321
+ 17 5 mod % Modulo: 17 % 5 = 2
322
+ ----
323
+
324
+ **Advanced Math:**
325
+
326
+ [source,postscript]
327
+ ----
328
+ 25 sqrt % Square root: √25 = 5
329
+ 2 8 exp % Exponentiation: 2⁸ = 256
330
+ 45 sin % Sine (degrees)
331
+ 45 cos % Cosine (degrees)
332
+ 1 atan % Arctangent
333
+ 100 ln % Natural logarithm
334
+ 10 log % Base-10 logarithm
335
+ -5 abs % Absolute value: |-5| = 5
336
+ ----
337
+
338
+ === Comparison Operators
339
+
340
+ [source,postscript]
341
+ ----
342
+ 3 4 eq % Equal: false
343
+ 3 3 eq % Equal: true
344
+ 5 3 ne % Not equal: true
345
+ 5 3 gt % Greater than: true
346
+ 3 5 lt % Less than: true
347
+ 5 5 ge % Greater or equal: true
348
+ 3 5 le % Less or equal: true
349
+ ----
350
+
351
+ === Logical Operators
352
+
353
+ [source,postscript]
354
+ ----
355
+ true true and % Logical AND: true
356
+ true false or % Logical OR: true
357
+ true not % Logical NOT: false
358
+ true false xor % Logical XOR: true
359
+ ----
360
+
361
+ === String Operators
362
+
363
+ [source,postscript]
364
+ ----
365
+ (Hello) length % String length: 5
366
+ (Hello) 0 get % Get char at index 0: H
367
+ (Hello) (World) eq % String equality: false
368
+ ----
369
+
370
+ === Array Operators
371
+
372
+ [source,postscript]
373
+ ----
374
+ [1 2 3 4] length % Array length: 4
375
+ [1 2 3] 1 get % Get element at index 1: 2
376
+ [10 20 30] 0 10 put % Set element 0 to 10
377
+ ----
378
+
379
+ == Control Flow
380
+
381
+ === Conditional Execution
382
+
383
+ **if:**
384
+
385
+ [source,postscript]
386
+ ----
387
+ condition { true-actions } if
388
+
389
+ % Example:
390
+ x 0 gt { (Positive) print } if
391
+ ----
392
+
393
+ **ifelse:**
394
+
395
+ [source,postscript]
396
+ ----
397
+ condition { true-actions } { false-actions } ifelse
398
+
399
+ % Example:
400
+ x 0 gt
401
+ { (Positive) print }
402
+ { (Not positive) print }
403
+ ifelse
404
+ ----
405
+
406
+ .Conditional Example
407
+ [example]
408
+ ====
409
+ [source,postscript]
410
+ ----
411
+ /x 10 def
412
+
413
+ % Test if x is positive
414
+ x 0 gt
415
+ {
416
+ % x > 0
417
+ x 0 moveto
418
+ x x lineto
419
+ stroke
420
+ }
421
+ {
422
+ % x ≤ 0
423
+ (x is not positive) print
424
+ }
425
+ ifelse
426
+ ----
427
+ ====
428
+
429
+ === Loops
430
+
431
+ **repeat:**
432
+
433
+ [source,postscript]
434
+ ----
435
+ n { actions } repeat
436
+
437
+ % Example: Print 1 to 5
438
+ 1 1 5 { dup = 1 add } repeat pop
439
+ ----
440
+
441
+ **for:**
442
+
443
+ [source,postscript]
444
+ ----
445
+ initial increment limit { actions } for
446
+
447
+ % Example: Count 0 to 10 by 2
448
+ 0 2 10 { = } for
449
+ % Output: 0 2 4 6 8 10
450
+ ----
451
+
452
+ **loop:**
453
+
454
+ [source,postscript]
455
+ ----
456
+ { actions exit-condition { exit } if } loop
457
+
458
+ % Example: Infinite loop with break
459
+ 0
460
+ {
461
+ dup = % Print current value
462
+ 1 add % Increment
463
+ dup 5 gt % Check if > 5
464
+ { exit } % Exit if true
465
+ if
466
+ } loop
467
+ ----
468
+
469
+ **forall:**
470
+
471
+ [source,postscript]
472
+ ----
473
+ array { actions } forall
474
+
475
+ % Example: Print array elements
476
+ [10 20 30 40] { = } forall
477
+ % Output: 10 20 30 40
478
+ ----
479
+
480
+ .Loop Examples
481
+ [example]
482
+ ====
483
+ [source,postscript]
484
+ ----
485
+ % Draw 10 circles
486
+ newpath
487
+ 10 {
488
+ 100 100 50 0 360 arc
489
+ stroke
490
+ 0 20 translate % Move down for next circle
491
+ } repeat
492
+
493
+ % Draw grid
494
+ 0 10 100 { % x from 0 to 100 by 10
495
+ 0 10 100 { % y from 0 to 100 by 10
496
+ 2 index % Get x
497
+ 1 index % Get y
498
+ moveto
499
+ 2 0 rlineto % Draw small mark
500
+ stroke
501
+ } for
502
+ pop % Remove y
503
+ } for
504
+ pop % Remove x
505
+ ----
506
+ ====
507
+
508
+ == Procedures and Functions
509
+
510
+ === Defining Procedures
511
+
512
+ [source,postscript]
513
+ ----
514
+ /name { procedure-body } def
515
+
516
+ % Examples:
517
+ /square { dup mul } def
518
+ /double { 2 mul } def
519
+ /greet { (Hello) print } def
520
+ ----
521
+
522
+ === Using Procedures
523
+
524
+ [source,postscript]
525
+ ----
526
+ % Define
527
+ /square { dup mul } def
528
+
529
+ % Use
530
+ 5 square % Result: 25
531
+ 10 square % Result: 100
532
+ ----
533
+
534
+ === Procedures with Parameters
535
+
536
+ .Procedure Parameter Pattern
537
+ [example]
538
+ ====
539
+ [source,postscript]
540
+ ----
541
+ % Define procedure that draws a rectangle
542
+ /rectangle { % x y width height
543
+ /h exch def
544
+ /w exch def
545
+ /y exch def
546
+ /x exch def
547
+
548
+ newpath
549
+ x y moveto
550
+ w 0 rlineto
551
+ 0 h rlineto
552
+ w neg 0 rlineto
553
+ closepath
554
+ } def
555
+
556
+ % Use
557
+ 100 100 200 150 rectangle
558
+ fill
559
+ ----
560
+
561
+ The pattern:
562
+
563
+ 1. Pop parameters from stack
564
+ 2. Store in local variables (`def`)
565
+ 3. Use variables in procedure body
566
+ ====
567
+
568
+ === Recursive Procedures
569
+
570
+ [source,postscript]
571
+ ----
572
+ % Factorial function
573
+ /factorial {
574
+ dup 1 le
575
+ { pop 1 } % Base case: n ≤ 1 → 1
576
+ { dup 1 sub % Recursive case:
577
+ factorial % factorial(n-1)
578
+ mul } % × n
579
+ ifelse
580
+ } def
581
+
582
+ % Use
583
+ 5 factorial % Result: 120
584
+ ----
585
+
586
+ == Dictionaries and Scope
587
+
588
+ === Dictionary Operations
589
+
590
+ **Create Dictionary:**
591
+
592
+ [source,postscript]
593
+ ----
594
+ 10 dict % Create dict with 10 slots
595
+ ----
596
+
597
+ **Define Entry:**
598
+
599
+ [source,postscript]
600
+ ----
601
+ /mydict 10 dict def
602
+ mydict begin
603
+ /x 100 def
604
+ /y 200 def
605
+ end
606
+ ----
607
+
608
+ **Access Entry:**
609
+
610
+ [source,postscript]
611
+ ----
612
+ /x load % Load x's value
613
+ mydict /x get % Get x from mydict
614
+ ----
615
+
616
+ === Dictionary Stack
617
+
618
+ PostScript maintains a **dictionary stack** for variable scope:
619
+
620
+ .Dictionary Stack
621
+ [source]
622
+ ----
623
+ Top ┌──────────────┐
624
+ │ Current Dict │ ← Definitions here
625
+ ├──────────────┤
626
+ │ User Dict │ ← User definitions
627
+ ├──────────────┤
628
+ Bottom │ System Dict │ ← Built-in operators
629
+ └──────────────┘
630
+ ----
631
+
632
+ **Dictionary Scope:**
633
+
634
+ [source,postscript]
635
+ ----
636
+ /x 10 def % Define in userdict
637
+
638
+ 100 dict begin % Push new dict
639
+ /x 20 def % Shadows outer x
640
+ x = % Prints: 20
641
+ end % Pop dict
642
+
643
+ x = % Prints: 10
644
+ ----
645
+
646
+ === Built-in Dictionaries
647
+
648
+ `systemdict`:: Built-in operators and constants
649
+
650
+ `userdict`:: User-defined variables (default)
651
+
652
+ `globaldict`:: Level 2+ global definitions
653
+
654
+ == Graphics Operators
655
+
656
+ === Path Construction
657
+
658
+ [source,postscript]
659
+ ----
660
+ newpath % Clear current path
661
+ x y moveto % Start subpath at (x,y)
662
+ x y lineto % Line to (x,y)
663
+ x y rmoveto % Relative move
664
+ dx dy rlineto % Relative line
665
+ x1 y1 x2 y2 x3 y3 curveto % Cubic curve
666
+ closepath % Close current subpath
667
+ ----
668
+
669
+ === Path Painting
670
+
671
+ [source,postscript]
672
+ ----
673
+ stroke % Paint path outline
674
+ fill % Fill path interior
675
+ eofill % Even-odd fill
676
+ clip % Set clipping path
677
+ ----
678
+
679
+ === Graphics State
680
+
681
+ [source,postscript]
682
+ ----
683
+ gsave % Save graphics state
684
+ grestore % Restore graphics state
685
+ ----
686
+
687
+ === Color
688
+
689
+ [source,postscript]
690
+ ----
691
+ gray setgray % Grayscale (0-1)
692
+ r g b setrgbcolor % RGB (0-1 each)
693
+ c m y k setcmykcolor % CMYK (0-1 each)
694
+ ----
695
+
696
+ === Line Attributes
697
+
698
+ [source,postscript]
699
+ ----
700
+ width setlinewidth % Line thickness
701
+ cap setlinecap % 0=butt, 1=round, 2=square
702
+ join setlinejoin % 0=miter, 1=round, 2=bevel
703
+ [array] offset setdash % Dash pattern
704
+ ----
705
+
706
+ === Transformations
707
+
708
+ [source,postscript]
709
+ ----
710
+ tx ty translate % Translate origin
711
+ sx sy scale % Scale axes
712
+ angle rotate % Rotate (degrees)
713
+ ----
714
+
715
+ == Comments
716
+
717
+ [source,postscript]
718
+ ----
719
+ % This is a comment to end of line
720
+
721
+ 100 100 moveto % Move to (100,100)
722
+
723
+ % Comments can be on their own line
724
+ % or at the end of code lines
725
+ ----
726
+
727
+ == Program Structure
728
+
729
+ === PostScript File Structure
730
+
731
+ [source,postscript]
732
+ ----
733
+ %!PS-Adobe-3.0
734
+ %%BoundingBox: 0 0 612 792
735
+ %%Title: My Document
736
+ %%Creator: Me
737
+ %%Pages: 1
738
+ %%EndComments
739
+
740
+ %%BeginProlog
741
+ % Procedure definitions
742
+ /square { dup mul } def
743
+ %%EndProlog
744
+
745
+ %%Page: 1 1
746
+ % Page content
747
+ 100 100 moveto
748
+ 200 200 lineto
749
+ stroke
750
+ showpage
751
+ %%EOF
752
+ ----
753
+
754
+ **Document Structure Comments:**
755
+
756
+ * `%!PS-Adobe-3.0` - File identifier
757
+ * `%%BoundingBox:` - Page dimensions
758
+ * `%%BeginProlog` / `%%EndProlog` - Definitions section
759
+ * `%%Page:` - Page marker
760
+ * `%%EOF` - End of file
761
+
762
+ === showpage
763
+
764
+ The `showpage` operator:
765
+
766
+ * Prints the current page
767
+ * Resets graphics state
768
+ * Advances to next page
769
+
770
+ [source,postscript]
771
+ ----
772
+ % Draw on page
773
+ newpath
774
+ 100 100 moveto
775
+ 200 200 lineto
776
+ stroke
777
+
778
+ showpage % Print page and reset
779
+ ----
780
+
781
+ == Common Patterns
782
+
783
+ === Drawing a Rectangle
784
+
785
+ [source,postscript]
786
+ ----
787
+ newpath
788
+ x y moveto
789
+ width 0 rlineto
790
+ 0 height rlineto
791
+ width neg 0 rlineto
792
+ closepath
793
+ ----
794
+
795
+ === Drawing a Circle
796
+
797
+ [source,postscript]
798
+ ----
799
+ cx cy radius 0 360 arc
800
+ ----
801
+
802
+ === Rounded Rectangle
803
+
804
+ [source,postscript]
805
+ ----
806
+ /roundrect {
807
+ /r exch def /h exch def /w exch def /y exch def /x exch def
808
+ newpath
809
+ x r add y moveto
810
+ x w add y x w add y r add r arcto 4 {pop} repeat
811
+ x w add y h add x w add r sub y h add r arcto 4 {pop} repeat
812
+ x y h add x r add y h add r arcto 4 {pop} repeat
813
+ x y x y r add r arcto 4 {pop} repeat
814
+ closepath
815
+ } def
816
+ ----
817
+
818
+ == PostScript Limitations in Postsvg
819
+
820
+ Postsvg supports a subset of PostScript focused on vector graphics:
821
+
822
+ **Supported:**
823
+
824
+ * Basic arithmetic and logic
825
+ * Path construction and painting
826
+ * Graphics state operations
827
+ * Color operations
828
+ * Transformations
829
+ * Basic control flow
830
+ * Dictionary operations
831
+
832
+ **Not Supported:**
833
+
834
+ * File I/O operations
835
+ * Font rendering (partial)
836
+ * Image operators
837
+ * Advanced Level 3 features
838
+ * Binary data
839
+ * Some device-specific operators
840
+
841
+ See the link:../cli-reference/check-command.adoc[Check Command] for validating PostScript compatibility.
842
+
843
+ == Next Steps
844
+
845
+ * Review link:conversion-pipeline.adoc[Conversion Pipeline] to see how PostScript is processed
846
+ * Explore link:path-operations.adoc[Path Operations] for graphics details
847
+ * See link:graphics-state.adoc[Graphics State] for state management
848
+ * Check link:../api-reference.adoc[API Reference] for implementation
849
+ * Read link:../architecture.adoc[Architecture] for system design
850
+
851
+ == Bibliography
852
+
853
+ * link:conversion-pipeline.adoc[Conversion Pipeline]
854
+ * link:path-operations.adoc[Path Operations]
855
+ * link:graphics-state.adoc[Graphics State Management]
856
+ * link:../architecture/interpreter-stage.adoc[Interpreter Architecture]
857
+ * link:https://www.adobe.com/jp/print/postscript/pdfs/PLRM.pdf[PostScript Language Reference Manual]
858
+ * link:https://www-cdf.fnal.gov/offline/PostScript/BLUEBOOK.PDF[PostScript Language Tutorial and Cookbook]
859
+ * link:https://en.wikipedia.org/wiki/PostScript[PostScript Wikipedia Article]