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
|
@@ -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
|