rsyntaxtree 0.8.6 → 0.9.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/bin/rsyntaxtree +4 -1
- data/fonts/NotoSansJP-Bold.otf +0 -0
- data/fonts/NotoSansJP-Regular.otf +0 -0
- data/fonts/NotoSansMath-Regular.ttf +0 -0
- data/fonts/NotoSerifJP-Bold.otf +0 -0
- data/fonts/NotoSerifJP-Regular.otf +0 -0
- data/lib/rsyntaxtree/element.rb +3 -3
- data/lib/rsyntaxtree/error_message.rb +1 -1
- data/lib/rsyntaxtree/graph.rb +10 -5
- data/lib/rsyntaxtree/string_parser.rb +9 -2
- data/lib/rsyntaxtree/svg_graph.rb +114 -59
- data/lib/rsyntaxtree/tree_graph.rb +52 -25
- data/lib/rsyntaxtree/version.rb +1 -1
- data/lib/rsyntaxtree.rb +35 -27
- metadata +6 -4
- data/fonts/NotoSansCJKjp-Regular.otf +0 -0
- data/fonts/NotoSerifCJKjp-Regular.otf +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 146c2bdc6330d735c979a82c0d83fc1351ad486a49e4e66b833d12adde1a5cd4
|
4
|
+
data.tar.gz: b45b7ecef617e60aea43f621914653dd0c027710d6f563a401eea5e88b670cf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daf6f67fcbb8887f7e183b6a0fdf232e7d5027d5b2f5e02dbc48e455eef0581a08a6c3e623c0b1dbea512bed8b2d40e8d76e8d8b01e206671357596e93bf65a3
|
7
|
+
data.tar.gz: 6343039919b40954e2c37a9b9267143607d0efecb0d81689b8fefcad6b2201b513b2d6d9cade7e55452d9ee5916bc4490415c03c4a5560d798c2889d65142937
|
data/bin/rsyntaxtree
CHANGED
@@ -37,6 +37,8 @@ EOS
|
|
37
37
|
:default => "on"
|
38
38
|
opt :autosub, "Put subscript numbers to nodes: on or off",
|
39
39
|
:default => "off"
|
40
|
+
opt :transparent, "Make background transparent: on or off",
|
41
|
+
:default => "off"
|
40
42
|
end
|
41
43
|
|
42
44
|
Optimist::die :outdir, "must be an exsting directory path" unless FileTest::directory?(opts[:outdir])
|
@@ -48,8 +50,9 @@ Optimist::die :fontsize, "must be in the range of 8-26" unless opts[:fontsize] >
|
|
48
50
|
Optimist::die :color, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:color]
|
49
51
|
Optimist::die :symmetrize, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:symmetrize]
|
50
52
|
Optimist::die :autosub, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:autosub]
|
51
|
-
Optimist::die :margin, "must be in the range of
|
53
|
+
Optimist::die :margin, "must be in the range of 0-5" if opts[:margin] < 1 || opts[:margin] > 5
|
52
54
|
Optimist::die :vheight, "must be in the range of 0.5-5.0" if opts[:vheight] < 0.5 || opts[:vheight] > 5.0
|
55
|
+
Optimist::die :transparent, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:transparent]
|
53
56
|
|
54
57
|
string_opts = {}
|
55
58
|
opts.each do |key, value|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/rsyntaxtree/element.rb
CHANGED
@@ -23,9 +23,9 @@ class Element
|
|
23
23
|
@level = level # Element level in the tree (0=top etc...)
|
24
24
|
@width = 0 # Width of the element in pixels
|
25
25
|
@indent = 0 # Drawing offset
|
26
|
-
|
27
|
-
if /\A.+\^\z/ =~ content
|
28
|
-
@content = content.gsub("^"){""}
|
26
|
+
content = content.strip
|
27
|
+
if /\A.+\^\z/m =~ content
|
28
|
+
@content = content.gsub("^"){""} # The actual element content
|
29
29
|
@triangle = true # draw triangle instead of stright bar when in auto mode
|
30
30
|
else
|
31
31
|
@content = content.gsub("^"){""}.strip # The actual element content
|
@@ -23,7 +23,7 @@ class ErrorMessage
|
|
23
23
|
@filename = filename
|
24
24
|
@format = format
|
25
25
|
|
26
|
-
metrics = img_get_txt_metrics(text, font, font_size, true)
|
26
|
+
metrics = img_get_txt_metrics(text, font, font_size, NoDecoration, true)
|
27
27
|
|
28
28
|
@im = Image.new(metrics.width, metrics.height)
|
29
29
|
@gc = Draw.new
|
data/lib/rsyntaxtree/graph.rb
CHANGED
@@ -66,6 +66,9 @@ class Graph
|
|
66
66
|
gc.pointsize = font_size
|
67
67
|
gc.gravity = CenterGravity
|
68
68
|
gc.stroke = 'none'
|
69
|
+
gc.kerning = 0
|
70
|
+
gc.interline_spacing = 0
|
71
|
+
gc.interword_spacing = 0
|
69
72
|
end
|
70
73
|
|
71
74
|
if multiline
|
@@ -81,18 +84,19 @@ class Graph
|
|
81
84
|
# for all child elements.
|
82
85
|
def calc_element_width(e)
|
83
86
|
w = 0
|
87
|
+
content = e.content.gsub("<>", " ")
|
84
88
|
|
85
89
|
children = @e_list.get_children(e.id)
|
86
90
|
|
87
91
|
if(children.length == 0)
|
88
|
-
w = img_get_txt_width(
|
92
|
+
w = img_get_txt_width(content, @font, @font_size) + @font_size
|
89
93
|
else
|
90
94
|
children.each do |child|
|
91
95
|
child_e = @e_list.get_id(child)
|
92
96
|
w += calc_element_width(child_e)
|
93
97
|
end
|
94
98
|
|
95
|
-
tw = img_get_txt_width(
|
99
|
+
tw = img_get_txt_width(content, @font, @font_size) + @font_size
|
96
100
|
if(tw > w)
|
97
101
|
fix_child_size(e.id, w, tw)
|
98
102
|
w = tw
|
@@ -186,13 +190,13 @@ class Graph
|
|
186
190
|
end
|
187
191
|
end
|
188
192
|
return true if !@symmetrize
|
189
|
-
|
193
|
+
|
190
194
|
elements_to_draw = {}
|
191
195
|
triangles_to_draw = []
|
192
196
|
lines_to_draw = []
|
193
197
|
|
194
198
|
lmost = {:level => nil, :value => nil, :type => nil}
|
195
|
-
rmost = nil
|
199
|
+
rmost = nil
|
196
200
|
h.times do |i|
|
197
201
|
curlevel = h - i - 1
|
198
202
|
e_arr.each_with_index do |j, idx|
|
@@ -299,8 +303,9 @@ class Graph
|
|
299
303
|
return text
|
300
304
|
end
|
301
305
|
|
302
|
-
def img_get_txt_height(text, font, font_size, multiline =
|
306
|
+
def img_get_txt_height(text, font, font_size, multiline = true)
|
303
307
|
metrics = img_get_txt_metrics(text, font, font_size, multiline)
|
308
|
+
# y = (metrics.bounds.y2 - metrics.bounds.y1).round
|
304
309
|
y = metrics.height
|
305
310
|
return y
|
306
311
|
end
|
@@ -171,8 +171,15 @@ class StringParser
|
|
171
171
|
end
|
172
172
|
when "\\"
|
173
173
|
escape = true
|
174
|
-
when
|
175
|
-
|
174
|
+
when "n", " ", "+", "-", "=", "~", "#", "*"
|
175
|
+
if escape
|
176
|
+
token += "\\#{ch}"
|
177
|
+
escape = false
|
178
|
+
else
|
179
|
+
token += ch
|
180
|
+
end
|
181
|
+
# when /[\n\r]/
|
182
|
+
# gottoken = false # same as do nothing
|
176
183
|
else
|
177
184
|
token += ch
|
178
185
|
escape = false if escape
|
@@ -18,37 +18,70 @@ require 'graph'
|
|
18
18
|
|
19
19
|
class SVGGraph < Graph
|
20
20
|
|
21
|
-
def initialize(e_list, metrics, symmetrize, color, leafstyle, multibyte, fontstyle, font, font_cjk, font_size)
|
21
|
+
def initialize(e_list, metrics, symmetrize, color, leafstyle, multibyte, fontstyle, font, font_cjk, font_size, margin, transparent)
|
22
22
|
|
23
23
|
# Store class-specific parameters
|
24
24
|
@font = multibyte ? font_cjk : font
|
25
25
|
@font_size = font_size
|
26
|
+
@transparent = transparent
|
27
|
+
|
26
28
|
case fontstyle
|
27
29
|
when /(?:sans|cjk)/
|
28
|
-
@fontstyle
|
29
|
-
|
30
|
-
|
30
|
+
@fontstyle = "\"'Noto Sans JP', 'Noto Sans', sans-serif\""
|
31
|
+
@fontcss = "http://fonts.googleapis.com/earlyaccess/notosansjp.css"
|
32
|
+
when /(?:serif)/
|
33
|
+
@fontstyle = "\"'Noto Serif JP', 'Noto Serif', serif\""
|
34
|
+
@fontcss = "https://fonts.googleapis.com/css?family=Noto+Serif+JP"
|
35
|
+
when /(?:math)/
|
36
|
+
@fontstyle = "\"Latin Modern Roman', sans-serif\""
|
37
|
+
@fontcss = "https://cdn.jsdelivr.net/gh/sugina-dev/latin-modern-web@1.0.1/style/latinmodern-roman.css"
|
31
38
|
end
|
32
39
|
|
33
|
-
|
40
|
+
@margin = margin.to_i
|
41
|
+
|
42
|
+
super(e_list, metrics, symmetrize, color, leafstyle, multibyte, @fontstyle, @font_size)
|
34
43
|
|
35
44
|
@line_styles = "<line style='stroke:black; stroke-width:#{FONT_SCALING};' x1='X1' y1='Y1' x2='X2' y2='Y2' />\n"
|
36
45
|
@polygon_styles = "<polygon style='fill: none; stroke: black; stroke-width:#{FONT_SCALING};' points='X1 Y1 X2 Y2 X3 Y3' />\n"
|
37
|
-
@text_styles = "<text style='fill: COLOR; font-size:
|
46
|
+
@text_styles = "<text letter-spacing='0' word-spacing='0' kerning='0' style='fill: COLOR; font-size: FONT_SIZE ST WA' x='X_VALUE' y='Y_VALUE' TD font-family=#{@fontstyle}>CONTENT</text>\n"
|
38
47
|
@tree_data = String.new
|
39
48
|
end
|
40
49
|
|
50
|
+
def get_left_most(tree_data)
|
51
|
+
xs = @tree_data.scan(/x1?=['"]([^'"]+)['"]/).map{|m| m.first.to_i}
|
52
|
+
xs.min
|
53
|
+
end
|
54
|
+
|
41
55
|
def svg_data
|
42
56
|
parse_list
|
57
|
+
lm = get_left_most(@tree_data)
|
58
|
+
width = @width - lm + @margin * 2
|
59
|
+
height = @height + @margin * 2
|
60
|
+
|
43
61
|
header =<<EOD
|
44
62
|
<?xml version="1.0" standalone="no"?>
|
45
|
-
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
63
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
46
64
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
47
|
-
<svg width="#{
|
65
|
+
<svg width="#{width}" height="#{height}" viewBox="#{-@margin + lm}, -#{@margin}, #{@width - lm + @margin * 2}, #{@height + @margin * 2}" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
66
|
+
<defs>
|
67
|
+
<style>
|
68
|
+
@import url(#{@fontcss});
|
69
|
+
</style>
|
70
|
+
</defs>
|
71
|
+
EOD
|
72
|
+
|
73
|
+
|
74
|
+
rect =<<EOD
|
75
|
+
<rect x="#{-@margin + lm}" y="-#{@margin}" width="#{@width - lm + @margin * 2}" height="#{@height + @margin * 2}" stroke="none" fill="white" />"
|
48
76
|
EOD
|
49
77
|
|
50
78
|
footer = "</svg>"
|
51
|
-
|
79
|
+
|
80
|
+
if @transparent
|
81
|
+
header + @tree_data + footer
|
82
|
+
else
|
83
|
+
header + rect + @tree_data + footer
|
84
|
+
end
|
52
85
|
end
|
53
86
|
|
54
87
|
# Create a temporary file and returns only its filename
|
@@ -68,21 +101,21 @@ EOD
|
|
68
101
|
end
|
69
102
|
|
70
103
|
:private
|
71
|
-
|
104
|
+
|
72
105
|
# Add the element into the tree (draw it)
|
73
106
|
def draw_element(x, y, w, string, type)
|
74
|
-
string = string.sub(/\^\z/){""}
|
107
|
+
string = string.sub(/\^\z/){""}
|
75
108
|
# Calculate element dimensions and position
|
76
109
|
if (type == ETYPE_LEAF) and @leafstyle == "nothing"
|
77
110
|
top = row2px(y - 1) + (@font_size * 1.5)
|
78
|
-
else
|
111
|
+
else
|
79
112
|
top = row2px(y)
|
80
113
|
end
|
81
114
|
left = x + @m[:b_side]
|
82
115
|
bottom = top + @e_height
|
83
116
|
right = left + w
|
84
117
|
|
85
|
-
# Split the string into the main part and the
|
118
|
+
# Split the string into the main part and the
|
86
119
|
# subscript part of the element (if any)
|
87
120
|
parts = string.split("_", 2)
|
88
121
|
if(parts.length > 1 )
|
@@ -127,11 +160,18 @@ EOD
|
|
127
160
|
main = $1
|
128
161
|
end
|
129
162
|
|
130
|
-
# Calculate text size for the main and the
|
163
|
+
# Calculate text size for the main and the
|
131
164
|
# subscript part of the element
|
132
165
|
# symbols for underline/overline removed temporarily
|
133
166
|
|
134
|
-
main_width =
|
167
|
+
main_width = 0
|
168
|
+
main_height = 0
|
169
|
+
main.split(/\\n/).each do |l|
|
170
|
+
l_width = img_get_txt_width(l, @font, @font_size)
|
171
|
+
main_width = l_width if main_width < l_width
|
172
|
+
main_height += img_get_txt_height(l, @font, @font_size)
|
173
|
+
end
|
174
|
+
|
135
175
|
|
136
176
|
if sub != ""
|
137
177
|
if /\A\=(.+)\=\z/ =~ sub
|
@@ -163,9 +203,11 @@ EOD
|
|
163
203
|
sub_style = ""
|
164
204
|
sub_weight = ""
|
165
205
|
end
|
206
|
+
sub_height = img_get_txt_height(sub, @font, @font_size)
|
166
207
|
sub_width = img_get_txt_width(sub.to_s, @font, @sub_size)
|
167
208
|
else
|
168
209
|
sub_width = 0
|
210
|
+
sub_height = 0
|
169
211
|
end
|
170
212
|
|
171
213
|
if /\A#(.+)#\z/ =~ sub
|
@@ -173,14 +215,13 @@ EOD
|
|
173
215
|
end
|
174
216
|
|
175
217
|
# Center text in the element
|
176
|
-
|
177
|
-
txt_pos = left + (right - left) / 2 - txt_width / 2
|
218
|
+
txt_pos = left + (right - left) / 2
|
178
219
|
|
179
220
|
# Select apropriate color
|
180
221
|
if(type == ETYPE_LEAF)
|
181
222
|
col = @col_leaf
|
182
223
|
else
|
183
|
-
col = @col_node
|
224
|
+
col = @col_node
|
184
225
|
end
|
185
226
|
|
186
227
|
if(main[0].chr == "<" && main[-1].chr == ">")
|
@@ -189,29 +230,47 @@ EOD
|
|
189
230
|
|
190
231
|
# Draw main text
|
191
232
|
main_data = @text_styles.sub(/COLOR/, col)
|
192
|
-
main_data = main_data.sub(/FONT_SIZE/, @font_size.to_s)
|
193
|
-
main_x = txt_pos
|
194
|
-
main_y = top + @e_height - @m[:e_padd]
|
233
|
+
main_data = main_data.sub(/FONT_SIZE/, @font_size.to_s + "px;")
|
234
|
+
main_x = txt_pos - (main_width + sub_width) / 2
|
235
|
+
main_y = top + @e_height - @m[:e_padd]
|
195
236
|
main_data = main_data.sub(/X_VALUE/, main_x.to_s)
|
196
237
|
main_data = main_data.sub(/Y_VALUE/, main_y.to_s)
|
197
|
-
|
238
|
+
if /\\n/ =~ main
|
239
|
+
lines = main.split(/\\n/)
|
240
|
+
new_main = ""
|
241
|
+
dy = 0
|
242
|
+
lines.each_with_index do |l, idx|
|
243
|
+
if idx == 0
|
244
|
+
dy = 0
|
245
|
+
else
|
246
|
+
dy = 1
|
247
|
+
main_y += img_get_txt_height(l, @font, @font_size)
|
248
|
+
end
|
249
|
+
this_width = img_get_txt_width(l, @font, @font_size)
|
250
|
+
this_x = txt_pos - (this_width + sub_width) / 2
|
251
|
+
new_main << "<tspan x='#{this_x}' y='#{main_y}'>#{l}</tspan>"
|
252
|
+
@height = main_y if main_y > @height
|
253
|
+
end
|
254
|
+
main = new_main
|
255
|
+
end
|
198
256
|
@tree_data += main_data.sub(/TD/, "text-decoration='#{main_decoration}'")
|
199
|
-
.sub(/ST/, main_style)
|
200
|
-
.sub(/WA/, main_weight)
|
257
|
+
.sub(/ST/, main_style + ";")
|
258
|
+
.sub(/WA/, main_weight + ";")
|
201
259
|
.sub(/CONTENT/, main)
|
202
260
|
|
203
261
|
# Draw subscript text
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
sub_data = sub_data.sub(/X_VALUE/, sub_x.
|
210
|
-
sub_data = sub_data.sub(/Y_VALUE/, sub_y.
|
262
|
+
if sub && sub != ""
|
263
|
+
sub_data = @text_styles.sub(/COLOR/, col)
|
264
|
+
sub_data = sub_data.sub(/FONT_SIZE/, @sub_size.to_s)
|
265
|
+
sub_x = txt_pos + (main_width / 2) - (sub_width / 2)
|
266
|
+
sub_y = main_y + sub_height / 6
|
267
|
+
sub_data = sub_data.sub(/X_VALUE/, sub_x.to_s)
|
268
|
+
sub_data = sub_data.sub(/Y_VALUE/, sub_y.to_s)
|
211
269
|
@tree_data += sub_data.sub(/TD/, "text-decoration='#{sub_decoration}'")
|
212
270
|
.sub(/ST/, sub_style)
|
213
271
|
.sub(/WA/, sub_weight)
|
214
|
-
.sub(/CONTENT/,
|
272
|
+
.sub(/CONTENT/, sub)
|
273
|
+
@height += sub_height / 4
|
215
274
|
end
|
216
275
|
end
|
217
276
|
|
@@ -227,10 +286,10 @@ EOD
|
|
227
286
|
toBot = (row2px(fromY - 1 ) + @e_height)
|
228
287
|
toLeft = (toX + toW / 2 + @m[:b_side])
|
229
288
|
|
230
|
-
line_data = @line_styles.sub(/X1/, fromLeft.
|
231
|
-
line_data = line_data.sub(/Y1/, fromTop.
|
232
|
-
line_data = line_data.sub(/X2/, toLeft.
|
233
|
-
@tree_data += line_data.sub(/Y2/, toBot.
|
289
|
+
line_data = @line_styles.sub(/X1/, fromLeft.to_s)
|
290
|
+
line_data = line_data.sub(/Y1/, fromTop.to_s)
|
291
|
+
line_data = line_data.sub(/X2/, toLeft.to_s)
|
292
|
+
@tree_data += line_data.sub(/Y2/, toBot.to_s)
|
234
293
|
|
235
294
|
end
|
236
295
|
|
@@ -243,9 +302,9 @@ EOD
|
|
243
302
|
toX = fromX
|
244
303
|
fromCenter = (fromX + fromW / 2 + @m[:b_side])
|
245
304
|
|
246
|
-
fromTop = row2px(fromY)
|
247
|
-
fromLeft1 = (fromCenter + textW / 2)
|
248
|
-
fromLeft2 = (fromCenter - textW / 2)
|
305
|
+
fromTop = row2px(fromY)
|
306
|
+
fromLeft1 = (fromCenter + textW / 2)
|
307
|
+
fromLeft2 = (fromCenter - textW / 2)
|
249
308
|
toBot = (row2px(fromY - 1) + @e_height)
|
250
309
|
|
251
310
|
if symmetrize
|
@@ -254,12 +313,12 @@ EOD
|
|
254
313
|
toLeft = (toX + textW / 2 + @m[:b_side] * 3)
|
255
314
|
end
|
256
315
|
|
257
|
-
polygon_data = @polygon_styles.sub(/X1/, fromLeft1.
|
258
|
-
polygon_data = polygon_data.sub(/Y1/, fromTop.
|
259
|
-
polygon_data = polygon_data.sub(/X2/, fromLeft2.
|
260
|
-
polygon_data = polygon_data.sub(/Y2/, fromTop.
|
261
|
-
polygon_data = polygon_data.sub(/X3/, toLeft.
|
262
|
-
@tree_data += polygon_data.sub(/Y3/, toBot.
|
316
|
+
polygon_data = @polygon_styles.sub(/X1/, fromLeft1.to_s)
|
317
|
+
polygon_data = polygon_data.sub(/Y1/, fromTop.to_s)
|
318
|
+
polygon_data = polygon_data.sub(/X2/, fromLeft2.to_s)
|
319
|
+
polygon_data = polygon_data.sub(/Y2/, fromTop.to_s)
|
320
|
+
polygon_data = polygon_data.sub(/X3/, toLeft.to_s)
|
321
|
+
@tree_data += polygon_data.sub(/Y3/, toBot.to_s)
|
263
322
|
end
|
264
323
|
|
265
324
|
# If a node element text is wider than the sum of it's
|
@@ -271,9 +330,9 @@ EOD
|
|
271
330
|
children = @e_list.get_children(id)
|
272
331
|
@e_list.set_element_width(id, target)
|
273
332
|
|
274
|
-
if(children.length > 0 )
|
333
|
+
if(children.length > 0 )
|
275
334
|
delta = target - current
|
276
|
-
target_delta = delta / children.length
|
335
|
+
target_delta = delta / children.length
|
277
336
|
|
278
337
|
children.each do |child|
|
279
338
|
child_width = @e_list.get_element_width(child)
|
@@ -282,27 +341,23 @@ EOD
|
|
282
341
|
end
|
283
342
|
end
|
284
343
|
|
285
|
-
def img_get_txt_width(text, font, font_size, multiline =
|
344
|
+
def img_get_txt_width(text, font, font_size, multiline = true)
|
286
345
|
parts = text.split("_", 2)
|
287
346
|
main_before = parts[0].strip
|
288
347
|
sub = parts[1]
|
289
348
|
main = get_txt_only(main_before)
|
290
|
-
# if(main.contains_cjk?)
|
291
|
-
# main = 'n' * main.strip.size * 2
|
292
|
-
# else
|
293
|
-
# main
|
294
|
-
# end
|
295
349
|
main_metrics = img_get_txt_metrics(main, font, font_size, multiline)
|
296
350
|
width = main_metrics.width
|
297
351
|
if sub
|
298
|
-
|
299
|
-
# sub = 'n' * sub.strip.size * 2
|
300
|
-
# else
|
301
|
-
# sub
|
302
|
-
# end
|
303
|
-
sub_metrics = img_get_txt_metrics(sub, font, font_size * SUBSCRIPT_CONST, multiline)
|
352
|
+
sub_metrics = img_get_txt_metrics(sub.strip, font, font_size * SUBSCRIPT_CONST, multiline)
|
304
353
|
width += sub_metrics.width
|
305
354
|
end
|
306
355
|
return width
|
307
356
|
end
|
357
|
+
|
358
|
+
def img_get_txt_height(text, font, font_size)
|
359
|
+
main_metrics = img_get_txt_metrics(text, font, font_size, false)
|
360
|
+
main_metrics.height
|
361
|
+
end
|
362
|
+
|
308
363
|
end
|
@@ -21,18 +21,19 @@ class TreeGraph < Graph
|
|
21
21
|
|
22
22
|
def initialize(e_list, metrics, symmetrize, color, leafstyle, multibyte,
|
23
23
|
fontstyle, font, font_it, font_bd, font_itbd, font_math, font_cjk, font_size,
|
24
|
-
margin)
|
24
|
+
margin, transparent)
|
25
25
|
|
26
26
|
# Store class-specific parameters
|
27
|
-
@fontstyle
|
28
|
-
@font
|
29
|
-
@font_size
|
30
|
-
@font_it
|
31
|
-
@font_bd
|
32
|
-
@font_itbd
|
33
|
-
@font_math
|
34
|
-
@font_cjk
|
35
|
-
@margin
|
27
|
+
@fontstyle = fontstyle
|
28
|
+
@font = multibyte ? font_cjk : font
|
29
|
+
@font_size = font_size
|
30
|
+
@font_it = font_it
|
31
|
+
@font_bd = font_bd
|
32
|
+
@font_itbd = font_itbd
|
33
|
+
@font_math = font_math
|
34
|
+
@font_cjk = font_cjk
|
35
|
+
@margin = margin
|
36
|
+
@transparent = transparent
|
36
37
|
|
37
38
|
super(e_list, metrics, symmetrize, color, leafstyle, multibyte, @font, @font_size)
|
38
39
|
|
@@ -49,7 +50,11 @@ class TreeGraph < Graph
|
|
49
50
|
def draw
|
50
51
|
parse_list
|
51
52
|
@im = Image.new(@width, @height)
|
52
|
-
@
|
53
|
+
if @transparent
|
54
|
+
@im.matte_reset!
|
55
|
+
end
|
56
|
+
# @im.interlace = PlaneInterlace
|
57
|
+
@im.interlace = LineInterlace
|
53
58
|
@gc.draw(@im)
|
54
59
|
end
|
55
60
|
|
@@ -63,7 +68,11 @@ class TreeGraph < Graph
|
|
63
68
|
def to_blob(fileformat='PNG')
|
64
69
|
draw
|
65
70
|
@im.trim!
|
66
|
-
|
71
|
+
if @transparent
|
72
|
+
@im.border!(@margin, @margin, "transparent")
|
73
|
+
else
|
74
|
+
@im.border!(@margin, @margin, "white")
|
75
|
+
end
|
67
76
|
@im.format = fileformat
|
68
77
|
@im.interlace = PlaneInterlace
|
69
78
|
return @im.to_blob
|
@@ -81,7 +90,6 @@ class TreeGraph < Graph
|
|
81
90
|
top = row2px(y)
|
82
91
|
end
|
83
92
|
left = x + @m[:b_side]
|
84
|
-
bottom = top + @e_height
|
85
93
|
right = left + w
|
86
94
|
|
87
95
|
# Split the string into the main part and the
|
@@ -135,7 +143,14 @@ class TreeGraph < Graph
|
|
135
143
|
# Calculate text size for the main and the
|
136
144
|
# subscript part of the element
|
137
145
|
|
138
|
-
|
146
|
+
|
147
|
+
main_width = 0
|
148
|
+
main_height = 0
|
149
|
+
main.split(/\\n/).each do |l|
|
150
|
+
l_width = img_get_txt_width(l, main_font, @font_size)
|
151
|
+
main_width = l_width if main_width < l_width
|
152
|
+
main_height += img_get_txt_height(l, @font, @font_size)
|
153
|
+
end
|
139
154
|
|
140
155
|
if /\A\=(.+)\=\z/ =~ sub
|
141
156
|
sub = $1
|
@@ -175,14 +190,14 @@ class TreeGraph < Graph
|
|
175
190
|
|
176
191
|
if sub != ""
|
177
192
|
sub_width = img_get_txt_width(sub.to_s, sub_font, @sub_size)
|
193
|
+
sub_height = img_get_txt_height(sub.to_s, sub_font, @sub_size)
|
178
194
|
else
|
179
195
|
sub_width = 0
|
196
|
+
sub_height = 0
|
180
197
|
end
|
181
198
|
|
182
199
|
# Center text in the element
|
183
|
-
|
184
|
-
|
185
|
-
txt_pos = left + (right - left) / 2 - txt_width / 2
|
200
|
+
txt_pos = left + (right - left) / 2
|
186
201
|
|
187
202
|
# Select apropriate color
|
188
203
|
if(type == ETYPE_LEAF)
|
@@ -200,22 +215,33 @@ class TreeGraph < Graph
|
|
200
215
|
|
201
216
|
# Draw main text
|
202
217
|
@gc.pointsize(@font_size)
|
203
|
-
|
218
|
+
@gc.kerning = 0
|
219
|
+
@gc.interline_spacing = 0
|
220
|
+
@gc.interword_spacing = 0
|
221
|
+
|
222
|
+
main_x = txt_pos - sub_width / 2
|
204
223
|
main_y = top + @e_height - @m[:e_padd]
|
205
224
|
|
206
|
-
@gc.interline_spacing = -(@main_height / 3)
|
225
|
+
# @gc.interline_spacing = -(@main_height / 3)
|
207
226
|
@gc.font(main_font)
|
208
227
|
@gc.decorate(main_decoration)
|
209
|
-
|
228
|
+
numlines = main.count("\\n")
|
229
|
+
if numlines > 1
|
230
|
+
@height = @height + @main_height * numlines
|
231
|
+
end
|
232
|
+
@gc.text_align(CenterAlign)
|
233
|
+
@gc.text(main_x.ceil, main_y.ceil, main.gsub("\\n", "\n"))
|
210
234
|
|
211
235
|
# Draw subscript text
|
212
|
-
if (sub
|
236
|
+
if (sub != "" )
|
213
237
|
@gc.pointsize(@sub_size)
|
214
|
-
sub_x =
|
215
|
-
sub_y = top +
|
238
|
+
sub_x = main_x + (main_width / 2) + (sub_width / 2)
|
239
|
+
sub_y = top + main_height + sub_height / 4
|
240
|
+
@height += sub_height / 4
|
216
241
|
@gc.font(sub_font)
|
217
242
|
@gc.decorate(sub_decoration)
|
218
|
-
@gc.
|
243
|
+
@gc.text_align(CenterAlign)
|
244
|
+
@gc.text(sub_x.ceil, sub_y.ceil, " " + sub.gsub("\\n", "\n"))
|
219
245
|
end
|
220
246
|
end
|
221
247
|
|
@@ -250,6 +276,7 @@ class TreeGraph < Graph
|
|
250
276
|
fromLeft1 = (fromCenter + textW / 2).ceil
|
251
277
|
fromLeft2 = (fromCenter - textW / 2).ceil
|
252
278
|
toBot = (row2px(fromY - 1) + @e_height)
|
279
|
+
|
253
280
|
if symmetrize
|
254
281
|
toLeft = (toX + textW / 2 + @m[:b_side])
|
255
282
|
else
|
@@ -284,7 +311,7 @@ class TreeGraph < Graph
|
|
284
311
|
end
|
285
312
|
end
|
286
313
|
|
287
|
-
def img_get_txt_width(text, font, font_size, multiline =
|
314
|
+
def img_get_txt_width(text, font, font_size, multiline = true)
|
288
315
|
parts = text.split("_", 2)
|
289
316
|
main_before = parts[0].strip
|
290
317
|
sub = parts[1]
|
data/lib/rsyntaxtree/version.rb
CHANGED
data/lib/rsyntaxtree.rb
CHANGED
@@ -40,7 +40,8 @@ class RSGenerator
|
|
40
40
|
key = keystr.to_sym
|
41
41
|
case key
|
42
42
|
when :data
|
43
|
-
data =
|
43
|
+
data = value
|
44
|
+
# data = CGI.unescape(value)
|
44
45
|
data = data.gsub('-AMP-', '&')
|
45
46
|
.gsub('-PERCENT-', "%")
|
46
47
|
.gsub('-PRIME-', "'")
|
@@ -49,7 +50,7 @@ class RSGenerator
|
|
49
50
|
.gsub('-CABRACKET-', '>')
|
50
51
|
new_params[key] = data
|
51
52
|
new_params[:multibyte] = data.contains_cjk?
|
52
|
-
when :symmetrize, :color, :autosub
|
53
|
+
when :symmetrize, :color, :autosub, :transparent
|
53
54
|
new_params[key] = value && value != "off" ? true : false
|
54
55
|
when :fontsize
|
55
56
|
new_params[key] = value.to_i * FONT_SCALING
|
@@ -64,7 +65,7 @@ class RSGenerator
|
|
64
65
|
new_params[:font_bd] = FONT_DIR + "/NotoSans-Bold.ttf"
|
65
66
|
new_params[:font_bdit] = FONT_DIR + "/NotoSans-BoldItalic.ttf"
|
66
67
|
new_params[:font_math] = FONT_DIR + "/NotoSansMath-Regular.ttf"
|
67
|
-
new_params[:font_cjk] = FONT_DIR + "/
|
68
|
+
new_params[:font_cjk] = FONT_DIR + "/NotoSansJP-Regular.otf"
|
68
69
|
new_params[:fontstyle] = "sans"
|
69
70
|
elsif value == "noto-serif" || value == "serif"
|
70
71
|
new_params[:font] = FONT_DIR + "/NotoSerif-Regular.ttf"
|
@@ -72,7 +73,7 @@ class RSGenerator
|
|
72
73
|
new_params[:font_bd] = FONT_DIR + "/NotoSerif-Bold.ttf"
|
73
74
|
new_params[:font_bdit] = FONT_DIR + "/NotoSerif-BoldItalic.ttf"
|
74
75
|
new_params[:font_math] = FONT_DIR + "/NotoSansMath-Regular.ttf"
|
75
|
-
new_params[:font_cjk] = FONT_DIR + "/
|
76
|
+
new_params[:font_cjk] = FONT_DIR + "/NotoSerifJP-Regular.otf"
|
76
77
|
new_params[:fontstyle] = "serif"
|
77
78
|
elsif value == "cjk zenhei" || value == "cjk"
|
78
79
|
new_params[:font] = FONT_DIR + "/wqy-zenhei.ttf"
|
@@ -88,7 +89,7 @@ class RSGenerator
|
|
88
89
|
new_params[:font_bd] = FONT_DIR + "/lmroman10-bold.otf"
|
89
90
|
new_params[:font_bdit] = FONT_DIR + "/lmroman10-bolditalic.otf"
|
90
91
|
new_params[:font_math] = FONT_DIR + "/latinmodern-math.otf"
|
91
|
-
new_params[:font_cjk] = FONT_DIR + "/
|
92
|
+
new_params[:font_cjk] = FONT_DIR + "/NotoSerifJP-Regular.otf"
|
92
93
|
new_params[:fontstyle] = "math"
|
93
94
|
end
|
94
95
|
else
|
@@ -98,30 +99,37 @@ class RSGenerator
|
|
98
99
|
|
99
100
|
# defaults to the following
|
100
101
|
@params = {
|
101
|
-
:symmetrize
|
102
|
-
:color
|
103
|
-
:autosub
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
109
|
-
:
|
110
|
-
:
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
115
|
-
:
|
116
|
-
:
|
102
|
+
:symmetrize => true,
|
103
|
+
:color => true,
|
104
|
+
:autosub => false,
|
105
|
+
:transparent => false,
|
106
|
+
:fontsize => 18,
|
107
|
+
:format => "png",
|
108
|
+
:leafstyle => "auto",
|
109
|
+
:filename => "syntree",
|
110
|
+
:data => "",
|
111
|
+
:margin => 0,
|
112
|
+
:vheight => 1.0,
|
113
|
+
:fontstyle => "sans",
|
114
|
+
:font => "/NotoSansJP-Regular.otf",
|
115
|
+
:font_it => "/NotoSans-Italic.ttf",
|
116
|
+
:font_bd => "/NotoSans-Bold.ttf",
|
117
|
+
:font_bdit => "/NotoSans-BoldItalic.ttf",
|
118
|
+
:font_math => "/NotoSansMath-Regular.ttf"
|
117
119
|
}
|
118
120
|
@metrics = {
|
119
|
-
:e_width =>
|
121
|
+
:e_width => 0,
|
120
122
|
:e_padd => 14,
|
121
123
|
:v_space => 20,
|
122
|
-
:h_space =>
|
123
|
-
:b_side =>
|
124
|
-
:b_topbot =>
|
124
|
+
:h_space => 0,
|
125
|
+
:b_side => 0,
|
126
|
+
:b_topbot => 0
|
127
|
+
# :e_width => 120,
|
128
|
+
# :e_padd => 14,
|
129
|
+
# :v_space => 20,
|
130
|
+
# :h_space => 20,
|
131
|
+
# :b_side => 10,
|
132
|
+
# :b_topbot => 10
|
125
133
|
}
|
126
134
|
|
127
135
|
@params.merge! new_params
|
@@ -163,7 +171,7 @@ class RSGenerator
|
|
163
171
|
elist = sp.get_elementlist
|
164
172
|
graph = SVGGraph.new(elist, @metrics,
|
165
173
|
@params[:symmetrize], @params[:color], @params[:leafstyle], @params[:multibyte],
|
166
|
-
@params[:fontstyle], @params[:font], @params[:font_cjk], @params[:fontsize],
|
174
|
+
@params[:fontstyle], @params[:font], @params[:font_cjk], @params[:fontsize], @params[:margin], @params[:transparent]
|
167
175
|
)
|
168
176
|
graph.svg_data
|
169
177
|
end
|
@@ -176,7 +184,7 @@ class RSGenerator
|
|
176
184
|
graph = TreeGraph.new(elist, @metrics,
|
177
185
|
@params[:symmetrize], @params[:color], @params[:leafstyle], @params[:multibyte],
|
178
186
|
@params[:fontstyle], @params[:font], @params[:font_it], @params[:font_bd], @params[:font_bdit], @params[:font_math],
|
179
|
-
@params[:font_cjk], @params[:fontsize], @params[:margin],
|
187
|
+
@params[:font_cjk], @params[:fontsize], @params[:margin], @params[:transparent]
|
180
188
|
)
|
181
189
|
graph.to_blob(@params[:format])
|
182
190
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsyntaxtree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yoichiro Hasebe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rmagick
|
@@ -67,13 +67,15 @@ files:
|
|
67
67
|
- fonts/NotoSans-BoldItalic.ttf
|
68
68
|
- fonts/NotoSans-Italic.ttf
|
69
69
|
- fonts/NotoSans-Regular.ttf
|
70
|
-
- fonts/
|
70
|
+
- fonts/NotoSansJP-Bold.otf
|
71
|
+
- fonts/NotoSansJP-Regular.otf
|
71
72
|
- fonts/NotoSansMath-Regular.ttf
|
72
73
|
- fonts/NotoSerif-Bold.ttf
|
73
74
|
- fonts/NotoSerif-BoldItalic.ttf
|
74
75
|
- fonts/NotoSerif-Italic.ttf
|
75
76
|
- fonts/NotoSerif-Regular.ttf
|
76
|
-
- fonts/
|
77
|
+
- fonts/NotoSerifJP-Bold.otf
|
78
|
+
- fonts/NotoSerifJP-Regular.otf
|
77
79
|
- fonts/latinmodern-math.otf
|
78
80
|
- fonts/lmroman10-bold.otf
|
79
81
|
- fonts/lmroman10-bolditalic.otf
|
Binary file
|
Binary file
|