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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +105 -0
- data/CLAUDE.md +173 -0
- data/Gemfile +2 -3
- data/README.adoc +456 -179
- data/Rakefile +100 -0
- data/TODO.roadmap/00-architecture.md +139 -0
- data/TODO.roadmap/01-autoload-migration.md +39 -0
- data/TODO.roadmap/02-isolate-dormant-code.md +51 -0
- data/TODO.roadmap/03-domain-model.md +66 -0
- data/TODO.roadmap/04-lexer.md +40 -0
- data/TODO.roadmap/05-parser.md +43 -0
- data/TODO.roadmap/06-graphics-state.md +45 -0
- data/TODO.roadmap/07-matrix-and-color.md +37 -0
- data/TODO.roadmap/08-svg-builder.md +51 -0
- data/TODO.roadmap/09-renderer.md +52 -0
- data/TODO.roadmap/10-visitor.md +58 -0
- data/TODO.roadmap/11-operator-coverage.md +103 -0
- data/TODO.roadmap/12-svg-domain.md +62 -0
- data/TODO.roadmap/13-translation-handlers.md +69 -0
- data/TODO.roadmap/14-ps-serializer.md +49 -0
- data/TODO.roadmap/15-cli-and-public-api.md +47 -0
- data/TODO.roadmap/16-specs.md +84 -0
- data/TODO.roadmap/17-docs-sync.md +47 -0
- data/TODO.roadmap/18-performance-and-determinism.md +47 -0
- data/TODO.roadmap/19-error-model.md +45 -0
- data/TODO.roadmap/20-font-and-text.md +46 -0
- data/TODO.roadmap/21-images.md +45 -0
- data/TODO.roadmap/22-forms-and-resources.md +25 -0
- data/TODO.roadmap/23-level2-level3.md +52 -0
- data/TODO.roadmap/24-ci-and-release.md +42 -0
- data/TODO.roadmap/README.md +77 -0
- data/docs/.gitignore +29 -0
- data/docs/CHANGELOG.md +114 -0
- data/docs/COMPLETE_DOCUMENTATION_STATUS.md +376 -0
- data/docs/DEPLOYMENT.md +456 -0
- data/docs/DEPLOYMENT_INSTRUCTIONS.md +229 -0
- data/docs/DOCUMENTATION_PLAN.md +425 -0
- data/docs/FINAL_SUMMARY.md +657 -0
- data/docs/Gemfile +15 -0
- data/docs/README.md +327 -0
- data/docs/_config.yml +99 -0
- data/docs/advanced-topics.adoc +370 -0
- data/docs/api-reference/colors.adoc +705 -0
- data/docs/api-reference/converter.adoc +699 -0
- data/docs/api-reference/execution-context.adoc +1210 -0
- data/docs/api-reference/graphics-state.adoc +1070 -0
- data/docs/api-reference/interpreter.adoc +810 -0
- data/docs/api-reference/matrix.adoc +1179 -0
- data/docs/api-reference/path-builder.adoc +1284 -0
- data/docs/api-reference/postsvg-module.adoc +388 -0
- data/docs/api-reference/svg-generator.adoc +891 -0
- data/docs/api-reference/tokenizer.adoc +925 -0
- data/docs/api-reference.adoc +221 -0
- data/docs/architecture/command-registry.adoc +1191 -0
- data/docs/architecture/conversion-pipeline.adoc +746 -0
- data/docs/architecture/design-decisions.adoc +999 -0
- data/docs/architecture/generator-stage.adoc +1115 -0
- data/docs/architecture/graphics-state-model.adoc +1089 -0
- data/docs/architecture/interpreter-stage.adoc +1125 -0
- data/docs/architecture/parser-stage.adoc +1051 -0
- data/docs/architecture.adoc +354 -0
- data/docs/cli-reference/batch-command.adoc +616 -0
- data/docs/cli-reference/check-command.adoc +677 -0
- data/docs/cli-reference/cli-options.adoc +802 -0
- data/docs/cli-reference/convert-command.adoc +462 -0
- data/docs/cli-reference/version-command.adoc +296 -0
- data/docs/cli-reference.adoc +317 -0
- data/docs/concepts/conversion-pipeline.adoc +903 -0
- data/docs/concepts/coordinate-systems.adoc +836 -0
- data/docs/concepts/graphics-state.adoc +861 -0
- data/docs/concepts/path-operations.adoc +1076 -0
- data/docs/concepts/postscript-language.adoc +859 -0
- data/docs/concepts/svg-generation.adoc +937 -0
- data/docs/concepts.adoc +198 -0
- data/docs/contributing.adoc +443 -0
- data/docs/development.adoc +420 -0
- data/docs/faq.adoc +493 -0
- data/docs/getting-started/basic-usage.adoc +538 -0
- data/docs/getting-started/common-workflows.adoc +577 -0
- data/docs/getting-started/first-conversion.adoc +492 -0
- data/docs/getting-started/installation.adoc +534 -0
- data/docs/getting-started.adoc +94 -0
- data/docs/index.adoc +248 -0
- data/docs/optimization.adoc +196 -0
- data/docs/ps2svg_compatibility.adoc +149 -0
- data/docs/quick-reference.adoc +453 -0
- data/docs/sitemap.adoc +337 -0
- data/docs/troubleshooting.adoc +486 -0
- data/docs/validation.adoc +772 -0
- data/exe/postsvg +1 -0
- data/lib/postsvg/cli.rb +104 -57
- data/lib/postsvg/color.rb +132 -0
- data/lib/postsvg/errors.rb +68 -3
- data/lib/postsvg/format_number.rb +22 -0
- data/lib/postsvg/graphics_context.rb +80 -0
- data/lib/postsvg/graphics_stack.rb +43 -0
- data/lib/postsvg/model/literals/array.rb +41 -0
- data/lib/postsvg/model/literals/dictionary.rb +34 -0
- data/lib/postsvg/model/literals/hex.rb +37 -0
- data/lib/postsvg/model/literals/name.rb +40 -0
- data/lib/postsvg/model/literals/number.rb +36 -0
- data/lib/postsvg/model/literals/procedure.rb +41 -0
- data/lib/postsvg/model/literals/string.rb +30 -0
- data/lib/postsvg/model/literals.rb +19 -0
- data/lib/postsvg/model/operator.rb +58 -0
- data/lib/postsvg/model/operators/arithmetic.rb +264 -0
- data/lib/postsvg/model/operators/boolean.rb +182 -0
- data/lib/postsvg/model/operators/color.rb +74 -0
- data/lib/postsvg/model/operators/container.rb +186 -0
- data/lib/postsvg/model/operators/control_flow.rb +119 -0
- data/lib/postsvg/model/operators/device.rb +21 -0
- data/lib/postsvg/model/operators/dictionary.rb +118 -0
- data/lib/postsvg/model/operators/font.rb +121 -0
- data/lib/postsvg/model/operators/graphics_state.rb +84 -0
- data/lib/postsvg/model/operators/painting.rb +29 -0
- data/lib/postsvg/model/operators/path.rb +169 -0
- data/lib/postsvg/model/operators/stack.rb +72 -0
- data/lib/postsvg/model/operators/transformations.rb +103 -0
- data/lib/postsvg/model/operators.rb +89 -0
- data/lib/postsvg/model/program.rb +68 -0
- data/lib/postsvg/model/token.rb +43 -0
- data/lib/postsvg/model.rb +17 -0
- data/lib/postsvg/options.rb +29 -0
- data/lib/postsvg/renderer.rb +85 -0
- data/lib/postsvg/serializer.rb +325 -0
- data/lib/postsvg/source/ast_builder.rb +308 -0
- data/lib/postsvg/source/lexer.rb +322 -0
- data/lib/postsvg/source/operand_stack.rb +55 -0
- data/lib/postsvg/source.rb +21 -0
- data/lib/postsvg/svg/attribute_parser.rb +45 -0
- data/lib/postsvg/svg/clip_path_registry.rb +44 -0
- data/lib/postsvg/svg/document.rb +22 -0
- data/lib/postsvg/svg/element.rb +84 -0
- data/lib/postsvg/svg/elements/circle.rb +36 -0
- data/lib/postsvg/svg/elements/clip_path.rb +26 -0
- data/lib/postsvg/svg/elements/defs.rb +24 -0
- data/lib/postsvg/svg/elements/ellipse.rb +38 -0
- data/lib/postsvg/svg/elements/group.rb +37 -0
- data/lib/postsvg/svg/elements/image.rb +35 -0
- data/lib/postsvg/svg/elements/line.rb +36 -0
- data/lib/postsvg/svg/elements/path.rb +32 -0
- data/lib/postsvg/svg/elements/polygon.rb +12 -0
- data/lib/postsvg/svg/elements/polyline.rb +32 -0
- data/lib/postsvg/svg/elements/rect.rb +44 -0
- data/lib/postsvg/svg/elements/svg.rb +39 -0
- data/lib/postsvg/svg/elements/text.rb +42 -0
- data/lib/postsvg/svg/elements.rb +31 -0
- data/lib/postsvg/svg/paint.rb +34 -0
- data/lib/postsvg/svg/parser.rb +39 -0
- data/lib/postsvg/svg/path_data/command.rb +27 -0
- data/lib/postsvg/svg/path_data/parser.rb +82 -0
- data/lib/postsvg/svg/path_data.rb +17 -0
- data/lib/postsvg/svg/stroke.rb +31 -0
- data/lib/postsvg/svg/transform_list.rb +59 -0
- data/lib/postsvg/svg.rb +22 -0
- data/lib/postsvg/svg_builder.rb +249 -0
- data/lib/postsvg/translation/arc_converter.rb +86 -0
- data/lib/postsvg/translation/bounding_box.rb +59 -0
- data/lib/postsvg/translation/context.rb +34 -0
- data/lib/postsvg/translation/handler_registry.rb +38 -0
- data/lib/postsvg/translation/handlers/circle_handler.rb +28 -0
- data/lib/postsvg/translation/handlers/clip_path_handler.rb +13 -0
- data/lib/postsvg/translation/handlers/defs_handler.rb +15 -0
- data/lib/postsvg/translation/handlers/ellipse_handler.rb +31 -0
- data/lib/postsvg/translation/handlers/group_handler.rb +21 -0
- data/lib/postsvg/translation/handlers/image_handler.rb +20 -0
- data/lib/postsvg/translation/handlers/line_handler.rb +23 -0
- data/lib/postsvg/translation/handlers/open_handler.rb +18 -0
- data/lib/postsvg/translation/handlers/path_handler.rb +356 -0
- data/lib/postsvg/translation/handlers/polygon_handler.rb +33 -0
- data/lib/postsvg/translation/handlers/polyline_handler.rb +31 -0
- data/lib/postsvg/translation/handlers/rect_handler.rb +27 -0
- data/lib/postsvg/translation/handlers/shared.rb +110 -0
- data/lib/postsvg/translation/handlers/svg_handler.rb +25 -0
- data/lib/postsvg/translation/handlers/text_handler.rb +56 -0
- data/lib/postsvg/translation/handlers.rb +25 -0
- data/lib/postsvg/translation/ps_renderer.rb +105 -0
- data/lib/postsvg/translation/record_emitter.rb +35 -0
- data/lib/postsvg/translation.rb +17 -0
- data/lib/postsvg/version.rb +1 -1
- data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +125 -0
- data/lib/postsvg/visitors/ps_visitor/boolean.rb +105 -0
- data/lib/postsvg/visitors/ps_visitor/color.rb +53 -0
- data/lib/postsvg/visitors/ps_visitor/common.rb +66 -0
- data/lib/postsvg/visitors/ps_visitor/container.rb +164 -0
- data/lib/postsvg/visitors/ps_visitor/control_flow.rb +110 -0
- data/lib/postsvg/visitors/ps_visitor/device.rb +20 -0
- data/lib/postsvg/visitors/ps_visitor/dictionary.rb +89 -0
- data/lib/postsvg/visitors/ps_visitor/font.rb +93 -0
- data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +55 -0
- data/lib/postsvg/visitors/ps_visitor/painting.rb +90 -0
- data/lib/postsvg/visitors/ps_visitor/path.rb +112 -0
- data/lib/postsvg/visitors/ps_visitor/stack.rb +47 -0
- data/lib/postsvg/visitors/ps_visitor/transformations.rb +101 -0
- data/lib/postsvg/visitors/ps_visitor.rb +208 -0
- data/lib/postsvg/visitors.rb +9 -0
- data/lib/postsvg.rb +93 -59
- data/lychee.toml +86 -0
- metadata +216 -11
- data/postsvg.gemspec +0 -38
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
= Architecture
|
|
2
|
+
:page-nav_order: 6
|
|
3
|
+
|
|
4
|
+
== Purpose
|
|
5
|
+
|
|
6
|
+
This section describes Postsvg's internal architecture, design patterns, and implementation details. Understanding the architecture helps developers contribute to Postsvg, extend its functionality, and troubleshoot complex issues.
|
|
7
|
+
|
|
8
|
+
== References
|
|
9
|
+
|
|
10
|
+
* link:index.adoc[Documentation Home]
|
|
11
|
+
* link:concepts.adoc[Core Concepts]
|
|
12
|
+
* link:api-reference.adoc[API Reference]
|
|
13
|
+
* link:development.adoc[Development Guide]
|
|
14
|
+
|
|
15
|
+
== Concepts
|
|
16
|
+
|
|
17
|
+
**Three-Stage Pipeline**:: Postsvg uses a clean separation between parsing, interpretation, and generation.
|
|
18
|
+
|
|
19
|
+
**Command Pattern**:: PostScript operators are implemented as command objects following the Command design pattern.
|
|
20
|
+
|
|
21
|
+
**Stack-Based Execution**:: Postsvg implements PostScript's stack-based execution model.
|
|
22
|
+
|
|
23
|
+
**State Management**:: Graphics state is managed through a stack of immutable state objects.
|
|
24
|
+
|
|
25
|
+
**Registry Pattern**:: Commands are registered and looked up through a central registry.
|
|
26
|
+
|
|
27
|
+
== Architecture Topics
|
|
28
|
+
|
|
29
|
+
link:architecture/conversion-pipeline.adoc[**Conversion Pipeline**]::
|
|
30
|
+
The three-stage architecture: tokenization/parsing, interpretation/execution, and SVG generation.
|
|
31
|
+
|
|
32
|
+
link:architecture/parser-stage.adoc[**Parser Stage**]::
|
|
33
|
+
Tokenization and parsing of PostScript syntax into executable tokens.
|
|
34
|
+
|
|
35
|
+
link:architecture/interpreter-stage.adoc[**Interpreter Stage**]::
|
|
36
|
+
Command execution, stack management, and graphics state manipulation.
|
|
37
|
+
|
|
38
|
+
link:architecture/generator-stage.adoc[**Generator Stage**]::
|
|
39
|
+
SVG generation from interpreted graphics operations.
|
|
40
|
+
|
|
41
|
+
link:architecture/command-registry.adoc[**Command Registry**]::
|
|
42
|
+
How PostScript operators are registered, looked up, and executed.
|
|
43
|
+
|
|
44
|
+
link:architecture/graphics-state-model.adoc[**Graphics State Model**]::
|
|
45
|
+
State management, transformation matrices, and the graphics state stack.
|
|
46
|
+
|
|
47
|
+
link:architecture/design-decisions.adoc[**Design Decisions**]::
|
|
48
|
+
Architectural choices, trade-offs, and rationale behind implementation decisions.
|
|
49
|
+
|
|
50
|
+
== High-Level Architecture
|
|
51
|
+
|
|
52
|
+
.Postsvg Architecture Overview
|
|
53
|
+
[source]
|
|
54
|
+
----
|
|
55
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
56
|
+
│ Postsvg Module │
|
|
57
|
+
│ - convert(ps_content) → svg │
|
|
58
|
+
│ - convert_file(input, output) → svg │
|
|
59
|
+
└────────────────────────┬────────────────────────────────────┘
|
|
60
|
+
│
|
|
61
|
+
▼
|
|
62
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
63
|
+
│ Converter Class │
|
|
64
|
+
│ - Initialize with PostScript content │
|
|
65
|
+
│ - Extract BoundingBox │
|
|
66
|
+
│ - Coordinate conversion pipeline │
|
|
67
|
+
└────┬──────────────────┬──────────────────┬──────────────────┘
|
|
68
|
+
│ │ │
|
|
69
|
+
▼ ▼ ▼
|
|
70
|
+
┌──────────┐ ┌──────────────┐ ┌─────────────┐
|
|
71
|
+
│Tokenizer │───>│ Interpreter │──>│SVG Generator│
|
|
72
|
+
└──────────┘ └──────────────┘ └─────────────┘
|
|
73
|
+
│ │ │
|
|
74
|
+
│ │ │
|
|
75
|
+
▼ ▼ ▼
|
|
76
|
+
Tokens ExecutionContext SVG Document
|
|
77
|
+
│ │
|
|
78
|
+
▼ ▼
|
|
79
|
+
┌────────┐ ┌──────────────┐
|
|
80
|
+
│ Stack │ │GraphicsState │
|
|
81
|
+
└────────┘ └──────────────┘
|
|
82
|
+
----
|
|
83
|
+
|
|
84
|
+
== Component Responsibilities
|
|
85
|
+
|
|
86
|
+
=== Postsvg Module
|
|
87
|
+
|
|
88
|
+
**Location:** [`lib/postsvg.rb`](../lib/postsvg.rb:10)
|
|
89
|
+
|
|
90
|
+
**Responsibilities:**
|
|
91
|
+
* Provide simple API for quick conversions
|
|
92
|
+
* Extract BoundingBox from PostScript header
|
|
93
|
+
* Delegate to Converter for actual conversion
|
|
94
|
+
|
|
95
|
+
**Methods:**
|
|
96
|
+
* [`convert(ps_content)`](../lib/postsvg.rb:13) - Convert PostScript string to SVG
|
|
97
|
+
* [`convert_file(input_path, output_path)`](../lib/postsvg.rb:24) - Convert file to SVG
|
|
98
|
+
|
|
99
|
+
=== Converter Class
|
|
100
|
+
|
|
101
|
+
**Location:** [`lib/postsvg/converter.rb`](../lib/postsvg/converter.rb:8)
|
|
102
|
+
|
|
103
|
+
**Responsibilities:**
|
|
104
|
+
* Orchestrate the conversion pipeline
|
|
105
|
+
* Extract BoundingBox information
|
|
106
|
+
* Configure strict mode
|
|
107
|
+
* Coordinate Tokenizer, Interpreter, and Generator
|
|
108
|
+
|
|
109
|
+
**Key Methods:**
|
|
110
|
+
* [`initialize(ps_content, strict_mode:)`](../lib/postsvg/converter.rb:12) - Set up converter
|
|
111
|
+
* [`convert`](../lib/postsvg/converter.rb:17) - Execute full conversion
|
|
112
|
+
* `extract_bounding_box` - Parse BoundingBox comment
|
|
113
|
+
|
|
114
|
+
=== Tokenizer Class
|
|
115
|
+
|
|
116
|
+
**Location:** [`lib/postsvg/tokenizer.rb`](../lib/postsvg/tokenizer.rb:8)
|
|
117
|
+
|
|
118
|
+
**Responsibilities:**
|
|
119
|
+
* Lexical analysis of PostScript source
|
|
120
|
+
* Break input into tokens (numbers, operators, strings, etc.)
|
|
121
|
+
* Handle string and hex string parsing
|
|
122
|
+
|
|
123
|
+
**Token Types:**
|
|
124
|
+
* `:number` - Integer or float values
|
|
125
|
+
* `:operator` - PostScript commands
|
|
126
|
+
* `:name` - Named identifiers (starting with `/`)
|
|
127
|
+
* `:string` - String literals
|
|
128
|
+
* `:hex_string` - Hexadecimal strings
|
|
129
|
+
* `:array_start`, `:array_end` - Array delimiters
|
|
130
|
+
* `:proc_start`, `:proc_end` - Procedure delimiters
|
|
131
|
+
|
|
132
|
+
=== Interpreter Class
|
|
133
|
+
|
|
134
|
+
**Location:** [`lib/postsvg/interpreter.rb`](../lib/postsvg/interpreter.rb:9)
|
|
135
|
+
|
|
136
|
+
**Responsibilities:**
|
|
137
|
+
* Execute PostScript commands
|
|
138
|
+
* Manage execution context
|
|
139
|
+
* Parse arrays and procedures
|
|
140
|
+
* Coordinate with ExecutionContext
|
|
141
|
+
* Generate final SVG document
|
|
142
|
+
|
|
143
|
+
**Key Methods:**
|
|
144
|
+
* [`interpret(tokens, bounding_box)`](../lib/postsvg/interpreter.rb:20) - Main interpretation loop
|
|
145
|
+
* `execute_operator` - Execute single operator
|
|
146
|
+
* `parse_procedure` - Parse procedure tokens
|
|
147
|
+
* `parse_array` - Parse array tokens
|
|
148
|
+
* `generate_svg_document` - Create final SVG
|
|
149
|
+
|
|
150
|
+
=== ExecutionContext Class
|
|
151
|
+
|
|
152
|
+
**Location:** [`lib/postsvg/execution_context.rb`](../lib/postsvg/execution_context.rb:9)
|
|
153
|
+
|
|
154
|
+
**Responsibilities:**
|
|
155
|
+
* Maintain operand stack
|
|
156
|
+
* Manage dictionary stack
|
|
157
|
+
* Track graphics state
|
|
158
|
+
* Manage graphics state stack
|
|
159
|
+
* Generate SVG elements
|
|
160
|
+
* Handle clipPath deduplication
|
|
161
|
+
|
|
162
|
+
**Key Components:**
|
|
163
|
+
* Operand stack for values
|
|
164
|
+
* Dictionary stack for definitions
|
|
165
|
+
* Graphics state for drawing parameters
|
|
166
|
+
* Graphics state stack for `gsave`/`grestore`
|
|
167
|
+
* ClipPath registry for optimization
|
|
168
|
+
|
|
169
|
+
=== GraphicsState Class
|
|
170
|
+
|
|
171
|
+
**Location:** [`lib/postsvg/graphics_state.rb`](../lib/postsvg/graphics_state.rb:5)
|
|
172
|
+
|
|
173
|
+
**Responsibilities:**
|
|
174
|
+
* Track current path
|
|
175
|
+
* Manage colors (fill and stroke)
|
|
176
|
+
* Store line attributes
|
|
177
|
+
* Maintain transformation matrix
|
|
178
|
+
* Handle path construction
|
|
179
|
+
|
|
180
|
+
**State Components:**
|
|
181
|
+
* Current path segments
|
|
182
|
+
* Current point (x, y)
|
|
183
|
+
* Fill and stroke colors
|
|
184
|
+
* Line width, cap, join, dash pattern
|
|
185
|
+
* Transformation matrix
|
|
186
|
+
|
|
187
|
+
=== SvgGenerator Class
|
|
188
|
+
|
|
189
|
+
**Location:** [`lib/postsvg/svg_generator.rb`](../lib/postsvg/svg_generator.rb:7)
|
|
190
|
+
|
|
191
|
+
**Responsibilities:**
|
|
192
|
+
* Build SVG document structure
|
|
193
|
+
* Transform paths to SVG format
|
|
194
|
+
* Apply coordinate transformations
|
|
195
|
+
* Generate optimized output
|
|
196
|
+
|
|
197
|
+
**Generation Steps:**
|
|
198
|
+
1. Create SVG root element
|
|
199
|
+
2. Set viewBox from BoundingBox
|
|
200
|
+
3. Generate `<defs>` section
|
|
201
|
+
4. Transform and output paths
|
|
202
|
+
5. Optimize clipPath references
|
|
203
|
+
|
|
204
|
+
=== Command Registry
|
|
205
|
+
|
|
206
|
+
**Location:** [`lib/postsvg/commands/registry.rb`](../lib/postsvg/commands/registry.rb:1)
|
|
207
|
+
|
|
208
|
+
**Responsibilities:**
|
|
209
|
+
* Register all PostScript operators
|
|
210
|
+
* Look up command implementations
|
|
211
|
+
* Provide command execution interface
|
|
212
|
+
|
|
213
|
+
**Command Categories:**
|
|
214
|
+
* Path construction (moveto, lineto, curveto, etc.)
|
|
215
|
+
* Painting (stroke, fill, clip, etc.)
|
|
216
|
+
* Graphics state (gsave, grestore, setlinewidth, etc.)
|
|
217
|
+
* Transformations (translate, scale, rotate, etc.)
|
|
218
|
+
* Stack operations (dup, pop, exch, roll, etc.)
|
|
219
|
+
* Arithmetic (add, sub, mul, div, etc.)
|
|
220
|
+
* Control flow (if, ifelse, for, repeat, etc.)
|
|
221
|
+
* Dictionary (dict, begin, end, def, etc.)
|
|
222
|
+
|
|
223
|
+
=== Matrix Class
|
|
224
|
+
|
|
225
|
+
**Location:** [`lib/postsvg/matrix.rb`](../lib/postsvg/matrix.rb:6)
|
|
226
|
+
|
|
227
|
+
**Responsibilities:**
|
|
228
|
+
* Represent 2D affine transformations
|
|
229
|
+
* Perform matrix operations
|
|
230
|
+
* Apply transformations to points
|
|
231
|
+
* Convert to SVG transform strings
|
|
232
|
+
|
|
233
|
+
**Operations:**
|
|
234
|
+
* Multiply matrices
|
|
235
|
+
* Translate, scale, rotate
|
|
236
|
+
* Transform points
|
|
237
|
+
* Invert transformations
|
|
238
|
+
* Decompose into components
|
|
239
|
+
|
|
240
|
+
== Design Patterns
|
|
241
|
+
|
|
242
|
+
=== Command Pattern
|
|
243
|
+
|
|
244
|
+
Each PostScript operator is implemented as a command class:
|
|
245
|
+
|
|
246
|
+
[source,ruby]
|
|
247
|
+
----
|
|
248
|
+
module Postsvg
|
|
249
|
+
module Commands
|
|
250
|
+
class Moveto < Base
|
|
251
|
+
def execute(context)
|
|
252
|
+
y = context.pop_number
|
|
253
|
+
x = context.pop_number
|
|
254
|
+
context.graphics_state.moveto(x, y)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
----
|
|
260
|
+
|
|
261
|
+
**Benefits:**
|
|
262
|
+
* Each operator is independently testable
|
|
263
|
+
* Easy to add new operators
|
|
264
|
+
* Clear separation of concerns
|
|
265
|
+
* Supports operator overriding
|
|
266
|
+
|
|
267
|
+
=== Registry Pattern
|
|
268
|
+
|
|
269
|
+
Commands are registered centrally:
|
|
270
|
+
|
|
271
|
+
[source,ruby]
|
|
272
|
+
----
|
|
273
|
+
Registry.register('moveto', Commands::Moveto.new)
|
|
274
|
+
Registry.register('lineto', Commands::Lineto.new)
|
|
275
|
+
# ...
|
|
276
|
+
|
|
277
|
+
# Later, look up and execute
|
|
278
|
+
command = Registry.lookup('moveto')
|
|
279
|
+
command.execute(context)
|
|
280
|
+
----
|
|
281
|
+
|
|
282
|
+
=== State Pattern
|
|
283
|
+
|
|
284
|
+
Graphics state is managed immutably:
|
|
285
|
+
|
|
286
|
+
[source,ruby]
|
|
287
|
+
----
|
|
288
|
+
# Save state
|
|
289
|
+
saved_state = graphics_state.dup
|
|
290
|
+
state_stack.push(saved_state)
|
|
291
|
+
|
|
292
|
+
# Modify state
|
|
293
|
+
graphics_state.translate(10, 20)
|
|
294
|
+
|
|
295
|
+
# Restore state
|
|
296
|
+
graphics_state = state_stack.pop
|
|
297
|
+
----
|
|
298
|
+
|
|
299
|
+
=== Strategy Pattern
|
|
300
|
+
|
|
301
|
+
Different output formats use strategy pattern:
|
|
302
|
+
|
|
303
|
+
[source,ruby]
|
|
304
|
+
----
|
|
305
|
+
# Text reporter
|
|
306
|
+
reporter = Reporters::TextReporter.new
|
|
307
|
+
|
|
308
|
+
# JSON reporter
|
|
309
|
+
reporter = Reporters::JsonReporter.new
|
|
310
|
+
|
|
311
|
+
# Both use same interface
|
|
312
|
+
reporter.report(validation_result)
|
|
313
|
+
----
|
|
314
|
+
|
|
315
|
+
## Data Flow
|
|
316
|
+
|
|
317
|
+
.Complete Data Flow
|
|
318
|
+
[source]
|
|
319
|
+
----
|
|
320
|
+
PostScript File
|
|
321
|
+
│
|
|
322
|
+
▼
|
|
323
|
+
[Tokenizer]
|
|
324
|
+
│
|
|
325
|
+
▼
|
|
326
|
+
Tokens[]
|
|
327
|
+
│
|
|
328
|
+
▼
|
|
329
|
+
[Interpreter] ──────> [ExecutionContext]
|
|
330
|
+
│ │
|
|
331
|
+
│ ├─> Operand Stack
|
|
332
|
+
│ ├─> Dictionary Stack
|
|
333
|
+
│ ├─> Graphics State
|
|
334
|
+
│ └─> SVG Output Buffer
|
|
335
|
+
│
|
|
336
|
+
▼
|
|
337
|
+
[SvgGenerator]
|
|
338
|
+
│
|
|
339
|
+
▼
|
|
340
|
+
SVG Document
|
|
341
|
+
----
|
|
342
|
+
|
|
343
|
+
== Next Steps
|
|
344
|
+
|
|
345
|
+
* Review link:architecture/conversion-pipeline.adoc[Conversion Pipeline] details
|
|
346
|
+
* Explore link:architecture/command-registry.adoc[Command Registry] implementation
|
|
347
|
+
* See link:development.adoc[Development Guide] for contributing
|
|
348
|
+
* Check link:api-reference.adoc[API Reference] for class details
|
|
349
|
+
|
|
350
|
+
== Bibliography
|
|
351
|
+
|
|
352
|
+
* link:architecture/conversion-pipeline.adoc[Conversion Pipeline Documentation]
|
|
353
|
+
* link:architecture/design-decisions.adoc[Design Decisions]
|
|
354
|
+
* Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four)
|