postsvg 0.2.2 → 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/.rubocop_todo.yml +49 -533
- data/Gemfile +1 -1
- data/lib/postsvg/cli.rb +5 -10
- data/lib/postsvg/color.rb +132 -0
- data/lib/postsvg/format_number.rb +22 -0
- data/lib/postsvg/graphics_context.rb +1 -2
- data/lib/postsvg/matrix.rb +106 -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 +1 -1
- data/lib/postsvg/parser/postscript_parser.rb +7 -7
- data/lib/postsvg/renderer.rb +3 -7
- 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/clip_path_registry.rb +1 -3
- data/lib/postsvg/svg/element.rb +1 -3
- data/lib/postsvg/svg/elements/ellipse.rb +1 -2
- data/lib/postsvg/svg/elements/svg.rb +1 -2
- data/lib/postsvg/svg/paint.rb +1 -1
- data/lib/postsvg/svg/path_data/parser.rb +6 -10
- data/lib/postsvg/svg/stroke.rb +2 -4
- data/lib/postsvg/svg/transform_list.rb +1 -1
- data/lib/postsvg/svg_builder.rb +11 -15
- data/lib/postsvg/translation/arc_converter.rb +12 -22
- data/lib/postsvg/translation/bounding_box.rb +4 -7
- data/lib/postsvg/translation/handlers/circle_handler.rb +2 -2
- data/lib/postsvg/translation/handlers/ellipse_handler.rb +3 -8
- data/lib/postsvg/translation/handlers/group_handler.rb +1 -2
- data/lib/postsvg/translation/handlers/image_handler.rb +2 -3
- data/lib/postsvg/translation/handlers/line_handler.rb +2 -6
- data/lib/postsvg/translation/handlers/open_handler.rb +2 -3
- data/lib/postsvg/translation/handlers/path_handler.rb +41 -57
- data/lib/postsvg/translation/handlers/polygon_handler.rb +2 -4
- data/lib/postsvg/translation/handlers/polyline_handler.rb +2 -4
- data/lib/postsvg/translation/handlers/rect_handler.rb +5 -10
- data/lib/postsvg/translation/handlers/shared.rb +11 -11
- data/lib/postsvg/translation/handlers/svg_handler.rb +2 -3
- data/lib/postsvg/translation/handlers/text_handler.rb +7 -8
- data/lib/postsvg/translation/handlers.rb +1 -2
- data/lib/postsvg/translation/ps_renderer.rb +1 -2
- data/lib/postsvg/version.rb +1 -1
- data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +6 -6
- data/lib/postsvg/visitors/ps_visitor/color.rb +5 -8
- data/lib/postsvg/visitors/ps_visitor/common.rb +2 -1
- data/lib/postsvg/visitors/ps_visitor/container.rb +13 -13
- data/lib/postsvg/visitors/ps_visitor/control_flow.rb +3 -3
- data/lib/postsvg/visitors/ps_visitor/dictionary.rb +4 -8
- data/lib/postsvg/visitors/ps_visitor/font.rb +4 -14
- data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +4 -4
- data/lib/postsvg/visitors/ps_visitor/painting.rb +1 -1
- data/lib/postsvg/visitors/ps_visitor/path.rb +4 -9
- data/lib/postsvg.rb +37 -42
- metadata +36 -16
|
@@ -72,14 +72,10 @@ module Postsvg
|
|
|
72
72
|
|
|
73
73
|
def visit_maxlength(op, _ctx)
|
|
74
74
|
# PS dictionaries can grow dynamically; report current size.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
case operand
|
|
80
|
-
when Hash then operand.length
|
|
81
|
-
when Model::Literals::Dictionary then operand.entries.length
|
|
82
|
-
else 0
|
|
75
|
+
case op.operand
|
|
76
|
+
when Hash then @stack << op.operand.length
|
|
77
|
+
when Model::Literals::Dictionary then @stack << op.operand.entries.length
|
|
78
|
+
else @stack << 0
|
|
83
79
|
end
|
|
84
80
|
end
|
|
85
81
|
|
|
@@ -31,25 +31,15 @@ module Postsvg
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def visit_scalefont(op, _ctx)
|
|
34
|
-
size = op.size.to_i
|
|
34
|
+
size = op.size.to_i || op.size.to_f
|
|
35
35
|
font = @stack.pop
|
|
36
|
-
base =
|
|
37
|
-
font
|
|
38
|
-
else
|
|
39
|
-
FontRef.new(name: "Helvetica",
|
|
40
|
-
size: nil)
|
|
41
|
-
end
|
|
36
|
+
base = font.is_a?(FontRef) ? font : FontRef.new(name: "Helvetica", size: nil)
|
|
42
37
|
@stack << FontRef.new(name: base.name, size: size.to_f)
|
|
43
38
|
end
|
|
44
39
|
|
|
45
40
|
def visit_setfont(_op, _ctx)
|
|
46
41
|
font = @stack.pop
|
|
47
|
-
ref =
|
|
48
|
-
font
|
|
49
|
-
else
|
|
50
|
-
FontRef.new(name: "Helvetica",
|
|
51
|
-
size: 12.0)
|
|
52
|
-
end
|
|
42
|
+
ref = font.is_a?(FontRef) ? font : FontRef.new(name: "Helvetica", size: 12.0)
|
|
53
43
|
@graphics.update(font_name: ref.name || "Helvetica",
|
|
54
44
|
font_size: ref.size || 12.0)
|
|
55
45
|
end
|
|
@@ -77,7 +67,7 @@ module Postsvg
|
|
|
77
67
|
y: -screen_pos[:y],
|
|
78
68
|
font_family: @graphics.current.font_name,
|
|
79
69
|
font_size: @graphics.current.font_size,
|
|
80
|
-
color: color ||
|
|
70
|
+
color: color || Postsvg::Color::BLACK,
|
|
81
71
|
transform: "scale(1 -1)",
|
|
82
72
|
)
|
|
83
73
|
@path.reset
|
|
@@ -23,14 +23,12 @@ module Postsvg
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def visit_setlinecap(op, _ctx)
|
|
26
|
-
name = { 0 => :butt, 1 => :round, 2 => :square }.fetch(op.cap_code,
|
|
27
|
-
:butt)
|
|
26
|
+
name = { 0 => :butt, 1 => :round, 2 => :square }.fetch(op.cap_code, :butt)
|
|
28
27
|
@graphics.update(line_cap: name)
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def visit_setlinejoin(op, _ctx)
|
|
32
|
-
name = { 0 => :miter, 1 => :round, 2 => :bevel }.fetch(op.join_code,
|
|
33
|
-
:miter)
|
|
31
|
+
name = { 0 => :miter, 1 => :round, 2 => :bevel }.fetch(op.join_code, :miter)
|
|
34
32
|
@graphics.update(line_join: name)
|
|
35
33
|
end
|
|
36
34
|
|
|
@@ -46,6 +44,8 @@ module Postsvg
|
|
|
46
44
|
pattern.map { |v| FormatNumber.call(v.to_f) }.join(" ")
|
|
47
45
|
when Numeric
|
|
48
46
|
FormatNumber.call(pattern.to_f)
|
|
47
|
+
else
|
|
48
|
+
nil
|
|
49
49
|
end
|
|
50
50
|
@graphics.update(dash: dash_str)
|
|
51
51
|
end
|
|
@@ -23,8 +23,7 @@ module Postsvg
|
|
|
23
23
|
pos = @graphics.current.last_text_position
|
|
24
24
|
base_x = pos ? pos[:x] : 0
|
|
25
25
|
base_y = pos ? pos[:y] : 0
|
|
26
|
-
@graphics.update(last_text_position: { x: base_x + op.dx,
|
|
27
|
-
y: base_y + op.dy })
|
|
26
|
+
@graphics.update(last_text_position: { x: base_x + op.dx, y: base_y + op.dy })
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def visit_lineto(op, _ctx)
|
|
@@ -78,8 +77,8 @@ module Postsvg
|
|
|
78
77
|
|
|
79
78
|
# If the current path is empty, the arc implicitly starts
|
|
80
79
|
# with a moveto to its starting point.
|
|
81
|
-
if
|
|
82
|
-
@path.move_to(start_x, start_y)
|
|
80
|
+
if @path.empty? || last_command_starts_with?("M")
|
|
81
|
+
@path.move_to(start_x, start_y) if @path.empty?
|
|
83
82
|
end
|
|
84
83
|
|
|
85
84
|
delta = (angle2 - angle1) % 360
|
|
@@ -87,11 +86,7 @@ module Postsvg
|
|
|
87
86
|
large_arc = delta > 180
|
|
88
87
|
|
|
89
88
|
# SVG sweep flag is 1 when the arc is drawn clockwise.
|
|
90
|
-
svg_sweep =
|
|
91
|
-
delta.positive? ? 1 : 0
|
|
92
|
-
else
|
|
93
|
-
0
|
|
94
|
-
end
|
|
89
|
+
svg_sweep = sweep ? (delta.positive? ? 1 : 0) : 0
|
|
95
90
|
if delta.abs < 1e-6
|
|
96
91
|
# Full circle: emit two arcs.
|
|
97
92
|
mid_angle = angle1 + 180
|
data/lib/postsvg.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "postscript"
|
|
4
3
|
require "parslet"
|
|
5
4
|
require "thor"
|
|
6
5
|
require "nokogiri"
|
|
@@ -8,61 +7,57 @@ require "nokogiri"
|
|
|
8
7
|
module Postsvg
|
|
9
8
|
autoload :VERSION, "postsvg/version"
|
|
10
9
|
|
|
11
|
-
#
|
|
12
|
-
# Posts created and managed by the +postscript+ gem.
|
|
13
|
-
# ============================================================
|
|
14
|
-
#
|
|
15
|
-
# `postscript` owns PS source parsing, the typed PS domain model,
|
|
16
|
-
# and the PS source serializer. The `Postscript` namespace is the
|
|
17
|
-
# canonical location; the aliases below keep existing user code
|
|
18
|
-
# working during the transition (deprecated, will be removed at
|
|
19
|
-
# postsvg 1.0).
|
|
20
|
-
#
|
|
21
|
-
# If you maintain postsvg, prefer `Postscript::*` in new code.
|
|
22
|
-
|
|
23
|
-
Source = Postscript::Source
|
|
24
|
-
Model = Postscript::Model
|
|
25
|
-
Serializer = Postscript::Serializer
|
|
26
|
-
Matrix = Postscript::Matrix
|
|
27
|
-
Color = Postscript::Color
|
|
28
|
-
FormatNumber = Postscript::FormatNumber
|
|
29
|
-
|
|
30
|
-
ParseError = Postscript::ParseError
|
|
31
|
-
LexError = Postscript::LexError
|
|
32
|
-
SyntaxError = Postscript::SyntaxError
|
|
33
|
-
StackUnderflowError = Postscript::StackUnderflowError
|
|
34
|
-
UndefinedOperatorError = Postscript::UndefinedOperatorError
|
|
35
|
-
RecursionLimitError = Postscript::RecursionLimitError
|
|
36
|
-
RenderError = Postscript::RenderError
|
|
37
|
-
SerializeError = Postscript::SerializeError
|
|
38
|
-
ExitSignal = Postscript::ExitSignal
|
|
39
|
-
QuitSignal = Postscript::QuitSignal
|
|
40
|
-
|
|
41
|
-
# ============================================================
|
|
42
|
-
# Errors that originate in the SVG side (kept here, not in postscript).
|
|
43
|
-
# ============================================================
|
|
10
|
+
# Errors
|
|
44
11
|
autoload :Error, "postsvg/errors"
|
|
12
|
+
autoload :ParseError, "postsvg/errors"
|
|
13
|
+
autoload :LexError, "postsvg/errors"
|
|
14
|
+
autoload :SyntaxError, "postsvg/errors"
|
|
15
|
+
autoload :RenderError, "postsvg/errors"
|
|
16
|
+
autoload :StackUnderflowError, "postsvg/errors"
|
|
17
|
+
autoload :UndefinedOperatorError, "postsvg/errors"
|
|
18
|
+
autoload :RecursionLimitError, "postsvg/errors"
|
|
19
|
+
autoload :SizeLimitError, "postsvg/errors"
|
|
45
20
|
autoload :TranslationError, "postsvg/errors"
|
|
46
21
|
autoload :UnsupportedElementError, "postsvg/errors"
|
|
47
22
|
autoload :UnresolvedReferenceError, "postsvg/errors"
|
|
23
|
+
autoload :SerializeError, "postsvg/errors"
|
|
24
|
+
autoload :ConversionError, "postsvg/errors"
|
|
25
|
+
autoload :UnsupportedOperatorError, "postsvg/errors"
|
|
26
|
+
autoload :ExitSignal, "postsvg/errors"
|
|
27
|
+
autoload :QuitSignal, "postsvg/errors"
|
|
48
28
|
|
|
49
|
-
#
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
29
|
+
# Foundational value types
|
|
30
|
+
autoload :FormatNumber, "postsvg/format_number"
|
|
31
|
+
autoload :Matrix, "postsvg/matrix"
|
|
32
|
+
autoload :Color, "postsvg/color"
|
|
53
33
|
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
34
|
+
# Source-reading layer (PS source -> Model::Program)
|
|
35
|
+
autoload :Source, "postsvg/source"
|
|
36
|
+
|
|
37
|
+
# PS domain model
|
|
38
|
+
autoload :Model, "postsvg/model"
|
|
39
|
+
|
|
40
|
+
# Graphics state
|
|
57
41
|
autoload :GraphicsContext, "postsvg/graphics_context"
|
|
58
42
|
autoload :GraphicsStack, "postsvg/graphics_stack"
|
|
59
43
|
autoload :PathBuilder, "postsvg/path_builder"
|
|
44
|
+
|
|
45
|
+
# SVG emission (forward direction)
|
|
60
46
|
autoload :SvgBuilder, "postsvg/svg_builder"
|
|
47
|
+
|
|
48
|
+
# Forward direction (PS -> SVG)
|
|
61
49
|
autoload :Options, "postsvg/options"
|
|
62
50
|
autoload :Renderer, "postsvg/renderer"
|
|
63
51
|
autoload :Visitors, "postsvg/visitors"
|
|
52
|
+
|
|
53
|
+
# SVG domain model (reverse direction input)
|
|
64
54
|
autoload :Svg, "postsvg/svg"
|
|
55
|
+
|
|
56
|
+
# Reverse direction (SVG -> PS)
|
|
65
57
|
autoload :Translation, "postsvg/translation"
|
|
58
|
+
autoload :Serializer, "postsvg/serializer"
|
|
59
|
+
|
|
60
|
+
# CLI
|
|
66
61
|
autoload :CLI, "postsvg/cli"
|
|
67
62
|
|
|
68
63
|
# Legacy implementations retained on disk for reference. Not on the
|
|
@@ -78,7 +73,7 @@ module Postsvg
|
|
|
78
73
|
class << self
|
|
79
74
|
# PS/EPS source -> SVG string.
|
|
80
75
|
def to_svg(source, **options)
|
|
81
|
-
program =
|
|
76
|
+
program = Source.parse(source)
|
|
82
77
|
Renderer.call(program, Options.new(**options))
|
|
83
78
|
end
|
|
84
79
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: postsvg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -38,20 +38,6 @@ dependencies:
|
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: postscript
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '0.2'
|
|
48
|
-
type: :runtime
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '0.2'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
42
|
name: thor
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -188,19 +174,53 @@ files:
|
|
|
188
174
|
- exe/postsvg
|
|
189
175
|
- lib/postsvg.rb
|
|
190
176
|
- lib/postsvg/cli.rb
|
|
177
|
+
- lib/postsvg/color.rb
|
|
191
178
|
- lib/postsvg/colors.rb
|
|
192
179
|
- lib/postsvg/converter.rb
|
|
193
180
|
- lib/postsvg/errors.rb
|
|
181
|
+
- lib/postsvg/format_number.rb
|
|
194
182
|
- lib/postsvg/graphics_context.rb
|
|
195
183
|
- lib/postsvg/graphics_stack.rb
|
|
196
184
|
- lib/postsvg/graphics_state.rb
|
|
197
185
|
- lib/postsvg/interpreter.rb
|
|
186
|
+
- lib/postsvg/matrix.rb
|
|
187
|
+
- lib/postsvg/model.rb
|
|
188
|
+
- lib/postsvg/model/literals.rb
|
|
189
|
+
- lib/postsvg/model/literals/array.rb
|
|
190
|
+
- lib/postsvg/model/literals/dictionary.rb
|
|
191
|
+
- lib/postsvg/model/literals/hex.rb
|
|
192
|
+
- lib/postsvg/model/literals/name.rb
|
|
193
|
+
- lib/postsvg/model/literals/number.rb
|
|
194
|
+
- lib/postsvg/model/literals/procedure.rb
|
|
195
|
+
- lib/postsvg/model/literals/string.rb
|
|
196
|
+
- lib/postsvg/model/operator.rb
|
|
197
|
+
- lib/postsvg/model/operators.rb
|
|
198
|
+
- lib/postsvg/model/operators/arithmetic.rb
|
|
199
|
+
- lib/postsvg/model/operators/boolean.rb
|
|
200
|
+
- lib/postsvg/model/operators/color.rb
|
|
201
|
+
- lib/postsvg/model/operators/container.rb
|
|
202
|
+
- lib/postsvg/model/operators/control_flow.rb
|
|
203
|
+
- lib/postsvg/model/operators/device.rb
|
|
204
|
+
- lib/postsvg/model/operators/dictionary.rb
|
|
205
|
+
- lib/postsvg/model/operators/font.rb
|
|
206
|
+
- lib/postsvg/model/operators/graphics_state.rb
|
|
207
|
+
- lib/postsvg/model/operators/painting.rb
|
|
208
|
+
- lib/postsvg/model/operators/path.rb
|
|
209
|
+
- lib/postsvg/model/operators/stack.rb
|
|
210
|
+
- lib/postsvg/model/operators/transformations.rb
|
|
211
|
+
- lib/postsvg/model/program.rb
|
|
212
|
+
- lib/postsvg/model/token.rb
|
|
198
213
|
- lib/postsvg/options.rb
|
|
199
214
|
- lib/postsvg/parser.rb
|
|
200
215
|
- lib/postsvg/parser/postscript_parser.rb
|
|
201
216
|
- lib/postsvg/parser/transform.rb
|
|
202
217
|
- lib/postsvg/path_builder.rb
|
|
203
218
|
- lib/postsvg/renderer.rb
|
|
219
|
+
- lib/postsvg/serializer.rb
|
|
220
|
+
- lib/postsvg/source.rb
|
|
221
|
+
- lib/postsvg/source/ast_builder.rb
|
|
222
|
+
- lib/postsvg/source/lexer.rb
|
|
223
|
+
- lib/postsvg/source/operand_stack.rb
|
|
204
224
|
- lib/postsvg/svg.rb
|
|
205
225
|
- lib/postsvg/svg/attribute_parser.rb
|
|
206
226
|
- lib/postsvg/svg/clip_path_registry.rb
|