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,1070 @@
|
|
|
1
|
+
= GraphicsState Class
|
|
2
|
+
:page-nav_order: 5
|
|
3
|
+
:page-parent: API Reference
|
|
4
|
+
|
|
5
|
+
== Purpose
|
|
6
|
+
|
|
7
|
+
The [`GraphicsState`](../../lib/postsvg/graphics_state.rb:5) class manages PostScript graphics state including path construction, color settings, transformations, and rendering parameters. It provides a legacy interface for graphics operations, though most functionality has been migrated to [`ExecutionContext`](execution-context.adoc).
|
|
8
|
+
|
|
9
|
+
== References
|
|
10
|
+
|
|
11
|
+
* link:../index.adoc[Documentation Home]
|
|
12
|
+
* link:../api-reference.adoc[API Reference Overview]
|
|
13
|
+
* link:execution-context.adoc[ExecutionContext Class]
|
|
14
|
+
* link:interpreter.adoc[Interpreter Class]
|
|
15
|
+
* link:../architecture.adoc[Architecture Overview]
|
|
16
|
+
|
|
17
|
+
== Concepts
|
|
18
|
+
|
|
19
|
+
**Graphics State**:: The collection of parameters that control how graphics are rendered, including colors, line width, transformations, and the current path.
|
|
20
|
+
|
|
21
|
+
**Current Path**:: The sequence of path segments (moveto, lineto, curveto) being constructed before rendering.
|
|
22
|
+
|
|
23
|
+
**Current Point**:: The coordinates where the next path segment will begin.
|
|
24
|
+
|
|
25
|
+
**Transformation Matrix**:: A 2D affine transformation matrix that maps coordinates from user space to device space.
|
|
26
|
+
|
|
27
|
+
**Graphics State Stack**:: A stack allowing graphics state to be saved and restored via `save`/`restore` operations.
|
|
28
|
+
|
|
29
|
+
**Color Space**:: The color model used for rendering (RGB, grayscale, CMYK, etc.).
|
|
30
|
+
|
|
31
|
+
== Class Overview
|
|
32
|
+
|
|
33
|
+
The [`GraphicsState`](../../lib/postsvg/graphics_state.rb:5) class is defined in [`lib/postsvg/graphics_state.rb`](../../lib/postsvg/graphics_state.rb:1).
|
|
34
|
+
|
|
35
|
+
**Responsibilities:**
|
|
36
|
+
|
|
37
|
+
* Manage current path construction
|
|
38
|
+
* Track current point coordinates
|
|
39
|
+
* Store color settings (fill and stroke)
|
|
40
|
+
* Maintain transformation matrix
|
|
41
|
+
* Implement graphics state stack (save/restore)
|
|
42
|
+
* Provide coordinate transformation
|
|
43
|
+
* Support Level 3 PostScript features
|
|
44
|
+
|
|
45
|
+
**Note on Usage:**
|
|
46
|
+
|
|
47
|
+
This class represents a legacy architecture component. In the current implementation, most graphics state functionality is handled by [`ExecutionContext`](execution-context.adoc). The `GraphicsState` class is maintained for compatibility but is not actively used in the primary execution path.
|
|
48
|
+
|
|
49
|
+
**Key Components:**
|
|
50
|
+
|
|
51
|
+
* Current path - Array of path segments
|
|
52
|
+
* Current point - (x, y) coordinates
|
|
53
|
+
* Colors - Fill and stroke RGB values
|
|
54
|
+
* Transform matrix - 6-element array [a, b, c, d, e, f]
|
|
55
|
+
* State stack - For save/restore operations
|
|
56
|
+
|
|
57
|
+
== Class Methods
|
|
58
|
+
|
|
59
|
+
=== new
|
|
60
|
+
|
|
61
|
+
Create a new GraphicsState with default values.
|
|
62
|
+
|
|
63
|
+
**Syntax:**
|
|
64
|
+
|
|
65
|
+
[source,ruby]
|
|
66
|
+
----
|
|
67
|
+
graphics_state = Postsvg::GraphicsState.new <1>
|
|
68
|
+
----
|
|
69
|
+
<1> Initialize graphics state with defaults
|
|
70
|
+
|
|
71
|
+
**Returns:**
|
|
72
|
+
|
|
73
|
+
New `GraphicsState` instance with:
|
|
74
|
+
|
|
75
|
+
* Empty path
|
|
76
|
+
* Current point at origin (0, 0)
|
|
77
|
+
* Line width of 1.0
|
|
78
|
+
* Black fill and stroke colors
|
|
79
|
+
* Identity transformation matrix
|
|
80
|
+
* Empty state stack
|
|
81
|
+
|
|
82
|
+
**Source:**
|
|
83
|
+
|
|
84
|
+
[`lib/postsvg/graphics_state.rb:10-26`](../../lib/postsvg/graphics_state.rb:10)
|
|
85
|
+
|
|
86
|
+
**Default Values:**
|
|
87
|
+
|
|
88
|
+
[source,ruby]
|
|
89
|
+
----
|
|
90
|
+
@current_path = []
|
|
91
|
+
@current_x = 0
|
|
92
|
+
@current_y = 0
|
|
93
|
+
@line_width = 1.0
|
|
94
|
+
@fill_color = { r: 0, g: 0, b: 0 } # Black
|
|
95
|
+
@stroke_color = { r: 0, g: 0, b: 0 } # Black
|
|
96
|
+
@transform_matrix = [1, 0, 0, 1, 0, 0] # Identity
|
|
97
|
+
@state_stack = []
|
|
98
|
+
|
|
99
|
+
# Level 3 features
|
|
100
|
+
@icc_profile = nil
|
|
101
|
+
@blend_mode = :normal
|
|
102
|
+
@soft_mask = nil
|
|
103
|
+
@opacity_alpha = 1.0
|
|
104
|
+
@shape_alpha = 1.0
|
|
105
|
+
----
|
|
106
|
+
|
|
107
|
+
.Create graphics state
|
|
108
|
+
[example]
|
|
109
|
+
====
|
|
110
|
+
[source,ruby]
|
|
111
|
+
----
|
|
112
|
+
require 'postsvg'
|
|
113
|
+
|
|
114
|
+
gs = Postsvg::GraphicsState.new
|
|
115
|
+
|
|
116
|
+
puts "Line width: #{gs.line_width}" # 1.0
|
|
117
|
+
puts "Current point: (#{gs.current_x}, #{gs.current_y})" # (0, 0)
|
|
118
|
+
puts "Fill color: #{gs.fill_color.inspect}" # {:r=>0, :g=>0, :b=>0}
|
|
119
|
+
puts "Path empty: #{gs.current_path.empty?}" # true
|
|
120
|
+
----
|
|
121
|
+
====
|
|
122
|
+
|
|
123
|
+
== Attributes
|
|
124
|
+
|
|
125
|
+
=== line_width (read/write)
|
|
126
|
+
|
|
127
|
+
The width of stroked lines.
|
|
128
|
+
|
|
129
|
+
**Type:** Float
|
|
130
|
+
|
|
131
|
+
**Default:** `1.0`
|
|
132
|
+
|
|
133
|
+
**Source:**
|
|
134
|
+
|
|
135
|
+
[`lib/postsvg/graphics_state.rb:6`](../../lib/postsvg/graphics_state.rb:6)
|
|
136
|
+
|
|
137
|
+
.Line width management
|
|
138
|
+
[example]
|
|
139
|
+
====
|
|
140
|
+
[source,ruby]
|
|
141
|
+
----
|
|
142
|
+
gs = Postsvg::GraphicsState.new
|
|
143
|
+
|
|
144
|
+
puts gs.line_width # 1.0
|
|
145
|
+
|
|
146
|
+
# Set custom width
|
|
147
|
+
gs.line_width = 2.5
|
|
148
|
+
puts gs.line_width # 2.5
|
|
149
|
+
|
|
150
|
+
# Thin line
|
|
151
|
+
gs.line_width = 0.5
|
|
152
|
+
----
|
|
153
|
+
====
|
|
154
|
+
|
|
155
|
+
=== current_x, current_y (read/write)
|
|
156
|
+
|
|
157
|
+
Current point coordinates in user space.
|
|
158
|
+
|
|
159
|
+
**Type:** Numeric
|
|
160
|
+
|
|
161
|
+
**Default:** `0`
|
|
162
|
+
|
|
163
|
+
**Source:**
|
|
164
|
+
|
|
165
|
+
[`lib/postsvg/graphics_state.rb:6-7`](../../lib/postsvg/graphics_state.rb:6)
|
|
166
|
+
|
|
167
|
+
.Track current point
|
|
168
|
+
[example]
|
|
169
|
+
====
|
|
170
|
+
[source,ruby]
|
|
171
|
+
----
|
|
172
|
+
gs = Postsvg::GraphicsState.new
|
|
173
|
+
|
|
174
|
+
puts "(#{gs.current_x}, #{gs.current_y})" # (0, 0)
|
|
175
|
+
|
|
176
|
+
# Update via path operations
|
|
177
|
+
gs.moveto(100, 200)
|
|
178
|
+
puts "(#{gs.current_x}, #{gs.current_y})" # (100, 200)
|
|
179
|
+
|
|
180
|
+
gs.lineto(150, 250)
|
|
181
|
+
puts "(#{gs.current_x}, #{gs.current_y})" # (150, 250)
|
|
182
|
+
----
|
|
183
|
+
====
|
|
184
|
+
|
|
185
|
+
=== current_path (read-only)
|
|
186
|
+
|
|
187
|
+
Array of path segment objects.
|
|
188
|
+
|
|
189
|
+
**Type:** Array of hashes
|
|
190
|
+
|
|
191
|
+
**Default:** `[]`
|
|
192
|
+
|
|
193
|
+
**Source:**
|
|
194
|
+
|
|
195
|
+
[`lib/postsvg/graphics_state.rb:8`](../../lib/postsvg/graphics_state.rb:8)
|
|
196
|
+
|
|
197
|
+
**Path Segment Structure:**
|
|
198
|
+
|
|
199
|
+
Each segment is a hash with a `:type` and coordinates:
|
|
200
|
+
|
|
201
|
+
[source,ruby]
|
|
202
|
+
----
|
|
203
|
+
# moveto segment
|
|
204
|
+
{ type: :moveto, x: 10, y: 20 }
|
|
205
|
+
|
|
206
|
+
# lineto segment
|
|
207
|
+
{ type: :lineto, x: 30, y: 40 }
|
|
208
|
+
|
|
209
|
+
# curveto segment
|
|
210
|
+
{ type: :curveto, x1: 10, y1: 20, x2: 30, y2: 40, x3: 50, y3: 60 }
|
|
211
|
+
|
|
212
|
+
# closepath segment
|
|
213
|
+
{ type: :closepath }
|
|
214
|
+
----
|
|
215
|
+
|
|
216
|
+
.Inspect path
|
|
217
|
+
[example]
|
|
218
|
+
====
|
|
219
|
+
[source,ruby]
|
|
220
|
+
----
|
|
221
|
+
gs = Postsvg::GraphicsState.new
|
|
222
|
+
|
|
223
|
+
gs.moveto(10, 20)
|
|
224
|
+
gs.lineto(30, 40)
|
|
225
|
+
gs.closepath
|
|
226
|
+
|
|
227
|
+
gs.current_path.each do |segment|
|
|
228
|
+
case segment[:type]
|
|
229
|
+
when :moveto
|
|
230
|
+
puts "Move to (#{segment[:x]}, #{segment[:y]})"
|
|
231
|
+
when :lineto
|
|
232
|
+
puts "Line to (#{segment[:x]}, #{segment[:y]})"
|
|
233
|
+
when :closepath
|
|
234
|
+
puts "Close path"
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
----
|
|
238
|
+
====
|
|
239
|
+
|
|
240
|
+
=== fill_color, stroke_color (read-only)
|
|
241
|
+
|
|
242
|
+
RGB color values for fill and stroke operations.
|
|
243
|
+
|
|
244
|
+
**Type:** Hash with `:r`, `:g`, `:b` keys
|
|
245
|
+
|
|
246
|
+
**Values:** 0.0 to 1.0 (not 0-255)
|
|
247
|
+
|
|
248
|
+
**Default:** `{ r: 0, g: 0, b: 0 }` (black)
|
|
249
|
+
|
|
250
|
+
**Source:**
|
|
251
|
+
|
|
252
|
+
[`lib/postsvg/graphics_state.rb:8`](../../lib/postsvg/graphics_state.rb:8)
|
|
253
|
+
|
|
254
|
+
.Access colors
|
|
255
|
+
[example]
|
|
256
|
+
====
|
|
257
|
+
[source,ruby]
|
|
258
|
+
----
|
|
259
|
+
gs = Postsvg::GraphicsState.new
|
|
260
|
+
|
|
261
|
+
# Default black
|
|
262
|
+
puts gs.fill_color # {:r=>0, :g=>0, :b=>0}
|
|
263
|
+
puts gs.stroke_color # {:r=>0, :g=>0, :b=>0}
|
|
264
|
+
|
|
265
|
+
# Set red
|
|
266
|
+
gs.set_rgb_color(1, 0, 0)
|
|
267
|
+
puts gs.fill_color # {:r=>1, :g=>0, :b=>0}
|
|
268
|
+
|
|
269
|
+
# Get as hex
|
|
270
|
+
hex = gs.fill_color_hex
|
|
271
|
+
puts hex # "#ff0000"
|
|
272
|
+
----
|
|
273
|
+
====
|
|
274
|
+
|
|
275
|
+
=== Level 3 Attributes
|
|
276
|
+
|
|
277
|
+
==== icc_profile (read/write)
|
|
278
|
+
|
|
279
|
+
ICC color profile for advanced color management.
|
|
280
|
+
|
|
281
|
+
**Type:** Object or nil
|
|
282
|
+
|
|
283
|
+
**Default:** `nil`
|
|
284
|
+
|
|
285
|
+
**Source:**
|
|
286
|
+
|
|
287
|
+
[`lib/postsvg/graphics_state.rb:6-7`](../../lib/postsvg/graphics_state.rb:6)
|
|
288
|
+
|
|
289
|
+
==== blend_mode (read/write)
|
|
290
|
+
|
|
291
|
+
Blend mode for compositing operations.
|
|
292
|
+
|
|
293
|
+
**Type:** Symbol
|
|
294
|
+
|
|
295
|
+
**Default:** `:normal`
|
|
296
|
+
|
|
297
|
+
**Source:**
|
|
298
|
+
|
|
299
|
+
[`lib/postsvg/graphics_state.rb:6-7`](../../lib/postsvg/graphics_state.rb:6)
|
|
300
|
+
|
|
301
|
+
==== soft_mask (read/write)
|
|
302
|
+
|
|
303
|
+
Soft mask for transparency effects.
|
|
304
|
+
|
|
305
|
+
**Type:** Object or nil
|
|
306
|
+
|
|
307
|
+
**Default:** `nil`
|
|
308
|
+
|
|
309
|
+
**Source:**
|
|
310
|
+
|
|
311
|
+
[`lib/postsvg/graphics_state.rb:6-7`](../../lib/postsvg/graphics_state.rb:6)
|
|
312
|
+
|
|
313
|
+
==== opacity_alpha (read/write)
|
|
314
|
+
|
|
315
|
+
Opacity alpha value.
|
|
316
|
+
|
|
317
|
+
**Type:** Float (0.0 to 1.0)
|
|
318
|
+
|
|
319
|
+
**Default:** `1.0` (fully opaque)
|
|
320
|
+
|
|
321
|
+
**Source:**
|
|
322
|
+
|
|
323
|
+
[`lib/postsvg/graphics_state.rb:6-7`](../../lib/postsvg/graphics_state.rb:6)
|
|
324
|
+
|
|
325
|
+
==== shape_alpha (read/write)
|
|
326
|
+
|
|
327
|
+
Shape alpha value for blending.
|
|
328
|
+
|
|
329
|
+
**Type:** Float (0.0 to 1.0)
|
|
330
|
+
|
|
331
|
+
**Default:** `1.0`
|
|
332
|
+
|
|
333
|
+
**Source:**
|
|
334
|
+
|
|
335
|
+
[`lib/postsvg/graphics_state.rb:6-7`](../../lib/postsvg/graphics_state.rb:6)
|
|
336
|
+
|
|
337
|
+
.Level 3 features
|
|
338
|
+
[example]
|
|
339
|
+
====
|
|
340
|
+
[source,ruby]
|
|
341
|
+
----
|
|
342
|
+
gs = Postsvg::GraphicsState.new
|
|
343
|
+
|
|
344
|
+
# Set transparency
|
|
345
|
+
gs.opacity_alpha = 0.5 # 50% transparent
|
|
346
|
+
gs.shape_alpha = 0.75
|
|
347
|
+
|
|
348
|
+
# Set blend mode
|
|
349
|
+
gs.blend_mode = :multiply
|
|
350
|
+
|
|
351
|
+
puts "Opacity: #{gs.opacity_alpha}" # 0.5
|
|
352
|
+
puts "Blend mode: #{gs.blend_mode}" # :multiply
|
|
353
|
+
----
|
|
354
|
+
====
|
|
355
|
+
|
|
356
|
+
== Path Construction Methods
|
|
357
|
+
|
|
358
|
+
=== moveto
|
|
359
|
+
|
|
360
|
+
Move current point to new coordinates.
|
|
361
|
+
|
|
362
|
+
**Syntax:**
|
|
363
|
+
|
|
364
|
+
[source,ruby]
|
|
365
|
+
----
|
|
366
|
+
gs.moveto(x, y) <1>
|
|
367
|
+
----
|
|
368
|
+
<1> Move to (x, y) starting a new subpath
|
|
369
|
+
|
|
370
|
+
**Where:**
|
|
371
|
+
|
|
372
|
+
`x`:: X coordinate in user space
|
|
373
|
+
`y`:: Y coordinate in user space
|
|
374
|
+
|
|
375
|
+
**Source:**
|
|
376
|
+
|
|
377
|
+
[`lib/postsvg/graphics_state.rb:29-34`](../../lib/postsvg/graphics_state.rb:29)
|
|
378
|
+
|
|
379
|
+
**Behavior:**
|
|
380
|
+
|
|
381
|
+
* Transforms coordinates via transformation matrix
|
|
382
|
+
* Updates current point
|
|
383
|
+
* Adds moveto segment to path
|
|
384
|
+
|
|
385
|
+
.Moveto example
|
|
386
|
+
[example]
|
|
387
|
+
====
|
|
388
|
+
[source,ruby]
|
|
389
|
+
----
|
|
390
|
+
gs = Postsvg::GraphicsState.new
|
|
391
|
+
|
|
392
|
+
gs.moveto(10, 20)
|
|
393
|
+
|
|
394
|
+
puts gs.current_path.last
|
|
395
|
+
# {:type=>:moveto, :x=>10, :y=>20}
|
|
396
|
+
|
|
397
|
+
puts "(#{gs.current_x}, #{gs.current_y})"
|
|
398
|
+
# (10, 20)
|
|
399
|
+
----
|
|
400
|
+
====
|
|
401
|
+
|
|
402
|
+
=== lineto
|
|
403
|
+
|
|
404
|
+
Draw line from current point to new coordinates.
|
|
405
|
+
|
|
406
|
+
**Syntax:**
|
|
407
|
+
|
|
408
|
+
[source,ruby]
|
|
409
|
+
----
|
|
410
|
+
gs.lineto(x, y) <1>
|
|
411
|
+
----
|
|
412
|
+
<1> Draw line to (x, y)
|
|
413
|
+
|
|
414
|
+
**Where:**
|
|
415
|
+
|
|
416
|
+
`x`:: X coordinate in user space
|
|
417
|
+
`y`:: Y coordinate in user space
|
|
418
|
+
|
|
419
|
+
**Source:**
|
|
420
|
+
|
|
421
|
+
[`lib/postsvg/graphics_state.rb:36-41`](../../lib/postsvg/graphics_state.rb:36)
|
|
422
|
+
|
|
423
|
+
**Behavior:**
|
|
424
|
+
|
|
425
|
+
* Transforms coordinates via transformation matrix
|
|
426
|
+
* Updates current point
|
|
427
|
+
* Adds lineto segment to path
|
|
428
|
+
|
|
429
|
+
.Lineto example
|
|
430
|
+
[example]
|
|
431
|
+
====
|
|
432
|
+
[source,ruby]
|
|
433
|
+
----
|
|
434
|
+
gs = Postsvg::GraphicsState.new
|
|
435
|
+
|
|
436
|
+
gs.moveto(10, 20)
|
|
437
|
+
gs.lineto(30, 40)
|
|
438
|
+
gs.lineto(50, 60)
|
|
439
|
+
|
|
440
|
+
# Path now has: moveto, lineto, lineto
|
|
441
|
+
puts gs.current_path.length # 3
|
|
442
|
+
puts "(#{gs.current_x}, #{gs.current_y})" # (50, 60)
|
|
443
|
+
----
|
|
444
|
+
====
|
|
445
|
+
|
|
446
|
+
=== rlineto
|
|
447
|
+
|
|
448
|
+
Draw line relative to current point.
|
|
449
|
+
|
|
450
|
+
**Syntax:**
|
|
451
|
+
|
|
452
|
+
[source,ruby]
|
|
453
|
+
----
|
|
454
|
+
gs.rlineto(dx, dy) <1>
|
|
455
|
+
----
|
|
456
|
+
<1> Draw line by relative offset (dx, dy)
|
|
457
|
+
|
|
458
|
+
**Where:**
|
|
459
|
+
|
|
460
|
+
`dx`:: X offset from current point
|
|
461
|
+
`dy`:: Y offset from current point
|
|
462
|
+
|
|
463
|
+
**Source:**
|
|
464
|
+
|
|
465
|
+
[`lib/postsvg/graphics_state.rb:43-46`](../../lib/postsvg/graphics_state.rb:43)
|
|
466
|
+
|
|
467
|
+
.Relative lineto
|
|
468
|
+
[example]
|
|
469
|
+
====
|
|
470
|
+
[source,ruby]
|
|
471
|
+
----
|
|
472
|
+
gs = Postsvg::GraphicsState.new
|
|
473
|
+
|
|
474
|
+
gs.moveto(10, 20)
|
|
475
|
+
|
|
476
|
+
# Draw 30 units right, 40 units up
|
|
477
|
+
gs.rlineto(30, 40)
|
|
478
|
+
|
|
479
|
+
puts "(#{gs.current_x}, #{gs.current_y})" # (40, 60)
|
|
480
|
+
----
|
|
481
|
+
====
|
|
482
|
+
|
|
483
|
+
=== curveto
|
|
484
|
+
|
|
485
|
+
Draw Bézier curve from current point.
|
|
486
|
+
|
|
487
|
+
**Syntax:**
|
|
488
|
+
|
|
489
|
+
[source,ruby]
|
|
490
|
+
----
|
|
491
|
+
gs.curveto(x1, y1, x2, y2, x3, y3) <1>
|
|
492
|
+
----
|
|
493
|
+
<1> Draw cubic Bézier curve with two control points
|
|
494
|
+
|
|
495
|
+
**Where:**
|
|
496
|
+
|
|
497
|
+
`x1, y1`:: First control point
|
|
498
|
+
`x2, y2`:: Second control point
|
|
499
|
+
`x3, y3`:: End point
|
|
500
|
+
|
|
501
|
+
**Source:**
|
|
502
|
+
|
|
503
|
+
[`lib/postsvg/graphics_state.rb:48-62`](../../lib/postsvg/graphics_state.rb:48)
|
|
504
|
+
|
|
505
|
+
**Behavior:**
|
|
506
|
+
|
|
507
|
+
* Transforms all coordinates via transformation matrix
|
|
508
|
+
* Updates current point to (x3, y3)
|
|
509
|
+
* Adds curveto segment to path
|
|
510
|
+
|
|
511
|
+
.Curveto example
|
|
512
|
+
[example]
|
|
513
|
+
====
|
|
514
|
+
[source,ruby]
|
|
515
|
+
----
|
|
516
|
+
gs = Postsvg::GraphicsState.new
|
|
517
|
+
|
|
518
|
+
gs.moveto(10, 10)
|
|
519
|
+
gs.curveto(20, 40, 40, 40, 50, 10)
|
|
520
|
+
|
|
521
|
+
segment = gs.current_path.last
|
|
522
|
+
puts segment[:type] # :curveto
|
|
523
|
+
puts "Control 1: (#{segment[:x1]}, #{segment[:y1]})"
|
|
524
|
+
puts "Control 2: (#{segment[:x2]}, #{segment[:y2]})"
|
|
525
|
+
puts "End: (#{segment[:x3]}, #{segment[:y3]})"
|
|
526
|
+
----
|
|
527
|
+
====
|
|
528
|
+
|
|
529
|
+
=== closepath
|
|
530
|
+
|
|
531
|
+
Close current subpath by connecting to start point.
|
|
532
|
+
|
|
533
|
+
**Syntax:**
|
|
534
|
+
|
|
535
|
+
[source,ruby]
|
|
536
|
+
----
|
|
537
|
+
gs.closepath <1>
|
|
538
|
+
----
|
|
539
|
+
<1> Add closepath segment to path
|
|
540
|
+
|
|
541
|
+
**Source:**
|
|
542
|
+
|
|
543
|
+
[`lib/postsvg/graphics_state.rb:64-66`](../../lib/postsvg/graphics_state.rb:64)
|
|
544
|
+
|
|
545
|
+
.Closepath example
|
|
546
|
+
[example]
|
|
547
|
+
====
|
|
548
|
+
[source,ruby]
|
|
549
|
+
----
|
|
550
|
+
gs = Postsvg::GraphicsState.new
|
|
551
|
+
|
|
552
|
+
# Draw triangle
|
|
553
|
+
gs.moveto(10, 10)
|
|
554
|
+
gs.lineto(50, 10)
|
|
555
|
+
gs.lineto(30, 40)
|
|
556
|
+
gs.closepath
|
|
557
|
+
|
|
558
|
+
# Path is now closed triangle
|
|
559
|
+
puts gs.current_path.length # 4 segments
|
|
560
|
+
puts gs.current_path.last[:type] # :closepath
|
|
561
|
+
----
|
|
562
|
+
====
|
|
563
|
+
|
|
564
|
+
=== newpath
|
|
565
|
+
|
|
566
|
+
Clear current path and start new one.
|
|
567
|
+
|
|
568
|
+
**Syntax:**
|
|
569
|
+
|
|
570
|
+
[source,ruby]
|
|
571
|
+
----
|
|
572
|
+
gs.newpath <1>
|
|
573
|
+
----
|
|
574
|
+
<1> Clear all path segments
|
|
575
|
+
|
|
576
|
+
**Source:**
|
|
577
|
+
|
|
578
|
+
[`lib/postsvg/graphics_state.rb:68-70`](../../lib/postsvg/graphics_state.rb:68)
|
|
579
|
+
|
|
580
|
+
.Newpath example
|
|
581
|
+
[example]
|
|
582
|
+
====
|
|
583
|
+
[source,ruby]
|
|
584
|
+
----
|
|
585
|
+
gs = Postsvg::GraphicsState.new
|
|
586
|
+
|
|
587
|
+
gs.moveto(10, 10)
|
|
588
|
+
gs.lineto(20, 20)
|
|
589
|
+
|
|
590
|
+
puts gs.current_path.length # 2
|
|
591
|
+
|
|
592
|
+
gs.newpath
|
|
593
|
+
|
|
594
|
+
puts gs.current_path.length # 0
|
|
595
|
+
puts gs.current_path.empty? # true
|
|
596
|
+
----
|
|
597
|
+
====
|
|
598
|
+
|
|
599
|
+
== Color Methods
|
|
600
|
+
|
|
601
|
+
=== set_rgb_color
|
|
602
|
+
|
|
603
|
+
Set both fill and stroke colors using RGB.
|
|
604
|
+
|
|
605
|
+
**Syntax:**
|
|
606
|
+
|
|
607
|
+
[source,ruby]
|
|
608
|
+
----
|
|
609
|
+
gs.set_rgb_color(r, g, b) <1>
|
|
610
|
+
----
|
|
611
|
+
<1> Set RGB color for fill and stroke
|
|
612
|
+
|
|
613
|
+
**Where:**
|
|
614
|
+
|
|
615
|
+
`r`:: Red component (0.0 to 1.0)
|
|
616
|
+
`g`:: Green component (0.0 to 1.0)
|
|
617
|
+
`b`:: Blue component (0.0 to 1.0)
|
|
618
|
+
|
|
619
|
+
**Source:**
|
|
620
|
+
|
|
621
|
+
[`lib/postsvg/graphics_state.rb:73-77`](../../lib/postsvg/graphics_state.rb:73)
|
|
622
|
+
|
|
623
|
+
.Set RGB color
|
|
624
|
+
[example]
|
|
625
|
+
====
|
|
626
|
+
[source,ruby]
|
|
627
|
+
----
|
|
628
|
+
gs = Postsvg::GraphicsState.new
|
|
629
|
+
|
|
630
|
+
# Set to red
|
|
631
|
+
gs.set_rgb_color(1, 0, 0)
|
|
632
|
+
|
|
633
|
+
puts gs.fill_color # {:r=>1, :g=>0, :b=>0}
|
|
634
|
+
puts gs.stroke_color # {:r=>1, :g=>0, :b=>0}
|
|
635
|
+
|
|
636
|
+
# Set to semi-transparent blue
|
|
637
|
+
gs.set_rgb_color(0, 0, 0.5)
|
|
638
|
+
|
|
639
|
+
# Convert to hex
|
|
640
|
+
puts gs.fill_color_hex # "#000080"
|
|
641
|
+
----
|
|
642
|
+
====
|
|
643
|
+
|
|
644
|
+
=== set_gray
|
|
645
|
+
|
|
646
|
+
Set grayscale color (same value for R, G, B).
|
|
647
|
+
|
|
648
|
+
**Syntax:**
|
|
649
|
+
|
|
650
|
+
[source,ruby]
|
|
651
|
+
----
|
|
652
|
+
gs.set_gray(gray) <1>
|
|
653
|
+
----
|
|
654
|
+
<1> Set grayscale value for fill and stroke
|
|
655
|
+
|
|
656
|
+
**Where:**
|
|
657
|
+
|
|
658
|
+
`gray`:: Gray level (0.0 = black, 1.0 = white)
|
|
659
|
+
|
|
660
|
+
**Source:**
|
|
661
|
+
|
|
662
|
+
[`lib/postsvg/graphics_state.rb:79-81`](../../lib/postsvg/graphics_state.rb:79)
|
|
663
|
+
|
|
664
|
+
.Set grayscale
|
|
665
|
+
[example]
|
|
666
|
+
====
|
|
667
|
+
[source,ruby]
|
|
668
|
+
----
|
|
669
|
+
gs = Postsvg::GraphicsState.new
|
|
670
|
+
|
|
671
|
+
# Set to 50% gray
|
|
672
|
+
gs.set_gray(0.5)
|
|
673
|
+
|
|
674
|
+
puts gs.fill_color # {:r=>0.5, :g=>0.5, :b=>0.5}
|
|
675
|
+
|
|
676
|
+
# White
|
|
677
|
+
gs.set_gray(1.0)
|
|
678
|
+
puts gs.fill_color_hex # "#ffffff"
|
|
679
|
+
|
|
680
|
+
# Black
|
|
681
|
+
gs.set_gray(0)
|
|
682
|
+
puts gs.fill_color_hex # "#000000"
|
|
683
|
+
----
|
|
684
|
+
====
|
|
685
|
+
|
|
686
|
+
=== rgb_to_hex
|
|
687
|
+
|
|
688
|
+
Convert RGB values to hex color string.
|
|
689
|
+
|
|
690
|
+
**Syntax:**
|
|
691
|
+
|
|
692
|
+
[source,ruby]
|
|
693
|
+
----
|
|
694
|
+
hex = gs.rgb_to_hex(r, g, b) <1>
|
|
695
|
+
----
|
|
696
|
+
<1> Convert RGB components to hex string
|
|
697
|
+
|
|
698
|
+
**Where:**
|
|
699
|
+
|
|
700
|
+
`r, g, b`:: Color components (0.0 to 1.0)
|
|
701
|
+
|
|
702
|
+
**Returns:**
|
|
703
|
+
|
|
704
|
+
String in format `"#RRGGBB"`
|
|
705
|
+
|
|
706
|
+
**Source:**
|
|
707
|
+
|
|
708
|
+
[`lib/postsvg/graphics_state.rb:153-155`](../../lib/postsvg/graphics_state.rb:153)
|
|
709
|
+
|
|
710
|
+
.RGB to hex conversion
|
|
711
|
+
[example]
|
|
712
|
+
====
|
|
713
|
+
[source,ruby]
|
|
714
|
+
----
|
|
715
|
+
gs = Postsvg::GraphicsState.new
|
|
716
|
+
|
|
717
|
+
hex = gs.rgb_to_hex(1, 0, 0)
|
|
718
|
+
puts hex # "#ff0000" (red)
|
|
719
|
+
|
|
720
|
+
hex = gs.rgb_to_hex(0, 0.5, 1)
|
|
721
|
+
puts hex # "#0080ff" (light blue)
|
|
722
|
+
|
|
723
|
+
hex = gs.rgb_to_hex(0.5, 0.5, 0.5)
|
|
724
|
+
puts hex # "#808080" (gray)
|
|
725
|
+
----
|
|
726
|
+
====
|
|
727
|
+
|
|
728
|
+
=== fill_color_hex
|
|
729
|
+
|
|
730
|
+
Get current fill color as hex string.
|
|
731
|
+
|
|
732
|
+
**Syntax:**
|
|
733
|
+
|
|
734
|
+
[source,ruby]
|
|
735
|
+
----
|
|
736
|
+
hex = gs.fill_color_hex <1>
|
|
737
|
+
----
|
|
738
|
+
<1> Convert current fill color to hex
|
|
739
|
+
|
|
740
|
+
**Returns:**
|
|
741
|
+
|
|
742
|
+
Hex color string or `"none"` if not RGB
|
|
743
|
+
|
|
744
|
+
**Source:**
|
|
745
|
+
|
|
746
|
+
[`lib/postsvg/graphics_state.rb:157-162`](../../lib/postsvg/graphics_state.rb:157)
|
|
747
|
+
|
|
748
|
+
=== stroke_color_hex
|
|
749
|
+
|
|
750
|
+
Get current stroke color as hex string.
|
|
751
|
+
|
|
752
|
+
**Syntax:**
|
|
753
|
+
|
|
754
|
+
[source,ruby]
|
|
755
|
+
----
|
|
756
|
+
hex = gs.stroke_color_hex <1>
|
|
757
|
+
----
|
|
758
|
+
<1> Convert current stroke color to hex
|
|
759
|
+
|
|
760
|
+
**Returns:**
|
|
761
|
+
|
|
762
|
+
Hex color string or `"none"` if not RGB
|
|
763
|
+
|
|
764
|
+
**Source:**
|
|
765
|
+
|
|
766
|
+
[`lib/postsvg/graphics_state.rb:164-169`](../../lib/postsvg/graphics_state.rb:164)
|
|
767
|
+
|
|
768
|
+
.Color hex conversion
|
|
769
|
+
[example]
|
|
770
|
+
====
|
|
771
|
+
[source,ruby]
|
|
772
|
+
----
|
|
773
|
+
gs = Postsvg::GraphicsState.new
|
|
774
|
+
|
|
775
|
+
gs.set_rgb_color(1, 0.5, 0) # Orange
|
|
776
|
+
|
|
777
|
+
puts gs.fill_color_hex # "#ff8000"
|
|
778
|
+
puts gs.stroke_color_hex # "#ff8000"
|
|
779
|
+
|
|
780
|
+
# Change to blue
|
|
781
|
+
gs.set_rgb_color(0, 0, 1)
|
|
782
|
+
puts gs.fill_color_hex # "#0000ff"
|
|
783
|
+
----
|
|
784
|
+
====
|
|
785
|
+
|
|
786
|
+
== Graphics State Stack
|
|
787
|
+
|
|
788
|
+
=== save
|
|
789
|
+
|
|
790
|
+
Save current graphics state onto stack.
|
|
791
|
+
|
|
792
|
+
**Syntax:**
|
|
793
|
+
|
|
794
|
+
[source,ruby]
|
|
795
|
+
----
|
|
796
|
+
gs.save <1>
|
|
797
|
+
----
|
|
798
|
+
<1> Push current state onto graphics state stack
|
|
799
|
+
|
|
800
|
+
**Source:**
|
|
801
|
+
|
|
802
|
+
[`lib/postsvg/graphics_state.rb:84-99`](../../lib/postsvg/graphics_state.rb:84)
|
|
803
|
+
|
|
804
|
+
**Saved State:**
|
|
805
|
+
|
|
806
|
+
* Current path (copy)
|
|
807
|
+
* Current point (x, y)
|
|
808
|
+
* Line width
|
|
809
|
+
* Fill color (copy)
|
|
810
|
+
* Stroke color (copy)
|
|
811
|
+
* Transformation matrix (copy)
|
|
812
|
+
* All Level 3 properties
|
|
813
|
+
|
|
814
|
+
.Save graphics state
|
|
815
|
+
[example]
|
|
816
|
+
====
|
|
817
|
+
[source,ruby]
|
|
818
|
+
----
|
|
819
|
+
gs = Postsvg::GraphicsState.new
|
|
820
|
+
|
|
821
|
+
# Set initial state
|
|
822
|
+
gs.set_rgb_color(1, 0, 0) # Red
|
|
823
|
+
gs.line_width = 2
|
|
824
|
+
|
|
825
|
+
# Save state
|
|
826
|
+
gs.save
|
|
827
|
+
|
|
828
|
+
# Modify state
|
|
829
|
+
gs.set_rgb_color(0, 0, 1) # Blue
|
|
830
|
+
gs.line_width = 5
|
|
831
|
+
|
|
832
|
+
puts gs.fill_color_hex # "#0000ff"
|
|
833
|
+
puts gs.line_width # 5
|
|
834
|
+
|
|
835
|
+
# Restore state
|
|
836
|
+
gs.restore
|
|
837
|
+
|
|
838
|
+
puts gs.fill_color_hex # "#ff0000"
|
|
839
|
+
puts gs.line_width # 2
|
|
840
|
+
----
|
|
841
|
+
====
|
|
842
|
+
|
|
843
|
+
=== restore
|
|
844
|
+
|
|
845
|
+
Restore previously saved graphics state.
|
|
846
|
+
|
|
847
|
+
**Syntax:**
|
|
848
|
+
|
|
849
|
+
[source,ruby]
|
|
850
|
+
----
|
|
851
|
+
gs.restore <1>
|
|
852
|
+
----
|
|
853
|
+
<1> Pop state from stack and apply
|
|
854
|
+
|
|
855
|
+
**Source:**
|
|
856
|
+
|
|
857
|
+
[`lib/postsvg/graphics_state.rb:101-117`](../../lib/postsvg/graphics_state.rb:101)
|
|
858
|
+
|
|
859
|
+
**Behavior:**
|
|
860
|
+
|
|
861
|
+
Does nothing if state stack is empty.
|
|
862
|
+
|
|
863
|
+
.Nested save/restore
|
|
864
|
+
[example]
|
|
865
|
+
====
|
|
866
|
+
[source,ruby]
|
|
867
|
+
----
|
|
868
|
+
gs = Postsvg::GraphicsState.new
|
|
869
|
+
|
|
870
|
+
gs.set_rgb_color(1, 0, 0) # Red
|
|
871
|
+
gs.save
|
|
872
|
+
|
|
873
|
+
gs.set_rgb_color(0, 1, 0) # Green
|
|
874
|
+
gs.save
|
|
875
|
+
|
|
876
|
+
gs.set_rgb_color(0, 0, 1) # Blue
|
|
877
|
+
puts gs.fill_color_hex # "#0000ff"
|
|
878
|
+
|
|
879
|
+
gs.restore
|
|
880
|
+
puts gs.fill_color_hex # "#00ff00"
|
|
881
|
+
|
|
882
|
+
gs.restore
|
|
883
|
+
puts gs.fill_color_hex # "#ff0000"
|
|
884
|
+
----
|
|
885
|
+
====
|
|
886
|
+
|
|
887
|
+
== Transformation Methods
|
|
888
|
+
|
|
889
|
+
=== translate
|
|
890
|
+
|
|
891
|
+
Apply translation transformation.
|
|
892
|
+
|
|
893
|
+
**Syntax:**
|
|
894
|
+
|
|
895
|
+
[source,ruby]
|
|
896
|
+
----
|
|
897
|
+
gs.translate(tx, ty) <1>
|
|
898
|
+
----
|
|
899
|
+
<1> Translate by (tx, ty)
|
|
900
|
+
|
|
901
|
+
**Where:**
|
|
902
|
+
|
|
903
|
+
`tx`:: X translation amount
|
|
904
|
+
`ty`:: Y translation amount
|
|
905
|
+
|
|
906
|
+
**Source:**
|
|
907
|
+
|
|
908
|
+
[`lib/postsvg/graphics_state.rb:120-124`](../../lib/postsvg/graphics_state.rb:120)
|
|
909
|
+
|
|
910
|
+
**Effect:**
|
|
911
|
+
|
|
912
|
+
Modifies transformation matrix to shift coordinate system.
|
|
913
|
+
|
|
914
|
+
.Translation example
|
|
915
|
+
[example]
|
|
916
|
+
====
|
|
917
|
+
[source,ruby]
|
|
918
|
+
----
|
|
919
|
+
gs = Postsvg::GraphicsState.new
|
|
920
|
+
|
|
921
|
+
# Translate 100 right, 50 up
|
|
922
|
+
gs.translate(100, 50)
|
|
923
|
+
|
|
924
|
+
# Draw at "origin" in new coordinate system
|
|
925
|
+
gs.moveto(0, 0)
|
|
926
|
+
|
|
927
|
+
# Actually at (100, 50) in device space
|
|
928
|
+
puts "(#{gs.current_x}, #{gs.current_y})" # (100, 50)
|
|
929
|
+
----
|
|
930
|
+
====
|
|
931
|
+
|
|
932
|
+
=== scale
|
|
933
|
+
|
|
934
|
+
Apply scaling transformation.
|
|
935
|
+
|
|
936
|
+
**Syntax:**
|
|
937
|
+
|
|
938
|
+
[source,ruby]
|
|
939
|
+
----
|
|
940
|
+
gs.scale(sx, sy) <1>
|
|
941
|
+
----
|
|
942
|
+
<1> Scale by factors (sx, sy)
|
|
943
|
+
|
|
944
|
+
**Where:**
|
|
945
|
+
|
|
946
|
+
`sx`:: X scale factor
|
|
947
|
+
`sy`:: Y scale factor
|
|
948
|
+
|
|
949
|
+
**Source:**
|
|
950
|
+
|
|
951
|
+
[`lib/postsvg/graphics_state.rb:126-132`](../../lib/postsvg/graphics_state.rb:126)
|
|
952
|
+
|
|
953
|
+
.Scaling example
|
|
954
|
+
[example]
|
|
955
|
+
====
|
|
956
|
+
[source,ruby]
|
|
957
|
+
----
|
|
958
|
+
gs = Postsvg::GraphicsState.new
|
|
959
|
+
|
|
960
|
+
# Scale 2x in X, 3x in Y
|
|
961
|
+
gs.scale(2, 3)
|
|
962
|
+
|
|
963
|
+
# Draw unit square
|
|
964
|
+
gs.moveto(0, 0)
|
|
965
|
+
gs.lineto(1, 0)
|
|
966
|
+
gs.lineto(1, 1)
|
|
967
|
+
gs.lineto(0, 1)
|
|
968
|
+
gs.closepath
|
|
969
|
+
|
|
970
|
+
# Actually 2x3 rectangle in device space
|
|
971
|
+
----
|
|
972
|
+
====
|
|
973
|
+
|
|
974
|
+
=== rotate
|
|
975
|
+
|
|
976
|
+
Apply rotation transformation.
|
|
977
|
+
|
|
978
|
+
**Syntax:**
|
|
979
|
+
|
|
980
|
+
[source,ruby]
|
|
981
|
+
----
|
|
982
|
+
gs.rotate(angle) <1>
|
|
983
|
+
----
|
|
984
|
+
<1> Rotate by angle in degrees
|
|
985
|
+
|
|
986
|
+
**Where:**
|
|
987
|
+
|
|
988
|
+
`angle`:: Rotation angle in degrees (positive = counter-clockwise)
|
|
989
|
+
|
|
990
|
+
**Source:**
|
|
991
|
+
|
|
992
|
+
[`lib/postsvg/graphics_state.rb:134-150`](../../lib/postsvg/graphics_state.rb:134)
|
|
993
|
+
|
|
994
|
+
.Rotation example
|
|
995
|
+
[example]
|
|
996
|
+
====
|
|
997
|
+
[source,ruby]
|
|
998
|
+
----
|
|
999
|
+
gs = Postsvg::GraphicsState.new
|
|
1000
|
+
|
|
1001
|
+
# Rotate 45 degrees
|
|
1002
|
+
gs.rotate(45)
|
|
1003
|
+
|
|
1004
|
+
# Draw horizontal line in rotated space
|
|
1005
|
+
gs.moveto(0, 0)
|
|
1006
|
+
gs.lineto(100, 0)
|
|
1007
|
+
|
|
1008
|
+
# Line actually at 45-degree angle in device space
|
|
1009
|
+
----
|
|
1010
|
+
====
|
|
1011
|
+
|
|
1012
|
+
## Usage Notes
|
|
1013
|
+
|
|
1014
|
+
=== Legacy Status
|
|
1015
|
+
|
|
1016
|
+
**Important:** This class is part of the legacy architecture. The current implementation primarily uses [`ExecutionContext`](execution-context.adoc) for graphics state management.
|
|
1017
|
+
|
|
1018
|
+
**Current Usage:**
|
|
1019
|
+
|
|
1020
|
+
* Not actively used in primary execution path
|
|
1021
|
+
* Maintained for compatibility
|
|
1022
|
+
* May be referenced by legacy code or tests
|
|
1023
|
+
|
|
1024
|
+
**Recommended Alternative:**
|
|
1025
|
+
|
|
1026
|
+
Use [`ExecutionContext`](execution-context.adoc) for all new code:
|
|
1027
|
+
|
|
1028
|
+
[source,ruby]
|
|
1029
|
+
----
|
|
1030
|
+
# Instead of GraphicsState
|
|
1031
|
+
context = Postsvg::ExecutionContext.new
|
|
1032
|
+
|
|
1033
|
+
# Access graphics state via context
|
|
1034
|
+
context.graphics_state[:fill] = "red"
|
|
1035
|
+
context.graphics_state[:stroke_width] = 2
|
|
1036
|
+
----
|
|
1037
|
+
|
|
1038
|
+
=== Coordinate Transformations
|
|
1039
|
+
|
|
1040
|
+
All path operations automatically apply the transformation matrix:
|
|
1041
|
+
|
|
1042
|
+
[source,ruby]
|
|
1043
|
+
----
|
|
1044
|
+
gs = Postsvg::GraphicsState.new
|
|
1045
|
+
|
|
1046
|
+
gs.translate(10, 20)
|
|
1047
|
+
gs.scale(2, 2)
|
|
1048
|
+
|
|
1049
|
+
# Coordinates are transformed before being added to path
|
|
1050
|
+
gs.moveto(5, 5) # Becomes (20, 30) after transforms
|
|
1051
|
+
----
|
|
1052
|
+
|
|
1053
|
+
## Thread Safety
|
|
1054
|
+
|
|
1055
|
+
The `GraphicsState` class is **not thread-safe**. Each thread should have its own instance.
|
|
1056
|
+
|
|
1057
|
+
== Next Steps
|
|
1058
|
+
|
|
1059
|
+
* Review link:execution-context.adoc[ExecutionContext] for current state management
|
|
1060
|
+
* Learn about link:interpreter.adoc[Interpreter Class] for execution flow
|
|
1061
|
+
* See link:../architecture.adoc[Architecture] for system design
|
|
1062
|
+
* Check link:converter.adoc[Converter Class] for high-level API
|
|
1063
|
+
|
|
1064
|
+
== Bibliography
|
|
1065
|
+
|
|
1066
|
+
* link:execution-context.adoc[ExecutionContext Documentation]
|
|
1067
|
+
* link:interpreter.adoc[Interpreter Class Documentation]
|
|
1068
|
+
* link:converter.adoc[Converter Class Documentation]
|
|
1069
|
+
* link:../architecture.adoc[Architecture Overview]
|
|
1070
|
+
* link:https://www.adobe.com/jp/print/postscript/pdfs/PLRM.pdf[PostScript Language Reference Manual]
|