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,836 @@
|
|
|
1
|
+
= Coordinate Systems
|
|
2
|
+
:page-nav_order: 3
|
|
3
|
+
:page-parent: Core Concepts
|
|
4
|
+
|
|
5
|
+
== Purpose
|
|
6
|
+
|
|
7
|
+
This document explains the fundamental differences between PostScript and SVG coordinate systems and how Postsvg handles the coordinate transformation between them. Understanding coordinate systems is essential for debugging rendering issues and working with transformations.
|
|
8
|
+
|
|
9
|
+
== References
|
|
10
|
+
|
|
11
|
+
* link:../index.adoc[Documentation Home]
|
|
12
|
+
* link:../concepts.adoc[Core Concepts Overview]
|
|
13
|
+
* link:graphics-state.adoc[Graphics State Management]
|
|
14
|
+
* link:conversion-pipeline.adoc[Conversion Pipeline]
|
|
15
|
+
* link:../architecture.adoc[Architecture Documentation]
|
|
16
|
+
|
|
17
|
+
== Concepts
|
|
18
|
+
|
|
19
|
+
**User Space**:: The coordinate system used in PostScript source code, before transformations are applied.
|
|
20
|
+
|
|
21
|
+
**Device Space**:: The coordinate system of the output device (screen, printer, SVG canvas).
|
|
22
|
+
|
|
23
|
+
**Current Transformation Matrix (CTM)**:: The matrix that transforms coordinates from user space to device space.
|
|
24
|
+
|
|
25
|
+
**Origin**:: The (0, 0) point of a coordinate system, which differs between PostScript and SVG.
|
|
26
|
+
|
|
27
|
+
**Y-Axis Orientation**:: The direction of the Y-axis, which is inverted between PostScript and SVG.
|
|
28
|
+
|
|
29
|
+
== PostScript Coordinate System
|
|
30
|
+
|
|
31
|
+
=== Origin and Orientation
|
|
32
|
+
|
|
33
|
+
PostScript uses a **bottom-left origin** with **Y increasing upward**.
|
|
34
|
+
|
|
35
|
+
.PostScript Coordinate System
|
|
36
|
+
[source]
|
|
37
|
+
----
|
|
38
|
+
Y
|
|
39
|
+
↑
|
|
40
|
+
│
|
|
41
|
+
100 │ ┌─────────┐
|
|
42
|
+
│ │ Content │
|
|
43
|
+
50 │ │ │
|
|
44
|
+
│ └─────────┘
|
|
45
|
+
0 └─────┴────┴────→ X
|
|
46
|
+
0 50 100
|
|
47
|
+
----
|
|
48
|
+
|
|
49
|
+
**Characteristics:**
|
|
50
|
+
|
|
51
|
+
* Origin (0, 0) is at **bottom-left**
|
|
52
|
+
* X-axis increases **left to right**
|
|
53
|
+
* Y-axis increases **bottom to top**
|
|
54
|
+
* Matches mathematical convention
|
|
55
|
+
* Used by printers and traditional graphics systems
|
|
56
|
+
|
|
57
|
+
=== Default Page Size
|
|
58
|
+
|
|
59
|
+
PostScript typically uses these standard page sizes (at 72 DPI):
|
|
60
|
+
|
|
61
|
+
**US Letter:**
|
|
62
|
+
[source,postscript]
|
|
63
|
+
----
|
|
64
|
+
%%BoundingBox: 0 0 612 792
|
|
65
|
+
% Width: 612 points (8.5 inches)
|
|
66
|
+
% Height: 792 points (11 inches)
|
|
67
|
+
----
|
|
68
|
+
|
|
69
|
+
**A4:**
|
|
70
|
+
[source,postscript]
|
|
71
|
+
----
|
|
72
|
+
%%BoundingBox: 0 0 595 842
|
|
73
|
+
% Width: 595 points (210mm)
|
|
74
|
+
% Height: 842 points (297mm)
|
|
75
|
+
----
|
|
76
|
+
|
|
77
|
+
=== Coordinate Example
|
|
78
|
+
|
|
79
|
+
.PostScript Coordinates
|
|
80
|
+
[example]
|
|
81
|
+
====
|
|
82
|
+
[source,postscript]
|
|
83
|
+
----
|
|
84
|
+
%!PS-Adobe-3.0
|
|
85
|
+
%%BoundingBox: 0 0 200 200
|
|
86
|
+
|
|
87
|
+
% Point at (50, 150) - near top-left
|
|
88
|
+
50 150 moveto
|
|
89
|
+
150 150 lineto
|
|
90
|
+
stroke
|
|
91
|
+
|
|
92
|
+
% Point at (50, 50) - near bottom-left
|
|
93
|
+
50 50 moveto
|
|
94
|
+
150 50 lineto
|
|
95
|
+
stroke
|
|
96
|
+
----
|
|
97
|
+
|
|
98
|
+
Visual representation:
|
|
99
|
+
|
|
100
|
+
[source]
|
|
101
|
+
----
|
|
102
|
+
200 ┌───────────────┐
|
|
103
|
+
│ │
|
|
104
|
+
150 │ ●─────────● │ ← (50,150) to (150,150)
|
|
105
|
+
│ │
|
|
106
|
+
100 │ │
|
|
107
|
+
│ │
|
|
108
|
+
50 │ ●─────────● │ ← (50,50) to (150,50)
|
|
109
|
+
│ │
|
|
110
|
+
0 └───────────────┘
|
|
111
|
+
0 100 200
|
|
112
|
+
----
|
|
113
|
+
====
|
|
114
|
+
|
|
115
|
+
== SVG Coordinate System
|
|
116
|
+
|
|
117
|
+
=== Origin and Orientation
|
|
118
|
+
|
|
119
|
+
SVG uses a **top-left origin** with **Y increasing downward**.
|
|
120
|
+
|
|
121
|
+
.SVG Coordinate System
|
|
122
|
+
[source]
|
|
123
|
+
----
|
|
124
|
+
0 ┌─────┴────┴────→ X
|
|
125
|
+
│ ┌─────────┐ 50 100
|
|
126
|
+
│ │ Content │
|
|
127
|
+
50 │ │ │
|
|
128
|
+
│ └─────────┘
|
|
129
|
+
100 │
|
|
130
|
+
↓
|
|
131
|
+
Y
|
|
132
|
+
----
|
|
133
|
+
|
|
134
|
+
**Characteristics:**
|
|
135
|
+
|
|
136
|
+
* Origin (0, 0) is at **top-left**
|
|
137
|
+
* X-axis increases **left to right**
|
|
138
|
+
* Y-axis increases **top to bottom**
|
|
139
|
+
* Matches screen/display convention
|
|
140
|
+
* Used by web browsers and most graphics software
|
|
141
|
+
|
|
142
|
+
=== ViewBox Attribute
|
|
143
|
+
|
|
144
|
+
SVG uses the `viewBox` attribute to define the coordinate system:
|
|
145
|
+
|
|
146
|
+
[source,xml]
|
|
147
|
+
----
|
|
148
|
+
<svg viewBox="min-x min-y width height">
|
|
149
|
+
----
|
|
150
|
+
|
|
151
|
+
.SVG ViewBox
|
|
152
|
+
[example]
|
|
153
|
+
====
|
|
154
|
+
[source,xml]
|
|
155
|
+
----
|
|
156
|
+
<svg xmlns="http://www.w3.org/2000/svg"
|
|
157
|
+
width="200" height="200"
|
|
158
|
+
viewBox="0 0 200 200">
|
|
159
|
+
<!-- Content here uses viewBox coordinates -->
|
|
160
|
+
</svg>
|
|
161
|
+
----
|
|
162
|
+
|
|
163
|
+
* `viewBox="0 0 200 200"` means:
|
|
164
|
+
* min-x: 0
|
|
165
|
+
* min-y: 0
|
|
166
|
+
* width: 200
|
|
167
|
+
* height: 200
|
|
168
|
+
====
|
|
169
|
+
|
|
170
|
+
== The Coordinate System Problem
|
|
171
|
+
|
|
172
|
+
The **fundamental challenge** in PostScript to SVG conversion is the Y-axis orientation difference.
|
|
173
|
+
|
|
174
|
+
.Coordinate System Comparison
|
|
175
|
+
[source]
|
|
176
|
+
----
|
|
177
|
+
PostScript (Y up) SVG (Y down)
|
|
178
|
+
|
|
179
|
+
100 ┌─────────┐ 200 0 ┌─────────┐ 0
|
|
180
|
+
│ A │ │ D │
|
|
181
|
+
50 │ │ 150 50 │ │ 50
|
|
182
|
+
│ B │ │ C │
|
|
183
|
+
0 └─────────┘ 100 100 └─────────┘ 100
|
|
184
|
+
0 100 0 100
|
|
185
|
+
|
|
186
|
+
Point A in PostScript: Point D in SVG:
|
|
187
|
+
PS: (50, 80) SVG: (50, 20)
|
|
188
|
+
Near top of page Near top of page
|
|
189
|
+
|
|
190
|
+
Point B in PostScript: Point C in SVG:
|
|
191
|
+
PS: (50, 20) SVG: (50, 80)
|
|
192
|
+
Near bottom of page Near bottom of page
|
|
193
|
+
----
|
|
194
|
+
|
|
195
|
+
**The Issue:**
|
|
196
|
+
|
|
197
|
+
A point at PostScript coordinate `(x, y)` would appear at the **wrong vertical position** if used directly in SVG.
|
|
198
|
+
|
|
199
|
+
* PS `(50, 20)` - near bottom
|
|
200
|
+
* SVG `(50, 20)` - near top
|
|
201
|
+
|
|
202
|
+
== Coordinate Transformation Strategy
|
|
203
|
+
|
|
204
|
+
Postsvg uses a **transformation group** approach to handle the coordinate difference.
|
|
205
|
+
|
|
206
|
+
=== The Transformation
|
|
207
|
+
|
|
208
|
+
[source,xml]
|
|
209
|
+
----
|
|
210
|
+
<g transform="translate(0 height) scale(1 -1)">
|
|
211
|
+
<!-- PostScript graphics elements -->
|
|
212
|
+
</g>
|
|
213
|
+
----
|
|
214
|
+
|
|
215
|
+
**This transformation:**
|
|
216
|
+
|
|
217
|
+
1. **Translates** the origin to the bottom-left
|
|
218
|
+
2. **Scales Y by -1** to flip the Y-axis
|
|
219
|
+
|
|
220
|
+
.Transformation Breakdown
|
|
221
|
+
[example]
|
|
222
|
+
====
|
|
223
|
+
Given a page height of 200:
|
|
224
|
+
|
|
225
|
+
[source,xml]
|
|
226
|
+
----
|
|
227
|
+
<g transform="translate(0 200) scale(1 -1)">
|
|
228
|
+
----
|
|
229
|
+
|
|
230
|
+
**Step 1: Translate (0, 200)**
|
|
231
|
+
|
|
232
|
+
[source]
|
|
233
|
+
----
|
|
234
|
+
Before: After translate(0, 200):
|
|
235
|
+
0,0 0,0
|
|
236
|
+
┌──── │
|
|
237
|
+
│ │
|
|
238
|
+
│ │ 200
|
|
239
|
+
│ ↓
|
|
240
|
+
200 ┌──── ← New origin
|
|
241
|
+
│
|
|
242
|
+
----
|
|
243
|
+
|
|
244
|
+
**Step 2: Scale (1, -1)**
|
|
245
|
+
|
|
246
|
+
[source]
|
|
247
|
+
----
|
|
248
|
+
After translate: After scale(1, -1):
|
|
249
|
+
|
|
250
|
+
200 ┌──── 0 ┌──── ← Y increasing downward
|
|
251
|
+
│ │ becomes upward
|
|
252
|
+
│ │
|
|
253
|
+
↓ ↑
|
|
254
|
+
Y 200
|
|
255
|
+
----
|
|
256
|
+
|
|
257
|
+
**Result:** Y-axis now increases upward, matching PostScript!
|
|
258
|
+
====
|
|
259
|
+
|
|
260
|
+
=== Why This Works
|
|
261
|
+
|
|
262
|
+
The combined transformation `translate(0 h) scale(1 -1)`:
|
|
263
|
+
|
|
264
|
+
[source]
|
|
265
|
+
----
|
|
266
|
+
Original SVG point: (x, y)
|
|
267
|
+
After translate: (x, y + h)
|
|
268
|
+
After scale: (x, h - y)
|
|
269
|
+
|
|
270
|
+
This is equivalent to the PostScript coordinate!
|
|
271
|
+
----
|
|
272
|
+
|
|
273
|
+
**Example:**
|
|
274
|
+
|
|
275
|
+
For height = 200:
|
|
276
|
+
|
|
277
|
+
[source]
|
|
278
|
+
----
|
|
279
|
+
PS point (50, 150):
|
|
280
|
+
→ SVG before transform: would be at (50, 150)
|
|
281
|
+
→ SVG with transform: translate gives (50, 350)
|
|
282
|
+
scale gives (50, 200-350) = (50, -150)
|
|
283
|
+
Which renders at correct position!
|
|
284
|
+
|
|
285
|
+
Actually, the math is:
|
|
286
|
+
PS (50, 150) → transform → SVG renders at visual position
|
|
287
|
+
that matches PS (50, 150) appearance
|
|
288
|
+
----
|
|
289
|
+
|
|
290
|
+
== User Space vs. Device Space
|
|
291
|
+
|
|
292
|
+
=== User Space
|
|
293
|
+
|
|
294
|
+
**User space** is the coordinate system used in PostScript source code. It's modified by transformation operators:
|
|
295
|
+
|
|
296
|
+
[source,postscript]
|
|
297
|
+
----
|
|
298
|
+
% User space coordinates
|
|
299
|
+
100 100 moveto % In current user space
|
|
300
|
+
200 200 lineto
|
|
301
|
+
stroke
|
|
302
|
+
|
|
303
|
+
% Transform user space
|
|
304
|
+
2 2 scale % User space units are now 2x larger
|
|
305
|
+
100 100 moveto % Actually 200,200 in original user space
|
|
306
|
+
----
|
|
307
|
+
|
|
308
|
+
=== Device Space
|
|
309
|
+
|
|
310
|
+
**Device space** is the final coordinate system of the output device after all transformations are applied.
|
|
311
|
+
|
|
312
|
+
.User Space to Device Space
|
|
313
|
+
[source]
|
|
314
|
+
----
|
|
315
|
+
User Space CTM Device Space
|
|
316
|
+
(100, 100) ──────────────→ (transformed coordinates)
|
|
317
|
+
[a b c d e f]
|
|
318
|
+
|
|
319
|
+
Example with CTM = [2 0 0 2 0 0] (scale 2x):
|
|
320
|
+
User (100, 100) → Device (200, 200)
|
|
321
|
+
----
|
|
322
|
+
|
|
323
|
+
=== The Current Transformation Matrix (CTM)
|
|
324
|
+
|
|
325
|
+
The **CTM** is a 2×3 affine transformation matrix: `[a b c d e f]`
|
|
326
|
+
|
|
327
|
+
.CTM Structure
|
|
328
|
+
[source]
|
|
329
|
+
----
|
|
330
|
+
[ a c e ] Matrix form: [ a c e ]
|
|
331
|
+
[ b d f ] [ b d f ]
|
|
332
|
+
[ 0 0 1 ] [ 0 0 1 ]
|
|
333
|
+
|
|
334
|
+
Point transformation:
|
|
335
|
+
[ x' ] [ a c e ] [ x ] [ ax + cy + e ]
|
|
336
|
+
[ y' ] = [ b d f ] × [ y ] = [ bx + dy + f ]
|
|
337
|
+
[ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
|
|
338
|
+
----
|
|
339
|
+
|
|
340
|
+
**Components:**
|
|
341
|
+
|
|
342
|
+
* `a, d` - **Scaling** factors
|
|
343
|
+
* `b, c` - **Rotation/skew** factors
|
|
344
|
+
* `e, f` - **Translation** offsets
|
|
345
|
+
|
|
346
|
+
=== Identity CTM
|
|
347
|
+
|
|
348
|
+
The **default CTM** is the identity matrix:
|
|
349
|
+
|
|
350
|
+
[source,ruby]
|
|
351
|
+
----
|
|
352
|
+
[1, 0, 0, 1, 0, 0]
|
|
353
|
+
----
|
|
354
|
+
|
|
355
|
+
This maps user space 1:1 to device space (no transformation).
|
|
356
|
+
|
|
357
|
+
== Transformation Operations
|
|
358
|
+
|
|
359
|
+
=== Translation
|
|
360
|
+
|
|
361
|
+
Shifts the origin without changing orientation or scale.
|
|
362
|
+
|
|
363
|
+
[source,postscript]
|
|
364
|
+
----
|
|
365
|
+
tx ty translate
|
|
366
|
+
----
|
|
367
|
+
|
|
368
|
+
**Effect on CTM:**
|
|
369
|
+
|
|
370
|
+
[source]
|
|
371
|
+
----
|
|
372
|
+
Before: [a b c d e f]
|
|
373
|
+
After: [a b c d (e+tx) (f+ty)]
|
|
374
|
+
----
|
|
375
|
+
|
|
376
|
+
.Translation Example
|
|
377
|
+
[example]
|
|
378
|
+
====
|
|
379
|
+
[source,postscript]
|
|
380
|
+
----
|
|
381
|
+
% Move origin to (100, 100)
|
|
382
|
+
100 100 translate
|
|
383
|
+
|
|
384
|
+
% Now (0, 0) in user space = (100, 100) in original space
|
|
385
|
+
0 0 moveto % Actually at (100, 100)
|
|
386
|
+
50 50 lineto % Actually at (150, 150)
|
|
387
|
+
stroke
|
|
388
|
+
----
|
|
389
|
+
|
|
390
|
+
Visual:
|
|
391
|
+
|
|
392
|
+
[source]
|
|
393
|
+
----
|
|
394
|
+
Original: After translate(100, 100):
|
|
395
|
+
0,0 0,0
|
|
396
|
+
┌──── │
|
|
397
|
+
│ │
|
|
398
|
+
│ 100,100 │
|
|
399
|
+
│ ● │ ● ← New 0,0
|
|
400
|
+
│ │ ┌───
|
|
401
|
+
│
|
|
402
|
+
----
|
|
403
|
+
====
|
|
404
|
+
|
|
405
|
+
=== Scaling
|
|
406
|
+
|
|
407
|
+
Changes the size of user space units.
|
|
408
|
+
|
|
409
|
+
[source,postscript]
|
|
410
|
+
----
|
|
411
|
+
sx sy scale
|
|
412
|
+
----
|
|
413
|
+
|
|
414
|
+
**Effect on CTM:**
|
|
415
|
+
|
|
416
|
+
[source]
|
|
417
|
+
----
|
|
418
|
+
Before: [a b c d e f]
|
|
419
|
+
After: [a×sx b×sx c×sy d×sy e f]
|
|
420
|
+
----
|
|
421
|
+
|
|
422
|
+
.Scaling Example
|
|
423
|
+
[example]
|
|
424
|
+
====
|
|
425
|
+
[source,postscript]
|
|
426
|
+
----
|
|
427
|
+
% Double all coordinates
|
|
428
|
+
2 2 scale
|
|
429
|
+
|
|
430
|
+
% Drawing in user space
|
|
431
|
+
0 0 50 50 rectfill % Actually draws 100×100 rectangle
|
|
432
|
+
----
|
|
433
|
+
|
|
434
|
+
**Non-uniform scaling:**
|
|
435
|
+
|
|
436
|
+
[source,postscript]
|
|
437
|
+
----
|
|
438
|
+
% Stretch horizontally, shrink vertically
|
|
439
|
+
3 0.5 scale
|
|
440
|
+
|
|
441
|
+
0 0 100 100 rectfill % Draws 300×50 rectangle
|
|
442
|
+
----
|
|
443
|
+
====
|
|
444
|
+
|
|
445
|
+
=== Rotation
|
|
446
|
+
|
|
447
|
+
Rotates the coordinate system about the origin.
|
|
448
|
+
|
|
449
|
+
[source,postscript]
|
|
450
|
+
----
|
|
451
|
+
angle rotate % angle in degrees, counter-clockwise
|
|
452
|
+
----
|
|
453
|
+
|
|
454
|
+
**Effect on CTM:**
|
|
455
|
+
|
|
456
|
+
[source]
|
|
457
|
+
----
|
|
458
|
+
Before: [a b c d e f]
|
|
459
|
+
Rotation matrix R = [cos(θ) sin(θ) -sin(θ) cos(θ) 0 0]
|
|
460
|
+
After: R × CTM
|
|
461
|
+
----
|
|
462
|
+
|
|
463
|
+
.Rotation Example
|
|
464
|
+
[example]
|
|
465
|
+
====
|
|
466
|
+
[source,postscript]
|
|
467
|
+
----
|
|
468
|
+
% Rotate 45 degrees counter-clockwise
|
|
469
|
+
45 rotate
|
|
470
|
+
|
|
471
|
+
0 0 moveto
|
|
472
|
+
100 0 lineto
|
|
473
|
+
stroke
|
|
474
|
+
% Draws line at 45° angle from origin
|
|
475
|
+
----
|
|
476
|
+
|
|
477
|
+
Visual:
|
|
478
|
+
|
|
479
|
+
[source]
|
|
480
|
+
----
|
|
481
|
+
Before rotation: After 45° rotation:
|
|
482
|
+
Y Y
|
|
483
|
+
↑ ↑ ╱
|
|
484
|
+
│ │ ╱
|
|
485
|
+
│ │╱
|
|
486
|
+
│─────→ X ├────→ X
|
|
487
|
+
0 0
|
|
488
|
+
|
|
489
|
+
100 0 lineto Line now at 45° angle
|
|
490
|
+
────→ ╱
|
|
491
|
+
╱
|
|
492
|
+
----
|
|
493
|
+
====
|
|
494
|
+
|
|
495
|
+
=== Rotation About a Point
|
|
496
|
+
|
|
497
|
+
To rotate about a point other than origin:
|
|
498
|
+
|
|
499
|
+
[source,postscript]
|
|
500
|
+
----
|
|
501
|
+
% Rotate 45° about point (100, 100)
|
|
502
|
+
100 100 translate % 1. Move point to origin
|
|
503
|
+
45 rotate % 2. Rotate
|
|
504
|
+
-100 -100 translate % 3. Move back
|
|
505
|
+
----
|
|
506
|
+
|
|
507
|
+
.Rotation About Point
|
|
508
|
+
[example]
|
|
509
|
+
====
|
|
510
|
+
[source,postscript]
|
|
511
|
+
----
|
|
512
|
+
% Draw square
|
|
513
|
+
0 0 100 100 rectfill
|
|
514
|
+
|
|
515
|
+
% Rotate square 45° about its center (50, 50)
|
|
516
|
+
gsave
|
|
517
|
+
50 50 translate
|
|
518
|
+
45 rotate
|
|
519
|
+
-50 -50 translate
|
|
520
|
+
0 0 100 100 rectfill
|
|
521
|
+
grestore
|
|
522
|
+
----
|
|
523
|
+
|
|
524
|
+
Transformation sequence:
|
|
525
|
+
|
|
526
|
+
[source]
|
|
527
|
+
----
|
|
528
|
+
Original: Translate(50,50): Rotate 45°:
|
|
529
|
+
┌───┐ ┌───┐ ◇
|
|
530
|
+
│ │ │ │ ╱ ╲
|
|
531
|
+
│ │ → │ + │ → ╱ ╲
|
|
532
|
+
│ │ │ │ ╲ ╱
|
|
533
|
+
└───┘ └───┘ ╲ ╱
|
|
534
|
+
↑ ◇
|
|
535
|
+
Center now at origin
|
|
536
|
+
----
|
|
537
|
+
====
|
|
538
|
+
|
|
539
|
+
== Matrix Operations in Postsvg
|
|
540
|
+
|
|
541
|
+
=== Matrix Class
|
|
542
|
+
|
|
543
|
+
The [`Matrix`](../../lib/postsvg/matrix.rb:6) class implements affine transformations:
|
|
544
|
+
|
|
545
|
+
[source,ruby]
|
|
546
|
+
----
|
|
547
|
+
# Create identity matrix
|
|
548
|
+
matrix = Matrix.new
|
|
549
|
+
# => { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }
|
|
550
|
+
|
|
551
|
+
# Create custom matrix
|
|
552
|
+
matrix = Matrix.new(a: 2, d: 2) # 2x scaling
|
|
553
|
+
----
|
|
554
|
+
|
|
555
|
+
=== Applying Transformations
|
|
556
|
+
|
|
557
|
+
[source,ruby]
|
|
558
|
+
----
|
|
559
|
+
# Translation
|
|
560
|
+
matrix = matrix.translate(10, 20)
|
|
561
|
+
|
|
562
|
+
# Scaling
|
|
563
|
+
matrix = matrix.scale(2, 3)
|
|
564
|
+
|
|
565
|
+
# Rotation (in degrees)
|
|
566
|
+
matrix = matrix.rotate(45)
|
|
567
|
+
|
|
568
|
+
# Transform a point
|
|
569
|
+
point = matrix.apply_point(100, 100)
|
|
570
|
+
# => { x: transformed_x, y: transformed_y }
|
|
571
|
+
----
|
|
572
|
+
|
|
573
|
+
=== Matrix Multiplication
|
|
574
|
+
|
|
575
|
+
Transformations compose via matrix multiplication:
|
|
576
|
+
|
|
577
|
+
[source,ruby]
|
|
578
|
+
----
|
|
579
|
+
# Multiple transformations
|
|
580
|
+
matrix = Matrix.new
|
|
581
|
+
matrix = matrix.translate(10, 20)
|
|
582
|
+
matrix = matrix.rotate(45)
|
|
583
|
+
matrix = matrix.scale(2, 2)
|
|
584
|
+
|
|
585
|
+
# Same as:
|
|
586
|
+
m1 = Matrix.new.translate(10, 20)
|
|
587
|
+
m2 = Matrix.new.rotate(45)
|
|
588
|
+
m3 = Matrix.new.scale(2, 2)
|
|
589
|
+
result = m1.multiply(m2).multiply(m3)
|
|
590
|
+
----
|
|
591
|
+
|
|
592
|
+
**Order matters!** `A × B ≠ B × A`
|
|
593
|
+
|
|
594
|
+
.Transformation Order Example
|
|
595
|
+
[example]
|
|
596
|
+
====
|
|
597
|
+
[source,ruby]
|
|
598
|
+
----
|
|
599
|
+
# Translate THEN scale
|
|
600
|
+
m1 = Matrix.new.translate(10, 10).scale(2, 2)
|
|
601
|
+
# (100, 100) → (110, 110) → (220, 220)
|
|
602
|
+
|
|
603
|
+
# Scale THEN translate
|
|
604
|
+
m2 = Matrix.new.scale(2, 2).translate(10, 10)
|
|
605
|
+
# (100, 100) → (200, 200) → (210, 210)
|
|
606
|
+
|
|
607
|
+
# Different results!
|
|
608
|
+
----
|
|
609
|
+
====
|
|
610
|
+
|
|
611
|
+
=== Matrix Decomposition
|
|
612
|
+
|
|
613
|
+
The `decompose` method extracts transformation components:
|
|
614
|
+
|
|
615
|
+
[source,ruby]
|
|
616
|
+
----
|
|
617
|
+
matrix = Matrix.new
|
|
618
|
+
matrix = matrix.translate(10, 20)
|
|
619
|
+
matrix = matrix.rotate(45)
|
|
620
|
+
matrix = matrix.scale(2, 3)
|
|
621
|
+
|
|
622
|
+
components = matrix.decompose
|
|
623
|
+
# => {
|
|
624
|
+
# translate: { x: 10, y: 20 },
|
|
625
|
+
# rotate: 45,
|
|
626
|
+
# scale: { x: 2, y: 3 },
|
|
627
|
+
# skew: { x: 0, y: 0 }
|
|
628
|
+
# }
|
|
629
|
+
----
|
|
630
|
+
|
|
631
|
+
This is useful for generating SVG transform strings.
|
|
632
|
+
|
|
633
|
+
== Coordinate Transformation in Practice
|
|
634
|
+
|
|
635
|
+
=== PostScript to SVG Path Conversion
|
|
636
|
+
|
|
637
|
+
When converting a PostScript path to SVG:
|
|
638
|
+
|
|
639
|
+
.Path Coordinate Example
|
|
640
|
+
[example]
|
|
641
|
+
====
|
|
642
|
+
**PostScript:**
|
|
643
|
+
|
|
644
|
+
[source,postscript]
|
|
645
|
+
----
|
|
646
|
+
%%BoundingBox: 0 0 200 200
|
|
647
|
+
newpath
|
|
648
|
+
50 50 moveto % Bottom-left area
|
|
649
|
+
150 150 lineto % Top-right area
|
|
650
|
+
stroke
|
|
651
|
+
----
|
|
652
|
+
|
|
653
|
+
**Direct (Wrong) SVG:**
|
|
654
|
+
|
|
655
|
+
[source,xml]
|
|
656
|
+
----
|
|
657
|
+
<svg viewBox="0 0 200 200">
|
|
658
|
+
<!-- Point (50,50) appears near TOP-left! -->
|
|
659
|
+
<!-- Point (150,150) appears near BOTTOM-right! -->
|
|
660
|
+
<path d="M 50 50 L 150 150" stroke="black"/>
|
|
661
|
+
</svg>
|
|
662
|
+
----
|
|
663
|
+
|
|
664
|
+
**Correct SVG with transform:**
|
|
665
|
+
|
|
666
|
+
[source,xml]
|
|
667
|
+
----
|
|
668
|
+
<svg viewBox="0 0 200 200">
|
|
669
|
+
<g transform="translate(0 200) scale(1 -1)">
|
|
670
|
+
<!-- Now (50,50) appears near bottom-left -->
|
|
671
|
+
<!-- And (150,150) appears near top-right -->
|
|
672
|
+
<path d="M 50 50 L 150 150" stroke="black"/>
|
|
673
|
+
</g>
|
|
674
|
+
</svg>
|
|
675
|
+
----
|
|
676
|
+
====
|
|
677
|
+
|
|
678
|
+
=== Handling the BoundingBox
|
|
679
|
+
|
|
680
|
+
The BoundingBox comment defines the page dimensions:
|
|
681
|
+
|
|
682
|
+
[source,postscript]
|
|
683
|
+
----
|
|
684
|
+
%%BoundingBox: llx lly urx ury
|
|
685
|
+
----
|
|
686
|
+
|
|
687
|
+
**Where:**
|
|
688
|
+
|
|
689
|
+
* `llx, lly` - Lower-left corner coordinates
|
|
690
|
+
* `urx, ury` - Upper-right corner coordinates
|
|
691
|
+
|
|
692
|
+
.BoundingBox to ViewBox
|
|
693
|
+
[example]
|
|
694
|
+
====
|
|
695
|
+
[source,postscript]
|
|
696
|
+
----
|
|
697
|
+
%%BoundingBox: 0 0 612 792
|
|
698
|
+
% US Letter page
|
|
699
|
+
----
|
|
700
|
+
|
|
701
|
+
Converts to:
|
|
702
|
+
|
|
703
|
+
[source,xml]
|
|
704
|
+
----
|
|
705
|
+
<svg viewBox="0 0 612 792"
|
|
706
|
+
width="612"
|
|
707
|
+
height="792">
|
|
708
|
+
<g transform="translate(0 792) scale(1 -1)">
|
|
709
|
+
<!-- Content -->
|
|
710
|
+
</g>
|
|
711
|
+
</svg>
|
|
712
|
+
----
|
|
713
|
+
|
|
714
|
+
The transform height (792) comes from the BoundingBox height.
|
|
715
|
+
====
|
|
716
|
+
|
|
717
|
+
=== Non-Zero BoundingBox Origin
|
|
718
|
+
|
|
719
|
+
Sometimes BoundingBox doesn't start at (0, 0):
|
|
720
|
+
|
|
721
|
+
[source,postscript]
|
|
722
|
+
----
|
|
723
|
+
%%BoundingBox: 50 50 250 250
|
|
724
|
+
% 200×200 area, offset by (50, 50)
|
|
725
|
+
----
|
|
726
|
+
|
|
727
|
+
.Offset BoundingBox Handling
|
|
728
|
+
[example]
|
|
729
|
+
====
|
|
730
|
+
**Approach 1: Adjust viewBox**
|
|
731
|
+
|
|
732
|
+
[source,xml]
|
|
733
|
+
----
|
|
734
|
+
<svg viewBox="50 50 200 200"
|
|
735
|
+
width="200"
|
|
736
|
+
height="200">
|
|
737
|
+
<g transform="translate(0 200) scale(1 -1)">
|
|
738
|
+
<!-- Content uses original coordinates -->
|
|
739
|
+
</g>
|
|
740
|
+
</svg>
|
|
741
|
+
----
|
|
742
|
+
|
|
743
|
+
**Approach 2: Normalize to origin**
|
|
744
|
+
|
|
745
|
+
[source,xml]
|
|
746
|
+
----
|
|
747
|
+
<svg viewBox="0 0 200 200"
|
|
748
|
+
width="200"
|
|
749
|
+
height="200">
|
|
750
|
+
<g transform="translate(-50 200) scale(1 -1) translate(0 -50)">
|
|
751
|
+
<!-- Content adjusted to start at (0, 0) -->
|
|
752
|
+
</g>
|
|
753
|
+
</svg>
|
|
754
|
+
----
|
|
755
|
+
====
|
|
756
|
+
|
|
757
|
+
== Common Coordinate Issues
|
|
758
|
+
|
|
759
|
+
=== Issue 1: Upside-Down Content
|
|
760
|
+
|
|
761
|
+
**Symptom:** Graphics appear flipped vertically
|
|
762
|
+
|
|
763
|
+
**Cause:** Missing or incorrect Y-axis flip transformation
|
|
764
|
+
|
|
765
|
+
**Solution:**
|
|
766
|
+
|
|
767
|
+
[source,xml]
|
|
768
|
+
----
|
|
769
|
+
<!-- Wrong: No transform -->
|
|
770
|
+
<svg><path d="..." /></svg>
|
|
771
|
+
|
|
772
|
+
<!-- Correct: Y-axis flip -->
|
|
773
|
+
<svg>
|
|
774
|
+
<g transform="translate(0 height) scale(1 -1)">
|
|
775
|
+
<path d="..." />
|
|
776
|
+
</g>
|
|
777
|
+
</svg>
|
|
778
|
+
----
|
|
779
|
+
|
|
780
|
+
=== Issue 2: Content Outside ViewBox
|
|
781
|
+
|
|
782
|
+
**Symptom:** Graphics not visible or clipped
|
|
783
|
+
|
|
784
|
+
**Cause:** ViewBox doesn't match BoundingBox
|
|
785
|
+
|
|
786
|
+
**Solution:**
|
|
787
|
+
|
|
788
|
+
[source,ruby]
|
|
789
|
+
----
|
|
790
|
+
# Extract BoundingBox correctly
|
|
791
|
+
bbox = {
|
|
792
|
+
llx: 0, lly: 0,
|
|
793
|
+
urx: 612, ury: 792,
|
|
794
|
+
width: 612, height: 792
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
# Use in SVG
|
|
798
|
+
viewBox = "#{bbox[:llx]} #{bbox[:lly]} #{bbox[:width]} #{bbox[:height]}"
|
|
799
|
+
----
|
|
800
|
+
|
|
801
|
+
=== Issue 3: Transformation Order
|
|
802
|
+
|
|
803
|
+
**Symptom:** Transformations produce unexpected results
|
|
804
|
+
|
|
805
|
+
**Cause:** Wrong order of transformations
|
|
806
|
+
|
|
807
|
+
**Example:**
|
|
808
|
+
|
|
809
|
+
[source,postscript]
|
|
810
|
+
----
|
|
811
|
+
% Wrong order
|
|
812
|
+
10 10 translate
|
|
813
|
+
2 2 scale
|
|
814
|
+
% (100,100) → (110,110) → (220,220)
|
|
815
|
+
|
|
816
|
+
% Correct order for centering scale
|
|
817
|
+
2 2 scale
|
|
818
|
+
10 10 translate
|
|
819
|
+
% (100,100) → (200,200) → (210,210)
|
|
820
|
+
----
|
|
821
|
+
|
|
822
|
+
== Next Steps
|
|
823
|
+
|
|
824
|
+
* Review link:graphics-state.adoc[Graphics State Management] for CTM details
|
|
825
|
+
* Explore link:path-operations.adoc[Path Operations] for coordinate usage
|
|
826
|
+
* See link:svg-generation.adoc[SVG Generation] for output details
|
|
827
|
+
* Check link:../architecture.adoc[Architecture] for implementation
|
|
828
|
+
* Read link:conversion-pipeline.adoc[Conversion Pipeline] for the full process
|
|
829
|
+
|
|
830
|
+
== Bibliography
|
|
831
|
+
|
|
832
|
+
* link:graphics-state.adoc[Graphics State Management]
|
|
833
|
+
* link:../architecture/graphics-state-model.adoc[Graphics State Implementation]
|
|
834
|
+
* link:svg-generation.adoc[SVG Generation]
|
|
835
|
+
* link:https://www.adobe.com/jp/print/postscript/pdfs/PLRM.pdf[PostScript Language Reference Manual] - Chapter 4: Graphics
|
|
836
|
+
* link:https://www.w3.org/TR/SVG/coords.html[SVG Coordinate Systems Specification]
|