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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +49 -533
  3. data/Gemfile +1 -1
  4. data/lib/postsvg/cli.rb +5 -10
  5. data/lib/postsvg/color.rb +132 -0
  6. data/lib/postsvg/format_number.rb +22 -0
  7. data/lib/postsvg/graphics_context.rb +1 -2
  8. data/lib/postsvg/matrix.rb +106 -0
  9. data/lib/postsvg/model/literals/array.rb +41 -0
  10. data/lib/postsvg/model/literals/dictionary.rb +34 -0
  11. data/lib/postsvg/model/literals/hex.rb +37 -0
  12. data/lib/postsvg/model/literals/name.rb +40 -0
  13. data/lib/postsvg/model/literals/number.rb +36 -0
  14. data/lib/postsvg/model/literals/procedure.rb +41 -0
  15. data/lib/postsvg/model/literals/string.rb +30 -0
  16. data/lib/postsvg/model/literals.rb +19 -0
  17. data/lib/postsvg/model/operator.rb +58 -0
  18. data/lib/postsvg/model/operators/arithmetic.rb +264 -0
  19. data/lib/postsvg/model/operators/boolean.rb +182 -0
  20. data/lib/postsvg/model/operators/color.rb +74 -0
  21. data/lib/postsvg/model/operators/container.rb +186 -0
  22. data/lib/postsvg/model/operators/control_flow.rb +119 -0
  23. data/lib/postsvg/model/operators/device.rb +21 -0
  24. data/lib/postsvg/model/operators/dictionary.rb +118 -0
  25. data/lib/postsvg/model/operators/font.rb +121 -0
  26. data/lib/postsvg/model/operators/graphics_state.rb +84 -0
  27. data/lib/postsvg/model/operators/painting.rb +29 -0
  28. data/lib/postsvg/model/operators/path.rb +169 -0
  29. data/lib/postsvg/model/operators/stack.rb +72 -0
  30. data/lib/postsvg/model/operators/transformations.rb +103 -0
  31. data/lib/postsvg/model/operators.rb +89 -0
  32. data/lib/postsvg/model/program.rb +68 -0
  33. data/lib/postsvg/model/token.rb +43 -0
  34. data/lib/postsvg/model.rb +17 -0
  35. data/lib/postsvg/options.rb +1 -1
  36. data/lib/postsvg/parser/postscript_parser.rb +7 -7
  37. data/lib/postsvg/renderer.rb +3 -7
  38. data/lib/postsvg/serializer.rb +325 -0
  39. data/lib/postsvg/source/ast_builder.rb +308 -0
  40. data/lib/postsvg/source/lexer.rb +322 -0
  41. data/lib/postsvg/source/operand_stack.rb +55 -0
  42. data/lib/postsvg/source.rb +21 -0
  43. data/lib/postsvg/svg/clip_path_registry.rb +1 -3
  44. data/lib/postsvg/svg/element.rb +1 -3
  45. data/lib/postsvg/svg/elements/ellipse.rb +1 -2
  46. data/lib/postsvg/svg/elements/svg.rb +1 -2
  47. data/lib/postsvg/svg/paint.rb +1 -1
  48. data/lib/postsvg/svg/path_data/parser.rb +6 -10
  49. data/lib/postsvg/svg/stroke.rb +2 -4
  50. data/lib/postsvg/svg/transform_list.rb +1 -1
  51. data/lib/postsvg/svg_builder.rb +11 -15
  52. data/lib/postsvg/translation/arc_converter.rb +12 -22
  53. data/lib/postsvg/translation/bounding_box.rb +4 -7
  54. data/lib/postsvg/translation/handlers/circle_handler.rb +2 -2
  55. data/lib/postsvg/translation/handlers/ellipse_handler.rb +3 -8
  56. data/lib/postsvg/translation/handlers/group_handler.rb +1 -2
  57. data/lib/postsvg/translation/handlers/image_handler.rb +2 -3
  58. data/lib/postsvg/translation/handlers/line_handler.rb +2 -6
  59. data/lib/postsvg/translation/handlers/open_handler.rb +2 -3
  60. data/lib/postsvg/translation/handlers/path_handler.rb +41 -57
  61. data/lib/postsvg/translation/handlers/polygon_handler.rb +2 -4
  62. data/lib/postsvg/translation/handlers/polyline_handler.rb +2 -4
  63. data/lib/postsvg/translation/handlers/rect_handler.rb +5 -10
  64. data/lib/postsvg/translation/handlers/shared.rb +11 -11
  65. data/lib/postsvg/translation/handlers/svg_handler.rb +2 -3
  66. data/lib/postsvg/translation/handlers/text_handler.rb +7 -8
  67. data/lib/postsvg/translation/handlers.rb +1 -2
  68. data/lib/postsvg/translation/ps_renderer.rb +1 -2
  69. data/lib/postsvg/version.rb +1 -1
  70. data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +6 -6
  71. data/lib/postsvg/visitors/ps_visitor/color.rb +5 -8
  72. data/lib/postsvg/visitors/ps_visitor/common.rb +2 -1
  73. data/lib/postsvg/visitors/ps_visitor/container.rb +13 -13
  74. data/lib/postsvg/visitors/ps_visitor/control_flow.rb +3 -3
  75. data/lib/postsvg/visitors/ps_visitor/dictionary.rb +4 -8
  76. data/lib/postsvg/visitors/ps_visitor/font.rb +4 -14
  77. data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +4 -4
  78. data/lib/postsvg/visitors/ps_visitor/painting.rb +1 -1
  79. data/lib/postsvg/visitors/ps_visitor/path.rb +4 -9
  80. data/lib/postsvg.rb +37 -42
  81. metadata +36 -16
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module ControlFlow
7
+ class If < Operator
8
+ register_as "if"
9
+ attr_reader :condition, :body
10
+ def initialize(condition:, body:)
11
+ @condition = condition
12
+ @body = body
13
+ freeze
14
+ end
15
+ def self.from_operands(stack)
16
+ body = stack.pop
17
+ condition = stack.pop
18
+ new(condition: condition, body: body)
19
+ end
20
+ end
21
+
22
+ class Ifelse < Operator
23
+ register_as "ifelse"
24
+ attr_reader :condition, :if_body, :else_body
25
+ def initialize(condition:, if_body:, else_body:)
26
+ @condition = condition
27
+ @if_body = if_body
28
+ @else_body = else_body
29
+ freeze
30
+ end
31
+ def self.from_operands(stack)
32
+ else_body = stack.pop
33
+ if_body = stack.pop
34
+ condition = stack.pop
35
+ new(condition: condition, if_body: if_body, else_body: else_body)
36
+ end
37
+ end
38
+
39
+ class Repeat < Operator
40
+ register_as "repeat"
41
+ attr_reader :count, :body
42
+ def initialize(count:, body:)
43
+ @count = count
44
+ @body = body
45
+ freeze
46
+ end
47
+ def self.from_operands(stack)
48
+ body = stack.pop
49
+ count = stack.pop_number.to_i
50
+ new(count: count, body: body)
51
+ end
52
+ end
53
+
54
+ class Loop < Operator
55
+ register_as "loop"
56
+ attr_reader :body
57
+ def initialize(body:)
58
+ @body = body
59
+ freeze
60
+ end
61
+ def self.from_operands(stack)
62
+ new(body: stack.pop)
63
+ end
64
+ end
65
+
66
+ class For < Operator
67
+ register_as "for"
68
+ attr_reader :initial, :increment, :limit, :body
69
+ def initialize(initial:, increment:, limit:, body:)
70
+ @initial = initial
71
+ @increment = increment
72
+ @limit = limit
73
+ @body = body
74
+ freeze
75
+ end
76
+ def self.from_operands(stack)
77
+ body = stack.pop
78
+ limit = stack.pop_number
79
+ increment = stack.pop_number
80
+ initial = stack.pop_number
81
+ new(initial: initial, increment: increment, limit: limit, body: body)
82
+ end
83
+ end
84
+
85
+ class Exit < Operator
86
+ register_as "exit"
87
+ end
88
+
89
+ class Quit < Operator
90
+ register_as "quit"
91
+ end
92
+
93
+ class Exec < Operator
94
+ register_as "exec"
95
+ attr_reader :operand
96
+ def initialize(operand:)
97
+ @operand = operand
98
+ freeze
99
+ end
100
+ def self.from_operands(stack)
101
+ new(operand: stack.pop)
102
+ end
103
+ end
104
+
105
+ class Stopped < Operator
106
+ register_as "stopped"
107
+ attr_reader :body
108
+ def initialize(body:)
109
+ @body = body
110
+ freeze
111
+ end
112
+ def self.from_operands(stack)
113
+ new(body: stack.pop)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Device
7
+ class Showpage < Operator
8
+ register_as "showpage"
9
+ end
10
+
11
+ class Copypage < Operator
12
+ register_as "copypage"
13
+ end
14
+
15
+ class Nulldevice < Operator
16
+ register_as "nulldevice"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ # Dictionary-specific operators. Note that +get+, +put+,
7
+ # +length+, +getinterval+, +putinterval+ live in the +Container+
8
+ # module because they dispatch on operand type (string, array,
9
+ # or dictionary) at runtime.
10
+ module Dictionary
11
+ class Dict < Operator
12
+ register_as "dict", consumes: 1, produces: 1
13
+ def self.from_operands(stack)
14
+ stack.pop
15
+ new
16
+ end
17
+ end
18
+
19
+ class Begin < Operator
20
+ register_as "begin", consumes: 1, produces: 0
21
+ def self.from_operands(stack)
22
+ stack.pop
23
+ new
24
+ end
25
+ end
26
+
27
+ class End < Operator
28
+ register_as "end", consumes: 0, produces: 0
29
+ end
30
+
31
+ class Def < Operator
32
+ register_as "def", consumes: 2, produces: 0
33
+ attr_reader :key, :value
34
+ def initialize(key:, value:)
35
+ @key = key
36
+ @value = value
37
+ freeze
38
+ end
39
+ def self.from_operands(stack)
40
+ value = stack.pop
41
+ key = stack.pop
42
+ new(key: key, value: value)
43
+ end
44
+ end
45
+
46
+ class Load < Operator
47
+ register_as "load", consumes: 1, produces: 1
48
+ attr_reader :key
49
+ def initialize(key:)
50
+ @key = key
51
+ freeze
52
+ end
53
+ def self.from_operands(stack)
54
+ new(key: stack.pop)
55
+ end
56
+ end
57
+
58
+ class Store < Operator
59
+ register_as "store", consumes: 2, produces: 0
60
+ attr_reader :key, :value
61
+ def initialize(key:, value:)
62
+ @key = key
63
+ @value = value
64
+ freeze
65
+ end
66
+ def self.from_operands(stack)
67
+ value = stack.pop
68
+ key = stack.pop
69
+ new(key: key, value: value)
70
+ end
71
+ end
72
+
73
+ class Known < Operator
74
+ register_as "known", consumes: 2, produces: 1
75
+ def self.from_operands(stack)
76
+ key = stack.pop
77
+ dict = stack.pop
78
+ new(key: key, dict: dict)
79
+ end
80
+ attr_reader :key, :dict
81
+ def initialize(key:, dict:)
82
+ @key = key
83
+ @dict = dict
84
+ freeze
85
+ end
86
+ end
87
+
88
+ class Currentdict < Operator
89
+ register_as "currentdict", consumes: 0, produces: 1
90
+ end
91
+
92
+ class Countdictstack < Operator
93
+ register_as "countdictstack", consumes: 0, produces: 1
94
+ end
95
+
96
+ class Dictstack < Operator
97
+ register_as "dictstack", consumes: 1, produces: 1
98
+ def self.from_operands(stack)
99
+ stack.pop
100
+ new
101
+ end
102
+ end
103
+
104
+ class Maxlength < Operator
105
+ register_as "maxlength", consumes: 1, produces: 1
106
+ def self.from_operands(stack)
107
+ new(operand: stack.pop)
108
+ end
109
+ attr_reader :operand
110
+ def initialize(operand:)
111
+ @operand = operand
112
+ freeze
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ # Font and text operators. These cover the subset of PLRM §5
7
+ # needed to round-trip basic SVG `<text>` content; richer
8
+ # font metrics (kerning, ligatures, glyph substitution) are
9
+ # tracked in TODO.roadmap/20-font-and-text.md.
10
+ module Font
11
+ # Pushes a font dictionary onto the stack by name. +name+ is
12
+ # the PostScript font name (e.g. "Helvetica"). The visitor
13
+ # pushes a Font value object.
14
+ class Findfont < Operator
15
+ register_as "findfont", consumes: 1, produces: 1
16
+ attr_reader :name
17
+ def initialize(name:)
18
+ @name = name
19
+ freeze
20
+ end
21
+ def self.from_operands(stack)
22
+ new(name: stack.pop)
23
+ end
24
+ end
25
+
26
+ # Returns a new font dictionary scaled to the given size.
27
+ class Scalefont < Operator
28
+ register_as "scalefont", consumes: 2, produces: 1
29
+ attr_reader :font, :size
30
+ def initialize(font:, size:)
31
+ @font = font
32
+ @size = size
33
+ freeze
34
+ end
35
+ def self.from_operands(stack)
36
+ size = stack.pop_number
37
+ font = stack.pop
38
+ new(font: font, size: size)
39
+ end
40
+ end
41
+
42
+ # Installs the font dictionary as the current font.
43
+ class Setfont < Operator
44
+ register_as "setfont", consumes: 1, produces: 0
45
+ attr_reader :font
46
+ def initialize(font:)
47
+ @font = font
48
+ freeze
49
+ end
50
+ def self.from_operands(stack)
51
+ new(font: stack.pop)
52
+ end
53
+ end
54
+
55
+ # Renders +text+ at the current point using the current font.
56
+ class Show < Operator
57
+ register_as "show", consumes: 1, produces: 0
58
+ attr_reader :text
59
+ def initialize(text:)
60
+ @text = text
61
+ freeze
62
+ end
63
+ def self.from_operands(stack)
64
+ new(text: stack.pop)
65
+ end
66
+ end
67
+
68
+ # Moves to (x, y) and renders +text+ (PLRM §5.5 xyshow
69
+ # variant not implemented here).
70
+ class Xyshow < Operator
71
+ register_as "xyshow"
72
+ attr_reader :text, :dx, :dy
73
+ def initialize(text:, dx:, dy:)
74
+ @text = text
75
+ @dx = dx
76
+ @dy = dy
77
+ freeze
78
+ end
79
+ def self.from_operands(stack)
80
+ dy = stack.pop
81
+ dx = stack.pop
82
+ text = stack.pop
83
+ new(text: text, dx: dx, dy: dy)
84
+ end
85
+ end
86
+
87
+ # Returns the width of +text+ under the current font (in
88
+ # thousandths of a unit, divided by 1000). The visitor
89
+ # pushes [x, y] onto the stack.
90
+ class Stringwidth < Operator
91
+ register_as "stringwidth"
92
+ attr_reader :text
93
+ def initialize(text:)
94
+ @text = text
95
+ freeze
96
+ end
97
+ def self.from_operands(stack)
98
+ new(text: stack.pop)
99
+ end
100
+ end
101
+
102
+ # Appends glyph outlines for +text+ to the current path
103
+ # (PLRM charpath).
104
+ class Charpath < Operator
105
+ register_as "charpath"
106
+ attr_reader :text, :stroke
107
+ def initialize(text:, stroke:)
108
+ @text = text
109
+ @stroke = stroke
110
+ freeze
111
+ end
112
+ def self.from_operands(stack)
113
+ stroke = stack.pop
114
+ text = stack.pop
115
+ new(text: text, stroke: stroke)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module GraphicsState
7
+ class Gsave < Operator
8
+ register_as "gsave"
9
+ end
10
+
11
+ class Grestore < Operator
12
+ register_as "grestore"
13
+ end
14
+
15
+ class Grestoreall < Operator
16
+ register_as "grestoreall"
17
+ end
18
+
19
+ class Setlinewidth < Operator
20
+ register_as "setlinewidth"
21
+ attr_reader :width
22
+ def initialize(width:)
23
+ @width = width
24
+ freeze
25
+ end
26
+ def self.from_operands(stack)
27
+ new(width: stack.pop_number)
28
+ end
29
+ end
30
+
31
+ class Setlinecap < Operator
32
+ register_as "setlinecap"
33
+ attr_reader :cap_code
34
+ def initialize(cap_code:)
35
+ @cap_code = cap_code.to_i
36
+ freeze
37
+ end
38
+ def self.from_operands(stack)
39
+ new(cap_code: stack.pop_number.to_i)
40
+ end
41
+ end
42
+
43
+ class Setlinejoin < Operator
44
+ register_as "setlinejoin"
45
+ attr_reader :join_code
46
+ def initialize(join_code:)
47
+ @join_code = join_code.to_i
48
+ freeze
49
+ end
50
+ def self.from_operands(stack)
51
+ new(join_code: stack.pop_number.to_i)
52
+ end
53
+ end
54
+
55
+ class Setmiterlimit < Operator
56
+ register_as "setmiterlimit"
57
+ attr_reader :limit
58
+ def initialize(limit:)
59
+ @limit = limit
60
+ freeze
61
+ end
62
+ def self.from_operands(stack)
63
+ new(limit: stack.pop_number)
64
+ end
65
+ end
66
+
67
+ class Setdash < Operator
68
+ register_as "setdash"
69
+ attr_reader :pattern, :offset
70
+ def initialize(pattern:, offset:)
71
+ @pattern = pattern
72
+ @offset = offset
73
+ freeze
74
+ end
75
+ def self.from_operands(stack)
76
+ offset = stack.pop_number
77
+ pattern = stack.pop
78
+ new(pattern: pattern, offset: offset)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Painting
7
+ class Stroke < Operator
8
+ register_as "stroke", consumes: 0, produces: 0
9
+ end
10
+
11
+ class Fill < Operator
12
+ register_as "fill", consumes: 0, produces: 0
13
+ end
14
+
15
+ class Eofill < Operator
16
+ register_as "eofill", consumes: 0, produces: 0
17
+ end
18
+
19
+ class Clip < Operator
20
+ register_as "clip", consumes: 0, produces: 0
21
+ end
22
+
23
+ class Eoclip < Operator
24
+ register_as "eoclip", consumes: 0, produces: 0
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postsvg
4
+ module Model
5
+ module Operators
6
+ module Path
7
+ class Newpath < Operator
8
+ register_as "newpath"
9
+ end
10
+
11
+ class Moveto < Operator
12
+ register_as "moveto"
13
+ attr_reader :x, :y
14
+ def initialize(x:, y:)
15
+ @x = x
16
+ @y = y
17
+ freeze
18
+ end
19
+ def self.from_operands(stack)
20
+ y = stack.pop_number
21
+ x = stack.pop_number
22
+ new(x: x, y: y)
23
+ end
24
+ end
25
+
26
+ class Rmoveto < Operator
27
+ register_as "rmoveto"
28
+ attr_reader :dx, :dy
29
+ def initialize(dx:, dy:)
30
+ @dx = dx
31
+ @dy = dy
32
+ freeze
33
+ end
34
+ def self.from_operands(stack)
35
+ dy = stack.pop_number
36
+ dx = stack.pop_number
37
+ new(dx: dx, dy: dy)
38
+ end
39
+ end
40
+
41
+ class Lineto < Operator
42
+ register_as "lineto"
43
+ attr_reader :x, :y
44
+ def initialize(x:, y:)
45
+ @x = x
46
+ @y = y
47
+ freeze
48
+ end
49
+ def self.from_operands(stack)
50
+ y = stack.pop_number
51
+ x = stack.pop_number
52
+ new(x: x, y: y)
53
+ end
54
+ end
55
+
56
+ class Rlineto < Operator
57
+ register_as "rlineto"
58
+ attr_reader :dx, :dy
59
+ def initialize(dx:, dy:)
60
+ @dx = dx
61
+ @dy = dy
62
+ freeze
63
+ end
64
+ def self.from_operands(stack)
65
+ dy = stack.pop_number
66
+ dx = stack.pop_number
67
+ new(dx: dx, dy: dy)
68
+ end
69
+ end
70
+
71
+ class Curveto < Operator
72
+ register_as "curveto"
73
+ attr_reader :x1, :y1, :x2, :y2, :x3, :y3
74
+ def initialize(x1:, y1:, x2:, y2:, x3:, y3:)
75
+ @x1 = x1
76
+ @y1 = y1
77
+ @x2 = x2
78
+ @y2 = y2
79
+ @x3 = x3
80
+ @y3 = y3
81
+ freeze
82
+ end
83
+ def self.from_operands(stack)
84
+ y3 = stack.pop_number
85
+ x3 = stack.pop_number
86
+ y2 = stack.pop_number
87
+ x2 = stack.pop_number
88
+ y1 = stack.pop_number
89
+ x1 = stack.pop_number
90
+ new(x1: x1, y1: y1, x2: x2, y2: y2, x3: x3, y3: y3)
91
+ end
92
+ end
93
+
94
+ class Rcurveto < Operator
95
+ register_as "rcurveto"
96
+ attr_reader :dx1, :dy1, :dx2, :dy2, :dx3, :dy3
97
+ def initialize(dx1:, dy1:, dx2:, dy2:, dx3:, dy3:)
98
+ @dx1 = dx1
99
+ @dy1 = dy1
100
+ @dx2 = dx2
101
+ @dy2 = dy2
102
+ @dx3 = dx3
103
+ @dy3 = dy3
104
+ freeze
105
+ end
106
+ def self.from_operands(stack)
107
+ dy3 = stack.pop_number
108
+ dx3 = stack.pop_number
109
+ dy2 = stack.pop_number
110
+ dx2 = stack.pop_number
111
+ dy1 = stack.pop_number
112
+ dx1 = stack.pop_number
113
+ new(dx1: dx1, dy1: dy1, dx2: dx2, dy2: dy2, dx3: dx3, dy3: dy3)
114
+ end
115
+ end
116
+
117
+ class Arc < Operator
118
+ register_as "arc"
119
+ attr_reader :x, :y, :radius, :angle1, :angle2
120
+ def initialize(x:, y:, radius:, angle1:, angle2:)
121
+ @x = x
122
+ @y = y
123
+ @radius = radius
124
+ @angle1 = angle1
125
+ @angle2 = angle2
126
+ freeze
127
+ end
128
+ def self.from_operands(stack)
129
+ angle2 = stack.pop_number
130
+ angle1 = stack.pop_number
131
+ radius = stack.pop_number
132
+ y = stack.pop_number
133
+ x = stack.pop_number
134
+ new(x: x, y: y, radius: radius, angle1: angle1, angle2: angle2)
135
+ end
136
+ end
137
+
138
+ class Arcn < Operator
139
+ register_as "arcn"
140
+ attr_reader :x, :y, :radius, :angle1, :angle2
141
+ def initialize(x:, y:, radius:, angle1:, angle2:)
142
+ @x = x
143
+ @y = y
144
+ @radius = radius
145
+ @angle1 = angle1
146
+ @angle2 = angle2
147
+ freeze
148
+ end
149
+ def self.from_operands(stack)
150
+ angle2 = stack.pop_number
151
+ angle1 = stack.pop_number
152
+ radius = stack.pop_number
153
+ y = stack.pop_number
154
+ x = stack.pop_number
155
+ new(x: x, y: y, radius: radius, angle1: angle1, angle2: angle2)
156
+ end
157
+ end
158
+
159
+ class Closepath < Operator
160
+ register_as "closepath"
161
+ end
162
+
163
+ class Currentpoint < Operator
164
+ register_as "currentpoint"
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end