rsyntaxtree 1.0.8 → 1.1.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.
@@ -1,264 +1,260 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
3
-
4
- #==========================
5
- # graph.rb
6
- #==========================
7
- #
8
- # Image utility functions to inspect text font metrics
9
- # Copyright (c) 2007-2021 Yoichiro Hasebe <yohasebe@gmail.com>
10
-
11
- require 'utils'
12
-
13
- module RSyntaxTree
14
- class BaseGraph
15
-
16
- def initialize(element_list, params)
17
-
18
- @element_list = element_list
19
- @symmetrize = params[:symmetrize]
20
-
21
- if params[:color]
22
- @col_node = "blue"
23
- @col_leaf = "green"
24
- @col_path = "purple"
25
- else
26
- @col_node = "black"
27
- @col_leaf = "black"
28
- @col_path = "black"
29
- end
30
-
31
- @col_bg = "none"
32
- @col_fg = "black"
33
- @col_line = "black"
34
-
35
- @leafstyle = params[:leafstyle]
36
- @fontset = params[:fontset]
37
- @fontsize = params[:fontsize]
38
- end
39
-
40
- def calculate_level
41
- @element_list.get_elements.select{|e| e.type == 2}.each do |e|
42
- e.level = @element_list.get_id(e.parent).level + 1
43
- end
44
- end
45
-
46
- def calculate_width(id = 1)
47
- target = @element_list.get_id(id)
48
- if target.children.empty?
49
- target.width = target.content_width + $h_gap_between_nodes * 4
50
-
51
- parent = @element_list.get_id(target.parent)
52
- while parent && parent.children.size == 1
53
- w = parent.content_width
54
- target.width = w + $h_gap_between_nodes * 4 if w > target.content_width
55
- parent = @element_list.get_id(parent.parent)
56
- end
57
- return target.width
58
- else
59
- if target.width != 0
60
- return target.width
61
- else
62
- accum_array = []
63
- target.children.each do |c|
64
- accum_array << calculate_width(c)
65
- end
66
- if @symmetrize
67
- accum_width = accum_array.max * target.children.size
68
- else
69
- accum_width = accum_array.sum
70
- end
71
-
72
- target.width = [accum_width, target.content_width].max
73
- end
74
-
75
- return target.width
76
- end
77
- end
78
-
79
- def calculate_height(id = 1)
80
- target = @element_list.get_id(id)
81
- if id == 1
82
- target.vertical_indent = 0
83
- else
84
- parent = @element_list.get_id(target.parent)
85
-
86
- if !target.triangle && @leafstyle == "nothing" && ETYPE_LEAF == target.type && parent.children.size == 1
87
- vertical_indent = parent.vertical_indent + parent.content_height
88
- else
89
- vertical_indent = parent.vertical_indent + parent.content_height + $height_connector
90
- end
91
-
92
- target.vertical_indent = vertical_indent
93
- end
94
-
95
- if target.children.empty?
96
- target.height = target.content_height
97
- vertical_end = target.vertical_indent + target.content_height
98
- else
99
- accum_array = []
100
- target.children.each do |c|
101
- accum_array << calculate_height(c)
102
- end
103
- target.height = accum_array.max - target.vertical_indent
104
- vertical_end = accum_array.max
105
- end
106
- return vertical_end
107
- end
108
-
109
- def make_balance(id = 1)
110
- target = @element_list.get_id(id)
111
- if target.children.empty?
112
- parent = @element_list.get_id(target.parent)
113
- accum_array = []
114
- parent.children.each do |c|
115
- accum_array << @element_list.get_id(c).width
116
- end
117
- max = accum_array.max
118
- parent.children.each do |c|
119
- @element_list.get_id(c).width = max
120
- end
121
- return max
122
- else
123
- accum_array = []
124
- target.children.each do |c|
125
- accum_array << make_balance(c)
126
- end
127
- accum_width = accum_array.max
128
- max = [accum_width, target.content_width].max
129
- target.children.each do |c|
130
- @element_list.get_id(c).width = max
131
- end
132
- return target.width
133
- end
134
- end
135
-
136
- def calculate_indent
137
- node_groups = @element_list.get_elements.group_by {|e| e.parent}
138
- node_groups.each do |k, v|
139
- next if k == 0
140
- parent = @element_list.get_id(k)
141
- if @symmetrize
142
- num_leaves = v.size
143
- partition_width = parent.width / num_leaves
144
- left_offset = parent.horizontal_indent + parent.content_width / 2.0 - parent.width / 2.0
145
- v.each do |e|
146
- indent = left_offset + (partition_width - e.content_width) / 2.0
147
- e.horizontal_indent = indent
148
- left_offset += partition_width
149
- end
150
- else
151
- left_offset = parent.horizontal_indent + parent.content_width / 2.0 - parent.width / 2.0
152
- v.each do |e|
153
- indent = left_offset + (e.width - e.content_width) / 2.0
154
- e.horizontal_indent = indent
155
- left_offset += e.width
156
- end
157
- end
158
- end
159
- end
160
-
161
- def draw_elements
162
- @element_list.get_elements.each do |element|
163
- draw_element(element)
164
- end
165
- end
166
-
167
- def draw_connector(id = 1)
168
- parent = @element_list.get_id(id)
169
- children = parent.children.map{|c| @element_list.get_id(c)}
170
-
171
- if children.empty?
172
- ;
173
- elsif children.size == 1
174
- child = children[0]
175
- if (@leafstyle == "auto")
176
- if child.contains_phrase || child.triangle
177
- triangle_to_parent(parent, child)
178
- else
179
- line_to_parent(parent, child)
180
- end
181
- elsif(@leafstyle == "bar")
182
- if child.triangle
183
- triangle_to_parent(parent, child)
184
- else
185
- line_to_parent(parent, child)
186
- end
187
- elsif(@leafstyle == "nothing")
188
- if child.triangle
189
- triangle_to_parent(parent, child)
190
- elsif ETYPE_LEAF != child.type
191
- line_to_parent(parent, child)
192
- elsif ETYPE_LEAF == child.type
193
- child.vertical_indent = parent.vertical_indent + parent.content_height + $height_connector / 2
194
- end
195
- end
196
- else
197
- children.each do |child|
198
- line_to_parent(parent, child)
199
- end
200
- end
201
-
202
- parent.children.each do |c|
203
- draw_connector(c)
204
- end
205
- end
206
-
207
- def get_leftmost(id = 1)
208
- target = @element_list.get_id(id)
209
- target_indent = target.horizontal_indent
210
- children_indent = target.children.map{|c| get_leftmost(c)}
211
- (children_indent << target_indent).min
212
- end
213
-
214
- def get_rightmost(id = 1)
215
- target = @element_list.get_id(id)
216
- target_right_end = target.horizontal_indent + target.content_width
217
- children_right_end = target.children.map{|c| get_rightmost(c)}
218
- (children_right_end << target_right_end).max
219
- end
220
-
221
- def node_centering
222
- node_groups = @element_list.get_elements.group_by {|e| e.parent}
223
- node_groups.sort_by{|k, v| -k}.each do |k, v|
224
- next if k == 0
225
- parent = @element_list.get_id(k)
226
- child_positions =v.map {|child| child.horizontal_indent + child.content_width / 2 }
227
- parent.horizontal_indent = child_positions.min + (child_positions.max - child_positions.min - parent.content_width) / 2
228
- end
229
- end
230
-
231
- def parse_list
232
- calculate_level
233
- calculate_width
234
- make_balance if @symmetrize
235
- calculate_indent
236
- node_centering
237
-
238
- top = @element_list.get_id(1)
239
- diff = top.horizontal_indent
240
- @element_list.get_elements.each do |e|
241
- e.horizontal_indent -= diff
242
- end
243
-
244
- offset_l = (top.horizontal_indent - get_leftmost) + $h_gap_between_nodes
245
- offset_r = top.width / 2 - offset_l - $h_gap_between_nodes
246
-
247
- @element_list.get_elements.each do |e|
248
- e.horizontal_indent += offset_l
249
- end
250
-
251
- calculate_height
252
- draw_elements
253
- draw_connector
254
- num_paths = draw_paths
255
-
256
- # width = get_rightmost - get_leftmost + $h_gap_between_nodes * 2
257
- width = get_rightmost - get_leftmost + $h_gap_between_nodes
258
- height = @element_list.get_id(1).height
259
- height = @height if @height > height
260
-
261
- return {height: height, width: width}
262
- end
263
- end
264
- end
1
+ # frozen_string_literal: true
2
+
3
+ #==========================
4
+ # graph.rb
5
+ #==========================
6
+ #
7
+ # Image utility functions to inspect text font metrics
8
+ # Copyright (c) 2007-2023 Yoichiro Hasebe <yohasebe@gmail.com>
9
+
10
+ require_relative 'utils'
11
+
12
+ module RSyntaxTree
13
+ class BaseGraph
14
+ def initialize(element_list, params, global)
15
+ @global = global
16
+ @element_list = element_list
17
+ @symmetrize = params[:symmetrize]
18
+
19
+ if params[:color]
20
+ @col_node = "blue"
21
+ @col_leaf = "green"
22
+ @col_path = "purple"
23
+ else
24
+ @col_node = "black"
25
+ @col_leaf = "black"
26
+ @col_path = "black"
27
+ end
28
+
29
+ @col_bg = "none"
30
+ @col_fg = "black"
31
+ @col_line = "black"
32
+
33
+ @leafstyle = params[:leafstyle]
34
+ @fontset = params[:fontset]
35
+ @fontsize = params[:fontsize]
36
+ end
37
+
38
+ def calculate_level
39
+ @element_list.get_elements.select { |e| e.type == 2 }.each do |e|
40
+ e.level = @element_list.get_id(e.parent).level + 1
41
+ end
42
+ end
43
+
44
+ def calculate_width(id = 1)
45
+ target = @element_list.get_id(id)
46
+ if target.children.empty?
47
+ target.width = target.content_width + @global[:h_gap_between_nodes] * 4
48
+
49
+ parent = @element_list.get_id(target.parent)
50
+ while parent && parent.children.size == 1
51
+ w = parent.content_width
52
+ target.width = w + @global[:h_gap_between_nodes] * 4 if w > target.content_width
53
+ parent = @element_list.get_id(parent.parent)
54
+ end
55
+ target.width
56
+ else
57
+ return target.width if target.width != 0
58
+
59
+ accum_array = []
60
+ target.children.each do |c|
61
+ accum_array << calculate_width(c)
62
+ end
63
+ accum_width = if @symmetrize
64
+ accum_array.max * target.children.size
65
+ else
66
+ accum_array.sum
67
+ end
68
+
69
+ target.width = [accum_width, target.content_width].max
70
+ end
71
+ end
72
+
73
+ def calculate_height(id = 1)
74
+ target = @element_list.get_id(id)
75
+ if id == 1
76
+ target.vertical_indent = 0
77
+ else
78
+ parent = @element_list.get_id(target.parent)
79
+
80
+ vertical_indent = if !target.triangle &&
81
+ @leafstyle == "nothing" &&
82
+ ETYPE_LEAF == target.type &&
83
+ parent.children.size == 1
84
+ parent.vertical_indent + parent.content_height
85
+ else
86
+ parent.vertical_indent + parent.content_height + @global[:height_connector]
87
+ end
88
+
89
+ target.vertical_indent = vertical_indent
90
+ end
91
+
92
+ if target.children.empty?
93
+ target.height = target.content_height
94
+ target.vertical_indent + target.content_height
95
+ else
96
+ accum_array = []
97
+ target.children.each do |c|
98
+ accum_array << calculate_height(c)
99
+ end
100
+ target.height = accum_array.max - target.vertical_indent
101
+ accum_array.max
102
+ end
103
+ end
104
+
105
+ def make_balance(id = 1)
106
+ target = @element_list.get_id(id)
107
+ if target.children.empty?
108
+ parent = @element_list.get_id(target.parent)
109
+ accum_array = []
110
+ parent.children.each do |c|
111
+ accum_array << @element_list.get_id(c).width
112
+ end
113
+ max = accum_array.max
114
+ parent.children.each do |c|
115
+ @element_list.get_id(c).width = max
116
+ end
117
+ max
118
+ else
119
+ accum_array = []
120
+ target.children.each do |c|
121
+ accum_array << make_balance(c)
122
+ end
123
+ accum_width = accum_array.max
124
+ max = [accum_width, target.content_width].max
125
+ target.children.each do |c|
126
+ @element_list.get_id(c).width = max
127
+ end
128
+ target.width
129
+ end
130
+ end
131
+
132
+ def calculate_indent
133
+ node_groups = @element_list.get_elements.group_by(&:parent)
134
+ node_groups.each do |k, v|
135
+ next if k.zero?
136
+
137
+ parent = @element_list.get_id(k)
138
+ if @symmetrize
139
+ num_leaves = v.size
140
+ partition_width = parent.width / num_leaves
141
+ left_offset = parent.horizontal_indent + parent.content_width / 2.0 - parent.width / 2.0
142
+ v.each do |e|
143
+ indent = left_offset + (partition_width - e.content_width) / 2.0
144
+ e.horizontal_indent = indent
145
+ left_offset += partition_width
146
+ end
147
+ else
148
+ left_offset = parent.horizontal_indent + parent.content_width / 2.0 - parent.width / 2.0
149
+ v.each do |e|
150
+ indent = left_offset + (e.width - e.content_width) / 2.0
151
+ e.horizontal_indent = indent
152
+ left_offset += e.width
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ def draw_elements
159
+ @element_list.get_elements.each do |element|
160
+ draw_element(element)
161
+ end
162
+ end
163
+
164
+ def draw_connector(id = 1)
165
+ parent = @element_list.get_id(id)
166
+ children = parent.children.map { |c| @element_list.get_id(c) }
167
+
168
+ if children.size == 1
169
+ child = children[0]
170
+ case @leafstyle
171
+ when "auto"
172
+ if child.contains_phrase || child.triangle
173
+ triangle_to_parent(parent, child)
174
+ else
175
+ line_to_parent(parent, child)
176
+ end
177
+ when "bar"
178
+ if child.triangle
179
+ triangle_to_parent(parent, child)
180
+ else
181
+ line_to_parent(parent, child)
182
+ end
183
+ when "nothing"
184
+ if child.triangle
185
+ triangle_to_parent(parent, child)
186
+ elsif ETYPE_LEAF != child.type
187
+ line_to_parent(parent, child)
188
+ elsif ETYPE_LEAF == child.type
189
+ child.vertical_indent = parent.vertical_indent + parent.content_height + @global[:height_connector] / 2
190
+ end
191
+ end
192
+ else
193
+ children.each do |child|
194
+ line_to_parent(parent, child)
195
+ end
196
+ end
197
+
198
+ parent.children.each do |c|
199
+ draw_connector(c)
200
+ end
201
+ end
202
+
203
+ def get_leftmost(id = 1)
204
+ target = @element_list.get_id(id)
205
+ target_indent = target.horizontal_indent
206
+ children_indent = target.children.map { |c| get_leftmost(c) }
207
+ (children_indent << target_indent).min
208
+ end
209
+
210
+ def get_rightmost(id = 1)
211
+ target = @element_list.get_id(id)
212
+ target_right_end = target.horizontal_indent + target.content_width
213
+ children_right_end = target.children.map { |c| get_rightmost(c) }
214
+ (children_right_end << target_right_end).max
215
+ end
216
+
217
+ def node_centering
218
+ node_groups = @element_list.get_elements.group_by(&:parent)
219
+ node_groups.sort_by { |k, _v| -k }.each do |k, v|
220
+ next if k.zero?
221
+
222
+ parent = @element_list.get_id(k)
223
+ child_positions = v.map { |child| child.horizontal_indent + child.content_width / 2 }
224
+ parent.horizontal_indent = child_positions.min + (child_positions.max - child_positions.min - parent.content_width) / 2
225
+ end
226
+ end
227
+
228
+ def parse_list
229
+ calculate_level
230
+ calculate_width
231
+ make_balance if @symmetrize
232
+ calculate_indent
233
+ node_centering
234
+
235
+ top = @element_list.get_id(1)
236
+ diff = top.horizontal_indent
237
+ @element_list.get_elements.each do |e|
238
+ e.horizontal_indent -= diff
239
+ end
240
+
241
+ offset_l = (top.horizontal_indent - get_leftmost) + @global[:h_gap_between_nodes]
242
+ # offset_r = top.width / 2 - offset_l - @global[:h_gap_between_nodes:
243
+
244
+ @element_list.get_elements.each do |e|
245
+ e.horizontal_indent += offset_l
246
+ end
247
+
248
+ calculate_height
249
+ draw_elements
250
+ draw_connector
251
+ draw_paths
252
+
253
+ width = get_rightmost - get_leftmost + @global[:h_gap_between_nodes]
254
+ height = @element_list.get_id(1).height
255
+ height = @height if @height > height
256
+
257
+ { height: height, width: width }
258
+ end
259
+ end
260
+ end