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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0a2ecbfa1ecb4e8bc18ce43304e7ea828054d255bb2183e9356cf08742e91483
4
+ data.tar.gz: c7520e5a867bd4992d169ffa496cfc70eb36dba2bddfc78a1c472b3b21009020
5
+ SHA512:
6
+ metadata.gz: 212ad8d736573633ab5d335908e1305f89e621e7389740420858fbaacf6c982165af4b69a0c154e21ff0ea456e3e0343c88b9d06c43a2c1b47202dc31078511e
7
+ data.tar.gz: 91f449c7d4a7a09560215bae0f83b58410ca64a472c43c97af9322198e1d2c249442263cdfe5aa41163735bdcd5728211169b30f67feeeaefb14a66e096b5f8f
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ inherit_from:
4
+ - https://raw.githubusercontent.com/riboseinc/oss-guides/main/ci/rubocop.yml
5
+ - .rubocop_todo.yml
6
+
7
+ inherit_mode:
8
+ merge:
9
+ - Exclude
10
+
11
+ # local repo-specific modifications
12
+ # ...
13
+ plugins:
14
+ - rubocop-rspec
15
+ - rubocop-performance
16
+ - rubocop-rake
17
+
18
+ AllCops:
19
+ TargetRubyVersion: 3.0
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,141 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2025-10-19 09:58:29 UTC using RuboCop version 1.81.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 36
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
12
+ # URISchemes: http, https
13
+ Layout/LineLength:
14
+ Exclude:
15
+ - 'lib/postsvg.rb'
16
+ - 'lib/postsvg/converter.rb'
17
+ - 'lib/postsvg/graphics_state.rb'
18
+ - 'lib/postsvg/interpreter.rb'
19
+ - 'lib/postsvg/parser/postscript_parser.rb'
20
+ - 'lib/postsvg/tokenizer.rb'
21
+ - 'postsvg.gemspec'
22
+ - 'scripts/regenerate_fixtures.rb'
23
+
24
+ # Offense count: 5
25
+ # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
26
+ Lint/DuplicateBranch:
27
+ Exclude:
28
+ - 'lib/postsvg/converter.rb'
29
+ - 'lib/postsvg/interpreter.rb'
30
+
31
+ # Offense count: 1
32
+ Lint/DuplicateCaseCondition:
33
+ Exclude:
34
+ - 'lib/postsvg/converter.rb'
35
+
36
+ # Offense count: 29
37
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
38
+ Metrics/AbcSize:
39
+ Exclude:
40
+ - 'lib/postsvg.rb'
41
+ - 'lib/postsvg/cli.rb'
42
+ - 'lib/postsvg/colors.rb'
43
+ - 'lib/postsvg/converter.rb'
44
+ - 'lib/postsvg/graphics_state.rb'
45
+ - 'lib/postsvg/interpreter.rb'
46
+ - 'lib/postsvg/matrix.rb'
47
+ - 'lib/postsvg/path_builder.rb'
48
+ - 'lib/postsvg/svg_generator.rb'
49
+ - 'lib/postsvg/tokenizer.rb'
50
+
51
+ # Offense count: 1
52
+ # Configuration parameters: CountBlocks, CountModifierForms.
53
+ Metrics/BlockNesting:
54
+ Max: 6
55
+
56
+ # Offense count: 14
57
+ # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
58
+ Metrics/CyclomaticComplexity:
59
+ Exclude:
60
+ - 'lib/postsvg/cli.rb'
61
+ - 'lib/postsvg/converter.rb'
62
+ - 'lib/postsvg/interpreter.rb'
63
+ - 'lib/postsvg/tokenizer.rb'
64
+
65
+ # Offense count: 30
66
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
67
+ Metrics/MethodLength:
68
+ Max: 111
69
+
70
+ # Offense count: 5
71
+ # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
72
+ Metrics/ParameterLists:
73
+ Max: 7
74
+
75
+ # Offense count: 13
76
+ # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
77
+ Metrics/PerceivedComplexity:
78
+ Exclude:
79
+ - 'lib/postsvg/cli.rb'
80
+ - 'lib/postsvg/converter.rb'
81
+ - 'lib/postsvg/interpreter.rb'
82
+ - 'lib/postsvg/tokenizer.rb'
83
+
84
+ # Offense count: 67
85
+ # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
86
+ # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
87
+ Naming/MethodParameterName:
88
+ Exclude:
89
+ - 'lib/postsvg.rb'
90
+ - 'lib/postsvg/converter.rb'
91
+ - 'lib/postsvg/graphics_state.rb'
92
+ - 'lib/postsvg/interpreter.rb'
93
+ - 'lib/postsvg/matrix.rb'
94
+ - 'lib/postsvg/path_builder.rb'
95
+ - 'lib/postsvg/tokenizer.rb'
96
+
97
+ # Offense count: 1
98
+ # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
99
+ # NamePrefix: is_, has_, have_, does_
100
+ # ForbiddenPrefixes: is_, has_, have_, does_
101
+ # AllowedMethods: is_a?
102
+ # MethodDefinitionMacros: define_method, define_singleton_method
103
+ Naming/PredicatePrefix:
104
+ Exclude:
105
+ - 'lib/postsvg/interpreter.rb'
106
+
107
+ # Offense count: 3
108
+ # Configuration parameters: MinSize.
109
+ Performance/CollectionLiteralInLoop:
110
+ Exclude:
111
+ - 'lib/postsvg/interpreter.rb'
112
+
113
+ # Offense count: 1
114
+ # Configuration parameters: IgnoredMetadata.
115
+ RSpec/DescribeClass:
116
+ Exclude:
117
+ - 'spec/postsvg/integration_spec.rb'
118
+
119
+ # Offense count: 7
120
+ # Configuration parameters: CountAsOne.
121
+ RSpec/ExampleLength:
122
+ Max: 16
123
+
124
+ # Offense count: 3
125
+ RSpec/MultipleExpectations:
126
+ Max: 4
127
+
128
+ # Offense count: 1
129
+ # This cop supports safe autocorrection (--autocorrect).
130
+ # Configuration parameters: EnforcedStyle, AllowComments.
131
+ # SupportedStyles: empty, nil, both
132
+ Style/EmptyElse:
133
+ Exclude:
134
+ - 'lib/postsvg/converter.rb'
135
+
136
+ # Offense count: 12
137
+ # This cop supports safe autocorrection (--autocorrect).
138
+ # Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
139
+ # SupportedStyles: annotated, template, unannotated
140
+ Style/FormatStringToken:
141
+ EnforcedStyle: unannotated
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in xml-c14n.gemspec
6
+ gemspec
7
+
8
+ gem "canon", github: "lutaml/canon",
9
+ branch: "rt-update-behavior-prevent-data-loss"
10
+ gem "rake"
11
+ gem "rspec"
12
+ gem "rubocop"
13
+ gem "rubocop-performance"
14
+ gem "rubocop-rake"
15
+ gem "rubocop-rspec"
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2025, Ribose Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.adoc ADDED
@@ -0,0 +1,473 @@
1
+ = Postsvg
2
+
3
+ image:https://img.shields.io/gem/v/postsvg.svg[Gem Version,
4
+ link=https://rubygems.org/gems/postsvg]
5
+ image:https://github.com/metanorma/postsvg/actions/workflows/test.yml/badge.svg[Build Status,
6
+ link=https://github.com/metanorma/postsvg/actions/workflows/test.yml]
7
+ image:https://img.shields.io/github/license/metanorma/postsvg.svg[License]
8
+
9
+ == Purpose
10
+
11
+ Postsvg is a pure Ruby library for converting PostScript (PS) and
12
+ Encapsulated PostScript (EPS) files to Scalable Vector Graphics (SVG)
13
+ format.
14
+
15
+ Unlike traditional approaches that rely on external tools like
16
+ Ghostscript or Inkscape, Postsvg provides a native Ruby implementation
17
+ using Parslet for parsing PostScript commands and generating clean,
18
+ standards-compliant SVG output.
19
+
20
+ This library is particularly useful for applications that need to:
21
+
22
+ * Convert legacy PostScript graphics to modern SVG format
23
+ * Process vector graphics without external dependencies
24
+ * Generate SVG from PostScript programmatically
25
+ * Work with EPS files in pure Ruby environments
26
+
27
+ == Features
28
+
29
+ * <<basic-conversion,Basic PostScript to SVG conversion>> - Ruby API
30
+ for converting PS/EPS content to SVG
31
+ * <<cli,Command-line interface>> - Thor-based CLI for file and batch
32
+ conversions
33
+ * <<postscript-language,PostScript language support>> - Comprehensive
34
+ documentation and implementation
35
+ * <<architecture,Pure Ruby architecture>> - No external dependencies,
36
+ Parslet-based parser
37
+
38
+ == Architecture
39
+
40
+ [[architecture]]
41
+
42
+ === General
43
+
44
+ Postsvg uses a three-stage architecture for converting PostScript to
45
+ SVG. This design follows separation of concerns principles, with each
46
+ component handling a specific responsibility in the conversion process.
47
+
48
+ .PostScript to SVG conversion pipeline
49
+ [source]
50
+ ----
51
+ ┌─────────────┐ ┌───────────┐ ┌──────────────┐
52
+ │ PostScript │──> │ Parser │──> │ Converter │
53
+ │ Input │ │ (Parslet) │ │ (Interpreter)│
54
+ └─────────────┘ └───────────┘ └───────┬──────┘
55
+
56
+
57
+ ┌─────────────────┐
58
+ │ SVG Generator │
59
+ └────────┬────────┘
60
+
61
+
62
+ ┌─────────────────┐
63
+ │ SVG Output │
64
+ └─────────────────┘
65
+ ----
66
+
67
+ === Parser stage
68
+
69
+ The parser uses Parslet to tokenize and parse PostScript commands into
70
+ an abstract syntax tree (AST). The parser handles PostScript syntax
71
+ including numbers, operators, names, strings, arrays, and procedures.
72
+
73
+ * `Postsvg::Parser::PostscriptParser` - Parslet grammar for PostScript
74
+ syntax
75
+ * `Postsvg::Parser::Transform` - Transforms AST into Ruby data
76
+ structures
77
+
78
+ === Converter stage
79
+
80
+ The converter interprets PostScript commands using a stack-based
81
+ execution model. It maintains an operand stack, dictionary, and graphics
82
+ state while executing PostScript operators.
83
+
84
+ * `Postsvg::Converter` - Main orchestrator that executes PostScript
85
+ commands
86
+ * `Postsvg::GraphicsState` - Manages current path, colors,
87
+ transformations, and graphics state stack
88
+
89
+ === Generator stage
90
+
91
+ The generator creates SVG output from the interpreted graphics
92
+ operations, handling coordinate system transformations and generating
93
+ standards-compliant SVG markup.
94
+
95
+ * `Postsvg::SvgGenerator` - Builds SVG document with proper structure
96
+ and viewBox
97
+
98
+ == Installation
99
+
100
+ Add this line to your application's Gemfile:
101
+
102
+ [source,ruby]
103
+ ----
104
+ gem "postsvg"
105
+ ----
106
+
107
+ And then execute:
108
+
109
+ [source,sh]
110
+ ----
111
+ bundle install
112
+ ----
113
+
114
+ Or install it yourself as:
115
+
116
+ [source,sh]
117
+ ----
118
+ gem install postsvg
119
+ ----
120
+
121
+ == Basic PostScript to SVG conversion
122
+
123
+ [[basic-conversion]]
124
+
125
+ === General
126
+
127
+ The Postsvg library provides a simple Ruby API for converting PostScript
128
+ content to SVG format. The conversion can be performed on in-memory
129
+ content or directly on files.
130
+
131
+ The library automatically handles BoundingBox extraction, coordinate
132
+ system transformations, and SVG generation while preserving the visual
133
+ appearance of the original PostScript graphics.
134
+
135
+ === Converting PostScript content
136
+
137
+ Syntax:
138
+
139
+ [source,ruby]
140
+ ----
141
+ svg_output = Postsvg.convert(ps_content) <1>
142
+ ----
143
+ <1> Convert PostScript string to SVG string
144
+
145
+ Where,
146
+
147
+ `ps_content`:: PostScript or EPS content as a string. Should include
148
+ proper PostScript header and BoundingBox comment for best results.
149
+
150
+ Returns:: SVG markup as a string
151
+
152
+ .Converting PostScript content to SVG
153
+ [example]
154
+ ====
155
+ [source,ruby]
156
+ ----
157
+ require "postsvg"
158
+
159
+ ps_content = <<~PS
160
+ %!PS-Adobe-3.0 EPSF-3.0
161
+ %%BoundingBox: 0 0 100 100
162
+ newpath
163
+ 10 10 moveto
164
+ 90 10 lineto
165
+ 90 90 lineto
166
+ 10 90 lineto
167
+ closepath
168
+ 0.5 0.5 0.5 setrgbcolor
169
+ fill
170
+ PS
171
+
172
+ svg = Postsvg.convert(ps_content)
173
+ File.write("output.svg", svg)
174
+ ----
175
+
176
+ This converts a PostScript square with gray fill to SVG format and saves
177
+ it to a file.
178
+ ====
179
+
180
+ === Converting PostScript files
181
+
182
+ Syntax:
183
+
184
+ [source,ruby]
185
+ ----
186
+ Postsvg.convert_file(input_path, output_path) <1>
187
+ svg_content = Postsvg.convert_file(input_path) <2>
188
+ ----
189
+ <1> Convert file and save to output path
190
+ <2> Convert file and return SVG content without saving
191
+
192
+ Where,
193
+
194
+ `input_path`:: Path to input PostScript (.ps) or EPS (.eps) file
195
+ `output_path`:: (Optional) Path where SVG file should be saved. If
196
+ omitted, SVG content is returned without saving.
197
+
198
+ Returns:: When `output_path` is omitted, returns SVG markup as a string.
199
+ When `output_path` is provided, returns the output path.
200
+
201
+ .Converting a PostScript file to SVG
202
+ [example]
203
+ ====
204
+ [source,ruby]
205
+ ----
206
+ require "postsvg"
207
+
208
+ # Convert and save in one step
209
+ Postsvg.convert_file("input.eps", "output.svg")
210
+
211
+ # Or get SVG content without saving
212
+ svg_content = Postsvg.convert_file("input.ps")
213
+ puts svg_content
214
+ ----
215
+
216
+ The first example converts an EPS file and saves the result as SVG. The
217
+ second example reads a PostScript file and returns the SVG content for
218
+ further processing.
219
+ ====
220
+
221
+ == Command-line interface
222
+
223
+ [[cli]]
224
+
225
+ === General
226
+
227
+ Postsvg provides a Thor-based command-line interface for converting
228
+ PostScript and EPS files to SVG format. The CLI supports single file
229
+ conversion, batch processing, and version information.
230
+
231
+ The CLI is available through the `postsvg` executable installed with the
232
+ gem.
233
+
234
+ === Converting single files
235
+
236
+ Syntax:
237
+
238
+ [source,sh]
239
+ ----
240
+ postsvg convert INPUT_FILE [OUTPUT_FILE] <1>
241
+ ----
242
+ <1> Convert INPUT_FILE to SVG, optionally saving to OUTPUT_FILE
243
+
244
+ Where,
245
+
246
+ `INPUT_FILE`:: Path to input PostScript (.ps) or EPS (.eps) file
247
+ `OUTPUT_FILE`:: (Optional) Path where SVG file should be saved. If
248
+ omitted, SVG is written to stdout.
249
+
250
+ .Converting a single PostScript file
251
+ [example]
252
+ ====
253
+ [source,sh]
254
+ ----
255
+ # Convert to stdout
256
+ postsvg convert input.ps
257
+
258
+ # Convert and save to file
259
+ postsvg convert input.eps output.svg
260
+
261
+ # Redirect stdout to file
262
+ postsvg convert input.ps > output.svg
263
+ ----
264
+
265
+ The first command prints SVG to stdout. The second saves directly to
266
+ output.svg. The third uses shell redirection to save the output.
267
+ ====
268
+
269
+ === Batch conversion
270
+
271
+ Syntax:
272
+
273
+ [source,sh]
274
+ ----
275
+ postsvg batch INPUT_DIR [OUTPUT_DIR] <1>
276
+ ----
277
+ <1> Convert all PS/EPS files in INPUT_DIR, optionally saving to
278
+ OUTPUT_DIR
279
+
280
+ Where,
281
+
282
+ `INPUT_DIR`:: Directory containing PostScript (.ps) and/or EPS (.eps)
283
+ files to convert
284
+ `OUTPUT_DIR`:: (Optional) Directory where SVG files should be saved. If
285
+ omitted, SVG files are saved in the same directory as input files with
286
+ .svg extension.
287
+
288
+ .Batch converting PostScript files
289
+ [example]
290
+ ====
291
+ [source,sh]
292
+ ----
293
+ # Convert all PS/EPS files in a directory
294
+ postsvg batch ps_files/
295
+
296
+ # Convert to a different directory
297
+ postsvg batch ps_files/ svg_files/
298
+ ----
299
+
300
+ The first example converts all PS and EPS files in the `ps_files/`
301
+ directory, saving the SVG files in the same directory. The second
302
+ example saves the converted files to the `svg_files/` directory.
303
+ ====
304
+
305
+ === Displaying version information
306
+
307
+ Syntax:
308
+
309
+ [source,sh]
310
+ ----
311
+ postsvg version <1>
312
+ ----
313
+ <1> Display the Postsvg version number
314
+
315
+ .Getting version information
316
+ [example]
317
+ ====
318
+ [source,sh]
319
+ ----
320
+ postsvg version
321
+ ----
322
+
323
+ Output:
324
+ ----
325
+ postsvg version 0.1.0
326
+ ----
327
+ ====
328
+
329
+ == PostScript language support
330
+
331
+ [[postscript-language]]
332
+
333
+ === General
334
+
335
+ Postsvg provides comprehensive PostScript language support with detailed
336
+ documentation covering fundamentals, operators, and conversion
337
+ strategies.
338
+
339
+ The implementation supports common PostScript operations including path
340
+ construction, painting, color management, graphics state, and coordinate
341
+ transformations.
342
+
343
+ === PostScript documentation
344
+
345
+ Complete PostScript language documentation is available at
346
+ link:docs/POSTSCRIPT.adoc[docs/POSTSCRIPT.adoc], organized into the
347
+ following topics:
348
+
349
+ * link:docs/postscript/fundamentals.adoc[Fundamentals] - PostScript
350
+ language basics, syntax, and data types
351
+ * link:docs/postscript/graphics-model.adoc[Graphics model] - Coordinate
352
+ systems, paths, and painting model
353
+ * link:docs/postscript/operators/index.adoc[Operators reference] -
354
+ Detailed documentation for all supported operators:
355
+ ** link:docs/postscript/operators/path-construction.adoc[Path
356
+ construction] - moveto, lineto, curveto, closepath, newpath
357
+ ** link:docs/postscript/operators/painting.adoc[Painting] - stroke,
358
+ fill
359
+ ** link:docs/postscript/operators/graphics-state.adoc[Graphics state] -
360
+ gsave, grestore, setlinewidth
361
+ ** link:docs/postscript/operators/transformations.adoc[Transformations]
362
+ - translate, scale, rotate
363
+ ** link:docs/postscript/operators/stack-manipulation.adoc[Stack
364
+ manipulation] - dup, pop, exch, roll
365
+ ** link:docs/postscript/operators/arithmetic.adoc[Arithmetic] - add,
366
+ sub, mul, div
367
+ ** link:docs/postscript/operators/control-flow.adoc[Control flow] - if,
368
+ ifelse, for, repeat
369
+ ** link:docs/postscript/operators/dictionary.adoc[Dictionary] - def,
370
+ dict, begin, end
371
+ * link:docs/postscript/svg-mapping.adoc[SVG mapping guide] - How
372
+ PostScript operations map to SVG
373
+ * link:docs/postscript/implementation-notes.adoc[Implementation notes] -
374
+ Postsvg-specific details and design decisions
375
+
376
+ === Supported PostScript operations
377
+
378
+ ==== Path construction
379
+
380
+ * `moveto` - Begin new subpath at coordinates
381
+ * `lineto` - Append straight line segment
382
+ * `rlineto` - Append relative line segment
383
+ * `curveto` - Append cubic Bézier curve
384
+ * `closepath` - Close current subpath
385
+ * `newpath` - Initialize new path
386
+
387
+ ==== Painting
388
+
389
+ * `stroke` - Stroke current path with current color and line width
390
+ * `fill` - Fill current path with current color
391
+
392
+ ==== Color
393
+
394
+ * `setrgbcolor` - Set RGB color (0-1 range for each component)
395
+ * `setgray` - Set grayscale color (0-1 range)
396
+
397
+ ==== Graphics state
398
+
399
+ * `gsave` - Save current graphics state to stack
400
+ * `grestore` - Restore graphics state from stack
401
+ * `setlinewidth` - Set line width for stroke operations
402
+
403
+ ==== Transformations
404
+
405
+ * `translate` - Translate coordinate system
406
+ * `scale` - Scale coordinate system
407
+ * `rotate` - Rotate coordinate system (angle in degrees)
408
+
409
+ == Limitations
410
+
411
+ Current version has the following limitations:
412
+
413
+ * Text rendering: Text operations (show, findfont, setfont, etc.) are
414
+ not yet supported. Convert text to outlines before processing.
415
+ * Complex clipping: Clipping paths (clip, eoclip) are not fully
416
+ implemented
417
+ * Gradients and patterns: Pattern fills and gradient operations are not
418
+ yet supported
419
+ * CMYK colors: Only RGB and grayscale colors are supported. CMYK color
420
+ operations will need conversion.
421
+ * Image embedding: Raster images within PostScript (image, imagemask)
422
+ are not supported
423
+ * Advanced operators: Some PostScript Level 2 and 3 operators are not
424
+ yet implemented
425
+
426
+ For files with these features, consider preprocessing with external
427
+ tools or contributing implementations of these features.
428
+
429
+ == Acknowledgments
430
+
431
+ This project uses test fixtures from
432
+ https://github.com/elalish/ps2svg[ps2svg] by Emmett Lalish, licensed
433
+ under the MIT License. These test files help ensure the correctness of
434
+ our SVG generation against a reference implementation. We are grateful
435
+ for this valuable resource that helps validate PostScript to SVG
436
+ conversion.
437
+
438
+ == Development
439
+
440
+ === Running tests
441
+
442
+ [source,sh]
443
+ ----
444
+ bundle exec rspec
445
+ ----
446
+
447
+ === Code style
448
+
449
+ [source,sh]
450
+ ----
451
+ bundle exec rubocop
452
+ ----
453
+
454
+ === Running all checks
455
+
456
+ [source,sh]
457
+ ----
458
+ bundle exec rake
459
+ ----
460
+
461
+ == Contributing
462
+
463
+ Bug reports and pull requests are welcome on GitHub at
464
+ https://github.com/metanorma/postsvg.
465
+
466
+ == Copyright
467
+
468
+ Copyright Ribose.
469
+
470
+ == License
471
+
472
+ The gem is available as open source under the terms of the
473
+ https://opensource.org/licenses/BSD-2-Clause[BSD 2-Clause License].
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[spec rubocop]
@@ -0,0 +1,13 @@
1
+ = PostScript Language Reference
2
+
3
+ For comprehensive PostScript documentation for the Postsvg library, see:
4
+
5
+ * link:postscript/index.adoc[PostScript Quick Reference Guide]
6
+
7
+ == Quick Links
8
+
9
+ * link:postscript/fundamentals.adoc[Language Fundamentals]
10
+ * link:postscript/graphics-model.adoc[Graphics Model]
11
+ * link:postscript/operators/index.adoc[Operator Reference]
12
+ * link:postscript/svg-mapping.adoc[PostScript to SVG Mapping]
13
+ * link:postscript/implementation-notes.adoc[Postsvg Implementation Notes]