rsyntaxtree 0.7.2 → 0.7.3
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/README.md +3 -3
- data/bin/rsyntaxtree +2 -2
- data/fonts/NotoSans-Bold.ttf +0 -0
- data/fonts/NotoSans-BoldItalic.ttf +0 -0
- data/fonts/NotoSans-Italic.ttf +0 -0
- data/fonts/NotoSans-Regular.ttf +0 -0
- data/fonts/NotoSerif-Bold.ttf +0 -0
- data/fonts/NotoSerif-BoldItalic.ttf +0 -0
- data/fonts/NotoSerif-Italic.ttf +0 -0
- data/fonts/NotoSerif-Regular.ttf +0 -0
- data/lib/rsyntaxtree.rb +46 -41
- data/lib/rsyntaxtree/element.rb +1 -15
- data/lib/rsyntaxtree/elementlist.rb +1 -17
- data/lib/rsyntaxtree/error_message.rb +22 -17
- data/lib/rsyntaxtree/graph.rb +305 -0
- data/lib/rsyntaxtree/string_parser.rb +19 -34
- data/lib/rsyntaxtree/svg_graph.rb +126 -301
- data/lib/rsyntaxtree/tree_graph.rb +129 -284
- data/lib/rsyntaxtree/utils.rb +20 -0
- data/lib/rsyntaxtree/version.rb +1 -1
- metadata +12 -6
- data/fonts/DroidSans.ttf +0 -0
- data/fonts/DroidSerif-Regular.ttf +0 -0
- data/fonts/NotoSansMonoCJKjp-Regular.otf +0 -0
- data/lib/rsyntaxtree/imgutils.rb +0 -70
@@ -13,20 +13,6 @@
|
|
13
13
|
#
|
14
14
|
# Copyright (c) 2007-2018 Yoichiro Hasebe <yohasebe@gmail.com>
|
15
15
|
# Copyright (c) 2003-2004 Andre Eisenbach <andre@ironcreek.net>
|
16
|
-
#
|
17
|
-
# This program is free software; you can redistribute it and/or modify
|
18
|
-
# it under the terms of the GNU General Public License as published by
|
19
|
-
# the Free Software Foundation; either version 2 of the License, or
|
20
|
-
# (at your option) any later version.
|
21
|
-
#
|
22
|
-
# This program is distributed in the hope that it will be useful,
|
23
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
24
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
25
|
-
# GNU General Public License for more details.
|
26
|
-
#
|
27
|
-
# You should have received a copy of the GNU General Public License
|
28
|
-
# along with this program; if not, write to the Free Software
|
29
|
-
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
30
16
|
|
31
17
|
require 'elementlist'
|
32
18
|
require 'element'
|
@@ -53,7 +39,7 @@ class StringParser
|
|
53
39
|
string.gsub!(/\s+/, " ")
|
54
40
|
string.gsub!(/\] \[/, "][")
|
55
41
|
string.gsub!(/ \[/, "[")
|
56
|
-
|
42
|
+
|
57
43
|
@data = string # Store it for later...
|
58
44
|
@elist = ElementList.new # Initialize internal element list
|
59
45
|
@pos = 0 # Position in the sentence
|
@@ -61,14 +47,14 @@ class StringParser
|
|
61
47
|
@level = 0 # Level in the diagram
|
62
48
|
@tncnt = Hash.new # Node type counts
|
63
49
|
end
|
64
|
-
|
50
|
+
|
65
51
|
# caution: quick and dirty solution
|
66
52
|
def valid?
|
67
53
|
if(@data.length < 1)
|
68
54
|
return false
|
69
55
|
end
|
70
56
|
|
71
|
-
if /\
|
57
|
+
if /\[\s*\]/m =~ @data
|
72
58
|
return false
|
73
59
|
end
|
74
60
|
|
@@ -96,15 +82,14 @@ class StringParser
|
|
96
82
|
end
|
97
83
|
|
98
84
|
return false unless open_br.length == close_br.length
|
99
|
-
make_tree(0)
|
100
|
-
return false if @tncnt.empty?
|
101
|
-
@tncnt.each do |key, value|
|
102
|
-
|
103
|
-
end
|
85
|
+
# make_tree(0)
|
86
|
+
# return false if @tncnt.empty?
|
87
|
+
# @tncnt.each do |key, value|
|
88
|
+
# return false if key == ""
|
89
|
+
# end
|
104
90
|
return true
|
105
91
|
end
|
106
|
-
|
107
|
-
|
92
|
+
|
108
93
|
def parse
|
109
94
|
make_tree(0);
|
110
95
|
end
|
@@ -112,7 +97,7 @@ class StringParser
|
|
112
97
|
def get_elementlist
|
113
98
|
@elist;
|
114
99
|
end
|
115
|
-
|
100
|
+
|
116
101
|
def auto_subscript
|
117
102
|
elements = @elist.get_elements
|
118
103
|
tmpcnt = Hash.new
|
@@ -120,18 +105,18 @@ class StringParser
|
|
120
105
|
if(element.type == ETYPE_NODE)
|
121
106
|
count = 1
|
122
107
|
content = element.content
|
123
|
-
|
108
|
+
|
124
109
|
if @tncnt[content]
|
125
110
|
count = @tncnt[content]
|
126
111
|
end
|
127
|
-
|
112
|
+
|
128
113
|
if(count > 1)
|
129
114
|
if tmpcnt[content]
|
130
115
|
tmpcnt[content] += 1
|
131
116
|
else
|
132
117
|
tmpcnt[content] = 1
|
133
118
|
end
|
134
|
-
|
119
|
+
|
135
120
|
element.content += ("_" + tmpcnt[content].to_s)
|
136
121
|
end
|
137
122
|
|
@@ -148,7 +133,7 @@ class StringParser
|
|
148
133
|
@tncnt[name] = 1
|
149
134
|
end
|
150
135
|
end
|
151
|
-
|
136
|
+
|
152
137
|
def get_next_token
|
153
138
|
data = @data.split(//)
|
154
139
|
gottoken = false
|
@@ -158,7 +143,7 @@ class StringParser
|
|
158
143
|
if((@pos + 1) >= data.length)
|
159
144
|
return ""
|
160
145
|
end
|
161
|
-
|
146
|
+
|
162
147
|
escape = false
|
163
148
|
while(((@pos + i) < data.length) && !gottoken)
|
164
149
|
ch = data[@pos + i];
|
@@ -202,11 +187,11 @@ class StringParser
|
|
202
187
|
end
|
203
188
|
return token
|
204
189
|
end
|
205
|
-
|
190
|
+
|
206
191
|
def make_tree(parent)
|
207
192
|
token = get_next_token.strip
|
208
193
|
parts = Array.new
|
209
|
-
|
194
|
+
|
210
195
|
while(token != "" && token != "]" )
|
211
196
|
token_r = token.split(//)
|
212
197
|
case token_r[0]
|
@@ -225,7 +210,7 @@ class StringParser
|
|
225
210
|
@elist.add(element)
|
226
211
|
newparent = element.id
|
227
212
|
count_node(parts[0])
|
228
|
-
|
213
|
+
|
229
214
|
element = Element.new(@id, @id - 1, parts[1], @level + 1 )
|
230
215
|
@id += 1
|
231
216
|
@elist.add(element)
|
@@ -248,7 +233,7 @@ class StringParser
|
|
248
233
|
count_node(token)
|
249
234
|
end
|
250
235
|
end
|
251
|
-
|
236
|
+
|
252
237
|
token = get_next_token
|
253
238
|
end
|
254
239
|
@level -= 1
|
@@ -12,71 +12,23 @@
|
|
12
12
|
#
|
13
13
|
# Copyright (c) 2007-2018 Yoichiro Hasebe <yohasebe@gmail.com>
|
14
14
|
# Copyright (c) 2003-2004 Andre Eisenbach <andre@ironcreek.net>
|
15
|
-
#
|
16
|
-
# This program is free software; you can redistribute it and/or modify
|
17
|
-
# it under the terms of the GNU General Public License as published by
|
18
|
-
# the Free Software Foundation; either version 2 of the License, or
|
19
|
-
# (at your option) any later version.
|
20
|
-
#
|
21
|
-
# This program is distributed in the hope that it will be useful,
|
22
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
23
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
24
|
-
# GNU General Public License for more details.
|
25
|
-
#
|
26
|
-
# You should have received a copy of the GNU General Public License
|
27
|
-
# along with this program; if not, write to the Free Software
|
28
|
-
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
29
|
-
|
30
|
-
require 'tmpdir'
|
31
|
-
require 'rvg/rvg'
|
32
|
-
include Magick
|
33
|
-
|
34
|
-
# constant variables are already set in tree_graph.rb
|
35
|
-
|
36
|
-
class SVGGraph
|
37
|
-
|
38
|
-
def initialize(e_list, metrics, symmetrize = true, color = true, leafstyle = "auto",
|
39
|
-
font = "Helvetica", font_size = 10, simple = false)
|
40
|
-
|
41
|
-
# Store parameters
|
42
|
-
@e_list = e_list
|
43
|
-
@m = metrics
|
44
|
-
@font = font
|
45
|
-
@font_size = font_size
|
46
|
-
@leafstyle = leafstyle
|
47
|
-
@symmetrize = symmetrize
|
48
|
-
|
49
|
-
|
50
|
-
# Calculate image dimensions
|
51
|
-
@e_height = @font_size + @m[:e_padd] * 2
|
52
|
-
h = @e_list.get_level_height
|
53
|
-
w = calc_level_width(0)
|
54
|
-
w_px = w + @m[:b_side]
|
55
|
-
h_px = h * @e_height + (h-1) * (@m[:v_space] + @font_size) + @m[:b_topbot] * 2
|
56
|
-
@height = h_px
|
57
|
-
@width = w_px
|
58
|
-
|
59
|
-
|
60
|
-
# Initialize the image and colors
|
61
|
-
@col_bg = "none"
|
62
|
-
@col_fg = "black"
|
63
|
-
@col_line = "black"
|
64
|
-
|
65
|
-
if color
|
66
|
-
@col_node = "blue"
|
67
|
-
@col_leaf = "green"
|
68
|
-
@col_trace = "red"
|
69
|
-
else
|
70
|
-
@col_node = "black"
|
71
|
-
@col_leaf = "black"
|
72
|
-
@col_trace = "black"
|
73
|
-
end
|
74
15
|
|
75
|
-
|
76
|
-
|
16
|
+
require "tempfile"
|
17
|
+
require 'graph'
|
18
|
+
|
19
|
+
class SVGGraph < Graph
|
20
|
+
|
21
|
+
def initialize(e_list, metrics, symmetrize, color, leafstyle, multibyte, fontstyle, font_size)
|
22
|
+
|
23
|
+
# Store class-specific parameters
|
24
|
+
@font = fontstyle == "sans" ? "sans-serif" : fontstyle
|
25
|
+
@font_size = font_size
|
77
26
|
|
78
|
-
|
27
|
+
super(e_list, metrics, symmetrize, color, leafstyle, multibyte, @font, @font_size)
|
79
28
|
|
29
|
+
@line_styles = "<line style='stroke:black; stroke-width:1;' x1='X1' y1='Y1' x2='X2' y2='Y2' />\n"
|
30
|
+
@polygon_styles = "<polygon style='fill: none; stroke: black; stroke-width:1;' points='X1 Y1 X2 Y2 X3 Y3' />\n"
|
31
|
+
@text_styles = "<text style='fill: COLOR; font-size: FONT_SIZEpx; ST; WA;' x='X_VALUE' y='Y_VALUE' TD font-family='#{@font}'>CONTENT</text>\n"
|
80
32
|
@tree_data = String.new
|
81
33
|
end
|
82
34
|
|
@@ -90,11 +42,6 @@ class SVGGraph
|
|
90
42
|
EOD
|
91
43
|
|
92
44
|
footer = "</svg>"
|
93
|
-
# File.open(filename, "w") do |f|
|
94
|
-
# f.write header
|
95
|
-
# f.write @tree_data
|
96
|
-
# f.write footer
|
97
|
-
# end
|
98
45
|
header + @tree_data + footer
|
99
46
|
end
|
100
47
|
|
@@ -113,12 +60,12 @@ EOD
|
|
113
60
|
return tfname
|
114
61
|
end
|
115
62
|
end
|
116
|
-
|
63
|
+
|
117
64
|
:private
|
118
65
|
|
119
66
|
# Add the element into the tree (draw it)
|
120
67
|
def draw_element(x, y, w, string, type)
|
121
|
-
|
68
|
+
string = string.sub(/\^\z/){""}
|
122
69
|
# Calculate element dimensions and position
|
123
70
|
if (type == ETYPE_LEAF) and @leafstyle == "nothing"
|
124
71
|
top = row2px(y - 1) + (@font_size * 1.5)
|
@@ -131,23 +78,82 @@ EOD
|
|
131
78
|
|
132
79
|
# Split the string into the main part and the
|
133
80
|
# subscript part of the element (if any)
|
134
|
-
main = string
|
135
|
-
sub = ""
|
136
|
-
|
137
|
-
sub_size = (@font_size * 0.7 )
|
138
81
|
parts = string.split("_", 2)
|
139
|
-
|
140
82
|
if(parts.length > 1 )
|
141
|
-
main = parts[0]
|
142
|
-
sub = parts[1].gsub(/_/, " ")
|
83
|
+
main = parts[0].strip
|
84
|
+
sub = parts[1].gsub(/_/, " ").strip
|
85
|
+
else
|
86
|
+
main = parts[0].strip
|
87
|
+
sub = ""
|
143
88
|
end
|
144
|
-
|
89
|
+
|
90
|
+
if /\A\+(.+)\+\z/ =~ main
|
91
|
+
main = $1
|
92
|
+
main_decoration= "overline"
|
93
|
+
elsif /\A\-(.+)\-\z/ =~ main
|
94
|
+
main = $1
|
95
|
+
main_decoration= "underline"
|
96
|
+
elsif /\A\=(.+)\=\z/ =~ main
|
97
|
+
main = $1
|
98
|
+
main_decoration= "line-through"
|
99
|
+
else
|
100
|
+
main_decoration= ""
|
101
|
+
end
|
102
|
+
|
103
|
+
if /\A\*\*\*(.+)\*\*\*\z/ =~ main
|
104
|
+
main = $1
|
105
|
+
main_style = "font-style: italic"
|
106
|
+
main_weight = "font-weight: bold"
|
107
|
+
elsif /\A\*\*(.+)\*\*\z/ =~ main
|
108
|
+
main = $1
|
109
|
+
main_style = ""
|
110
|
+
main_weight = "font-weight: bold"
|
111
|
+
elsif /\A\*(.+)\*\z/ =~ main
|
112
|
+
main = $1
|
113
|
+
main_style = "font-style: italic"
|
114
|
+
main_weight = ""
|
115
|
+
else
|
116
|
+
main_style = ""
|
117
|
+
main_weight = ""
|
118
|
+
end
|
119
|
+
|
145
120
|
# Calculate text size for the main and the
|
146
121
|
# subscript part of the element
|
122
|
+
# symbols for underline/overline removed temporarily
|
123
|
+
|
147
124
|
main_width = img_get_txt_width(main, @font, @font_size)
|
148
125
|
|
149
126
|
if sub != ""
|
150
|
-
|
127
|
+
if /\A\+(.+)\+\z/ =~ sub
|
128
|
+
sub = $1
|
129
|
+
sub_decoration= "overline"
|
130
|
+
elsif /\A\-(.+)\-\z/ =~ sub
|
131
|
+
sub = $1
|
132
|
+
sub_decoration= "underline"
|
133
|
+
elsif /\A\=(.+)\=\z/ =~ sub
|
134
|
+
sub = $1
|
135
|
+
sub_decoration= "line-through"
|
136
|
+
else
|
137
|
+
sub_decoration= ""
|
138
|
+
end
|
139
|
+
|
140
|
+
if /\A\*\*\*(.+)\*\*\*\z/ =~ sub
|
141
|
+
sub = $1
|
142
|
+
sub_style = "font-style: italic"
|
143
|
+
sub_weight = "font-weight: bold"
|
144
|
+
elsif /\A\*\*(.+)\*\*\z/ =~ sub
|
145
|
+
sub = $1
|
146
|
+
sub_style = ""
|
147
|
+
sub_weight = "font-weight: bold"
|
148
|
+
elsif /\A\*(.+)\*\z/ =~ sub
|
149
|
+
sub = $1
|
150
|
+
sub_style = "font-style: italic"
|
151
|
+
sub_weight = ""
|
152
|
+
else
|
153
|
+
sub_style = ""
|
154
|
+
sub_weight = ""
|
155
|
+
end
|
156
|
+
sub_width = img_get_txt_width(sub.to_s, @font, @sub_size)
|
151
157
|
else
|
152
158
|
sub_width = 0
|
153
159
|
end
|
@@ -155,14 +161,14 @@ EOD
|
|
155
161
|
# Center text in the element
|
156
162
|
txt_width = main_width + sub_width
|
157
163
|
txt_pos = left + (right - left) / 2 - txt_width / 2
|
158
|
-
|
164
|
+
|
159
165
|
# Select apropriate color
|
160
166
|
if(type == ETYPE_LEAF)
|
161
167
|
col = @col_leaf
|
162
168
|
else
|
163
169
|
col = @col_node
|
164
170
|
end
|
165
|
-
|
171
|
+
|
166
172
|
if(main[0].chr == "<" && main[-1].chr == ">")
|
167
173
|
col = @col_trace
|
168
174
|
end
|
@@ -171,20 +177,27 @@ EOD
|
|
171
177
|
main_data = @text_styles.sub(/COLOR/, col)
|
172
178
|
main_data = main_data.sub(/FONT_SIZE/, @font_size.to_s)
|
173
179
|
main_x = txt_pos
|
174
|
-
main_y = top + @e_height - @m[:e_padd]
|
180
|
+
main_y = top + @e_height - @m[:e_padd] * 1.5
|
175
181
|
main_data = main_data.sub(/X_VALUE/, main_x.to_s)
|
176
182
|
main_data = main_data.sub(/Y_VALUE/, main_y.to_s)
|
177
|
-
|
183
|
+
|
184
|
+
@tree_data += main_data.sub(/TD/, "text-decoration='#{main_decoration}'")
|
185
|
+
.sub(/ST/, main_style)
|
186
|
+
.sub(/WA/, main_weight)
|
187
|
+
.sub(/CONTENT/, main)
|
178
188
|
|
179
189
|
# Draw subscript text
|
180
190
|
sub_data = @text_styles.sub(/COLOR/, col)
|
181
|
-
sub_data = sub_data.sub(/FONT_SIZE/, @
|
182
|
-
sub_x = main_x + main_width
|
183
|
-
sub_y = top + (@e_height - @m[:e_padd] + sub_size /
|
191
|
+
sub_data = sub_data.sub(/FONT_SIZE/, @sub_size.to_s)
|
192
|
+
sub_x = main_x + main_width
|
193
|
+
sub_y = top + (@e_height - @m[:e_padd] + @sub_size / 10)
|
184
194
|
if (sub.length > 0 )
|
185
195
|
sub_data = sub_data.sub(/X_VALUE/, sub_x.ceil.to_s)
|
186
196
|
sub_data = sub_data.sub(/Y_VALUE/, sub_y.ceil.to_s)
|
187
|
-
@tree_data += sub_data.sub(/
|
197
|
+
@tree_data += sub_data.sub(/TD/, "text-decoration='#{sub_decoration}'")
|
198
|
+
.sub(/ST/, sub_style)
|
199
|
+
.sub(/WA/, sub_weight)
|
200
|
+
.sub(/CONTENT/, sub)
|
188
201
|
end
|
189
202
|
end
|
190
203
|
|
@@ -194,28 +207,28 @@ EOD
|
|
194
207
|
if (fromY == 0 )
|
195
208
|
return
|
196
209
|
end
|
197
|
-
|
210
|
+
|
198
211
|
fromTop = row2px(fromY)
|
199
212
|
fromLeft = (fromX + fromW / 2 + @m[:b_side])
|
200
213
|
toBot = (row2px(fromY - 1 ) + @e_height)
|
201
214
|
toLeft = (toX + toW / 2 + @m[:b_side])
|
202
215
|
|
203
|
-
line_data = @line_styles.sub(/X1/, fromLeft.ceil.to_s
|
204
|
-
line_data = line_data.sub(/Y1/, fromTop.ceil.to_s
|
205
|
-
line_data = line_data.sub(/X2/, toLeft.ceil.to_s
|
206
|
-
@tree_data += line_data.sub(/Y2/, toBot.ceil.to_s
|
216
|
+
line_data = @line_styles.sub(/X1/, fromLeft.ceil.to_s)
|
217
|
+
line_data = line_data.sub(/Y1/, fromTop.ceil.to_s)
|
218
|
+
line_data = line_data.sub(/X2/, toLeft.ceil.to_s)
|
219
|
+
@tree_data += line_data.sub(/Y2/, toBot.ceil.to_s)
|
207
220
|
|
208
221
|
end
|
209
222
|
|
210
223
|
# Draw a triangle between child/parent elements
|
211
|
-
def triangle_to_parent(fromX, fromY, fromW,
|
224
|
+
def triangle_to_parent(fromX, fromY, fromW, textW, symmetrize = true)
|
212
225
|
if (fromY == 0)
|
213
226
|
return
|
214
227
|
end
|
215
|
-
|
228
|
+
|
216
229
|
toX = fromX
|
217
230
|
fromCenter = (fromX + fromW / 2 + @m[:b_side])
|
218
|
-
|
231
|
+
|
219
232
|
fromTop = row2px(fromY).ceil
|
220
233
|
fromLeft1 = (fromCenter + textW / 2).ceil
|
221
234
|
fromLeft2 = (fromCenter - textW / 2).ceil
|
@@ -226,7 +239,7 @@ EOD
|
|
226
239
|
else
|
227
240
|
toLeft = (toX + textW / 2 + @m[:b_side] * 3)
|
228
241
|
end
|
229
|
-
|
242
|
+
|
230
243
|
polygon_data = @polygon_styles.sub(/X1/, fromLeft1.ceil.to_s)
|
231
244
|
polygon_data = polygon_data.sub(/Y1/, fromTop.ceil.to_s)
|
232
245
|
polygon_data = polygon_data.sub(/X2/, fromLeft2.ceil.to_s)
|
@@ -235,8 +248,6 @@ EOD
|
|
235
248
|
@tree_data += polygon_data.sub(/Y3/, toBot.ceil.to_s)
|
236
249
|
end
|
237
250
|
|
238
|
-
|
239
|
-
|
240
251
|
# If a node element text is wider than the sum of it's
|
241
252
|
# child elements, then the child elements need to
|
242
253
|
# be resized to even out the space. This function
|
@@ -257,213 +268,27 @@ EOD
|
|
257
268
|
end
|
258
269
|
end
|
259
270
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
if(children.length == 0)
|
269
|
-
w = img_get_txt_width(e.content, @font, @font_size) + @font_size
|
271
|
+
def img_get_txt_width(text, font, font_size, multiline = false)
|
272
|
+
parts = text.split("_", 2)
|
273
|
+
main_before = parts[0].strip
|
274
|
+
sub = parts[1]
|
275
|
+
main = get_txt_only(main_before)
|
276
|
+
if(main.contains_cjk?)
|
277
|
+
main = 'n' * main.strip.size * 2
|
270
278
|
else
|
271
|
-
|
272
|
-
child_e = @e_list.get_id(child)
|
273
|
-
w += calc_element_width(child_e)
|
274
|
-
end
|
275
|
-
|
276
|
-
tw = img_get_txt_width(e.content, @font, @font_size) + @font_size
|
277
|
-
if(tw > w)
|
278
|
-
fix_child_size(e.id, w, tw)
|
279
|
-
w = tw
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
@e_list.set_element_width(e.id, w)
|
284
|
-
return w
|
285
|
-
end
|
286
|
-
|
287
|
-
# Calculate the width of all elements in a certain level
|
288
|
-
def calc_level_width(level)
|
289
|
-
w = 0
|
290
|
-
e = @e_list.get_first
|
291
|
-
while e
|
292
|
-
if(e.level == level)
|
293
|
-
w += calc_element_width(e)
|
294
|
-
end
|
295
|
-
e = @e_list.get_next
|
279
|
+
main
|
296
280
|
end
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
c_list = @e_list.get_children(id)
|
305
|
-
return nil if c_list.empty?
|
306
|
-
|
307
|
-
c_list.each do |c|
|
308
|
-
left = c.indent if indent == 0 or left > c.indent
|
309
|
-
end
|
310
|
-
c_list.each do |c|
|
311
|
-
right = c.indent + e.width if c.indent + c.width > right
|
312
|
-
end
|
313
|
-
return [left, right]
|
314
|
-
end
|
315
|
-
|
316
|
-
def get_children_indent(id)
|
317
|
-
calc_children_width(id)[0]
|
318
|
-
end
|
319
|
-
|
320
|
-
def get_children_width(id)
|
321
|
-
calc_children_width(id)[1] - get_children_indent(id)
|
322
|
-
end
|
323
|
-
|
324
|
-
# Parse the elements in the list top to bottom and
|
325
|
-
# draw the elements into the image.
|
326
|
-
# As we it iterate through the levels, the element
|
327
|
-
# indentation is calculated.
|
328
|
-
def parse_list
|
329
|
-
|
330
|
-
# Calc element list recursively....
|
331
|
-
e_arr = @e_list.get_elements
|
332
|
-
|
333
|
-
h = @e_list.get_level_height
|
334
|
-
|
335
|
-
h.times do |i|
|
336
|
-
x = 0
|
337
|
-
e_arr.each do |j|
|
338
|
-
|
339
|
-
if (j.level == i)
|
340
|
-
cw = @e_list.get_element_width(j.id)
|
341
|
-
parent_indent = @e_list.get_indent(j.parent)
|
342
|
-
|
343
|
-
if (x < parent_indent)
|
344
|
-
x = parent_indent
|
345
|
-
end
|
346
|
-
|
347
|
-
@e_list.set_indent(j.id, x)
|
348
|
-
if !@symmetrize
|
349
|
-
draw_element(x, i, cw, j.content, j.type)
|
350
|
-
if(j.parent != 0 )
|
351
|
-
words = j.content.split(" ")
|
352
|
-
unless @leafstyle == "nothing" && ETYPE_LEAF == j.type
|
353
|
-
if (@leafstyle == "triangle" && ETYPE_LEAF == j.type && x == parent_indent && words.length > 0)
|
354
|
-
txt_width = img_get_txt_width(j.content, @font, @font_size)
|
355
|
-
triangle_to_parent(x, i, cw, @e_list.get_element_width(j.parent), txt_width)
|
356
|
-
elsif (@leafstyle == "auto" && ETYPE_LEAF == j.type && x == parent_indent)
|
357
|
-
if words.length > 1 || j.triangle
|
358
|
-
txt_width = img_get_txt_width(j.content, @font, @font_size)
|
359
|
-
triangle_to_parent(x, i, cw, @e_list.get_element_width(j.parent), txt_width, @symmetrize)
|
360
|
-
else
|
361
|
-
line_to_parent(x, i, cw, @e_list.get_indent(j.parent), @e_list.get_element_width(j.parent))
|
362
|
-
end
|
363
|
-
else
|
364
|
-
line_to_parent(x, i, cw, @e_list.get_indent(j.parent), @e_list.get_element_width(j.parent))
|
365
|
-
end
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
x += cw
|
370
|
-
end
|
281
|
+
main_metrics = img_get_txt_metrics(main, font, font_size, multiline)
|
282
|
+
width = main_metrics.width
|
283
|
+
if sub
|
284
|
+
if(sub.contains_cjk?)
|
285
|
+
sub = 'n' * sub.strip.size * 2
|
286
|
+
else
|
287
|
+
sub
|
371
288
|
end
|
289
|
+
sub_metrics = img_get_txt_metrics(sub, font, font_size * SUBSCRIPT_CONST, multiline)
|
290
|
+
width += sub_metrics.width
|
372
291
|
end
|
373
|
-
return
|
374
|
-
h.times do |i|
|
375
|
-
curlevel = h - i - 1
|
376
|
-
indent = 0
|
377
|
-
e_arr.each_with_index do |j, idx|
|
378
|
-
if (j.level == curlevel)
|
379
|
-
# Draw a line to the parent element
|
380
|
-
children = @e_list.get_children(j.id)
|
381
|
-
|
382
|
-
tw = img_get_txt_width(j.content, @font, @font_size)
|
383
|
-
if children.length > 1
|
384
|
-
left, right = -1, -1
|
385
|
-
children.each do |child|
|
386
|
-
k = @e_list.get_id(child)
|
387
|
-
kw = img_get_txt_width(k.content, @font, @font_size)
|
388
|
-
left = k.indent + kw / 2 if k.indent + kw / 2 < left or left == -1
|
389
|
-
right = k.indent + kw / 2 if k.indent + kw / 2 > right
|
390
|
-
end
|
391
|
-
draw_element(left, curlevel, right - left, j.content, j.type)
|
392
|
-
@e_list.set_indent(j.id, left + (right - left) / 2 - tw / 2)
|
393
|
-
|
394
|
-
children.each do |child|
|
395
|
-
k = @e_list.get_id(child)
|
396
|
-
words = k.content.split(" ")
|
397
|
-
dw = img_get_txt_width(k.content, @font, @font_size)
|
398
|
-
unless @leafstyle == "nothing" && ETYPE_LEAF == k.type
|
399
|
-
if (@leafstyle == "triangle" && ETYPE_LEAF == k.type && k.indent == j.indent && words.length > 0)
|
400
|
-
txt_width = img_get_txt_width(k.content, @font, @font_size)
|
401
|
-
triangle_to_parent(k.indent, curlevel + 1, dw, tw, txt_width)
|
402
|
-
elsif (@leafstyle == "auto" && ETYPE_LEAF == k.type && k.indent == j.indent)
|
403
|
-
if words.length > 1 || k.triangle
|
404
|
-
txt_width = img_get_txt_width(k.content, @font, @font_size)
|
405
|
-
triangle_to_parent(k.indent, curlevel + 1, dw, tw, txt_width)
|
406
|
-
else
|
407
|
-
line_to_parent(k.indent, curlevel + 1, dw, j.indent, tw)
|
408
|
-
end
|
409
|
-
else
|
410
|
-
line_to_parent(k.indent, curlevel + 1, dw, j.indent, tw)
|
411
|
-
end
|
412
|
-
end
|
413
|
-
end
|
414
|
-
|
415
|
-
else
|
416
|
-
unless children.empty?
|
417
|
-
k = @e_list.get_id(children[0])
|
418
|
-
kw = img_get_txt_width(k.content, @font, @font_size)
|
419
|
-
left = k.indent
|
420
|
-
right = k.indent + kw
|
421
|
-
draw_element(left, curlevel, right - left, j.content, j.type)
|
422
|
-
@e_list.set_indent(j.id, left + (right - left) / 2 - tw / 2)
|
423
|
-
else
|
424
|
-
parent = @e_list.get_id(j.parent)
|
425
|
-
pw = img_get_txt_width(parent.content, @font, @font_size)
|
426
|
-
pleft = parent.indent
|
427
|
-
pright = pleft + pw
|
428
|
-
left = j.indent
|
429
|
-
right = left + tw
|
430
|
-
if pw > tw
|
431
|
-
left = pleft
|
432
|
-
right = pright
|
433
|
-
end
|
434
|
-
draw_element(left, curlevel, right - left, j.content, j.type)
|
435
|
-
@e_list.set_indent(j.id, left + (right - left) / 2 - tw / 2)
|
436
|
-
end
|
437
|
-
|
438
|
-
unless children.empty?
|
439
|
-
k = @e_list.get_id(children[0])
|
440
|
-
words = k.content.split(" ")
|
441
|
-
dw = img_get_txt_width(k.content, @font, @font_size)
|
442
|
-
unless @leafstyle == "nothing" && ETYPE_LEAF == k.type
|
443
|
-
if (@leafstyle == "triangle" && ETYPE_LEAF == k.type && words.length > 0)
|
444
|
-
txt_width = img_get_txt_width(k.content, @font, @font_size)
|
445
|
-
triangle_to_parent(k.indent, curlevel + 1, dw,
|
446
|
-
@e_list.get_element_width(k.parent), txt_width)
|
447
|
-
elsif (@leafstyle == "auto" && ETYPE_LEAF == k.type)
|
448
|
-
if words.length > 1 || k.triangle
|
449
|
-
txt_width = img_get_txt_width(k.content, @font, @font_size)
|
450
|
-
triangle_to_parent(k.indent, curlevel + 1, dw, tw, txt_width)
|
451
|
-
else
|
452
|
-
line_to_parent(k.indent, curlevel + 1, dw, j.indent, tw)
|
453
|
-
end
|
454
|
-
else
|
455
|
-
line_to_parent(k.indent, curlevel + 1, dw, j.indent, tw)
|
456
|
-
end
|
457
|
-
end
|
458
|
-
end
|
459
|
-
end
|
460
|
-
end
|
461
|
-
end
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
# Calculate top position from row (level)
|
466
|
-
def row2px(row)
|
467
|
-
@m[:b_topbot] + @e_height * row + (@m[:v_space] + @font_size) * row
|
292
|
+
return width
|
468
293
|
end
|
469
294
|
end
|